Skip to content

Commit ff837cb

Browse files
committed
Merge branch 'master' into tangent-snap
2 parents 491b933 + 90be1f4 commit ff837cb

File tree

18 files changed

+586
-269
lines changed

18 files changed

+586
-269
lines changed

demo-artwork/changing-seasons.graphite

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

editor/src/consts.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,9 @@ pub const MIN_LENGTH_FOR_SKEW_TRIANGLE_VISIBILITY: f64 = 48.;
9999
pub const MANIPULATOR_GROUP_MARKER_SIZE: f64 = 6.;
100100
pub const SELECTION_THRESHOLD: f64 = 10.;
101101
pub const HIDE_HANDLE_DISTANCE: f64 = 3.;
102-
pub const INSERT_POINT_ON_SEGMENT_TOO_FAR_DISTANCE: f64 = 50.;
103102
pub const HANDLE_ROTATE_SNAP_ANGLE: f64 = 15.;
103+
pub const SEGMENT_INSERTION_DISTANCE: f64 = 7.5;
104+
pub const SEGMENT_OVERLAY_SIZE: f64 = 10.;
104105

105106
// PEN TOOL
106107
pub const CREATE_CURVE_THRESHOLD: f64 = 5.;

editor/src/messages/input_mapper/input_mappings.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,13 @@ pub fn input_mappings() -> Mapping {
212212
entry!(KeyDown(Delete); modifiers=[Shift], action_dispatch=PathToolMessage::BreakPath),
213213
entry!(KeyDown(Backspace); modifiers=[Shift], action_dispatch=PathToolMessage::BreakPath),
214214
entry!(KeyDownNoRepeat(Tab); action_dispatch=PathToolMessage::SwapSelectedHandles),
215-
entry!(KeyDown(MouseLeft); action_dispatch=PathToolMessage::MouseDown { direct_insert_without_sliding: Control, extend_selection: Shift, lasso_select: Control, handle_drag_from_anchor: Alt }),
215+
entry!(KeyDown(MouseLeft); action_dispatch=PathToolMessage::MouseDown { extend_selection: Shift, lasso_select: Control, handle_drag_from_anchor: Alt }),
216216
entry!(KeyDown(MouseRight); action_dispatch=PathToolMessage::RightClick),
217217
entry!(KeyDown(Escape); action_dispatch=PathToolMessage::Escape),
218218
entry!(KeyDown(KeyG); action_dispatch=PathToolMessage::GRS { key: KeyG }),
219219
entry!(KeyDown(KeyR); action_dispatch=PathToolMessage::GRS { key: KeyR }),
220220
entry!(KeyDown(KeyS); action_dispatch=PathToolMessage::GRS { key: KeyS }),
221-
entry!(PointerMove; refresh_keys=[KeyC, Space, Control, Shift, Alt], action_dispatch=PathToolMessage::PointerMove { toggle_colinear: KeyC, equidistant: Alt, move_anchor_with_handles: Space, snap_angle: Shift, lock_angle: Control }),
221+
entry!(PointerMove; refresh_keys=[KeyC, Space, Control, Shift, Alt], action_dispatch=PathToolMessage::PointerMove { toggle_colinear: KeyC, equidistant: Alt, move_anchor_with_handles: Space, snap_angle: Shift, lock_angle: Control, delete_segment: Alt }),
222222
entry!(KeyDown(Delete); action_dispatch=PathToolMessage::Delete),
223223
entry!(KeyDown(KeyA); modifiers=[Accel], action_dispatch=PathToolMessage::SelectAllAnchors),
224224
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], action_dispatch=PathToolMessage::DeselectAllPoints),

editor/src/messages/portfolio/document/document_message_handler.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -684,15 +684,17 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
684684
insert_index: calculated_insert_index,
685685
});
686686

687-
let layer_local_transform = self.network_interface.document_metadata().transform_to_viewport(layer_to_move);
688-
let undo_transform = self.network_interface.document_metadata().transform_to_viewport(parent).inverse();
689-
let transform = undo_transform * layer_local_transform;
690-
responses.add(GraphOperationMessage::TransformSet {
691-
layer: layer_to_move,
692-
transform,
693-
transform_in: TransformIn::Local,
694-
skip_rerender: false,
695-
});
687+
if layer_to_move.parent(self.metadata()) != Some(parent) {
688+
let layer_local_transform = self.network_interface.document_metadata().transform_to_viewport(layer_to_move);
689+
let undo_transform = self.network_interface.document_metadata().transform_to_viewport(parent).inverse();
690+
let transform = undo_transform * layer_local_transform;
691+
responses.add(GraphOperationMessage::TransformSet {
692+
layer: layer_to_move,
693+
transform,
694+
transform_in: TransformIn::Local,
695+
skip_rerender: false,
696+
});
697+
}
696698
}
697699

698700
responses.add(NodeGraphMessage::RunDocumentGraph);

editor/src/messages/portfolio/document/overlays/utility_types.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -310,13 +310,10 @@ impl OverlayContext {
310310
}
311311

