From c12a4955378b9ae58b5d163fe04e2dc61425399e Mon Sep 17 00:00:00 2001 From: Kulratan Thapar Date: Tue, 24 Feb 2026 22:27:19 +0000 Subject: [PATCH 1/3] Guide-1: Core guide infrastructure + overlays + frontend ruler drag --- editor/src/dispatcher.rs | 2 + .../menu_bar/menu_bar_message_handler.rs | 7 ++ .../portfolio/document/document_message.rs | 3 + .../document/document_message_handler.rs | 15 +++ .../portfolio/document/guide_message.rs | 14 +++ .../document/guide_message_handler.rs | 111 ++++++++++++++++++ editor/src/messages/portfolio/document/mod.rs | 2 + .../document/overlays/guide_overlays.rs | 57 +++++++++ .../portfolio/document/overlays/mod.rs | 1 + .../overlays/overlays_message_handler.rs | 9 ++ .../portfolio/document/utility_types/guide.rs | 61 ++++++++++ .../portfolio/document/utility_types/mod.rs | 1 + .../src/components/panels/Document.svelte | 109 ++++++++++++++++- .../widgets/inputs/RulerInput.svelte | 45 ++++++- frontend/wasm/src/editor_api.rs | 47 +++++++- 15 files changed, 479 insertions(+), 5 deletions(-) create mode 100644 editor/src/messages/portfolio/document/guide_message.rs create mode 100644 editor/src/messages/portfolio/document/guide_message_handler.rs create mode 100644 editor/src/messages/portfolio/document/overlays/guide_overlays.rs create mode 100644 editor/src/messages/portfolio/document/utility_types/guide.rs diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index 05d3a8e93e..9fe73d0565 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -253,6 +253,7 @@ impl Dispatcher { menu_bar_message_handler.canvas_tilted = document.document_ptz.tilt() != 0.; menu_bar_message_handler.canvas_flipped = document.document_ptz.flip; menu_bar_message_handler.rulers_visible = document.rulers_visible; + menu_bar_message_handler.guides_visible = document.guide_handler.guides_visible; menu_bar_message_handler.node_graph_open = document.is_graph_overlay_open(); menu_bar_message_handler.has_selected_nodes = selected_nodes.selected_nodes().next().is_some(); menu_bar_message_handler.has_selected_layers = selected_nodes.selected_visible_layers(&document.network_interface).next().is_some(); @@ -263,6 +264,7 @@ impl Dispatcher { menu_bar_message_handler.canvas_tilted = false; menu_bar_message_handler.canvas_flipped = false; menu_bar_message_handler.rulers_visible = false; + menu_bar_message_handler.guides_visible = false; menu_bar_message_handler.node_graph_open = false; menu_bar_message_handler.has_selected_nodes = false; menu_bar_message_handler.has_selected_layers = false; diff --git a/editor/src/messages/menu_bar/menu_bar_message_handler.rs b/editor/src/messages/menu_bar/menu_bar_message_handler.rs index b52cc25907..9956833d57 100644 --- a/editor/src/messages/menu_bar/menu_bar_message_handler.rs +++ b/editor/src/messages/menu_bar/menu_bar_message_handler.rs @@ -1,6 +1,7 @@ use crate::messages::debug::utility_types::MessageLoggingVerbosity; use crate::messages::input_mapper::utility_types::macros::action_shortcut; use crate::messages::layout::utility_types::widget_prelude::*; +use crate::messages::portfolio::document::guide_message::GuideMessage; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GroupFolderType}; use crate::messages::prelude::*; use graphene_std::path_bool::BooleanOperation; @@ -11,6 +12,7 @@ pub struct MenuBarMessageHandler { pub canvas_tilted: bool, pub canvas_flipped: bool, pub rulers_visible: bool, + pub guides_visible: bool, pub node_graph_open: bool, pub has_selected_nodes: bool, pub has_selected_layers: bool, @@ -616,6 +618,11 @@ impl LayoutHolder for MenuBarMessageHandler { .tooltip_shortcut(action_shortcut!(PortfolioMessageDiscriminant::ToggleRulers)) .on_commit(|_| PortfolioMessage::ToggleRulers.into()) .disabled(no_active_document), + MenuListEntry::new("Guides") + .label("Guides") + .icon(if self.guides_visible { "CheckboxChecked" } else { "CheckboxUnchecked" }) + .on_commit(|_| GuideMessage::ToggleGuidesVisibility.into()) + .disabled(no_active_document), ], ]) .widget_instance(), diff --git a/editor/src/messages/portfolio/document/document_message.rs b/editor/src/messages/portfolio/document/document_message.rs index 7fce9daa58..c12d57a43d 100644 --- a/editor/src/messages/portfolio/document/document_message.rs +++ b/editor/src/messages/portfolio/document/document_message.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use super::utility_types::misc::{GroupFolderType, SnappingState}; use crate::messages::input_mapper::utility_types::input_keyboard::Key; use crate::messages::portfolio::document::data_panel::DataPanelMessage; +use crate::messages::portfolio::document::guide_message::GuideMessage; use crate::messages::portfolio::document::overlays::utility_types::{OverlayContext, OverlaysType}; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GridSnapping}; @@ -37,6 +38,8 @@ pub enum DocumentMessage { PropertiesPanel(PropertiesPanelMessage), #[child] DataPanel(DataPanelMessage), + #[child] + Guide(GuideMessage), // Messages AlignSelectedLayers { diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 76fbfa4828..e047645a27 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -10,6 +10,7 @@ use crate::messages::input_mapper::utility_types::macros::action_shortcut; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::data_panel::{DataPanelMessageContext, DataPanelMessageHandler}; use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn; +use crate::messages::portfolio::document::guide_message_handler::{GuideMessageContext, GuideMessageHandler}; use crate::messages::portfolio::document::node_graph::NodeGraphMessageContext; use crate::messages::portfolio::document::node_graph::document_node_definitions::DefinitionIdentifier; use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType; @@ -76,6 +77,8 @@ pub struct DocumentMessageHandler { pub properties_panel_message_handler: PropertiesPanelMessageHandler, #[serde(skip)] pub data_panel_message_handler: DataPanelMessageHandler, + #[serde(flatten)] + pub guide_handler: GuideMessageHandler, // ============================================ // Fields that are saved in the document format @@ -154,6 +157,7 @@ impl Default for DocumentMessageHandler { overlays_message_handler: OverlaysMessageHandler::default(), properties_panel_message_handler: PropertiesPanelMessageHandler::default(), data_panel_message_handler: DataPanelMessageHandler::default(), + guide_handler: GuideMessageHandler::default(), // ============================================ // Fields that are saved in the document format // ============================================ @@ -179,6 +183,7 @@ impl Default for DocumentMessageHandler { saved_hash: None, auto_saved_hash: None, layer_range_selection_reference: None, + is_loaded: false, } } @@ -215,6 +220,14 @@ impl MessageHandler> for DocumentMes self.navigation_handler.process_message(message, responses, context); } + DocumentMessage::Guide(message) => { + let context = GuideMessageContext { + navigation_handler: &self.navigation_handler, + document_ptz: &self.document_ptz, + viewport, + }; + self.guide_handler.process_message(message, responses, context); + } DocumentMessage::Overlays(message) => { let visibility_settings = self.overlays_visibility_settings; @@ -622,6 +635,7 @@ impl MessageHandler> for DocumentMes self.snapping_state.grid_snapping = visible; responses.add(OverlaysMessage::Draw); } + // Guide messages DocumentMessage::GroupSelectedLayers { group_folder_type } => { self.handle_group_selected_layers(group_folder_type, responses); } @@ -1433,6 +1447,7 @@ impl MessageHandler> for DocumentMes ZoomCanvasTo200Percent, ZoomCanvasToFitAll, ); + common.extend(self.guide_handler.actions()); // Additional actions available on desktop #[cfg(not(target_family = "wasm"))] diff --git a/editor/src/messages/portfolio/document/guide_message.rs b/editor/src/messages/portfolio/document/guide_message.rs new file mode 100644 index 0000000000..6fb54c90ff --- /dev/null +++ b/editor/src/messages/portfolio/document/guide_message.rs @@ -0,0 +1,14 @@ +use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; +use crate::messages::portfolio::document::utility_types::guide::{GuideDirection, GuideId}; +use crate::messages::prelude::*; + +#[impl_message(Message, DocumentMessage, Guide)] +#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] +pub enum GuideMessage { + CreateGuide { id: GuideId, direction: GuideDirection, mouse_x: f64, mouse_y: f64 }, + MoveGuide { id: GuideId, mouse_x: f64, mouse_y: f64 }, + DeleteGuide { id: GuideId }, + GuideOverlays { context: OverlayContext }, + ToggleGuidesVisibility, + SetHoveredGuide { id: Option }, +} diff --git a/editor/src/messages/portfolio/document/guide_message_handler.rs b/editor/src/messages/portfolio/document/guide_message_handler.rs new file mode 100644 index 0000000000..b3ae51e1df --- /dev/null +++ b/editor/src/messages/portfolio/document/guide_message_handler.rs @@ -0,0 +1,111 @@ +use super::utility_types::guide::{Guide, GuideDirection, GuideId}; +use crate::messages::portfolio::document::guide_message::{GuideMessage, GuideMessageDiscriminant}; +use crate::messages::portfolio::document::overlays::guide_overlays::guide_overlay; +use crate::messages::portfolio::document::utility_types::misc::PTZ; +use crate::messages::prelude::*; +use glam::DVec2; + +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ExtractField)] +#[serde(default)] +pub struct GuideMessageHandler { + #[serde(default)] + pub guides: Vec, + #[serde(default = "default_guides_visible")] + pub guides_visible: bool, + #[serde(skip)] + pub hovered_guide_id: Option, +} + +fn default_guides_visible() -> bool { + true +} + +impl Default for GuideMessageHandler { + fn default() -> Self { + Self { + guides: Vec::new(), + guides_visible: true, + hovered_guide_id: None, + } + } +} + +#[derive(ExtractField)] +pub struct GuideMessageContext<'a> { + pub navigation_handler: &'a NavigationMessageHandler, + pub document_ptz: &'a PTZ, + pub viewport: &'a ViewportMessageHandler, +} + +#[message_handler_data] +impl MessageHandler> for GuideMessageHandler { + fn actions(&self) -> ActionList { + actions!(GuideMessageDiscriminant; ToggleGuidesVisibility) + } + + fn process_message(&mut self, message: GuideMessage, responses: &mut VecDeque, context: GuideMessageContext) { + let GuideMessageContext { + navigation_handler, + document_ptz, + viewport, + } = context; + + match message { + GuideMessage::CreateGuide { id, direction, mouse_x, mouse_y } => { + let document_to_viewport = navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), document_ptz); + let viewport_to_document = document_to_viewport.inverse(); + + let viewport_point = DVec2::new(mouse_x, mouse_y); + let document_point = viewport_to_document.transform_point2(viewport_point); + + let document_position = match direction { + GuideDirection::Horizontal => document_point.y, + GuideDirection::Vertical => document_point.x, + }; + + let guide = Guide::with_id(id, direction, document_position); + self.guides.push(guide); + responses.add(OverlaysMessage::Draw); + responses.add(PortfolioMessage::UpdateDocumentWidgets); + } + GuideMessage::MoveGuide { id, mouse_x, mouse_y } => { + let document_to_viewport = navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), document_ptz); + let viewport_to_document = document_to_viewport.inverse(); + + let viewport_point = DVec2::new(mouse_x, mouse_y); + let document_point = viewport_to_document.transform_point2(viewport_point); + + if let Some(guide) = self.guides.iter_mut().find(|guide| guide.id == id) { + guide.position = match guide.direction { + GuideDirection::Horizontal => document_point.y, + GuideDirection::Vertical => document_point.x, + }; + } + responses.add(OverlaysMessage::Draw); + } + GuideMessage::DeleteGuide { id } => { + self.guides.retain(|g| g.id != id); + responses.add(OverlaysMessage::Draw); + responses.add(PortfolioMessage::UpdateDocumentWidgets); + } + GuideMessage::GuideOverlays { context: mut overlay_context } => { + if self.guides_visible { + let document_to_viewport = navigation_handler.calculate_offset_transform(overlay_context.viewport.center_in_viewport_space().into(), document_ptz); + guide_overlay(self, &mut overlay_context, document_to_viewport); + } + } + GuideMessage::ToggleGuidesVisibility => { + self.guides_visible = !self.guides_visible; + responses.add(OverlaysMessage::Draw); + responses.add(PortfolioMessage::UpdateDocumentWidgets); + responses.add(MenuBarMessage::SendLayout); + } + GuideMessage::SetHoveredGuide { id } => { + if self.hovered_guide_id != id { + self.hovered_guide_id = id; + responses.add(OverlaysMessage::Draw); + } + } + } + } +} diff --git a/editor/src/messages/portfolio/document/mod.rs b/editor/src/messages/portfolio/document/mod.rs index 767126b248..33c598e925 100644 --- a/editor/src/messages/portfolio/document/mod.rs +++ b/editor/src/messages/portfolio/document/mod.rs @@ -3,6 +3,8 @@ mod document_message_handler; pub mod data_panel; pub mod graph_operation; +pub mod guide_message; +pub mod guide_message_handler; pub mod navigation; pub mod node_graph; pub mod overlays; diff --git a/editor/src/messages/portfolio/document/overlays/guide_overlays.rs b/editor/src/messages/portfolio/document/overlays/guide_overlays.rs new file mode 100644 index 0000000000..cffc29a13d --- /dev/null +++ b/editor/src/messages/portfolio/document/overlays/guide_overlays.rs @@ -0,0 +1,57 @@ +use crate::consts::{COLOR_OVERLAY_BLUE, COLOR_OVERLAY_BLUE_50}; +use crate::messages::portfolio::document::guide_message_handler::GuideMessageHandler; +use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; +use crate::messages::portfolio::document::utility_types::guide::GuideDirection; +use glam::{DAffine2, DVec2}; + +fn extend_line_to_viewport(point: DVec2, direction: DVec2, viewport_size: DVec2) -> Option<(DVec2, DVec2)> { + let dir = direction.try_normalize()?; + + // Calculates t values for intersections with viewport edges + let mut t_values = Vec::new(); + + let edges = graphene_std::renderer::Quad::from_box([DVec2::ZERO, viewport_size]).all_edges(); + for [start, end] in edges { + let t_along_viewport = (point - start).perp_dot(dir) / (end - start).perp_dot(dir); + let t_along_direction = (point - start).perp_dot(end - start) / (end - start).perp_dot(dir); + if 0. <= t_along_viewport && t_along_viewport <= 1. && t_along_direction.is_finite() { + t_values.push(t_along_direction); + } + } + + if t_values.len() < 2 { + return None; + } + + let t_min = t_values.iter().cloned().fold(f64::INFINITY, f64::min); + let t_max = t_values.iter().cloned().fold(f64::NEG_INFINITY, f64::max); + + let start = point + dir * t_min; + let end = point + dir * t_max; + + Some((start, end)) +} + +pub fn guide_overlay(guide_handler: &GuideMessageHandler, overlay_context: &mut OverlayContext, document_to_viewport: DAffine2) { + let viewport_size: DVec2 = overlay_context.viewport.size().into(); + + for guide in &guide_handler.guides { + let (doc_point, doc_direction) = match guide.direction { + GuideDirection::Horizontal => (DVec2::new(0.0, guide.position), DVec2::X), + GuideDirection::Vertical => (DVec2::new(guide.position, 0.0), DVec2::Y), + }; + + let viewport_point = document_to_viewport.transform_point2(doc_point); + let viewport_direction = document_to_viewport.transform_vector2(doc_direction); + + let color = if guide_handler.hovered_guide_id == Some(guide.id) { + COLOR_OVERLAY_BLUE_50 + } else { + COLOR_OVERLAY_BLUE + }; + + if let Some((start, end)) = extend_line_to_viewport(viewport_point, viewport_direction, viewport_size) { + overlay_context.line(start, end, Some(color), None); + } + } +} diff --git a/editor/src/messages/portfolio/document/overlays/mod.rs b/editor/src/messages/portfolio/document/overlays/mod.rs index 4445dbfe84..2b2218096b 100644 --- a/editor/src/messages/portfolio/document/overlays/mod.rs +++ b/editor/src/messages/portfolio/document/overlays/mod.rs @@ -1,4 +1,5 @@ pub mod grid_overlays; +pub mod guide_overlays; mod overlays_message; mod overlays_message_handler; pub mod utility_functions; diff --git a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs index 3bf436251c..6c015f5d6e 100644 --- a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs +++ b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs @@ -1,4 +1,5 @@ use super::utility_types::{OverlayProvider, OverlaysVisibilitySettings}; +use crate::messages::portfolio::document::guide_message::GuideMessage; use crate::messages::prelude::*; #[derive(ExtractField)] @@ -57,6 +58,13 @@ impl MessageHandler> for OverlaysMes viewport: *viewport, }, }); + responses.add(GuideMessage::GuideOverlays { + context: OverlayContext { + render_context: canvas_context.clone(), + visibility_settings: visibility_settings.clone(), + viewport: *viewport, + }, + }); for provider in &self.overlay_providers { responses.add(provider(OverlayContext { render_context: canvas_context.clone(), @@ -74,6 +82,7 @@ impl MessageHandler> for OverlaysMes if visibility_settings.all() { responses.add(DocumentMessage::GridOverlays { context: overlay_context.clone() }); + responses.add(GuideMessage::GuideOverlays { context: overlay_context.clone() }); for provider in &self.overlay_providers { responses.add(provider(overlay_context.clone())); diff --git a/editor/src/messages/portfolio/document/utility_types/guide.rs b/editor/src/messages/portfolio/document/utility_types/guide.rs new file mode 100644 index 0000000000..e19ddaf69e --- /dev/null +++ b/editor/src/messages/portfolio/document/utility_types/guide.rs @@ -0,0 +1,61 @@ +use crate::application::generate_uuid; + +#[repr(transparent)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize)] +pub struct GuideId(u64); + +impl GuideId { + pub fn new() -> Self { + Self(generate_uuid()) + } + + pub fn from_raw(id: u64) -> Self { + Self(id) + } + + pub fn as_raw(&self) -> u64 { + self.0 + } +} + +impl Default for GuideId { + fn default() -> Self { + Self::new() + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] +pub enum GuideDirection { + Horizontal, + Vertical, +} + +#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct Guide { + pub id: GuideId, + pub direction: GuideDirection, + /// Position in document space (Y coordinate for horizontal guides, X coordinate for vertical guides) + pub position: f64, +} + +impl Guide { + pub fn new(direction: GuideDirection, position: f64) -> Self { + Self { + id: GuideId::new(), + direction, + position, + } + } + + pub fn with_id(id: GuideId, direction: GuideDirection, position: f64) -> Self { + Self { id, direction, position } + } + + pub fn horizontal(y: f64) -> Self { + Self::new(GuideDirection::Horizontal, y) + } + + pub fn vertical(x: f64) -> Self { + Self::new(GuideDirection::Vertical, x) + } +} diff --git a/editor/src/messages/portfolio/document/utility_types/mod.rs b/editor/src/messages/portfolio/document/utility_types/mod.rs index 8bed0dbb85..6f2862f40b 100644 --- a/editor/src/messages/portfolio/document/utility_types/mod.rs +++ b/editor/src/messages/portfolio/document/utility_types/mod.rs @@ -1,6 +1,7 @@ pub mod clipboards; pub mod document_metadata; pub mod error; +pub mod guide; pub mod misc; pub mod network_interface; pub mod nodes; diff --git a/frontend/src/components/panels/Document.svelte b/frontend/src/components/panels/Document.svelte index 98722c4d76..f1f812847b 100644 --- a/frontend/src/components/panels/Document.svelte +++ b/frontend/src/components/panels/Document.svelte @@ -1,6 +1,8 @@ -
+
{#each svgTexts as svgText} diff --git a/frontend/wasm/src/editor_api.rs b/frontend/wasm/src/editor_api.rs index e0353b1b65..172b3cbfe8 100644 --- a/frontend/wasm/src/editor_api.rs +++ b/frontend/wasm/src/editor_api.rs @@ -10,7 +10,9 @@ use editor::consts::FILE_EXTENSION; use editor::messages::clipboard::utility_types::ClipboardContentRaw; use editor::messages::input_mapper::utility_types::input_keyboard::ModifierKeys; use editor::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, ScrollDelta}; +use editor::messages::portfolio::document::guide_message::GuideMessage; use editor::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; +use editor::messages::portfolio::document::utility_types::guide::{GuideDirection, GuideId}; use editor::messages::portfolio::document::utility_types::network_interface::ImportOrExport; use editor::messages::portfolio::utility_types::{FontCatalog, FontCatalogFamily}; use editor::messages::prelude::*; @@ -45,7 +47,18 @@ fn calculate_hash(t: &T) -> u64 { hasher.finish() } -/// Provides a handle to access the raw Wasm memory. +#[wasm_bindgen(js_name = setRandomSeed)] +pub fn set_random_seed(seed: u64) { + editor::application::set_uuid_seed(seed); +} + +/// Generates a unique guide ID +#[wasm_bindgen(js_name = generateGuideId)] +pub fn generate_guide_id() -> u64 { + editor::application::generate_uuid() +} + +/// Provides a handle to access the raw WASM memory. #[wasm_bindgen(js_name = wasmMemory)] pub fn wasm_memory() -> JsValue { wasm_bindgen::memory() @@ -885,6 +898,38 @@ impl EditorHandle { }; self.dispatch(message); } + + /// Create a new guide line from a ruler drag + #[wasm_bindgen(js_name = createGuide)] + pub fn create_guide(&self, id: u64, direction: String, mouse_x: f64, mouse_y: f64) { + let id = GuideId::from_raw(id); + let direction = match direction.as_str() { + "Horizontal" => GuideDirection::Horizontal, + "Vertical" => GuideDirection::Vertical, + _ => { + log::error!("Invalid guide direction: {}", direction); + return; + } + }; + let message = GuideMessage::CreateGuide { id, direction, mouse_x, mouse_y }; + self.dispatch(message); + } + + /// Move an existing guide to a new position + #[wasm_bindgen(js_name = moveGuide)] + pub fn move_guide(&self, id: u64, mouse_x: f64, mouse_y: f64) { + let id = GuideId::from_raw(id); + let message = GuideMessage::MoveGuide { id, mouse_x, mouse_y }; + self.dispatch(message); + } + + /// Delete a guide by its ID + #[wasm_bindgen(js_name = deleteGuide)] + pub fn delete_guide(&self, id: u64) { + let id = GuideId::from_raw(id); + let message = GuideMessage::DeleteGuide { id }; + self.dispatch(message); + } } // ============================================================================ From e5a8e7c764c3a78a4839b9226fa10efab53f83e3 Mon Sep 17 00:00:00 2001 From: Kulratan Thapar Date: Tue, 24 Feb 2026 22:53:03 +0000 Subject: [PATCH 2/3] Refactor: extract duplicate viewport-to-document conversion, simplify getViewportElement, fix GuideMessage import --- .../portfolio/document/guide_message_handler.rs | 17 +++++++---------- .../overlays/overlays_message_handler.rs | 1 + frontend/src/components/panels/Document.svelte | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/editor/src/messages/portfolio/document/guide_message_handler.rs b/editor/src/messages/portfolio/document/guide_message_handler.rs index b3ae51e1df..f587db4c56 100644 --- a/editor/src/messages/portfolio/document/guide_message_handler.rs +++ b/editor/src/messages/portfolio/document/guide_message_handler.rs @@ -50,13 +50,14 @@ impl MessageHandler> for GuideMessageHandl viewport, } = context; + let viewport_to_document_point = |mouse_x: f64, mouse_y: f64| -> DVec2 { + let document_to_viewport = navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), document_ptz); + document_to_viewport.inverse().transform_point2(DVec2::new(mouse_x, mouse_y)) + }; + match message { GuideMessage::CreateGuide { id, direction, mouse_x, mouse_y } => { - let document_to_viewport = navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), document_ptz); - let viewport_to_document = document_to_viewport.inverse(); - - let viewport_point = DVec2::new(mouse_x, mouse_y); - let document_point = viewport_to_document.transform_point2(viewport_point); + let document_point = viewport_to_document_point(mouse_x, mouse_y); let document_position = match direction { GuideDirection::Horizontal => document_point.y, @@ -69,11 +70,7 @@ impl MessageHandler> for GuideMessageHandl responses.add(PortfolioMessage::UpdateDocumentWidgets); } GuideMessage::MoveGuide { id, mouse_x, mouse_y } => { - let document_to_viewport = navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), document_ptz); - let viewport_to_document = document_to_viewport.inverse(); - - let viewport_point = DVec2::new(mouse_x, mouse_y); - let document_point = viewport_to_document.transform_point2(viewport_point); + let document_point = viewport_to_document_point(mouse_x, mouse_y); if let Some(guide) = self.guides.iter_mut().find(|guide| guide.id == id) { guide.position = match guide.direction { diff --git a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs index 6c015f5d6e..a570f02ea6 100644 --- a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs +++ b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs @@ -1,4 +1,5 @@ use super::utility_types::{OverlayProvider, OverlaysVisibilitySettings}; +#[cfg(not(test))] use crate::messages::portfolio::document::guide_message::GuideMessage; use crate::messages::prelude::*; diff --git a/frontend/src/components/panels/Document.svelte b/frontend/src/components/panels/Document.svelte index f1f812847b..0b24cbde07 100644 --- a/frontend/src/components/panels/Document.svelte +++ b/frontend/src/components/panels/Document.svelte @@ -162,7 +162,7 @@ type GuideDirection = "Horizontal" | "Vertical"; function getViewportElement(): HTMLElement | undefined { - return viewport ?? (window.document.querySelector("[data-viewport]") as HTMLElement) ?? undefined; + return viewport; } function getGuideMousePosition(event: PointerEvent, viewportRect: DOMRect): { mouseX: number; mouseY: number } { From 117c69dc6165c60fe654752d0821a9901c1991dd Mon Sep 17 00:00:00 2001 From: Kulratan Thapar Date: Wed, 25 Feb 2026 08:26:15 +0000 Subject: [PATCH 3/3] Rename --- editor/src/dispatcher.rs | 4 +- .../menu_bar/menu_bar_message_handler.rs | 8 +- .../portfolio/document/document_message.rs | 4 +- .../document/document_message_handler.rs | 14 +-- .../portfolio/document/guide_lines_message.rs | 29 +++++ .../document/guide_lines_message_handler.rs | 102 +++++++++++++++++ .../portfolio/document/guide_message.rs | 14 --- .../document/guide_message_handler.rs | 108 ------------------ editor/src/messages/portfolio/document/mod.rs | 4 +- ...ide_overlays.rs => guide_line_overlays.rs} | 14 +-- .../portfolio/document/overlays/mod.rs | 2 +- .../overlays/overlays_message_handler.rs | 6 +- .../utility_types/{guide.rs => guide_line.rs} | 26 ++--- .../portfolio/document/utility_types/mod.rs | 2 +- .../src/components/panels/Document.svelte | 58 +++++----- .../widgets/inputs/RulerInput.svelte | 4 +- frontend/wasm/src/editor_api.rs | 28 ++--- 17 files changed, 218 insertions(+), 209 deletions(-) create mode 100644 editor/src/messages/portfolio/document/guide_lines_message.rs create mode 100644 editor/src/messages/portfolio/document/guide_lines_message_handler.rs delete mode 100644 editor/src/messages/portfolio/document/guide_message.rs delete mode 100644 editor/src/messages/portfolio/document/guide_message_handler.rs rename editor/src/messages/portfolio/document/overlays/{guide_overlays.rs => guide_line_overlays.rs} (72%) rename editor/src/messages/portfolio/document/utility_types/{guide.rs => guide_line.rs} (63%) diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index 9fe73d0565..bddbfba4ab 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -253,7 +253,7 @@ impl Dispatcher { menu_bar_message_handler.canvas_tilted = document.document_ptz.tilt() != 0.; menu_bar_message_handler.canvas_flipped = document.document_ptz.flip; menu_bar_message_handler.rulers_visible = document.rulers_visible; - menu_bar_message_handler.guides_visible = document.guide_handler.guides_visible; + menu_bar_message_handler.guide_lines_visible = document.guide_lines_message_handler.guide_lines_visible; menu_bar_message_handler.node_graph_open = document.is_graph_overlay_open(); menu_bar_message_handler.has_selected_nodes = selected_nodes.selected_nodes().next().is_some(); menu_bar_message_handler.has_selected_layers = selected_nodes.selected_visible_layers(&document.network_interface).next().is_some(); @@ -264,7 +264,7 @@ impl Dispatcher { menu_bar_message_handler.canvas_tilted = false; menu_bar_message_handler.canvas_flipped = false; menu_bar_message_handler.rulers_visible = false; - menu_bar_message_handler.guides_visible = false; + menu_bar_message_handler.guide_lines_visible = false; menu_bar_message_handler.node_graph_open = false; menu_bar_message_handler.has_selected_nodes = false; menu_bar_message_handler.has_selected_layers = false; diff --git a/editor/src/messages/menu_bar/menu_bar_message_handler.rs b/editor/src/messages/menu_bar/menu_bar_message_handler.rs index 9956833d57..b45c74e664 100644 --- a/editor/src/messages/menu_bar/menu_bar_message_handler.rs +++ b/editor/src/messages/menu_bar/menu_bar_message_handler.rs @@ -1,7 +1,7 @@ use crate::messages::debug::utility_types::MessageLoggingVerbosity; use crate::messages::input_mapper::utility_types::macros::action_shortcut; use crate::messages::layout::utility_types::widget_prelude::*; -use crate::messages::portfolio::document::guide_message::GuideMessage; +use crate::messages::portfolio::document::guide_lines_message::GuideLinesMessage; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GroupFolderType}; use crate::messages::prelude::*; use graphene_std::path_bool::BooleanOperation; @@ -12,7 +12,7 @@ pub struct MenuBarMessageHandler { pub canvas_tilted: bool, pub canvas_flipped: bool, pub rulers_visible: bool, - pub guides_visible: bool, + pub guide_lines_visible: bool, pub node_graph_open: bool, pub has_selected_nodes: bool, pub has_selected_layers: bool, @@ -620,8 +620,8 @@ impl LayoutHolder for MenuBarMessageHandler { .disabled(no_active_document), MenuListEntry::new("Guides") .label("Guides") - .icon(if self.guides_visible { "CheckboxChecked" } else { "CheckboxUnchecked" }) - .on_commit(|_| GuideMessage::ToggleGuidesVisibility.into()) + .icon(if self.guide_lines_visible { "CheckboxChecked" } else { "CheckboxUnchecked" }) + .on_commit(|_| GuideLinesMessage::ToggleGuideLinesVisibility.into()) .disabled(no_active_document), ], ]) diff --git a/editor/src/messages/portfolio/document/document_message.rs b/editor/src/messages/portfolio/document/document_message.rs index c12d57a43d..25a0d61d9f 100644 --- a/editor/src/messages/portfolio/document/document_message.rs +++ b/editor/src/messages/portfolio/document/document_message.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use super::utility_types::misc::{GroupFolderType, SnappingState}; use crate::messages::input_mapper::utility_types::input_keyboard::Key; use crate::messages::portfolio::document::data_panel::DataPanelMessage; -use crate::messages::portfolio::document::guide_message::GuideMessage; +use crate::messages::portfolio::document::guide_lines_message::GuideLinesMessage; use crate::messages::portfolio::document::overlays::utility_types::{OverlayContext, OverlaysType}; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, GridSnapping}; @@ -39,7 +39,7 @@ pub enum DocumentMessage { #[child] DataPanel(DataPanelMessage), #[child] - Guide(GuideMessage), + GuideLines(GuideLinesMessage), // Messages AlignSelectedLayers { diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index e047645a27..1dc6bc8c71 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -10,7 +10,7 @@ use crate::messages::input_mapper::utility_types::macros::action_shortcut; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::data_panel::{DataPanelMessageContext, DataPanelMessageHandler}; use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn; -use crate::messages::portfolio::document::guide_message_handler::{GuideMessageContext, GuideMessageHandler}; +use crate::messages::portfolio::document::guide_lines_message_handler::{GuideLinesMessageContext, GuideLinesMessageHandler}; use crate::messages::portfolio::document::node_graph::NodeGraphMessageContext; use crate::messages::portfolio::document::node_graph::document_node_definitions::DefinitionIdentifier; use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType; @@ -78,7 +78,7 @@ pub struct DocumentMessageHandler { #[serde(skip)] pub data_panel_message_handler: DataPanelMessageHandler, #[serde(flatten)] - pub guide_handler: GuideMessageHandler, + pub guide_lines_message_handler: GuideLinesMessageHandler, // ============================================ // Fields that are saved in the document format @@ -157,7 +157,7 @@ impl Default for DocumentMessageHandler { overlays_message_handler: OverlaysMessageHandler::default(), properties_panel_message_handler: PropertiesPanelMessageHandler::default(), data_panel_message_handler: DataPanelMessageHandler::default(), - guide_handler: GuideMessageHandler::default(), + guide_lines_message_handler: GuideLinesMessageHandler::default(), // ============================================ // Fields that are saved in the document format // ============================================ @@ -220,13 +220,13 @@ impl MessageHandler> for DocumentMes self.navigation_handler.process_message(message, responses, context); } - DocumentMessage::Guide(message) => { - let context = GuideMessageContext { + DocumentMessage::GuideLines(message) => { + let context = GuideLinesMessageContext { navigation_handler: &self.navigation_handler, document_ptz: &self.document_ptz, viewport, }; - self.guide_handler.process_message(message, responses, context); + self.guide_lines_message_handler.process_message(message, responses, context); } DocumentMessage::Overlays(message) => { let visibility_settings = self.overlays_visibility_settings; @@ -1447,7 +1447,7 @@ impl MessageHandler> for DocumentMes ZoomCanvasTo200Percent, ZoomCanvasToFitAll, ); - common.extend(self.guide_handler.actions()); + common.extend(self.guide_lines_message_handler.actions()); // Additional actions available on desktop #[cfg(not(target_family = "wasm"))] diff --git a/editor/src/messages/portfolio/document/guide_lines_message.rs b/editor/src/messages/portfolio/document/guide_lines_message.rs new file mode 100644 index 0000000000..6ff121254a --- /dev/null +++ b/editor/src/messages/portfolio/document/guide_lines_message.rs @@ -0,0 +1,29 @@ +use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; +use crate::messages::portfolio::document::utility_types::guide_line::{GuideLineDirection, GuideLineId}; +use crate::messages::prelude::*; + +#[impl_message(Message, DocumentMessage, GuideLines)] +#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] +pub enum GuideLinesMessage { + CreateGuideLine { + id: GuideLineId, + direction: GuideLineDirection, + mouse_x: f64, + mouse_y: f64, + }, + MoveGuideLine { + id: GuideLineId, + mouse_x: f64, + mouse_y: f64, + }, + DeleteGuideLine { + id: GuideLineId, + }, + GuideLineOverlays { + context: OverlayContext, + }, + ToggleGuideLinesVisibility, + SetHoveredGuideLine { + id: Option, + }, +} diff --git a/editor/src/messages/portfolio/document/guide_lines_message_handler.rs b/editor/src/messages/portfolio/document/guide_lines_message_handler.rs new file mode 100644 index 0000000000..3780c28875 --- /dev/null +++ b/editor/src/messages/portfolio/document/guide_lines_message_handler.rs @@ -0,0 +1,102 @@ +use super::utility_types::guide_line::{GuideLine, GuideLineDirection, GuideLineId}; +use crate::messages::portfolio::document::guide_lines_message::{GuideLinesMessage, GuideLinesMessageDiscriminant}; +use crate::messages::portfolio::document::overlays::guide_line_overlays::guide_line_overlay; +use crate::messages::portfolio::document::utility_types::misc::PTZ; +use crate::messages::prelude::*; +use glam::DVec2; + +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ExtractField)] +#[serde(default)] +pub struct GuideLinesMessageHandler { + pub guide_lines: Vec, + pub guide_lines_visible: bool, + #[serde(skip)] + pub hovered_guide_line_id: Option, +} + +impl Default for GuideLinesMessageHandler { + fn default() -> Self { + Self { + guide_lines: Vec::new(), + guide_lines_visible: true, + hovered_guide_line_id: None, + } + } +} + +#[derive(ExtractField)] +pub struct GuideLinesMessageContext<'a> { + pub navigation_handler: &'a NavigationMessageHandler, + pub document_ptz: &'a PTZ, + pub viewport: &'a ViewportMessageHandler, +} + +#[message_handler_data] +impl MessageHandler> for GuideLinesMessageHandler { + fn actions(&self) -> ActionList { + actions!(GuideLinesMessageDiscriminant; ToggleGuideLinesVisibility) + } + + fn process_message(&mut self, message: GuideLinesMessage, responses: &mut VecDeque, context: GuideLinesMessageContext) { + let GuideLinesMessageContext { + navigation_handler, + document_ptz, + viewport, + } = context; + + let viewport_to_document_point = |mouse_x: f64, mouse_y: f64| -> DVec2 { + let document_to_viewport = navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), document_ptz); + document_to_viewport.inverse().transform_point2(DVec2::new(mouse_x, mouse_y)) + }; + + match message { + GuideLinesMessage::CreateGuideLine { id, direction, mouse_x, mouse_y } => { + let document_point = viewport_to_document_point(mouse_x, mouse_y); + + let document_position = match direction { + GuideLineDirection::Horizontal => document_point.y, + GuideLineDirection::Vertical => document_point.x, + }; + + let guide = GuideLine::with_id(id, direction, document_position); + self.guide_lines.push(guide); + responses.add(OverlaysMessage::Draw); + responses.add(PortfolioMessage::UpdateDocumentWidgets); + } + GuideLinesMessage::MoveGuideLine { id, mouse_x, mouse_y } => { + let document_point = viewport_to_document_point(mouse_x, mouse_y); + + if let Some(guide) = self.guide_lines.iter_mut().find(|guide| guide.id == id) { + guide.position = match guide.direction { + GuideLineDirection::Horizontal => document_point.y, + GuideLineDirection::Vertical => document_point.x, + }; + } + responses.add(OverlaysMessage::Draw); + } + GuideLinesMessage::DeleteGuideLine { id } => { + self.guide_lines.retain(|g| g.id != id); + responses.add(OverlaysMessage::Draw); + responses.add(PortfolioMessage::UpdateDocumentWidgets); + } + GuideLinesMessage::GuideLineOverlays { context: mut overlay_context } => { + if self.guide_lines_visible { + let document_to_viewport = navigation_handler.calculate_offset_transform(overlay_context.viewport.center_in_viewport_space().into(), document_ptz); + guide_line_overlay(self, &mut overlay_context, document_to_viewport); + } + } + GuideLinesMessage::ToggleGuideLinesVisibility => { + self.guide_lines_visible = !self.guide_lines_visible; + responses.add(OverlaysMessage::Draw); + responses.add(PortfolioMessage::UpdateDocumentWidgets); + responses.add(MenuBarMessage::SendLayout); + } + GuideLinesMessage::SetHoveredGuideLine { id } => { + if self.hovered_guide_line_id != id { + self.hovered_guide_line_id = id; + responses.add(OverlaysMessage::Draw); + } + } + } + } +} diff --git a/editor/src/messages/portfolio/document/guide_message.rs b/editor/src/messages/portfolio/document/guide_message.rs deleted file mode 100644 index 6fb54c90ff..0000000000 --- a/editor/src/messages/portfolio/document/guide_message.rs +++ /dev/null @@ -1,14 +0,0 @@ -use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; -use crate::messages::portfolio::document::utility_types::guide::{GuideDirection, GuideId}; -use crate::messages::prelude::*; - -#[impl_message(Message, DocumentMessage, Guide)] -#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] -pub enum GuideMessage { - CreateGuide { id: GuideId, direction: GuideDirection, mouse_x: f64, mouse_y: f64 }, - MoveGuide { id: GuideId, mouse_x: f64, mouse_y: f64 }, - DeleteGuide { id: GuideId }, - GuideOverlays { context: OverlayContext }, - ToggleGuidesVisibility, - SetHoveredGuide { id: Option }, -} diff --git a/editor/src/messages/portfolio/document/guide_message_handler.rs b/editor/src/messages/portfolio/document/guide_message_handler.rs deleted file mode 100644 index f587db4c56..0000000000 --- a/editor/src/messages/portfolio/document/guide_message_handler.rs +++ /dev/null @@ -1,108 +0,0 @@ -use super::utility_types::guide::{Guide, GuideDirection, GuideId}; -use crate::messages::portfolio::document::guide_message::{GuideMessage, GuideMessageDiscriminant}; -use crate::messages::portfolio::document::overlays::guide_overlays::guide_overlay; -use crate::messages::portfolio::document::utility_types::misc::PTZ; -use crate::messages::prelude::*; -use glam::DVec2; - -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ExtractField)] -#[serde(default)] -pub struct GuideMessageHandler { - #[serde(default)] - pub guides: Vec, - #[serde(default = "default_guides_visible")] - pub guides_visible: bool, - #[serde(skip)] - pub hovered_guide_id: Option, -} - -fn default_guides_visible() -> bool { - true -} - -impl Default for GuideMessageHandler { - fn default() -> Self { - Self { - guides: Vec::new(), - guides_visible: true, - hovered_guide_id: None, - } - } -} - -#[derive(ExtractField)] -pub struct GuideMessageContext<'a> { - pub navigation_handler: &'a NavigationMessageHandler, - pub document_ptz: &'a PTZ, - pub viewport: &'a ViewportMessageHandler, -} - -#[message_handler_data] -impl MessageHandler> for GuideMessageHandler { - fn actions(&self) -> ActionList { - actions!(GuideMessageDiscriminant; ToggleGuidesVisibility) - } - - fn process_message(&mut self, message: GuideMessage, responses: &mut VecDeque, context: GuideMessageContext) { - let GuideMessageContext { - navigation_handler, - document_ptz, - viewport, - } = context; - - let viewport_to_document_point = |mouse_x: f64, mouse_y: f64| -> DVec2 { - let document_to_viewport = navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), document_ptz); - document_to_viewport.inverse().transform_point2(DVec2::new(mouse_x, mouse_y)) - }; - - match message { - GuideMessage::CreateGuide { id, direction, mouse_x, mouse_y } => { - let document_point = viewport_to_document_point(mouse_x, mouse_y); - - let document_position = match direction { - GuideDirection::Horizontal => document_point.y, - GuideDirection::Vertical => document_point.x, - }; - - let guide = Guide::with_id(id, direction, document_position); - self.guides.push(guide); - responses.add(OverlaysMessage::Draw); - responses.add(PortfolioMessage::UpdateDocumentWidgets); - } - GuideMessage::MoveGuide { id, mouse_x, mouse_y } => { - let document_point = viewport_to_document_point(mouse_x, mouse_y); - - if let Some(guide) = self.guides.iter_mut().find(|guide| guide.id == id) { - guide.position = match guide.direction { - GuideDirection::Horizontal => document_point.y, - GuideDirection::Vertical => document_point.x, - }; - } - responses.add(OverlaysMessage::Draw); - } - GuideMessage::DeleteGuide { id } => { - self.guides.retain(|g| g.id != id); - responses.add(OverlaysMessage::Draw); - responses.add(PortfolioMessage::UpdateDocumentWidgets); - } - GuideMessage::GuideOverlays { context: mut overlay_context } => { - if self.guides_visible { - let document_to_viewport = navigation_handler.calculate_offset_transform(overlay_context.viewport.center_in_viewport_space().into(), document_ptz); - guide_overlay(self, &mut overlay_context, document_to_viewport); - } - } - GuideMessage::ToggleGuidesVisibility => { - self.guides_visible = !self.guides_visible; - responses.add(OverlaysMessage::Draw); - responses.add(PortfolioMessage::UpdateDocumentWidgets); - responses.add(MenuBarMessage::SendLayout); - } - GuideMessage::SetHoveredGuide { id } => { - if self.hovered_guide_id != id { - self.hovered_guide_id = id; - responses.add(OverlaysMessage::Draw); - } - } - } - } -} diff --git a/editor/src/messages/portfolio/document/mod.rs b/editor/src/messages/portfolio/document/mod.rs index 33c598e925..6199fc338b 100644 --- a/editor/src/messages/portfolio/document/mod.rs +++ b/editor/src/messages/portfolio/document/mod.rs @@ -3,8 +3,8 @@ mod document_message_handler; pub mod data_panel; pub mod graph_operation; -pub mod guide_message; -pub mod guide_message_handler; +pub mod guide_lines_message; +pub mod guide_lines_message_handler; pub mod navigation; pub mod node_graph; pub mod overlays; diff --git a/editor/src/messages/portfolio/document/overlays/guide_overlays.rs b/editor/src/messages/portfolio/document/overlays/guide_line_overlays.rs similarity index 72% rename from editor/src/messages/portfolio/document/overlays/guide_overlays.rs rename to editor/src/messages/portfolio/document/overlays/guide_line_overlays.rs index cffc29a13d..c0592c737f 100644 --- a/editor/src/messages/portfolio/document/overlays/guide_overlays.rs +++ b/editor/src/messages/portfolio/document/overlays/guide_line_overlays.rs @@ -1,7 +1,7 @@ use crate::consts::{COLOR_OVERLAY_BLUE, COLOR_OVERLAY_BLUE_50}; -use crate::messages::portfolio::document::guide_message_handler::GuideMessageHandler; +use crate::messages::portfolio::document::guide_lines_message_handler::GuideLinesMessageHandler; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; -use crate::messages::portfolio::document::utility_types::guide::GuideDirection; +use crate::messages::portfolio::document::utility_types::guide_line::GuideLineDirection; use glam::{DAffine2, DVec2}; fn extend_line_to_viewport(point: DVec2, direction: DVec2, viewport_size: DVec2) -> Option<(DVec2, DVec2)> { @@ -32,19 +32,19 @@ fn extend_line_to_viewport(point: DVec2, direction: DVec2, viewport_size: DVec2) Some((start, end)) } -pub fn guide_overlay(guide_handler: &GuideMessageHandler, overlay_context: &mut OverlayContext, document_to_viewport: DAffine2) { +pub fn guide_line_overlay(guide_lines_message_handler: &GuideLinesMessageHandler, overlay_context: &mut OverlayContext, document_to_viewport: DAffine2) { let viewport_size: DVec2 = overlay_context.viewport.size().into(); - for guide in &guide_handler.guides { + for guide in &guide_lines_message_handler.guide_lines { let (doc_point, doc_direction) = match guide.direction { - GuideDirection::Horizontal => (DVec2::new(0.0, guide.position), DVec2::X), - GuideDirection::Vertical => (DVec2::new(guide.position, 0.0), DVec2::Y), + GuideLineDirection::Horizontal => (DVec2::new(0.0, guide.position), DVec2::X), + GuideLineDirection::Vertical => (DVec2::new(guide.position, 0.0), DVec2::Y), }; let viewport_point = document_to_viewport.transform_point2(doc_point); let viewport_direction = document_to_viewport.transform_vector2(doc_direction); - let color = if guide_handler.hovered_guide_id == Some(guide.id) { + let color = if guide_lines_message_handler.hovered_guide_line_id == Some(guide.id) { COLOR_OVERLAY_BLUE_50 } else { COLOR_OVERLAY_BLUE diff --git a/editor/src/messages/portfolio/document/overlays/mod.rs b/editor/src/messages/portfolio/document/overlays/mod.rs index 2b2218096b..88a777148e 100644 --- a/editor/src/messages/portfolio/document/overlays/mod.rs +++ b/editor/src/messages/portfolio/document/overlays/mod.rs @@ -1,5 +1,5 @@ pub mod grid_overlays; -pub mod guide_overlays; +pub mod guide_line_overlays; mod overlays_message; mod overlays_message_handler; pub mod utility_functions; diff --git a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs index a570f02ea6..d4c0eba3da 100644 --- a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs +++ b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs @@ -1,6 +1,6 @@ use super::utility_types::{OverlayProvider, OverlaysVisibilitySettings}; #[cfg(not(test))] -use crate::messages::portfolio::document::guide_message::GuideMessage; +use crate::messages::portfolio::document::guide_lines_message::GuideLinesMessage; use crate::messages::prelude::*; #[derive(ExtractField)] @@ -59,7 +59,7 @@ impl MessageHandler> for OverlaysMes viewport: *viewport, }, }); - responses.add(GuideMessage::GuideOverlays { + responses.add(GuideLinesMessage::GuideLineOverlays { context: OverlayContext { render_context: canvas_context.clone(), visibility_settings: visibility_settings.clone(), @@ -83,7 +83,7 @@ impl MessageHandler> for OverlaysMes if visibility_settings.all() { responses.add(DocumentMessage::GridOverlays { context: overlay_context.clone() }); - responses.add(GuideMessage::GuideOverlays { context: overlay_context.clone() }); + responses.add(GuideLinesMessage::GuideLineOverlays { context: overlay_context.clone() }); for provider in &self.overlay_providers { responses.add(provider(overlay_context.clone())); diff --git a/editor/src/messages/portfolio/document/utility_types/guide.rs b/editor/src/messages/portfolio/document/utility_types/guide_line.rs similarity index 63% rename from editor/src/messages/portfolio/document/utility_types/guide.rs rename to editor/src/messages/portfolio/document/utility_types/guide_line.rs index e19ddaf69e..ef9acc106e 100644 --- a/editor/src/messages/portfolio/document/utility_types/guide.rs +++ b/editor/src/messages/portfolio/document/utility_types/guide_line.rs @@ -2,9 +2,9 @@ use crate::application::generate_uuid; #[repr(transparent)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize)] -pub struct GuideId(u64); +pub struct GuideLineId(u64); -impl GuideId { +impl GuideLineId { pub fn new() -> Self { Self(generate_uuid()) } @@ -18,44 +18,44 @@ impl GuideId { } } -impl Default for GuideId { +impl Default for GuideLineId { fn default() -> Self { Self::new() } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] -pub enum GuideDirection { +pub enum GuideLineDirection { Horizontal, Vertical, } #[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct Guide { - pub id: GuideId, - pub direction: GuideDirection, +pub struct GuideLine { + pub id: GuideLineId, + pub direction: GuideLineDirection, /// Position in document space (Y coordinate for horizontal guides, X coordinate for vertical guides) pub position: f64, } -impl Guide { - pub fn new(direction: GuideDirection, position: f64) -> Self { +impl GuideLine { + pub fn new(direction: GuideLineDirection, position: f64) -> Self { Self { - id: GuideId::new(), + id: GuideLineId::new(), direction, position, } } - pub fn with_id(id: GuideId, direction: GuideDirection, position: f64) -> Self { + pub fn with_id(id: GuideLineId, direction: GuideLineDirection, position: f64) -> Self { Self { id, direction, position } } pub fn horizontal(y: f64) -> Self { - Self::new(GuideDirection::Horizontal, y) + Self::new(GuideLineDirection::Horizontal, y) } pub fn vertical(x: f64) -> Self { - Self::new(GuideDirection::Vertical, x) + Self::new(GuideLineDirection::Vertical, x) } } diff --git a/editor/src/messages/portfolio/document/utility_types/mod.rs b/editor/src/messages/portfolio/document/utility_types/mod.rs index 6f2862f40b..ab8f9275eb 100644 --- a/editor/src/messages/portfolio/document/utility_types/mod.rs +++ b/editor/src/messages/portfolio/document/utility_types/mod.rs @@ -1,7 +1,7 @@ pub mod clipboards; pub mod document_metadata; pub mod error; -pub mod guide; +pub mod guide_line; pub mod misc; pub mod network_interface; pub mod nodes; diff --git a/frontend/src/components/panels/Document.svelte b/frontend/src/components/panels/Document.svelte index 0b24cbde07..98e525d10e 100644 --- a/frontend/src/components/panels/Document.svelte +++ b/frontend/src/components/panels/Document.svelte @@ -1,7 +1,7 @@