From 7d53b0cb22e4dddcbcc9ff1fce77cb3448ad4013 Mon Sep 17 00:00:00 2001 From: 0SlowPoke0 Date: Tue, 29 Jul 2025 00:44:45 +0530 Subject: [PATCH] impl spacing gizmo-not fully integrated --- .../shape_gizmos/grid_row_columns_gizmo.rs | 22 +- .../shape_gizmos/grid_spacing_gizmos.rs | 296 ++++++++++++++++++ .../gizmos/shape_gizmos/mod.rs | 1 + .../common_functionality/shapes/grid_shape.rs | 29 +- 4 files changed, 332 insertions(+), 16 deletions(-) create mode 100644 editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/grid_spacing_gizmos.rs diff --git a/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/grid_row_columns_gizmo.rs b/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/grid_row_columns_gizmo.rs index 5d24e0aa91..bb5ac5f972 100644 --- a/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/grid_row_columns_gizmo.rs +++ b/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/grid_row_columns_gizmo.rs @@ -175,7 +175,7 @@ fn check_if_over_gizmo(grid_type: GridType, columns: u32, rows: u32, spacing: DV None } -fn convert_to_gizmo_line(p0: DVec2, p1: DVec2) -> Line { +pub fn convert_to_gizmo_line(p0: DVec2, p1: DVec2) -> Line { Line { p0: dvec2_to_point(p0), p1: dvec2_to_point(p1), @@ -198,7 +198,7 @@ fn get_corners(columns: u32, rows: u32, spacing: DVec2) -> (DVec2, DVec2, DVec2, (point0, point1, point2, point3) } -fn get_viewport_grid_spacing(grid_type: GridType, angles: DVec2, spacing: DVec2, viewport: DAffine2) -> DVec2 { +pub fn get_viewport_grid_spacing(grid_type: GridType, angles: DVec2, spacing: DVec2, viewport: DAffine2) -> DVec2 { match grid_type { GridType::Rectangular => { let p0 = DVec2::ZERO; @@ -223,28 +223,28 @@ fn get_viewport_grid_spacing(grid_type: GridType, angles: DVec2, spacing: DVec2, } } -fn get_rectangle_top_line_points(columns: u32, rows: u32, spacing: DVec2) -> (DVec2, DVec2) { +pub fn get_rectangle_top_line_points(columns: u32, rows: u32, spacing: DVec2) -> (DVec2, DVec2) { let (top_left, top_right, _, _) = get_corners(columns, rows, spacing); let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(spacing.x * 0.5, 0.) }; (top_left + offset, top_right - offset) } -fn get_rectangle_bottom_line_points(columns: u32, rows: u32, spacing: DVec2) -> (DVec2, DVec2) { +pub fn get_rectangle_bottom_line_points(columns: u32, rows: u32, spacing: DVec2) -> (DVec2, DVec2) { let (_, _, bottom_right, bottom_left) = get_corners(columns, rows, spacing); let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(spacing.x * 0.5, 0.) }; (bottom_left + offset, bottom_right - offset) } -fn get_rectangle_right_line_points(columns: u32, rows: u32, spacing: DVec2) -> (DVec2, DVec2) { +pub fn get_rectangle_right_line_points(columns: u32, rows: u32, spacing: DVec2) -> (DVec2, DVec2) { let (_, top_right, bottom_right, _) = get_corners(columns, rows, spacing); let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(0., -spacing.y * 0.5) }; (top_right - offset, bottom_right + offset) } -fn get_rectangle_left_line_points(columns: u32, rows: u32, spacing: DVec2) -> (DVec2, DVec2) { +pub fn get_rectangle_left_line_points(columns: u32, rows: u32, spacing: DVec2) -> (DVec2, DVec2) { let (top_left, _, _, bottom_left) = get_corners(columns, rows, spacing); let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(0., -spacing.y * 0.5) }; @@ -292,14 +292,14 @@ fn calculate_isometric_bottom_line_points(columns: u32, rows: u32, spacing: DVec (bottom_left + offset, bottom_right - offset + isometric_offset) } -fn calculate_isometric_offset(spacing: DVec2, angles: DVec2) -> DVec2 { +pub fn calculate_isometric_offset(spacing: DVec2, angles: DVec2) -> DVec2 { let first_point = calculate_isometric_point(0, 0, angles, spacing); let second_point = calculate_isometric_point(1, 0, angles, spacing); DVec2::new(first_point.x - second_point.x, first_point.y - second_point.y) } -fn calculate_isometric_right_line_points(columns: u32, rows: u32, spacing: DVec2, angles: DVec2) -> (DVec2, DVec2) { +pub fn calculate_isometric_right_line_points(columns: u32, rows: u32, spacing: DVec2, angles: DVec2) -> (DVec2, DVec2) { let top_right = calculate_isometric_point(columns - 1, 0, angles, spacing); let bottom_right = calculate_isometric_point(columns - 1, rows - 1, angles, spacing); @@ -308,7 +308,7 @@ fn calculate_isometric_right_line_points(columns: u32, rows: u32, spacing: DVec2 (top_right - offset, bottom_right + offset) } -fn calculate_isometric_left_line_points(columns: u32, rows: u32, spacing: DVec2, angles: DVec2) -> (DVec2, DVec2) { +pub fn calculate_isometric_left_line_points(columns: u32, rows: u32, spacing: DVec2, angles: DVec2) -> (DVec2, DVec2) { let top_left = calculate_isometric_point(0, 0, angles, spacing); let bottom_left = calculate_isometric_point(0, rows - 1, angles, spacing); @@ -317,13 +317,13 @@ fn calculate_isometric_left_line_points(columns: u32, rows: u32, spacing: DVec2, (top_left - offset, bottom_left + offset) } -fn calculate_rectangle_side_direction(spacing: DVec2, viewport: DAffine2) -> DVec2 { +pub fn calculate_rectangle_side_direction(spacing: DVec2, viewport: DAffine2) -> DVec2 { let p0 = DVec2::ZERO; let p1 = DVec2::new(spacing.x, 0.); (viewport.transform_point2(p1) - viewport.transform_point2(p0)).normalize() } -fn calculate_rectangle_top_direction(spacing: DVec2, viewport: DAffine2) -> DVec2 { +pub fn calculate_rectangle_top_direction(spacing: DVec2, viewport: DAffine2) -> DVec2 { let p0 = DVec2::ZERO; let p1 = DVec2::new(0., spacing.y); (viewport.transform_point2(p0) - viewport.transform_point2(p1)).try_normalize().unwrap_or(DVec2::ZERO) diff --git a/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/grid_spacing_gizmos.rs b/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/grid_spacing_gizmos.rs new file mode 100644 index 0000000000..9621104648 --- /dev/null +++ b/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/grid_spacing_gizmos.rs @@ -0,0 +1,296 @@ +use crate::consts::{GRID_COLUMNS_INDEX, GRID_ROW_COLUMN_GIZMO_OFFSET, GRID_ROW_INDEX, GRID_SPACING_INDEX}; +use crate::messages::frontend::utility_types::MouseCursorIcon; +use crate::messages::message::Message; +use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn; +use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; +use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; +use crate::messages::portfolio::document::utility_types::network_interface::InputConnector; +use crate::messages::prelude::{DocumentMessageHandler, FrontendMessage, InputPreprocessorMessageHandler, NodeGraphMessage}; +use crate::messages::prelude::{GraphOperationMessage, Responses}; +use crate::messages::tool::common_functionality::gizmos::shape_gizmos::grid_row_columns_gizmo::{ + calculate_rectangle_side_direction, calculate_rectangle_top_direction, convert_to_gizmo_line, get_viewport_grid_spacing, +}; +use crate::messages::tool::common_functionality::graph_modification_utils; +use crate::messages::tool::common_functionality::shape_editor::ShapeState; +use crate::messages::tool::common_functionality::shapes::shape_utility::extract_grid_parameters; +use glam::{DAffine2, DVec2}; +use graph_craft::document::NodeInput; +use graph_craft::document::value::TaggedValue; +use graphene_std::renderer::Quad; +use graphene_std::vector::misc::{GridType, dvec2_to_point, get_line_endpoints}; +use kurbo::{Line, ParamCurveNearest, Rect}; +use std::collections::VecDeque; + +#[derive(Clone, Debug, Default, PartialEq)] +pub enum GridSpacingGizmoState { + #[default] + Inactive, + Hover, + Dragging, +} + +#[derive(Clone, Debug, Default)] +pub struct GridSpacingGizmo { + pub layer: Option, + gizmo_state: GridSpacingGizmoState, + column_index: u32, + row_index: u32, + initial_spacing: DVec2, + gizmo_type: Option, +} + +impl GridSpacingGizmo { + pub fn cleanup(&mut self) { + self.layer = None; + self.gizmo_state = GridSpacingGizmoState::Inactive; + } + + pub fn update_state(&mut self, state: GridSpacingGizmoState) { + self.gizmo_state = state; + } + + pub fn is_hovered(&self) -> bool { + self.gizmo_state == GridSpacingGizmoState::Hover + } + + pub fn is_dragging(&self) -> bool { + self.gizmo_state == GridSpacingGizmoState::Dragging + } + + pub fn handle_actions(&mut self, layer: LayerNodeIdentifier, mouse_position: DVec2, document: &DocumentMessageHandler, responses: &mut VecDeque) { + let Some((grid_type, spacing, columns, rows, angles)) = extract_grid_parameters(layer, document) else { + return; + }; + let stroke_width = graph_modification_utils::get_stroke_width(layer, &document.network_interface); + let viewport = document.metadata().transform_to_viewport(layer); + if let Some((col, row)) = check_if_over_gizmo(grid_type, columns, rows, spacing, mouse_position, viewport) { + self.layer = Some(layer); + self.column_index = col; + self.row_index = row; + self.initial_spacing = spacing; + self.update_state(GridSpacingGizmoState::Hover); + let closest_gizmo = GridSpacingGizmoType::get_closest_line(mouse_position, col, row, spacing, viewport, stroke_width); + responses.add(FrontendMessage::UpdateMouseCursor { cursor: closest_gizmo.mouse_icon() }); + self.gizmo_type = Some(closest_gizmo); + } + } + + pub fn overlays(&self, document: &DocumentMessageHandler, layer: Option, _shape_editor: &mut &mut ShapeState, _mouse_position: DVec2, overlay_context: &mut OverlayContext) { + let Some(layer) = layer.or(self.layer) else { return }; + let Some((grid_type, spacing, columns, rows, angles)) = extract_grid_parameters(layer, document) else { + return; + }; + let viewport = document.metadata().transform_to_viewport(layer); + let stroke_width = graph_modification_utils::get_stroke_width(layer, &document.network_interface); + + match self.gizmo_state { + GridSpacingGizmoState::Inactive => {} + GridSpacingGizmoState::Hover | GridSpacingGizmoState::Dragging => { + if let Some(gizmo_type) = &self.gizmo_type { + let line = gizmo_type.line(self.column_index, self.row_index, spacing, viewport, stroke_width); + let (p0, p1) = get_line_endpoints(line); + overlay_context.dashed_line(p0, p1, None, None, Some(5.), Some(5.), Some(0.5)); + + if matches!(self.gizmo_state, GridSpacingGizmoState::Hover) { + let line = gizmo_type.opposite_gizmo_type().line(self.column_index, self.row_index, spacing, viewport, stroke_width); + let (p0, p1) = get_line_endpoints(line); + overlay_context.dashed_line(p0, p1, None, None, Some(5.), Some(5.), Some(0.5)); + } + } + } + } + } + + pub fn update(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque, drag_start: DVec2) { + let Some(layer) = self.layer else { return }; + let viewport = document.metadata().transform_to_viewport(layer); + + let Some((grid_type, spacing, columns, rows, angles)) = extract_grid_parameters(layer, document) else { + return; + }; + + let Some(gizmo_type) = &self.gizmo_type else { return }; + let direction = gizmo_type.direction(spacing, viewport); + let delta_vector = input.mouse.position - drag_start; + + let delta = delta_vector.dot(direction); + + let Some(node_id) = graph_modification_utils::get_grid_id(layer, &document.network_interface) else { + return; + }; + + let new_spacing = gizmo_type.new_spacing(delta, self.initial_spacing); + let delta_spacing = new_spacing - spacing; + + // let transform = self.transform_grid(dimensions_delta, grid_type, viewport_spacing, angles, viewport); + + responses.add(NodeGraphMessage::SetInput { + input_connector: InputConnector::node(node_id, GRID_SPACING_INDEX), + input: NodeInput::value(TaggedValue::DVec2(new_spacing), false), + }); + + // responses.add(GraphOperationMessage::TransformChange { + // layer, + // transform: DAffine2::from_translation(-delta_spacing * direction), + // transform_in: TransformIn::Viewport, + // skip_rerender: false, + // }); + + responses.add(NodeGraphMessage::RunDocumentGraph); + + // if self.initial_dimension() as i32 + dimensions_to_add < 1 { + // self.initial_mouse_start = Some(input.mouse.position); + // self.gizmo_type = self.gizmo_type.opposite_gizmo_type(); + // self.initial_rows = 1; + // self.initial_columns = 1; + // } + } + + fn transform_grid(&self, dimensions_delta: i32, grid_type: GridType, spacing: DVec2, angles: DVec2, viewport: DAffine2) {} +} + +fn check_if_over_gizmo(grid_type: GridType, columns: u32, rows: u32, spacing: DVec2, mouse_position: DVec2, viewport: DAffine2) -> Option<(u32, u32)> { + let layer_mouse = viewport.inverse().transform_point2(mouse_position); + for column in 0..columns - 1 { + for row in 0..rows - 1 { + let p0 = DVec2::new(spacing.x * column as f64, spacing.y * row as f64); + let p1 = DVec2::new((1 + column) as f64 * spacing.x, (1 + row) as f64 * spacing.y); + let rect = Rect::from_points(dvec2_to_point(p0), dvec2_to_point(p1)); + + if rect.contains(dvec2_to_point(layer_mouse)) { + return Some((column, row)); + }; + } + } + + None +} + +#[derive(Clone, Debug, Default, PartialEq)] +pub enum GridSpacingGizmoType { + #[default] + None, + Top, + Down, + Left, + Right, +} + +impl GridSpacingGizmoType { + pub fn get_line_points(&self, column_index: u32, row_index: u32, spacing: DVec2, stroke: Option) -> (DVec2, DVec2) { + match self { + Self::Top => get_rectangular_top_points(column_index, row_index, spacing, stroke), + Self::Right => get_rectangular_right_points(column_index, row_index, spacing, stroke), + Self::Down => get_rectangular_down_points(column_index, row_index, spacing, stroke), + Self::Left => get_rectangular_left_points(column_index, row_index, spacing, stroke), + Self::None => panic!("RowColumnGizmoType::None does not have line points"), + } + } + + pub fn get_closest_line(mouse_position: DVec2, column_index: u32, row_index: u32, spacing: DVec2, viewport: DAffine2, stroke_width: Option) -> Self { + let mut gizmo_type = GridSpacingGizmoType::Top; + let mut closest_distance = gizmo_type + .line(column_index, row_index, spacing, viewport, stroke_width) + .nearest(dvec2_to_point(mouse_position), 1e-6) + .distance_sq; + + for t in Self::all() { + if matches!(t, GridSpacingGizmoType::Top) { + continue; + } + let line = t.line(column_index, row_index, spacing, viewport, stroke_width); + let nearest = line.nearest(dvec2_to_point(mouse_position), 1e-6); + if nearest.distance_sq < closest_distance { + gizmo_type = t; + closest_distance = nearest.distance_sq; + } + } + gizmo_type + } + + pub fn line(&self, column_index: u32, row_index: u32, spacing: DVec2, viewport: DAffine2, stroke_width: Option) -> Line { + let (p0, p1) = self.get_line_points(column_index, row_index, spacing, stroke_width); + let gap = -5. * self.direction(spacing, viewport); + + convert_to_gizmo_line(viewport.transform_point2(p0) + gap, viewport.transform_point2(p1) + gap) + } + + fn opposite(&self, grid_type: GridType, column_index: u32, row_index: u32, spacing: DVec2, angles: DVec2, viewport: DAffine2, stroke: Option) -> Line { + let opposite_gizmo_type = self.opposite_gizmo_type(); + opposite_gizmo_type.line(column_index, row_index, spacing, viewport, stroke) + } + + fn opposite_gizmo_type(&self) -> Self { + return match self { + Self::Top => Self::Down, + Self::Right => Self::Left, + Self::Down => Self::Top, + Self::Left => Self::Right, + Self::None => panic!("RowColumnGizmoType::None does not have opposite"), + }; + } + + fn new_spacing(&self, delta: f64, spacing: DVec2) -> DVec2 { + match self { + GridSpacingGizmoType::Top | GridSpacingGizmoType::Down => DVec2::new(spacing.x, spacing.y + delta), + GridSpacingGizmoType::Right | GridSpacingGizmoType::Left => DVec2::new(spacing.x + delta, spacing.y), + GridSpacingGizmoType::None => panic!("RowColumnGizmoType::None does not have a mouse_icon"), + } + } + + fn direction(&self, spacing: DVec2, viewport: DAffine2) -> DVec2 { + match self { + GridSpacingGizmoType::Top => calculate_rectangle_top_direction(spacing, viewport), + GridSpacingGizmoType::Down => -calculate_rectangle_top_direction(spacing, viewport), + GridSpacingGizmoType::Right => calculate_rectangle_side_direction(spacing, viewport), + GridSpacingGizmoType::Left => -calculate_rectangle_side_direction(spacing, viewport), + GridSpacingGizmoType::None => panic!("RowColumnGizmoType::None does not have a line"), + } + } + + fn mouse_icon(&self) -> MouseCursorIcon { + match self { + GridSpacingGizmoType::Top | GridSpacingGizmoType::Down => MouseCursorIcon::NSResize, + GridSpacingGizmoType::Right | GridSpacingGizmoType::Left => MouseCursorIcon::EWResize, + GridSpacingGizmoType::None => panic!("RowColumnGizmoType::None does not have a mouse_icon"), + } + } + + pub fn all() -> [Self; 4] { + [Self::Top, Self::Right, Self::Down, Self::Left] + } +} + +fn get_rectangular_top_points(column_index: u32, row_index: u32, spacing: DVec2, stroke_width: Option) -> (DVec2, DVec2) { + let stroke_width = stroke_width.unwrap_or_default(); + let p0 = DVec2::new(column_index as f64 * spacing.x, row_index as f64 * spacing.y) + DVec2::new(stroke_width, stroke_width); + let p1 = p0 + DVec2::new(spacing.x - 2. * stroke_width, 0.); + + (p0, p1) +} + +fn get_rectangular_right_points(column_index: u32, row_index: u32, spacing: DVec2, stroke_width: Option) -> (DVec2, DVec2) { + let stroke_width = stroke_width.unwrap_or_default(); + let p0 = DVec2::new((1 + column_index) as f64 * spacing.x, row_index as f64 * spacing.y) + DVec2::new(-stroke_width, stroke_width); + let p1 = p0 + DVec2::new(0., spacing.y - 2. * stroke_width); + + (p0, p1) +} + +fn get_rectangular_down_points(column_index: u32, row_index: u32, spacing: DVec2, stroke_width: Option) -> (DVec2, DVec2) { + let stroke_width = stroke_width.unwrap_or_default(); + + let p0 = DVec2::new(column_index as f64 * spacing.x, (1 + row_index) as f64 * spacing.y) + DVec2::new(stroke_width, -stroke_width); + let p1 = p0 + DVec2::new(spacing.x - 2. * stroke_width, 0.); + + (p0, p1) +} + +fn get_rectangular_left_points(column_index: u32, row_index: u32, spacing: DVec2, stroke_width: Option) -> (DVec2, DVec2) { + let stroke_width = stroke_width.unwrap_or_default(); + + let p0 = DVec2::new(column_index as f64 * spacing.x, row_index as f64 * spacing.y) + DVec2::new(stroke_width, stroke_width); + let p1 = p0 + DVec2::new(0., spacing.y - 2. * stroke_width); + + (p0, p1) +} diff --git a/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/mod.rs b/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/mod.rs index 8999f5c5b9..b2af3b4b46 100644 --- a/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/mod.rs +++ b/editor/src/messages/tool/common_functionality/gizmos/shape_gizmos/mod.rs @@ -1,3 +1,4 @@ pub mod grid_row_columns_gizmo; +pub mod grid_spacing_gizmos; pub mod number_of_points_dial; pub mod point_radius_handle; diff --git a/editor/src/messages/tool/common_functionality/shapes/grid_shape.rs b/editor/src/messages/tool/common_functionality/shapes/grid_shape.rs index 9b11c13340..99eda8b279 100644 --- a/editor/src/messages/tool/common_functionality/shapes/grid_shape.rs +++ b/editor/src/messages/tool/common_functionality/shapes/grid_shape.rs @@ -5,9 +5,9 @@ use crate::messages::portfolio::document::node_graph::document_node_definitions: use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeTemplate}; -use crate::messages::tool::common_functionality::gizmos::shape_gizmos::grid_row_columns_gizmo::RowColumnGizmo; use crate::messages::tool::common_functionality::gizmos::shape_gizmos::grid_row_columns_gizmo::RowColumnGizmoState; - +use crate::messages::tool::common_functionality::gizmos::shape_gizmos::grid_row_columns_gizmo::{RowColumnGizmo, calculate_rectangle_side_direction, calculate_rectangle_top_direction}; +use crate::messages::tool::common_functionality::gizmos::shape_gizmos::grid_spacing_gizmos::{GridSpacingGizmo, GridSpacingGizmoState}; use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::shape_editor::ShapeState; use crate::messages::tool::common_functionality::shapes::shape_utility::ShapeGizmoHandler; @@ -15,33 +15,44 @@ use crate::messages::tool::tool_messages::tool_prelude::*; use glam::DAffine2; use graph_craft::document::NodeInput; use graph_craft::document::value::TaggedValue; -use graphene_std::vector::misc::GridType; +use graphene_std::vector::misc::{GridType, dvec2_to_point}; +use kurbo::{Line, ParamCurveNearest}; use std::collections::VecDeque; #[derive(Clone, Debug, Default)] pub struct GridGizmoHandler { row_column_gizmo: RowColumnGizmo, + grid_spacing_gizmo: GridSpacingGizmo, } impl ShapeGizmoHandler for GridGizmoHandler { fn is_any_gizmo_hovered(&self) -> bool { - self.row_column_gizmo.is_hovered() + self.row_column_gizmo.is_hovered() || self.grid_spacing_gizmo.is_hovered() } fn handle_state(&mut self, selected_grid_layer: LayerNodeIdentifier, mouse_position: DVec2, document: &DocumentMessageHandler, responses: &mut VecDeque) { self.row_column_gizmo.handle_actions(selected_grid_layer, mouse_position, document, responses); + self.grid_spacing_gizmo.handle_actions(selected_grid_layer, mouse_position, document, responses); } fn handle_click(&mut self) { if self.row_column_gizmo.is_hovered() { self.row_column_gizmo.update_state(RowColumnGizmoState::Dragging); } + + if self.grid_spacing_gizmo.is_hovered() { + self.grid_spacing_gizmo.update_state(GridSpacingGizmoState::Dragging); + } } fn handle_update(&mut self, drag_start: DVec2, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque) { if self.row_column_gizmo.is_dragging() { self.row_column_gizmo.update(document, input, responses, drag_start); } + + if self.grid_spacing_gizmo.is_dragging() { + self.grid_spacing_gizmo.update(document, input, responses, drag_start); + } } fn overlays( @@ -54,6 +65,7 @@ impl ShapeGizmoHandler for GridGizmoHandler { overlay_context: &mut OverlayContext, ) { self.row_column_gizmo.overlays(document, selected_grid_layer, shape_editor, mouse_position, overlay_context); + self.grid_spacing_gizmo.overlays(document, selected_grid_layer, shape_editor, mouse_position, overlay_context); } fn dragging_overlays( @@ -67,9 +79,16 @@ impl ShapeGizmoHandler for GridGizmoHandler { if self.row_column_gizmo.is_dragging() { self.row_column_gizmo.overlays(document, None, shape_editor, mouse_position, overlay_context); } + + if self.grid_spacing_gizmo.is_dragging() { + self.grid_spacing_gizmo.overlays(document, None, shape_editor, mouse_position, overlay_context); + } } - fn cleanup(&mut self) {} + fn cleanup(&mut self) { + self.grid_spacing_gizmo.cleanup(); + self.row_column_gizmo.cleanup(); + } } #[derive(Default)]