Skip to content

Commit

Permalink
Merge branch 'master' into new-layer-artboard-bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
james-ryans authored Nov 25, 2024
2 parents 8889e90 + 9fb4947 commit 377b910
Show file tree
Hide file tree
Showing 33 changed files with 1,548 additions and 291 deletions.
75 changes: 65 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ members = [
"libraries/dyn-any",
"libraries/path-bool",
"libraries/bezier-rs",
"libraries/math-parser",
"website/other/bezier-rs-demos/wasm",
]
exclude = ["node-graph/gpu-compiler"]
Expand All @@ -31,6 +32,7 @@ graph-craft = { path = "node-graph/graph-craft", features = ["serde"] }
wgpu-executor = { path = "node-graph/wgpu-executor" }
bezier-rs = { path = "libraries/bezier-rs", features = ["dyn-any"] }
path-bool = { path = "libraries/path-bool", default-features = false }
math-parser = { path = "libraries/math-parser" }
node-macro = { path = "node-graph/node-macro" }

# Workspace dependencies
Expand Down Expand Up @@ -77,7 +79,6 @@ glam = { version = "0.28", default-features = false, features = ["serde"] }
base64 = "0.22"
image = { version = "0.25", default-features = false, features = ["png"] }
rustybuzz = "0.17"
meval = "0.2"
spirv = "0.3"
fern = { version = "0.6", features = ["colored"] }
num_enum = "0.7"
Expand All @@ -94,9 +95,6 @@ syn = { version = "2.0", default-features = false, features = [
] }
kurbo = { version = "0.11.0", features = ["serde"] }

[patch.crates-io]
meval = { git = "https://github.com/Titaniumtown/meval-rs" }

[profile.dev]
opt-level = 1

Expand Down
3 changes: 3 additions & 0 deletions editor/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ pub const DRAG_BEYOND_VIEWPORT_SPEED_FACTOR: f64 = 20.;

// Snapping point
pub const SNAP_POINT_TOLERANCE: f64 = 5.;
pub const MAX_ALIGNMENT_CANDIDATES: usize = 100; // These are layers whose bounding boxes are used for alignment.
pub const MAX_SNAP_CANDIDATES: usize = 10; // These are layers that are used for the layer snapper
pub const MAX_LAYER_SNAP_POINTS: usize = 100; // These are points (anchors and bounding box corners etc.) in the layer snapper

pub const DRAG_THRESHOLD: f64 = 1.;

Expand Down
18 changes: 10 additions & 8 deletions editor/src/messages/tool/common_functionality/resize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::messages::tool::common_functionality::snapping::SnapManager;
use crate::messages::{input_mapper::utility_types::input_keyboard::Key, portfolio::document::graph_operation::utility_types::TransformIn};
use glam::{DAffine2, DVec2, Vec2Swizzles};

use super::snapping::{SnapCandidatePoint, SnapConstraint, SnapData};
use super::snapping::{SnapCandidatePoint, SnapConstraint, SnapData, SnapTypeConfiguration};