312312
pub fn draw_angle(&mut self, pivot: DVec2, radius: f64, arc_radius: f64, offset_angle: f64, angle: f64) {
313-
let color_line = COLOR_OVERLAY_BLUE;
314-
315313
let end_point1 = pivot + radius * DVec2::from_angle(angle + offset_angle);
316314
let end_point2 = pivot + radius * DVec2::from_angle(offset_angle);
317-
self.line(pivot, end_point1, Some(color_line), None);
318-
self.line(pivot, end_point2, Some(color_line), None);
319-
315+
self.line(pivot, end_point1, None, None);
316+
self.dashed_line(pivot, end_point2, None, None, Some(2.), Some(2.), Some(0.5));
320317
self.draw_arc(pivot, arc_radius, offset_angle, (angle) % TAU + offset_angle);
321318
}
322319

editor/src/messages/portfolio/document/utility_types/document_metadata.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,11 +261,21 @@ impl LayerNodeIdentifier {
261261
metadata.get_relations(self).and_then(|relations| relations.last_child)
262262
}
263263

264-
/// Does the layer have children? If so, then it is a folder
264+
/// Does the layer have children? If so, then it is a folder.
265265
pub fn has_children(self, metadata: &DocumentMetadata) -> bool {
266266
self.first_child(metadata).is_some()
267267
}
268268

269+
/// Is the layer a child of the given layer?
270+
pub fn is_child_of(self, metadata: &DocumentMetadata, parent: &LayerNodeIdentifier) -> bool {
271+
parent.children(metadata).any(|child| child == self)
272+
}
273+
274+
/// Is the layer an ancestor of the given layer?
275+
pub fn is_ancestor_of(self, metadata: &DocumentMetadata, child: &LayerNodeIdentifier) -> bool {
276+
child.ancestors(metadata).any(|ancestor| ancestor == self)
277+
}
278+
269279
/// Iterator over all direct children (excluding self and recursive children)
270280
pub fn children(self, metadata: &DocumentMetadata) -> AxisIter {
271281
AxisIter {

editor/src/messages/portfolio/portfolio_message_handler.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,23 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
905905
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
906906
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
907907
}
908+
909+
if reference == "Morph" && inputs_count == 4 {
910+
let node_definition = resolve_document_node_type(reference).unwrap();
911+
let new_node_template = node_definition.default_node_template();
912+
let document_node = new_node_template.document_node;
913+
document.network_interface.replace_implementation(node_id, network_path, document_node.implementation.clone());
914+
document
915+
.network_interface
916+
.replace_implementation_metadata(node_id, network_path, new_node_template.persistent_node_metadata);
917+
918+
let old_inputs = document.network_interface.replace_inputs(node_id, document_node.inputs.clone(), network_path);
919+
920+
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
921+
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
922+
document.network_interface.set_input(&InputConnector::node(*node_id, 2), old_inputs[2].clone(), network_path);
923+
// We have removed the last input, so we don't add index 3
924+
}
908925
}
909926

910927
// TODO: Eventually remove this document upgrade code

