diff --git a/render-wasm/src/render/ui.rs b/render-wasm/src/render/ui.rs index b59eb6f235..38818b99ba 100644 --- a/render-wasm/src/render/ui.rs +++ b/render-wasm/src/render/ui.rs @@ -66,7 +66,8 @@ pub fn render(render_state: &mut RenderState, shapes: ShapesPoolRef) { let ruler_state = render_state.rulers; rulers::render(canvas, viewbox, &render_state.fonts, &ruler_state); // TODO: pass guides data here - guides::render(canvas, zoom, viewbox.area, &get_ui_state().guides); + let (horizontal, vertical) = get_ui_state().guides(); + guides::render(canvas, zoom, viewbox.area, horizontal, vertical); canvas.restore(); diff --git a/render-wasm/src/render/ui/guides.rs b/render-wasm/src/render/ui/guides.rs index 8c71433b71..4af6333e55 100644 --- a/render-wasm/src/render/ui/guides.rs +++ b/render-wasm/src/render/ui/guides.rs @@ -5,8 +5,17 @@ use crate::ui::{Guide, GuideKind}; /// Renders the ruler guides overlay using the guides provided by the host /// (ClojureScript) and stored in the render state. -pub fn render(canvas: &skia::Canvas, zoom: f32, area: Rect, guides: &[Guide]) { - for guide in guides { +pub fn render( + canvas: &skia::Canvas, + zoom: f32, + area: Rect, + horizontal: &[Guide], + vertical: &[Guide], +) { + for guide in horizontal { + render_guide(canvas, zoom, area, *guide); + } + for guide in vertical { render_guide(canvas, zoom, area, *guide); } } diff --git a/render-wasm/src/state/ui.rs b/render-wasm/src/state/ui.rs index b03b6d45a8..d9226f7ab0 100644 --- a/render-wasm/src/state/ui.rs +++ b/render-wasm/src/state/ui.rs @@ -1,16 +1,58 @@ -use crate::ui::Guide; +use crate::ui::{Guide, GuideKind}; use crate::uuid::Uuid; +pub struct GuidePool { + horizontal: Vec, + vertical: Vec, +} + +impl GuidePool { + pub fn new() -> Self { + Self { + horizontal: Vec::new(), + vertical: Vec::new(), + } + } + + pub fn set(&mut self, guides: Vec) { + for guide in guides { + match guide.kind { + GuideKind::Vertical(_) => self.vertical.push(guide), + GuideKind::Horizontal(_) => self.horizontal.push(guide), + } + } + + // TODO: handle the unwraps here + self.horizontal + .sort_by(|a, b| a.position().total_cmp(&b.position())); + self.vertical + .sort_by(|a, b| a.position().total_cmp(&b.position())); + } +} + pub struct UIState { - pub guides: Vec, + guides: GuidePool, pub _show_grid: Option, } impl UIState { pub fn new() -> Self { Self { - guides: Vec::new(), + guides: GuidePool::new(), _show_grid: None, } } + + pub fn guides(&self) -> (&Vec, &Vec) { + (&self.guides.horizontal, &self.guides.vertical) + } + + pub fn set_guides(&mut self, guides: Vec) { + self.guides.set(guides); + } + + #[allow(dead_code)] + fn find_guide_at(&self, _x: f32, _y: f32, _zoom: f32) -> Option<&Guide> { + unimplemented!("TODO: Implement guide finding"); + } } diff --git a/render-wasm/src/ui.rs b/render-wasm/src/ui.rs index 51bcd018e4..effa1381c0 100644 --- a/render-wasm/src/ui.rs +++ b/render-wasm/src/ui.rs @@ -1,19 +1,46 @@ +use std::cmp::Ordering; + use crate::shapes::Color; -#[derive(Debug, Clone, PartialEq, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub enum GuideKind { Vertical(f32), Horizontal(f32), } -#[derive(Debug, Clone, PartialEq, Copy)] +impl GuideKind { + fn value(self) -> f32 { + match self { + GuideKind::Vertical(x) => x, + GuideKind::Horizontal(y) => y, + } + } +} + +impl PartialOrd for GuideKind { + fn partial_cmp(&self, other: &Self) -> Option { + self.value().partial_cmp(&other.value()) + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Guide { pub kind: GuideKind, pub color: Color, + /// Index of the guide in the guide list (clojure side) + pub index: usize, } impl Guide { - pub fn new(kind: GuideKind, color: Color) -> Self { - Self { kind, color } + pub fn new(kind: GuideKind, color: Color, index: Option) -> Self { + Self { + kind, + color, + index: index.unwrap_or_default(), + } + } + + pub fn position(&self) -> f32 { + self.kind.value() } } diff --git a/render-wasm/src/wasm/ui.rs b/render-wasm/src/wasm/ui.rs index 2e2fc93ef9..b30f79425f 100644 --- a/render-wasm/src/wasm/ui.rs +++ b/render-wasm/src/wasm/ui.rs @@ -43,7 +43,7 @@ impl From for Guide { RawGuideKind::Vertical => GuideKind::Vertical(value.position), RawGuideKind::Horizontal => GuideKind::Horizontal(value.position), }; - Guide::new(kind, value.color.into()) + Guide::new(kind, value.color.into(), None) } } @@ -67,7 +67,14 @@ fn read_guides_from_bytes(buffer: &[u8], count: usize) -> Result> { buffer .chunks_exact(RAW_GUIDE_SIZE) .take(count) - .map(|bytes| RawGuide::try_from(bytes).map(|guide| guide.into())) + .enumerate() + .map(|(i, bytes)| { + RawGuide::try_from(bytes).map(|raw_guide| { + let mut guide: Guide = raw_guide.into(); + guide.index = i; + guide + }) + }) .collect::>>() } @@ -83,7 +90,7 @@ pub extern "C" fn set_guides() -> Result<()> { .unwrap_or([0; 4]), ) as usize; let guides = read_guides_from_bytes(&bytes[4..], count)?; - get_ui_state().guides = guides; + get_ui_state().set_guides(guides); mem::free_bytes()?; Ok(())