Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions editor/src/messages/input_mapper/input_mappings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub fn input_mappings() -> Mapping {
entry!(KeyDown(MouseLeft); modifiers=[Alt], action_dispatch=NodeGraphMessage::PointerDown { shift_click: false, control_click: false, alt_click: true, right_click: false }),
entry!(KeyDown(MouseRight); action_dispatch=NodeGraphMessage::PointerDown { shift_click: false, control_click: false, alt_click: false, right_click: true }),
entry!(DoubleClick(MouseButton::Left); action_dispatch=NodeGraphMessage::EnterNestedNetwork),
entry!(PointerMove; refresh_keys=[Shift], action_dispatch=NodeGraphMessage::PointerMove { shift: Shift }),
entry!(PointerMove; refresh_keys=[Shift, Space], action_dispatch=NodeGraphMessage::PointerMove { shift: Shift }),
entry!(PointerShake; action_dispatch=NodeGraphMessage::ShakeNode),
entry!(KeyUp(MouseLeft); action_dispatch=NodeGraphMessage::PointerUp),
entry!(KeyDown(Delete); modifiers=[Accel], action_dispatch=NodeGraphMessage::DeleteSelectedNodes { delete_children: false }),
Expand Down Expand Up @@ -102,7 +102,7 @@ pub fn input_mappings() -> Mapping {
entry!(PointerMove; refresh_keys=[Control, Shift], action_dispatch=TransformLayerMessage::PointerMove { slow_key: Shift, increments_key: Control }),
//
// SelectToolMessage
entry!(PointerMove; refresh_keys=[Control, Alt, Shift], action_dispatch=SelectToolMessage::PointerMove { modifier_keys: SelectToolPointerKeys { axis_align: Shift, snap_angle: Shift, center: Alt, duplicate: Alt } }),
entry!(PointerMove; refresh_keys=[Control, Alt, Shift], action_dispatch=SelectToolMessage::PointerMove { modifier_keys: SelectToolPointerKeys { axis_align: Shift, snap_angle: Shift, center: Alt, duplicate: Alt, space_drag: Space } }),
entry!(KeyDown(MouseLeft); action_dispatch=SelectToolMessage::DragStart { extend_selection: Shift, remove_from_selection: Alt, select_deepest: Accel, lasso_select: Control, skew: Control }),
entry!(KeyUp(MouseLeft); action_dispatch=SelectToolMessage::DragStop { remove_from_selection: Alt }),
entry!(KeyDown(Enter); action_dispatch=SelectToolMessage::Enter),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
snap_angle: Key::Shift,
center: Key::Alt,
duplicate: Key::Alt,
space_drag: Key::Space,
},
});
responses.add(NodeGraphMessage::RunDocumentGraph);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub struct NodeGraphMessageHandler {
frontend_nodes: Vec<NodeId>,
/// Used to keep track of what wires are sent to the front end so the old ones can be removed
frontend_wires: HashSet<(NodeId, usize)>,
last_mouse_viewport_for_space: Option<DVec2>,
}