editor/src/messages/tool/common_functionality/measure.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ fn draw_dashed_line(line_start: DVec2, line_end: DVec2, transform: DAffine2, ove
1010

1111
overlay_context.dashed_line(min_viewport, max_viewport, None, None, Some(2.), Some(2.), Some(0.5));
1212
}
13+
1314
/// Draws a solid line with a length annotation between two points transformed by the given affine transformations.
1415
fn draw_line_with_length(line_start: DVec2, line_end: DVec2, transform: DAffine2, document_to_viewport: DAffine2, overlay_context: &mut OverlayContext, label_alignment: LabelAlignment) {
1516
let transform_to_document = document_to_viewport.inverse() * transform;

editor/src/messages/tool/common_functionality/shape_editor.rs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ impl ClosestSegment {
104104
self.layer
105105
}
106106

107+
pub fn segment(&self) -> SegmentId {
108+
self.segment
109+
}
110+
111+
pub fn points(&self) -> [PointId; 2] {
112+
self.points
113+
}
114+
107115
pub fn closest_point_to_viewport(&self) -> DVec2 {
108116
self.bezier_point_to_viewport
109117
}
@@ -128,9 +136,7 @@ impl ClosestSegment {
128136
pub fn too_far(&self, mouse_position: DVec2, tolerance: f64, document_metadata: &DocumentMetadata) -> bool {
129137
let dist_sq = self.distance_squared(mouse_position);
130138
let stroke_width = document_metadata.document_to_viewport.decompose_scale().x.max(1.) * self.stroke_width;
131-
let stroke_width_sq = stroke_width * stroke_width;
132-
let tolerance_sq = tolerance * tolerance;
133-
(stroke_width_sq + tolerance_sq) < dist_sq
139+
(stroke_width + tolerance).powi(2) < dist_sq
134140
}
135141

136142
pub fn handle_positions(&self, document_metadata: &DocumentMetadata) -> (Option<DVec2>, Option<DVec2>) {
@@ -199,6 +205,28 @@ impl ClosestSegment {
199205
let id = self.adjusted_insert(responses);
200206
shape_editor.select_anchor_point_by_id(self.layer, id, extend_selection)
201207
}
208+
209+
pub fn calculate_perp(&self, document: &DocumentMessageHandler) -> DVec2 {
210+
let tangent = if let (Some(handle1), Some(handle2)) = self.handle_positions(document.metadata()) {
211+
(handle1 - handle2).try_normalize()
212+
} else {
213+
let [first_point, last_point] = self.points();
214+
if let Some(vector_data) = document.network_interface.compute_modified_vector(self.layer()) {
215+
if let (Some(pos1), Some(pos2)) = (
216+
ManipulatorPointId::Anchor(first_point).get_position(&vector_data),
217+
ManipulatorPointId::Anchor(last_point).get_position(&vector_data),
218+
) {
219+
(pos1 - pos2).try_normalize()
220+
} else {
221+
None
222+
}
223+
} else {
224+
None
225+
}
226+
}
227+
.unwrap_or(DVec2::ZERO);
228+
tangent.perp()
229+
}
202230
}
203231

204232
// TODO Consider keeping a list of selected manipulators to minimize traversals of the layers
@@ -900,6 +928,29 @@ impl ShapeState {
900928
.collect::<HashMap<_, _>>()
901929
}
902930

931+
pub fn dissolve_segment(&self, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, vector_data: &VectorData, segment: SegmentId, points: [PointId; 2]) {
932+
// Checking which point is terminal point
933+
let is_point1_terminal = vector_data.connected_count(points[0]) == 1;
934+
let is_point2_terminal = vector_data.connected_count(points[1]) == 1;
935+
936+
// Delete the segment and terminal points
937+
let modification_type = VectorModificationType::RemoveSegment { id: segment };
938+
responses.add(GraphOperationMessage::Vector { layer, modification_type });
939+
for &handles in vector_data.colinear_manipulators.iter().filter(|handles| handles.iter().any(|handle| handle.segment == segment)) {
940+
let modification_type = VectorModificationType::SetG1Continuous { handles, enabled: false };
941+
responses.add(GraphOperationMessage::Vector { layer, modification_type });
942+
}
943+
944+
if is_point1_terminal {
945+
let modification_type = VectorModificationType::RemovePoint { id: points[0] };
946+
responses.add(GraphOperationMessage::Vector { layer, modification_type });
947+
}
948+
if is_point2_terminal {
949+
let modification_type = VectorModificationType::RemovePoint { id: points[1] };
950+
responses.add(GraphOperationMessage::Vector { layer, modification_type });
951+
}
952+
}
953+
903954
fn dissolve_anchor(anchor: PointId, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, vector_data: &VectorData) -> Option<[(HandleId, PointId); 2]> {
904955
// Delete point
905956
let modification_type = VectorModificationType::RemovePoint { id: anchor };

editor/src/messages/tool/tool_messages/artboard_tool.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ impl Fsm for ArtboardToolFsmState {
267267
let constrain_square = input.keyboard.get(constrain_axis_or_aspect as usize);
268268
tool_data.resize_artboard(responses, document, input, from_center, constrain_square);
269269

270-
// AutoPanning
270+
// Auto-panning
271271
let messages = [
272272
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
273273
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
@@ -306,7 +306,7 @@ impl Fsm for ArtboardToolFsmState {
306306
bounds.bounds[0] = position.round();
307307
bounds.bounds[1] = position.round() + size.round();
308308

309-
// AutoPanning
309+
// Auto-panning
310310
let messages = [
311311
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
312312
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
@@ -345,7 +345,7 @@ impl Fsm for ArtboardToolFsmState {
345345
})
346346
}
347347

348-
// AutoPanning
348+
// Auto-panning
349349
let messages = [
350350
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
351351
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
@@ -377,25 +377,25 @@ impl Fsm for ArtboardToolFsmState {
377377
ArtboardToolFsmState::Ready { hovered }
378378
}
379379
(ArtboardToolFsmState::ResizingBounds, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
380-
// AutoPanning
380+
// Auto-panning
381381
let _ = tool_data.auto_panning.shift_viewport(input, responses);
382382

383383
ArtboardToolFsmState::ResizingBounds
384384
}
385385
(ArtboardToolFsmState::Dragging, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
386-
// AutoPanning
386+
// Auto-panning
387387
tool_data.auto_panning.shift_viewport(input, responses);
388388

389389
ArtboardToolFsmState::Dragging
390390
}
391391
(ArtboardToolFsmState::Drawing, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
392-
// AutoPanning
392+
// Auto-panning
393393
tool_data.auto_panning.shift_viewport(input, responses);
394394

395395
ArtboardToolFsmState::Drawing
396396
}
397397
(state, ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }) => {
398-
// AutoPanning
398+
// Auto-panning
399399
let messages = [
400400
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
401401
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),

0 commit comments

Comments
 (0)