#[derive(Clone, Debug, Default)]
pub struct Resize {
Expand All @@ -19,7 +19,7 @@ impl Resize {
pub fn start(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) {
let root_transform = document.metadata().document_to_viewport;
let point = SnapCandidatePoint::handle(root_transform.inverse().transform_point2(input.mouse.position));
let snapped = self.snap_manager.free_snap(&SnapData::new(document, input), &point, None, false);
let snapped = self.snap_manager.free_snap(&SnapData::new(document, input), &point, SnapTypeConfiguration::default());
self.drag_start = snapped.snapped_point_document;
}

Expand Down Expand Up @@ -51,6 +51,7 @@ impl Resize {
let ratio = input.keyboard.get(lock_ratio as usize);
let center = input.keyboard.get(center as usize);
let snap_data = SnapData::ignore(document, input, &ignore);
let config = SnapTypeConfiguration::default();
if ratio {
let size = points_viewport[1] - points_viewport[0];
let size = size.abs().max(size.abs().yx()) * size.signum();
Expand All @@ -61,27 +62,28 @@ impl Resize {
direction: end_document - self.drag_start,
};
if center {
let snapped = self.snap_manager.constrained_snap(&snap_data, &SnapCandidatePoint::handle(end_document), constraint, None);
let snapped = self.snap_manager.constrained_snap(&snap_data, &SnapCandidatePoint::handle(end_document), constraint, config);
let far = SnapCandidatePoint::handle(2. * self.drag_start - end_document);
let snapped_far = self.snap_manager.constrained_snap(&snap_data, &far, constraint, None);
let snapped_far = self.snap_manager.constrained_snap(&snap_data, &far, constraint, config);
let best = if snapped_far.other_snap_better(&snapped) { snapped } else { snapped_far };
points_viewport[0] = document_to_viewport.transform_point2(best.snapped_point_document);
points_viewport[1] = document_to_viewport.transform_point2(self.drag_start * 2. - best.snapped_point_document);
self.snap_manager.update_indicator(best);
} else {
let snapped = self.snap_manager.constrained_snap(&snap_data, &SnapCandidatePoint::handle(end_document), constraint, None);
let snapped = self.snap_manager.constrained_snap(&snap_data, &SnapCandidatePoint::handle(end_document), constraint, config);
points_viewport[1] = document_to_viewport.transform_point2(snapped.snapped_point_document);
self.snap_manager.update_indicator(snapped);
}
} else if center {
let snapped = self.snap_manager.free_snap(&snap_data, &SnapCandidatePoint::handle(document_mouse), None, false);
let snapped_far = self.snap_manager.free_snap(&snap_data, &SnapCandidatePoint::handle(2. * self.drag_start - document_mouse), None, false);
let snapped = self.snap_manager.free_snap(&snap_data, &SnapCandidatePoint::handle(document_mouse), config);
let opposite = 2. * self.drag_start - document_mouse;
let snapped_far = self.snap_manager.free_snap(&snap_data, &SnapCandidatePoint::handle(opposite), config);
let best = if snapped_far.other_snap_better(&snapped) { snapped } else { snapped_far };
points_viewport[0] = document_to_viewport.transform_point2(best.snapped_point_document);
points_viewport[1] = document_to_viewport.transform_point2(self.drag_start * 2. - best.snapped_point_document);
self.snap_manager.update_indicator(best);
} else {
let snapped = self.snap_manager.free_snap(&snap_data, &SnapCandidatePoint::handle(document_mouse), None, false);
let snapped = self.snap_manager.free_snap(&snap_data, &SnapCandidatePoint::handle(document_mouse), config);
points_viewport[1] = document_to_viewport.transform_point2(snapped.snapped_point_document);
self.snap_manager.update_indicator(snapped);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::messages::portfolio::document::utility_types::document_metadata::{Doc
use crate::messages::portfolio::document::utility_types::misc::{GeometrySnapSource, SnapSource};
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::snapping::SnapTypeConfiguration;
use crate::messages::tool::tool_messages::path_tool::PointSelectState;

use bezier_rs::{Bezier, BezierHandles, TValue};
Expand Down Expand Up @@ -210,7 +211,7 @@ impl ShapeState {
}
}

let snapped = snap_manager.free_snap(&snap_data, &point, None, false);
let snapped = snap_manager.free_snap(&snap_data, &point, SnapTypeConfiguration::default());
if best_snapped.other_snap_better(&snapped) {
offset = snapped.snapped_point_document - point.document_point + mouse_delta;
best_snapped = snapped;
Expand Down
43 changes: 26 additions & 17 deletions editor/src/messages/tool/common_functionality/snapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ use glam::{DAffine2, DVec2};
use graphene_std::vector::NoHashBuilder;
use std::cmp::Ordering;

/// Configuration for the relevant snap type
#[derive(Debug, Clone, Copy, Default)]
pub struct SnapTypeConfiguration {
pub only_geometry: bool,
pub use_existing_candidates: bool,
pub accept_distribution: bool,
pub bbox: Option<Rect>,
}

/// Handles snapping and snap overlays
#[derive(Debug, Clone, Default)]
pub struct SnapManager {
Expand Down Expand Up @@ -242,7 +251,7 @@ impl SnapManager {
}
pub fn preview_draw(&mut self, snap_data: &SnapData, mouse: DVec2) {
let point = SnapCandidatePoint::handle(snap_data.document.metadata().document_to_viewport.inverse().transform_point2(mouse));
let snapped = self.free_snap(snap_data, &point, None, false);
let snapped = self.free_snap(snap_data, &point, SnapTypeConfiguration::default());
self.update_indicator(snapped);
}

Expand Down Expand Up @@ -342,64 +351,64 @@ impl SnapManager {
self.add_candidates(layer, snap_data, quad);
}

if self.alignment_candidates.as_ref().is_some_and(|candidates| candidates.len() > 100) {
if self.alignment_candidates.as_ref().is_some_and(|candidates| candidates.len() > crate::consts::MAX_ALIGNMENT_CANDIDATES) {
warn!("Alignment candidate overflow");
}
if self.candidates.as_ref().is_some_and(|candidates| candidates.len() > 10) {
if self.candidates.as_ref().is_some_and(|candidates| candidates.len() > crate::consts::MAX_SNAP_CANDIDATES) {
warn!("Snap candidate overflow");
}
}

pub fn free_snap(&mut self, snap_data: &SnapData, point: &SnapCandidatePoint, bbox: Option<Rect>, to_paths: bool) -> SnappedPoint {
pub fn free_snap(&mut self, snap_data: &SnapData, point: &SnapCandidatePoint, config: SnapTypeConfiguration) -> SnappedPoint {
if !point.document_point.is_finite() {
warn!("Snapping non-finite position");
return SnappedPoint::infinite_snap(DVec2::ZERO);
}

let mut snap_results = SnapResults::default();
if point.source_index == 0 {
if !config.use_existing_candidates {
self.candidates = None;
}

let mut snap_data = snap_data.clone();
if snap_data.candidates.is_none() {
self.find_candidates(&snap_data, point, bbox);
self.find_candidates(&snap_data, point, config.bbox);
}
snap_data.candidates = self.candidates.as_ref();
snap_data.alignment_candidates = self.alignment_candidates.as_ref();

self.layer_snapper.free_snap(&mut snap_data, point, &mut snap_results);
self.layer_snapper.free_snap(&mut snap_data, point, &mut snap_results, config);
self.grid_snapper.free_snap(&mut snap_data, point, &mut snap_results);
self.alignment_snapper.free_snap(&mut snap_data, point, &mut snap_results);
self.distribution_snapper.free_snap(&mut snap_data, point, &mut snap_results, bbox);
self.alignment_snapper.free_snap(&mut snap_data, point, &mut snap_results, config);
self.distribution_snapper.free_snap(&mut snap_data, point, &mut snap_results, config);

Self::find_best_snap(&mut snap_data, point, snap_results, false, false, to_paths)
Self::find_best_snap(&mut snap_data, point, snap_results, false, false, config.only_geometry)
}

pub fn constrained_snap(&mut self, snap_data: &SnapData, point: &SnapCandidatePoint, constraint: SnapConstraint, bbox: Option<Rect>) -> SnappedPoint {
pub fn constrained_snap(&mut self, snap_data: &SnapData, point: &SnapCandidatePoint, constraint: SnapConstraint, config: SnapTypeConfiguration) -> SnappedPoint {
if !point.document_point.is_finite() {
warn!("Snapping non-finite position");
return SnappedPoint::infinite_snap(DVec2::ZERO);
}

let mut snap_results = SnapResults::default();
if point.source_index == 0 {
if !config.use_existing_candidates {
self.candidates = None;
}

let mut snap_data = snap_data.clone();
if snap_data.candidates.is_none() {
self.find_candidates(&snap_data, point, bbox);
self.find_candidates(&snap_data, point, config.bbox);
}
snap_data.candidates = self.candidates.as_ref();
snap_data.alignment_candidates = self.alignment_candidates.as_ref();

self.layer_snapper.constrained_snap(&mut snap_data, point, &mut snap_results, constraint);
self.layer_snapper.constrained_snap(&mut snap_data, point, &mut snap_results, constraint, config);
self.grid_snapper.constrained_snap(&mut snap_data, point, &mut snap_results, constraint);
self.alignment_snapper.constrained_snap(&mut snap_data, point, &mut snap_results, constraint);
self.distribution_snapper.constrained_snap(&mut snap_data, point, &mut snap_results, constraint, bbox);
self.alignment_snapper.constrained_snap(&mut snap_data, point, &mut snap_results, constraint, config);
self.distribution_snapper.constrained_snap(&mut snap_data, point, &mut snap_results, constraint, config);

Self::find_best_snap(&mut snap_data, point, snap_results, true, false, false)
Self::find_best_snap(&mut snap_data, point, snap_results, true, false, config.only_geometry)
}

fn alignment_x_overlay(boxes: &VecDeque<Rect>, transform: DAffine2, overlay_context: &mut OverlayContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ impl AlignmentSnapper {
}
}

pub fn snap_bbox_points(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint) {
self.collect_bounding_box_points(snap_data, point.source_index == 0);
pub fn snap_bbox_points(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint, config: SnapTypeConfiguration) {
self.collect_bounding_box_points(snap_data, !config.use_existing_candidates);
let unselected_geometry = if snap_data.document.snapping_state.target_enabled(SnapTarget::Alignment(AlignmentSnapTarget::Handle)) {
snap_data.node_snap_cache.map(|cache| cache.unselected.as_slice()).unwrap_or(&[])
} else {
Expand Down Expand Up @@ -154,23 +154,23 @@ impl AlignmentSnapper {
_ => {}
}
}
pub fn free_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults) {
pub fn free_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, config: SnapTypeConfiguration) {
let is_bbox = matches!(point.source, SnapSource::BoundingBox(_));
let is_geometry = matches!(point.source, SnapSource::Geometry(_));
let geometry_selected = snap_data.has_manipulators();

if is_bbox || (is_geometry && geometry_selected) || (is_geometry && point.alignment) {
self.snap_bbox_points(snap_data, point, snap_results, SnapConstraint::None);
self.snap_bbox_points(snap_data, point, snap_results, SnapConstraint::None, config);
}
}

pub fn constrained_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint) {
pub fn constrained_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults, constraint: SnapConstraint, config: SnapTypeConfiguration) {
let is_bbox = matches!(point.source, SnapSource::BoundingBox(_));
let is_geometry = matches!(point.source, SnapSource::Geometry(_));
let geometry_selected = snap_data.has_manipulators();

if is_bbox || (is_geometry && geometry_selected) || (is_geometry && point.alignment) {
self.snap_bbox_points(snap_data, point, snap_results, constraint);
self.snap_bbox_points(snap_data, point, snap_results, constraint, config);
}
}
}
Loading

0 comments on commit 377b910

Please sign in to comment.