/// NodeGraphMessageHandler always modifies the network which the selected nodes are in. No GraphOperationMessages should be added here, since those messages will always affect the document network.
Expand Down Expand Up @@ -746,6 +747,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
alt_click,
right_click,
} => {
self.last_mouse_viewport_for_space = None;

if selection_network_path != breadcrumb_network_path {
log::error!("Selection network path does not match breadcrumb network path in PointerDown");
return;
Expand Down Expand Up @@ -1013,9 +1016,26 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
return;
};

// Auto-panning
let messages = [NodeGraphMessage::PointerOutsideViewport { shift }.into(), NodeGraphMessage::PointerMove { shift }.into()];
self.auto_panning.setup_by_mouse_position(ipp, viewport, &messages, responses);
if ipp.keyboard.get(Key::Space as usize) {
if let Some(last_mouse) = self.last_mouse_viewport_for_space {
let delta = ipp.mouse.position - last_mouse;
if let Some((box_start, _)) = &mut self.box_selection_start {
let graph_delta = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_vector2(delta);
*box_start += graph_delta;
} else {
responses.add(NavigationMessage::CanvasPan { delta });
}
}
self.last_mouse_viewport_for_space = Some(ipp.mouse.position);
} else {
self.last_mouse_viewport_for_space = None;
}

if self.last_mouse_viewport_for_space.is_none() {
// Auto-panning
let messages = [NodeGraphMessage::PointerOutsideViewport { shift }.into(), NodeGraphMessage::PointerMove { shift }.into()];
self.auto_panning.setup_by_mouse_position(ipp, &messages, responses);
}

let viewport_location = ipp.mouse.position;
let point = network_metadata
Expand Down Expand Up @@ -1181,6 +1201,8 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
}
}
NodeGraphMessage::PointerUp => {
self.last_mouse_viewport_for_space = None;

if selection_network_path != breadcrumb_network_path {
log::error!("Selection network path does not match breadcrumb network path in PointerUp");
return;
Expand Down Expand Up @@ -1436,7 +1458,9 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
}
NodeGraphMessage::PointerOutsideViewport { shift } => {
if self.drag_start.is_some() || self.box_selection_start.is_some() || (self.wire_in_progress_from_connector.is_some() && self.context_menu.is_none()) {
let _ = self.auto_panning.shift_viewport(ipp, viewport, responses);
if self.last_mouse_viewport_for_space.is_none() {
let _ = self.auto_panning.shift_viewport(ipp, responses);
}
} else {
// Auto-panning
let messages = [NodeGraphMessage::PointerOutsideViewport { shift }.into(), NodeGraphMessage::PointerMove { shift }.into()];
Expand Down Expand Up @@ -2811,6 +2835,7 @@ impl Default for NodeGraphMessageHandler {
end_index: None,
frontend_nodes: Vec::new(),
frontend_wires: HashSet::new(),
last_mouse_viewport_for_space: None,
}
}
}
Expand All @@ -2829,5 +2854,6 @@ impl PartialEq for NodeGraphMessageHandler {
&& self.wire_in_progress_from_connector == other.wire_in_progress_from_connector
&& self.wire_in_progress_to_connector == other.wire_in_progress_to_connector
&& self.context_menu == other.context_menu
&& self.last_mouse_viewport_for_space == other.last_mouse_viewport_for_space
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,35 @@ impl OriginalTransforms {
Some(transform_utils::get_current_transform(&document_node.inputs))
}

pub fn shift(&mut self, delta: DVec2, metadata: &DocumentMetadata) {
match self {
OriginalTransforms::Layer(layer_map) => {
for (&layer, transform) in layer_map {
let to = metadata.downstream_transform_to_viewport(layer);
let layer_delta = to.inverse() * DAffine2::from_translation(delta) * to;
*transform = layer_delta * *transform;
}
}
OriginalTransforms::Path(path_map) => {
for (&layer, points) in path_map {
let to = metadata.transform_to_viewport(layer);
let layer_delta = to.inverse() * DAffine2::from_translation(delta) * to;
for anchor in points.anchors.values_mut() {
anchor.initial = layer_delta.transform_point2(anchor.initial);
anchor.current = layer_delta.transform_point2(anchor.current);
}
for handle in points.handles.values_mut() {
handle.initial = layer_delta.transform_point2(handle.initial);
handle.relative = layer_delta.transform_point2(handle.relative);
if let Some((_, pos)) = &mut handle.mirror {
*pos = layer_delta.transform_point2(*pos);
}
}
}
}
}
}

pub fn update<'a>(&mut self, selected: &'a [LayerNodeIdentifier], network_interface: &NodeNetworkInterface, shape_editor: Option<&'a ShapeState>) {
match self {
OriginalTransforms::Layer(layer_map) => {
Expand Down
30 changes: 27 additions & 3 deletions editor/src/messages/tool/common_functionality/resize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ pub struct Resize {
pub drag_start: DVec2,
pub layer: Option<LayerNodeIdentifier>,
pub snap_manager: SnapManager,
/// Last mouse position in viewport while Space is held, for offsetting during drag
pub last_mouse_viewport_for_space: Option<DVec2>,
/// Snapshot of the drag start position when Space was first pressed
pub base_drag_start: DVec2,
}

impl Resize {
Expand All @@ -20,6 +24,8 @@ impl Resize {
let point = SnapCandidatePoint::handle(root_transform.inverse().transform_point2(input.mouse.position));
let snapped = self.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
self.drag_start = snapped.snapped_point_document;
self.base_drag_start = self.drag_start;
self.last_mouse_viewport_for_space = None;
}

/// Calculate the drag start position in viewport space.
Expand Down Expand Up @@ -110,9 +116,26 @@ impl Resize {
) -> [DVec2; 2] {
let start = self.viewport_drag_start(document);
let mouse = input.mouse.position;
let document_to_viewport = document
.navigation_handler
.calculate_offset_transform(viewport.center_in_viewport_space().into(), &document.document_ptz);
let document_to_viewport = document.navigation_handler.calculate_offset_transform(input.viewport_bounds.center(), &document.document_ptz);

let space_down = input.keyboard.get(Key::Space as usize);
if space_down {
if self.last_mouse_viewport_for_space.is_none() {
self.last_mouse_viewport_for_space = Some(mouse);
self.base_drag_start = self.drag_start;
}
let total_offset_viewport = mouse - self.last_mouse_viewport_for_space.unwrap();
let total_offset_document = document_to_viewport.inverse().transform_vector2(total_offset_viewport);
self.drag_start = self.base_drag_start + total_offset_document;
} else {
if let Some(initial_mouse) = self.last_mouse_viewport_for_space {
let total_offset_viewport = mouse - initial_mouse;
let total_offset_document = document_to_viewport.inverse().transform_vector2(total_offset_viewport);
self.drag_start = self.base_drag_start + total_offset_document;
}
self.last_mouse_viewport_for_space = None;
}

let drag_start = self.drag_start;
let mut points_viewport = [start, mouse];

Expand Down Expand Up @@ -179,5 +202,6 @@ impl Resize {
pub fn cleanup(&mut self, responses: &mut VecDeque<Message>) {
self.snap_manager.cleanup(responses);
self.layer = None;
self.last_mouse_viewport_for_space = None;
}
}
17 changes: 17 additions & 0 deletions editor/src/messages/tool/common_functionality/shapes/line_shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,23 @@ impl Line {

shape_tool_data.line_data.drag_current = ipp.mouse.position;

let current_mouse = ipp.mouse.position;
let space_down = ipp.keyboard.key(Key::Space);

if space_down {
if let Some(previous_mouse) = shape_tool_data.data.last_mouse_viewport_for_space {
let delta_viewport = current_mouse - previous_mouse;
if delta_viewport.length_squared() > 0. {
let document_to_viewport = document.metadata().document_to_viewport;
let delta_document = document_to_viewport.inverse().transform_vector2(delta_viewport);
shape_tool_data.data.drag_start += delta_document;
}
}
shape_tool_data.data.last_mouse_viewport_for_space = Some(current_mouse);
} else {
shape_tool_data.data.last_mouse_viewport_for_space = None;
}

let keyboard = &ipp.keyboard;
let ignore = [layer];
let snap_data = SnapData::ignore(document, ipp, viewport, &ignore);
Expand Down
64 changes: 61 additions & 3 deletions editor/src/messages/tool/tool_messages/artboard_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ struct ArtboardToolData {
snap_candidates: Vec<SnapCandidatePoint>,
dragging_current_artboard_location: glam::IVec2,
draw: Resize,
last_mouse_viewport_for_space: Option<DVec2>,
}

impl ArtboardToolData {
Expand Down Expand Up @@ -294,6 +295,7 @@ impl Fsm for ArtboardToolFsmState {
self
}
(ArtboardToolFsmState::Ready { .. }, ArtboardToolMessage::PointerDown) => {
tool_data.last_mouse_viewport_for_space = None;
let to_viewport = document.metadata().document_to_viewport;
let to_document = to_viewport.inverse();
tool_data.drag_start = to_document.transform_point2(input.mouse.position);
Expand All @@ -315,6 +317,32 @@ impl Fsm for ArtboardToolFsmState {
state
}
(ArtboardToolFsmState::ResizingBounds, ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }) => {
let current_mouse = input.mouse.position;
let space_down = input.keyboard.get(Key::Space as usize);
if space_down {
if let Some(previous_mouse) = tool_data.last_mouse_viewport_for_space {
let delta_viewport = current_mouse - previous_mouse;
if delta_viewport.length_squared() > 0. {
let document_to_viewport = document.metadata().document_to_viewport;
let delta_document = document_to_viewport.inverse().transform_vector2(delta_viewport);

if let Some(bounds) = &mut tool_data.bounding_box_manager {
bounds.center_of_transformation += delta_viewport;
if let Some(movement) = &mut bounds.selected_edges {
movement.bounds[0] += delta_document;
movement.bounds[1] += delta_document;
}
tool_data.drag_start += delta_document;
}
}
}
tool_data.last_mouse_viewport_for_space = Some(current_mouse);
} else {
tool_data.last_mouse_viewport_for_space = None;
}

responses.add(OverlaysMessage::Draw);

let from_center = input.keyboard.get(center as usize);
let constrain_square = input.keyboard.get(constrain_axis_or_aspect as usize);
tool_data.resize_artboard(responses, document, input, viewport, from_center, constrain_square);
Expand All @@ -329,6 +357,22 @@ impl Fsm for ArtboardToolFsmState {
ArtboardToolFsmState::ResizingBounds
}
(ArtboardToolFsmState::Dragging, ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }) => {
let current_mouse = input.mouse.position;
if input.keyboard.get(Key::Space as usize) {
if let Some(previous_mouse) = tool_data.last_mouse_viewport_for_space {
let delta_viewport = current_mouse - previous_mouse;
if delta_viewport.length_squared() > 0. {
let document_to_viewport = document.metadata().document_to_viewport;
let delta_document = document_to_viewport.inverse().transform_vector2(delta_viewport);
tool_data.drag_start += delta_document;
tool_data.drag_current += delta_document;
}
}
tool_data.last_mouse_viewport_for_space = Some(current_mouse);
} else {
tool_data.last_mouse_viewport_for_space = None;
}

if let Some(bounds) = &mut tool_data.bounding_box_manager {
let axis_align = input.keyboard.get(constrain_axis_or_aspect as usize);

Expand Down Expand Up @@ -368,9 +412,23 @@ impl Fsm for ArtboardToolFsmState {
ArtboardToolFsmState::Dragging
}
(ArtboardToolFsmState::Drawing, ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }) => {
// The draw.calculate_points_ignore_layer uses this value to avoid snapping to itself.
tool_data.draw.layer = tool_data.selected_artboard;
let [start, end] = tool_data.draw.calculate_points_ignore_layer(document, input, viewport, center, constrain_axis_or_aspect, true);
let current_mouse = input.mouse.position;
let space_down = input.keyboard.get(Key::Space as usize);
if space_down {
if let Some(previous_mouse) = tool_data.last_mouse_viewport_for_space {
let delta_viewport = current_mouse - previous_mouse;
if delta_viewport.length_squared() > 0. {
let document_to_viewport = document.metadata().document_to_viewport;
let delta_document = document_to_viewport.inverse().transform_vector2(delta_viewport);
tool_data.drag_start += delta_document;
}
}
tool_data.last_mouse_viewport_for_space = Some(current_mouse);
} else {
tool_data.last_mouse_viewport_for_space = None;
}

let [start, end] = tool_data.draw.calculate_points_ignore_layer(document, input, center, constrain_axis_or_aspect, true);
let viewport_to_document = document.metadata().document_to_viewport.inverse();
let [start, end] = [start, end].map(|point| viewport_to_document.transform_point2(point));
if let Some(artboard) = tool_data.selected_artboard {
Expand Down
38 changes: 33 additions & 5 deletions editor/src/messages/tool/tool_messages/freehand_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ struct FreehandToolData {
dragged: bool,
weight: f64,
layer: Option<LayerNodeIdentifier>,
last_mouse_for_space: Option<DVec2>,
points: Vec<(PointId, DVec2)>,
}

impl Fsm for FreehandToolFsmState {
Expand Down Expand Up @@ -253,6 +255,7 @@ impl Fsm for FreehandToolFsmState {
tool_data.dragged = false;
tool_data.end_point = None;
tool_data.weight = tool_options.line_weight;
tool_data.points.clear();

// Extend an endpoint of the selected path
let selected_nodes = document.network_interface.selected_nodes();
Expand Down Expand Up @@ -297,13 +300,37 @@ impl Fsm for FreehandToolFsmState {
FreehandToolFsmState::Drawing
}
(FreehandToolFsmState::Drawing, FreehandToolMessage::PointerMove) => {
if let Some(layer) = tool_data.layer {
let transform = document.metadata().transform_to_viewport(layer);
let position = transform.inverse().transform_point2(input.mouse.position);
let space_down = input.keyboard.get(Key::Space as usize);
if space_down {
if let Some(previous_mouse) = tool_data.last_mouse_for_space {
let delta_viewport = input.mouse.position - previous_mouse;
if delta_viewport.length_squared() > 0. {
let document_to_viewport = document.metadata().document_to_viewport;
let delta_document = document_to_viewport.inverse().transform_vector2(delta_viewport);

if let Some(layer) = tool_data.layer {
if let Some((pos, _)) = &mut tool_data.end_point {
*pos += delta_document;
}
for (id, point) in &mut tool_data.points {
*point += delta_document;
let modification_type = VectorModificationType::ApplyPointDelta { point: *id, delta: delta_document };
responses.add(GraphOperationMessage::Vector { layer, modification_type });
}
}
}
}
tool_data.last_mouse_for_space = Some(input.mouse.position);
} else {
tool_data.last_mouse_for_space = None;

extend_path_with_next_segment(tool_data, position, true, responses);
}
if let Some(layer) = tool_data.layer {
let transform = document.metadata().transform_to_viewport(layer);
let position = transform.inverse().transform_point2(input.mouse.position);

extend_path_with_next_segment(tool_data, position, true, responses);
}
}
FreehandToolFsmState::Drawing
}
(FreehandToolFsmState::Drawing, FreehandToolMessage::DragStop) => {
Expand Down Expand Up @@ -382,6 +409,7 @@ fn extend_path_with_next_segment(tool_data: &mut FreehandToolData, position: DVe

tool_data.dragged = true;
tool_data.end_point = Some((position, id));
tool_data.points.push((id, position));
}

#[cfg(test)]
Expand Down
Loading