mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-25 16:48:11 +08:00
impl spacing gizmo-not fully integrated
This commit is contained in:
+11
-11
@@ -175,7 +175,7 @@ fn check_if_over_gizmo(grid_type: GridType, columns: u32, rows: u32, spacing: DV
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_to_gizmo_line(p0: DVec2, p1: DVec2) -> Line {
|
pub fn convert_to_gizmo_line(p0: DVec2, p1: DVec2) -> Line {
|
||||||
Line {
|
Line {
|
||||||
p0: dvec2_to_point(p0),
|
p0: dvec2_to_point(p0),
|
||||||
p1: dvec2_to_point(p1),
|
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)
|
(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 {
|
match grid_type {
|
||||||
GridType::Rectangular => {
|
GridType::Rectangular => {
|
||||||
let p0 = DVec2::ZERO;
|
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 (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.) };
|
let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(spacing.x * 0.5, 0.) };
|
||||||
|
|
||||||
(top_left + offset, top_right - offset)
|
(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 (_, _, 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.) };
|
let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(spacing.x * 0.5, 0.) };
|
||||||
|
|
||||||
(bottom_left + offset, bottom_right - offset)
|
(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 (_, 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) };
|
let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(0., -spacing.y * 0.5) };
|
||||||
|
|
||||||
(top_right - offset, bottom_right + offset)
|
(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 (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) };
|
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)
|
(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 first_point = calculate_isometric_point(0, 0, angles, spacing);
|
||||||
let second_point = calculate_isometric_point(1, 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)
|
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 top_right = calculate_isometric_point(columns - 1, 0, angles, spacing);
|
||||||
let bottom_right = calculate_isometric_point(columns - 1, rows - 1, 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)
|
(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 top_left = calculate_isometric_point(0, 0, angles, spacing);
|
||||||
let bottom_left = calculate_isometric_point(0, rows - 1, 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)
|
(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 p0 = DVec2::ZERO;
|
||||||
let p1 = DVec2::new(spacing.x, 0.);
|
let p1 = DVec2::new(spacing.x, 0.);
|
||||||
(viewport.transform_point2(p1) - viewport.transform_point2(p0)).normalize()
|
(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 p0 = DVec2::ZERO;
|
||||||
let p1 = DVec2::new(0., spacing.y);
|
let p1 = DVec2::new(0., spacing.y);
|
||||||
(viewport.transform_point2(p0) - viewport.transform_point2(p1)).try_normalize().unwrap_or(DVec2::ZERO)
|
(viewport.transform_point2(p0) - viewport.transform_point2(p1)).try_normalize().unwrap_or(DVec2::ZERO)
|
||||||
|
|||||||
+296
@@ -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<LayerNodeIdentifier>,
|
||||||
|
gizmo_state: GridSpacingGizmoState,
|
||||||
|
column_index: u32,
|
||||||
|
row_index: u32,
|
||||||
|
initial_spacing: DVec2,
|
||||||
|
gizmo_type: Option<GridSpacingGizmoType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Message>) {
|
||||||
|
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<LayerNodeIdentifier>, _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<Message>, 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<f64>) -> (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<f64>) -> 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<f64>) -> 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<f64>) -> 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<f64>) -> (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<f64>) -> (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<f64>) -> (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<f64>) -> (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)
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod grid_row_columns_gizmo;
|
pub mod grid_row_columns_gizmo;
|
||||||
|
pub mod grid_spacing_gizmos;
|
||||||
pub mod number_of_points_dial;
|
pub mod number_of_points_dial;
|
||||||
pub mod point_radius_handle;
|
pub mod point_radius_handle;
|
||||||
|
|||||||
@@ -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::overlays::utility_types::OverlayContext;
|
||||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||||
use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeTemplate};
|
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::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::graph_modification_utils;
|
||||||
use crate::messages::tool::common_functionality::shape_editor::ShapeState;
|
use crate::messages::tool::common_functionality::shape_editor::ShapeState;
|
||||||
use crate::messages::tool::common_functionality::shapes::shape_utility::ShapeGizmoHandler;
|
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 glam::DAffine2;
|
||||||
use graph_craft::document::NodeInput;
|
use graph_craft::document::NodeInput;
|
||||||
use graph_craft::document::value::TaggedValue;
|
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;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct GridGizmoHandler {
|
pub struct GridGizmoHandler {
|
||||||
row_column_gizmo: RowColumnGizmo,
|
row_column_gizmo: RowColumnGizmo,
|
||||||
|
grid_spacing_gizmo: GridSpacingGizmo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShapeGizmoHandler for GridGizmoHandler {
|
impl ShapeGizmoHandler for GridGizmoHandler {
|
||||||
fn is_any_gizmo_hovered(&self) -> bool {
|
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<Message>) {
|
fn handle_state(&mut self, selected_grid_layer: LayerNodeIdentifier, mouse_position: DVec2, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||||
self.row_column_gizmo.handle_actions(selected_grid_layer, mouse_position, document, responses);
|
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) {
|
fn handle_click(&mut self) {
|
||||||
if self.row_column_gizmo.is_hovered() {
|
if self.row_column_gizmo.is_hovered() {
|
||||||
self.row_column_gizmo.update_state(RowColumnGizmoState::Dragging);
|
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<Message>) {
|
fn handle_update(&mut self, drag_start: DVec2, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) {
|
||||||
if self.row_column_gizmo.is_dragging() {
|
if self.row_column_gizmo.is_dragging() {
|
||||||
self.row_column_gizmo.update(document, input, responses, drag_start);
|
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(
|
fn overlays(
|
||||||
@@ -54,6 +65,7 @@ impl ShapeGizmoHandler for GridGizmoHandler {
|
|||||||
overlay_context: &mut OverlayContext,
|
overlay_context: &mut OverlayContext,
|
||||||
) {
|
) {
|
||||||
self.row_column_gizmo.overlays(document, selected_grid_layer, shape_editor, mouse_position, overlay_context);
|
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(
|
fn dragging_overlays(
|
||||||
@@ -67,9 +79,16 @@ impl ShapeGizmoHandler for GridGizmoHandler {
|
|||||||
if self.row_column_gizmo.is_dragging() {
|
if self.row_column_gizmo.is_dragging() {
|
||||||
self.row_column_gizmo.overlays(document, None, shape_editor, mouse_position, overlay_context);
|
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)]
|
#[derive(Default)]
|
||||||
|
|||||||
Reference in New Issue
Block a user