mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-03 13:38:11 +08:00
Split out viewport handling into its own message handler (#3331)
* extract viewport handeling * fix web overlays * some cleanup * remove some physical conversions * fix resize snapping * fixup * apply some review feedback * make viewport api more ergonomic * fix * fix web overlay canvas clear size * clear workaround for canvas * rename trigger message --------- Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
@@ -145,12 +145,12 @@ impl ArtboardToolData {
|
||||
}
|
||||
}
|
||||
|
||||
fn hovered_artboard(document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) -> Option<LayerNodeIdentifier> {
|
||||
document.click_xray(input).find(|&layer| document.network_interface.is_artboard(&layer.to_node(), &[]))
|
||||
fn hovered_artboard(document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, viewport: &ViewportMessageHandler) -> Option<LayerNodeIdentifier> {
|
||||
document.click_xray(input, viewport).find(|&layer| document.network_interface.is_artboard(&layer.to_node(), &[]))
|
||||
}
|
||||
|
||||
fn select_artboard(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) -> bool {
|
||||
if let Some(intersection) = Self::hovered_artboard(document, input) {
|
||||
fn select_artboard(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, viewport: &ViewportMessageHandler, responses: &mut VecDeque<Message>) -> bool {
|
||||
if let Some(intersection) = Self::hovered_artboard(document, input, viewport) {
|
||||
self.selected_artboard = Some(intersection);
|
||||
|
||||
if let Some(bounds) = document.metadata().bounding_box_document(intersection) {
|
||||
@@ -171,7 +171,15 @@ impl ArtboardToolData {
|
||||
}
|
||||
}
|
||||
|
||||
fn resize_artboard(&mut self, responses: &mut VecDeque<Message>, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, from_center: bool, constrain_square: bool) {
|
||||
fn resize_artboard(
|
||||
&mut self,
|
||||
responses: &mut VecDeque<Message>,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
from_center: bool,
|
||||
constrain_square: bool,
|
||||
) {
|
||||
let Some(bounds) = &self.bounding_box_manager else {
|
||||
return;
|
||||
};
|
||||
@@ -193,7 +201,7 @@ impl ArtboardToolData {
|
||||
let snap = Some(SizeSnapData {
|
||||
manager: &mut self.draw.snap_manager,
|
||||
points: &mut self.snap_candidates,
|
||||
snap_data: SnapData::ignore(document, input, &ignore),
|
||||
snap_data: SnapData::ignore(document, input, viewport, &ignore),
|
||||
});
|
||||
let (min, size) = movement.new_size(input.mouse.position, bounds.transform, center, constrain_square, snap);
|
||||
let max = min + size;
|
||||
@@ -225,9 +233,9 @@ impl Fsm for ArtboardToolFsmState {
|
||||
type ToolOptions = ();
|
||||
|
||||
fn transition(self, event: ToolMessage, tool_data: &mut Self::ToolData, tool_action_data: &mut ToolActionMessageContext, _tool_options: &(), responses: &mut VecDeque<Message>) -> Self {
|
||||
let ToolActionMessageContext { document, input, .. } = tool_action_data;
|
||||
let ToolActionMessageContext { document, input, viewport, .. } = tool_action_data;
|
||||
|
||||
let hovered = ArtboardToolData::hovered_artboard(document, input).is_some();
|
||||
let hovered = ArtboardToolData::hovered_artboard(document, input, viewport).is_some();
|
||||
|
||||
let ToolMessage::Artboard(event) = event else { return self };
|
||||
match (self, event) {
|
||||
@@ -259,8 +267,8 @@ impl Fsm for ArtboardToolFsmState {
|
||||
let selected_artboard_bounds = tool_data.selected_artboard.and_then(|layer| document.metadata().bounding_box_document(layer)).map(Rect::from_box);
|
||||
|
||||
// Find hovered artboard or regular layer
|
||||
let hovered_artboard = ArtboardToolData::hovered_artboard(document, input);
|
||||
let hovered_layer = document.click_xray(input).find(|&layer| !document.network_interface.is_artboard(&layer.to_node(), &[]));
|
||||
let hovered_artboard = ArtboardToolData::hovered_artboard(document, input, viewport);
|
||||
let hovered_layer = document.click_xray(input, viewport).find(|&layer| !document.network_interface.is_artboard(&layer.to_node(), &[]));
|
||||
|
||||
// Get bounds for the hovered object (prioritize artboards)
|
||||
let hovered_bounds = if let Some(artboard) = hovered_artboard {
|
||||
@@ -281,7 +289,7 @@ impl Fsm for ArtboardToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
tool_data.draw.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context);
|
||||
tool_data.draw.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
||||
|
||||
self
|
||||
}
|
||||
@@ -295,11 +303,11 @@ impl Fsm for ArtboardToolFsmState {
|
||||
tool_data.start_resizing(selected_edges, document, input);
|
||||
tool_data.get_snap_candidates(document, input);
|
||||
ArtboardToolFsmState::ResizingBounds
|
||||
} else if tool_data.select_artboard(document, input, responses) {
|
||||
} else if tool_data.select_artboard(document, input, viewport, responses) {
|
||||
tool_data.get_snap_candidates(document, input);
|
||||
ArtboardToolFsmState::Dragging
|
||||
} else {
|
||||
tool_data.draw.start(document, input);
|
||||
tool_data.draw.start(document, input, viewport);
|
||||
|
||||
ArtboardToolFsmState::Drawing
|
||||
};
|
||||
@@ -309,14 +317,14 @@ impl Fsm for ArtboardToolFsmState {
|
||||
(ArtboardToolFsmState::ResizingBounds, ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }) => {
|
||||
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, from_center, constrain_square);
|
||||
tool_data.resize_artboard(responses, document, input, viewport, from_center, constrain_square);
|
||||
|
||||
// Auto-panning
|
||||
let messages = [
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
ArtboardToolFsmState::ResizingBounds
|
||||
}
|
||||
@@ -325,7 +333,7 @@ impl Fsm for ArtboardToolFsmState {
|
||||
let axis_align = input.keyboard.get(constrain_axis_or_aspect as usize);
|
||||
|
||||
let ignore = tool_data.selected_artboard.map_or(Vec::new(), |layer| vec![layer]);
|
||||
let snap_data = SnapData::ignore(document, input, &ignore);
|
||||
let snap_data = SnapData::ignore(document, input, viewport, &ignore);
|
||||
let document_to_viewport = document.metadata().document_to_viewport;
|
||||
let [start, current] = [tool_data.drag_start, tool_data.drag_current].map(|point| document_to_viewport.transform_point2(point));
|
||||
let mouse_delta = snap_drag(start, current, axis_align, Axis::None, snap_data, &mut tool_data.draw.snap_manager, &tool_data.snap_candidates);
|
||||
@@ -355,14 +363,14 @@ impl Fsm for ArtboardToolFsmState {
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
}
|
||||
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, center, constrain_axis_or_aspect, true);
|
||||
let [start, end] = tool_data.draw.calculate_points_ignore_layer(document, input, viewport, 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 {
|
||||
@@ -396,7 +404,7 @@ impl Fsm for ArtboardToolFsmState {
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
ArtboardToolFsmState::Drawing
|
||||
}
|
||||
@@ -408,7 +416,7 @@ impl Fsm for ArtboardToolFsmState {
|
||||
.map_or(MouseCursorIcon::Default, |bounds| bounds.get_cursor(input, false, false, None));
|
||||
|
||||
if cursor == MouseCursorIcon::Default && !hovered {
|
||||
tool_data.draw.snap_manager.preview_draw(&SnapData::new(document, input), input.mouse.position);
|
||||
tool_data.draw.snap_manager.preview_draw(&SnapData::new(document, input, viewport), input.mouse.position);
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
cursor = MouseCursorIcon::Crosshair;
|
||||
} else {
|
||||
@@ -424,19 +432,19 @@ impl Fsm for ArtboardToolFsmState {
|
||||
}
|
||||
(ArtboardToolFsmState::ResizingBounds, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, viewport, responses);
|
||||
|
||||
ArtboardToolFsmState::ResizingBounds
|
||||
}
|
||||
(ArtboardToolFsmState::Dragging, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
tool_data.auto_panning.shift_viewport(input, responses);
|
||||
tool_data.auto_panning.shift_viewport(input, viewport, responses);
|
||||
|
||||
ArtboardToolFsmState::Dragging
|
||||
}
|
||||
(ArtboardToolFsmState::Drawing, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
tool_data.auto_panning.shift_viewport(input, responses);
|
||||
tool_data.auto_panning.shift_viewport(input, viewport, responses);
|
||||
|
||||
ArtboardToolFsmState::Drawing
|
||||
}
|
||||
@@ -545,7 +553,9 @@ impl Fsm for ArtboardToolFsmState {
|
||||
let scale = DAffine2::from_scale(enlargement_factor);
|
||||
let pivot = DAffine2::from_translation(pivot);
|
||||
let transformation = pivot * scale * pivot.inverse();
|
||||
let document_to_viewport = document.navigation_handler.calculate_offset_transform(input.viewport_bounds.center(), &document.document_ptz);
|
||||
let document_to_viewport = document
|
||||
.navigation_handler
|
||||
.calculate_offset_transform(viewport.center_in_viewport_space().into(), &document.document_ptz);
|
||||
let to = document_to_viewport.inverse() * document.metadata().downstream_transform_to_viewport(selected_artboard);
|
||||
let original_transform = document.metadata().upstream_transform(selected_artboard.to_node());
|
||||
let new = to.inverse() * transformation * to * original_transform;
|
||||
|
||||
@@ -81,7 +81,9 @@ impl Fsm for EyedropperToolFsmState {
|
||||
type ToolOptions = ();
|
||||
|
||||
fn transition(self, event: ToolMessage, _tool_data: &mut Self::ToolData, tool_action_data: &mut ToolActionMessageContext, _tool_options: &(), responses: &mut VecDeque<Message>) -> Self {
|
||||
let ToolActionMessageContext { global_tool_data, input, .. } = tool_action_data;
|
||||
let ToolActionMessageContext {
|
||||
global_tool_data, input, viewport, ..
|
||||
} = tool_action_data;
|
||||
|
||||
let ToolMessage::Eyedropper(event) = event else { return self };
|
||||
match (self, event) {
|
||||
@@ -97,7 +99,8 @@ impl Fsm for EyedropperToolFsmState {
|
||||
}
|
||||
// Sampling -> Sampling
|
||||
(EyedropperToolFsmState::SamplingPrimary | EyedropperToolFsmState::SamplingSecondary, EyedropperToolMessage::PointerMove) => {
|
||||
if input.viewport_bounds.in_bounds(input.mouse.position) {
|
||||
let mouse_position = viewport.logical(input.mouse.position);
|
||||
if viewport.is_in_bounds(mouse_position) {
|
||||
update_cursor_preview(responses, input, global_tool_data, None);
|
||||
} else {
|
||||
disable_cursor_preview(responses);
|
||||
|
||||
@@ -94,7 +94,11 @@ impl Fsm for FillToolFsmState {
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
let ToolActionMessageContext {
|
||||
document, global_tool_data, input, ..
|
||||
document,
|
||||
global_tool_data,
|
||||
input,
|
||||
viewport,
|
||||
..
|
||||
} = handler_data;
|
||||
|
||||
let ToolMessage::Fill(event) = event else { return self };
|
||||
@@ -105,7 +109,7 @@ impl Fsm for FillToolFsmState {
|
||||
let preview_color = if use_secondary { global_tool_data.secondary_color } else { global_tool_data.primary_color };
|
||||
|
||||
// Get the layer the user is hovering over
|
||||
if let Some(layer) = document.click(input) {
|
||||
if let Some(layer) = document.click(input, viewport) {
|
||||
overlay_context.fill_path_pattern(document.metadata().layer_outline(layer), document.metadata().transform_to_viewport(layer), &preview_color);
|
||||
}
|
||||
|
||||
@@ -117,7 +121,7 @@ impl Fsm for FillToolFsmState {
|
||||
self
|
||||
}
|
||||
(FillToolFsmState::Ready, color_event) => {
|
||||
let Some(layer_identifier) = document.click(input) else {
|
||||
let Some(layer_identifier) = document.click(input, viewport) else {
|
||||
return self;
|
||||
};
|
||||
// If the layer is a raster layer, don't fill it, wait till the flood fill tool is implemented
|
||||
|
||||
@@ -237,6 +237,7 @@ impl Fsm for FreehandToolFsmState {
|
||||
input,
|
||||
shape_editor,
|
||||
preferences,
|
||||
viewport,
|
||||
..
|
||||
} = tool_action_data;
|
||||
|
||||
@@ -283,7 +284,7 @@ impl Fsm for FreehandToolFsmState {
|
||||
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
|
||||
let parent = document.new_layer_bounding_artboard(input);
|
||||
let parent = document.new_layer_bounding_artboard(input, viewport);
|
||||
|
||||
let node_type = resolve_document_node_type("Path").expect("Path node does not exist");
|
||||
let node = node_type.default_node_template();
|
||||
|
||||
@@ -255,7 +255,11 @@ impl Fsm for GradientToolFsmState {
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
let ToolActionMessageContext {
|
||||
document, global_tool_data, input, ..
|
||||
document,
|
||||
global_tool_data,
|
||||
input,
|
||||
viewport,
|
||||
..
|
||||
} = tool_action_data;
|
||||
|
||||
let ToolMessage::Gradient(event) = event else { return self };
|
||||
@@ -420,7 +424,7 @@ impl Fsm for GradientToolFsmState {
|
||||
let gradient_state = if dragging {
|
||||
GradientToolFsmState::Drawing
|
||||
} else {
|
||||
let selected_layer = document.click(input);
|
||||
let selected_layer = document.click(input, viewport);
|
||||
|
||||
// Apply the gradient to the selected layer
|
||||
if let Some(layer) = selected_layer {
|
||||
@@ -464,13 +468,13 @@ impl Fsm for GradientToolFsmState {
|
||||
GradientToolMessage::PointerOutsideViewport { constrain_axis }.into(),
|
||||
GradientToolMessage::PointerMove { constrain_axis }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
GradientToolFsmState::Drawing
|
||||
}
|
||||
(GradientToolFsmState::Drawing, GradientToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
|
||||
if let Some(selected_gradient) = &mut tool_data.selected_gradient {
|
||||
selected_gradient.transform.translation += shift;
|
||||
}
|
||||
@@ -494,7 +498,7 @@ impl Fsm for GradientToolFsmState {
|
||||
let was_dragging = tool_data.selected_gradient.is_some();
|
||||
|
||||
if !was_dragging {
|
||||
if let Some(selected_layer) = document.click(input) {
|
||||
if let Some(selected_layer) = document.click(input, viewport) {
|
||||
if let Some(gradient) = get_gradient(selected_layer, &document.network_interface) {
|
||||
tool_data.selected_gradient = Some(SelectedGradient::new(gradient, selected_layer, document));
|
||||
}
|
||||
|
||||
@@ -701,6 +701,7 @@ impl PathToolData {
|
||||
shape_editor: &mut ShapeState,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
extend_selection: bool,
|
||||
lasso_select: bool,
|
||||
@@ -871,7 +872,7 @@ impl PathToolData {
|
||||
}
|
||||
}
|
||||
// If no other layers are selected and this is a single-click, then also select the layer (exception)
|
||||
else if let Some(layer) = document.click(input) {
|
||||
else if let Some(layer) = document.click(input, viewport) {
|
||||
if shape_editor.selected_shape_state.is_empty() {
|
||||
self.first_selected_with_single_click = true;
|
||||
// This ensures we don't need to double click a second time to get the drill through to work
|
||||
@@ -1109,8 +1110,9 @@ impl PathToolData {
|
||||
handle_position: DVec2,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
) -> DVec2 {
|
||||
let snap_data = SnapData::new(document, input);
|
||||
let snap_data = SnapData::new(document, input, viewport);
|
||||
let snap_point = SnapCandidatePoint::handle_neighbors(new_handle_position, [anchor_position]);
|
||||
|
||||
let snap_result = match using_angle_constraints {
|
||||
@@ -1380,6 +1382,7 @@ impl PathToolData {
|
||||
shape_editor: &mut ShapeState,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) {
|
||||
// First check if selection is not just a single handle point
|
||||
@@ -1430,9 +1433,10 @@ impl PathToolData {
|
||||
handle_position,
|
||||
document,
|
||||
input,
|
||||
viewport,
|
||||
)
|
||||
} else {
|
||||
shape_editor.snap(&mut self.snap_manager, &self.snap_cache, document, input, previous_mouse)
|
||||
shape_editor.snap(&mut self.snap_manager, &self.snap_cache, document, input, viewport, previous_mouse)
|
||||
};
|
||||
|
||||
let handle_lengths = if equidistant { None } else { self.opposing_handle_lengths.take() };
|
||||
@@ -1538,7 +1542,13 @@ impl Fsm for PathToolFsmState {
|
||||
tool_options: &Self::ToolOptions,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
let ToolActionMessageContext { document, input, shape_editor, .. } = tool_action_data;
|
||||
let ToolActionMessageContext {
|
||||
document,
|
||||
input,
|
||||
viewport,
|
||||
shape_editor,
|
||||
..
|
||||
} = tool_action_data;
|
||||
|
||||
update_dynamic_hints(self, responses, shape_editor, document, tool_data, tool_options, input.mouse.position);
|
||||
|
||||
@@ -1939,13 +1949,13 @@ impl Fsm for PathToolFsmState {
|
||||
}
|
||||
}
|
||||
Self::Dragging(_) => {
|
||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context);
|
||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
||||
|
||||
// Draw the snapping axis lines
|
||||
if tool_data.snapping_axis.is_some() {
|
||||
let Some(axis) = tool_data.snapping_axis else { return self };
|
||||
let origin = tool_data.drag_start_pos;
|
||||
let viewport_diagonal = input.viewport_bounds.size().length();
|
||||
let viewport_diagonal = viewport.size().into_dvec2().length();
|
||||
|
||||
let faded = |color: &str| {
|
||||
let mut color = graphene_std::Color::from_rgb_str(color.strip_prefix('#').unwrap()).unwrap().with_alpha(0.25).to_rgba_hex_srgb();
|
||||
@@ -1996,6 +2006,7 @@ impl Fsm for PathToolFsmState {
|
||||
shape_editor,
|
||||
document,
|
||||
input,
|
||||
viewport,
|
||||
responses,
|
||||
extend_selection,
|
||||
lasso_select,
|
||||
@@ -2056,7 +2067,7 @@ impl Fsm for PathToolFsmState {
|
||||
}
|
||||
.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
PathToolFsmState::Drawing { selection_shape }
|
||||
}
|
||||
@@ -2144,6 +2155,7 @@ impl Fsm for PathToolFsmState {
|
||||
tool_action_data.shape_editor,
|
||||
tool_action_data.document,
|
||||
input,
|
||||
viewport,
|
||||
responses,
|
||||
);
|
||||
}
|
||||
@@ -2173,7 +2185,7 @@ impl Fsm for PathToolFsmState {
|
||||
}
|
||||
.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
PathToolFsmState::Dragging(tool_data.dragging_state)
|
||||
}
|
||||
@@ -2203,7 +2215,7 @@ impl Fsm for PathToolFsmState {
|
||||
|
||||
// When moving the cursor around we want to update the hovered layers
|
||||
let new_hovered_layers: Vec<LayerNodeIdentifier> = document
|
||||
.click_list_no_parents(input)
|
||||
.click_list_no_parents(input, viewport)
|
||||
.filter(|&layer| {
|
||||
// Filter out artboards and parent holders, and already selected layers
|
||||
!document.network_interface.is_artboard(&layer.to_node(), &[])
|
||||
@@ -2220,7 +2232,7 @@ impl Fsm for PathToolFsmState {
|
||||
}
|
||||
(PathToolFsmState::Drawing { selection_shape: selection_type }, PathToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
if let Some(offset) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
if let Some(offset) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
|
||||
tool_data.drag_start_pos += offset;
|
||||
}
|
||||
|
||||
@@ -2228,7 +2240,7 @@ impl Fsm for PathToolFsmState {
|
||||
}
|
||||
(PathToolFsmState::Dragging(dragging_state), PathToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
if let Some(offset) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
if let Some(offset) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
|
||||
tool_data.drag_start_pos += offset;
|
||||
}
|
||||
|
||||
@@ -2388,7 +2400,7 @@ impl Fsm for PathToolFsmState {
|
||||
|
||||
if tool_data.drag_start_pos.distance(previous_mouse) < 1e-8 {
|
||||
// Clicked inside or outside the shape then deselect all of the points/segments
|
||||
if document.click(input).is_some() && tool_data.stored_selection.is_none() {
|
||||
if document.click(input, viewport).is_some() && tool_data.stored_selection.is_none() {
|
||||
tool_data.stored_selection = Some(shape_editor.selected_shape_state.clone());
|
||||
}
|
||||
|
||||
@@ -2941,7 +2953,7 @@ impl Fsm for PathToolFsmState {
|
||||
let nearest_point = shape_editor.find_nearest_point_indices(&document.network_interface, input.mouse.position, SELECTION_THRESHOLD);
|
||||
|
||||
let mut get_drill_through_layer = || -> Option<LayerNodeIdentifier> {
|
||||
let drill_through_layers = document.click_list_no_parents(input).collect::<Vec<LayerNodeIdentifier>>();
|
||||
let drill_through_layers = document.click_list_no_parents(input, viewport).collect::<Vec<LayerNodeIdentifier>>();
|
||||
if drill_through_layers.is_empty() {
|
||||
tool_data.reset_drill_through_cycle();
|
||||
None
|
||||
|
||||
@@ -612,7 +612,7 @@ impl PenToolData {
|
||||
self.handle_end = None;
|
||||
self.handle_mode = HandleMode::Free;
|
||||
|
||||
self.store_clicked_endpoint(document, &transform, snap_data.input, preferences);
|
||||
self.store_clicked_endpoint(document, &transform, snap_data.input, snap_data.viewport, preferences);
|
||||
|
||||
if self.modifiers.lock_angle {
|
||||
self.set_lock_angle(&vector, id, self.prior_segment);
|
||||
@@ -668,7 +668,7 @@ impl PenToolData {
|
||||
self.handle_end_offset = None;
|
||||
self.path_closed = true;
|
||||
self.next_handle_start = self.next_point;
|
||||
self.store_clicked_endpoint(document, transform, snap_data.input, preferences);
|
||||
self.store_clicked_endpoint(document, transform, snap_data.input, snap_data.viewport, preferences);
|
||||
self.handle_mode = HandleMode::Free;
|
||||
if let (true, Some(prior_endpoint)) = (self.modifiers.lock_angle, self.prior_segment_endpoint) {
|
||||
self.set_lock_angle(vector, prior_endpoint, self.prior_segment);
|
||||
@@ -802,13 +802,14 @@ impl PenToolData {
|
||||
mouse: &DVec2,
|
||||
vector: &Vector,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
) -> Option<DVec2> {
|
||||
let reference_handle = if self.path_closed { TargetHandle::PreviewInHandle } else { TargetHandle::FuturePreviewOutHandle };
|
||||
let end_handle = self.get_opposite_handle_type(reference_handle, vector);
|
||||
let end_handle_pos = self.target_handle_position(end_handle, vector);
|
||||
let ref_pos = self.target_handle_position(reference_handle, vector)?;
|
||||
let snap = &mut self.snap_manager;
|
||||
let snap_data = SnapData::new_snap_cache(snap_data.document, input, &self.snap_cache);
|
||||
let snap_data = SnapData::new_snap_cache(snap_data.document, input, viewport, &self.snap_cache);
|
||||
|
||||
let handle_start_offset = self.handle_start_offset.unwrap_or(DVec2::ZERO);
|
||||
let document_pos = viewport_to_document.transform_point2(*mouse + handle_start_offset);
|
||||
@@ -964,6 +965,7 @@ impl PenToolData {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn drag_handle(
|
||||
&mut self,
|
||||
snap_data: SnapData,
|
||||
@@ -972,6 +974,7 @@ impl PenToolData {
|
||||
responses: &mut VecDeque<Message>,
|
||||
layer: Option<LayerNodeIdentifier>,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
) -> Option<PenToolFsmState> {
|
||||
let colinear = (self.handle_mode == HandleMode::ColinearEquidistant && self.modifiers.break_handle) || (self.handle_mode == HandleMode::ColinearLocked && !self.modifiers.break_handle);
|
||||
let document = snap_data.document;
|
||||
@@ -982,7 +985,7 @@ impl PenToolData {
|
||||
|
||||
// Handles pressing Space to drag anchor and its handles
|
||||
if self.modifiers.move_anchor_with_handles {
|
||||
let Some(delta) = self.space_anchor_handle_snap(&viewport_to_document, &transform, &snap_data, &mouse, &vector, input) else {
|
||||
let Some(delta) = self.space_anchor_handle_snap(&viewport_to_document, &transform, &snap_data, &mouse, &vector, input, viewport) else {
|
||||
return Some(PenToolFsmState::DraggingHandle(self.handle_mode));
|
||||
};
|
||||
|
||||
@@ -1221,6 +1224,7 @@ impl PenToolData {
|
||||
&mut self,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
tool_options: &PenOptions,
|
||||
append: bool,
|
||||
@@ -1228,21 +1232,21 @@ impl PenToolData {
|
||||
shape_editor: &mut ShapeState,
|
||||
) {
|
||||
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||
let snapped = self.snap_manager.free_snap(&SnapData::new(document, input), &point, SnapTypeConfiguration::default());
|
||||
let viewport = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
let snapped = self.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||
let viewport_vec = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
self.handle_type = TargetHandle::FuturePreviewOutHandle;
|
||||
|
||||
let selected_nodes = document.network_interface.selected_nodes();
|
||||
self.handle_end = None;
|
||||
|
||||
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
||||
let extension_choice = should_extend(document, viewport, tolerance, selected_nodes.selected_layers(document.metadata()), preferences);
|
||||
let extension_choice = should_extend(document, viewport_vec, tolerance, selected_nodes.selected_layers(document.metadata()), preferences);
|
||||
if let Some((layer, point, position)) = extension_choice {
|
||||
self.current_layer = Some(layer);
|
||||
self.extend_existing_path(document, layer, point, position);
|
||||
return;
|
||||
} else if preferences.vector_meshes {
|
||||
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport, tolerance) {
|
||||
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport_vec, tolerance) {
|
||||
let (point, segments) = closest_segment.adjusted_insert(responses);
|
||||
let layer = closest_segment.layer();
|
||||
let position = closest_segment.closest_point_document();
|
||||
@@ -1258,7 +1262,7 @@ impl PenToolData {
|
||||
}
|
||||
|
||||
if append {
|
||||
if let Some((layer, point, _)) = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences) {
|
||||
if let Some((layer, point, _)) = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false, preferences) {
|
||||
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
|
||||
let segment = vector.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
|
||||
|
||||
@@ -1271,12 +1275,12 @@ impl PenToolData {
|
||||
let existing_layer = selected_layers_except_artboards.next().filter(|_| selected_layers_except_artboards.next().is_none());
|
||||
if let Some(layer) = existing_layer {
|
||||
// Add point to existing layer
|
||||
responses.add(PenToolMessage::AddPointLayerPosition { layer, viewport });
|
||||
responses.add(PenToolMessage::AddPointLayerPosition { layer, viewport: viewport_vec });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((layer, point, _position)) = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences) {
|
||||
if let Some((layer, point, _position)) = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false, preferences) {
|
||||
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
|
||||
let segment = vector.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
|
||||
self.handle_mode = HandleMode::Free;
|
||||
@@ -1290,7 +1294,7 @@ impl PenToolData {
|
||||
let node_type = resolve_document_node_type("Path").expect("Path node does not exist");
|
||||
let nodes = vec![(NodeId(0), node_type.default_node_template())];
|
||||
|
||||
let parent = document.new_layer_bounding_artboard(input);
|
||||
let parent = document.new_layer_bounding_artboard(input, viewport);
|
||||
let layer = graph_modification_utils::new_custom(NodeId::new(), nodes, parent, responses);
|
||||
self.current_layer = Some(layer);
|
||||
tool_options.fill.apply_fill(layer, responses);
|
||||
@@ -1301,7 +1305,7 @@ impl PenToolData {
|
||||
|
||||
// It is necessary to defer this until the transform of the layer can be accurately computed (quite hacky)
|
||||
responses.add(DeferMessage::AfterGraphRun {
|
||||
messages: vec![PenToolMessage::AddPointLayerPosition { layer, viewport }.into()],
|
||||
messages: vec![PenToolMessage::AddPointLayerPosition { layer, viewport: viewport_vec }.into()],
|
||||
});
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
}
|
||||
@@ -1360,14 +1364,21 @@ impl PenToolData {
|
||||
}
|
||||
|
||||
// Stores the segment and point ID of the clicked endpoint
|
||||
fn store_clicked_endpoint(&mut self, document: &DocumentMessageHandler, transform: &DAffine2, input: &InputPreprocessorMessageHandler, preferences: &PreferencesMessageHandler) {
|
||||
fn store_clicked_endpoint(
|
||||
&mut self,
|
||||
document: &DocumentMessageHandler,
|
||||
transform: &DAffine2,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
preferences: &PreferencesMessageHandler,
|
||||
) {
|
||||
let mut manipulators = HashMap::with_hasher(NoHashBuilder);
|
||||
let mut unselected = Vec::new();
|
||||
let mut layer_manipulators = HashSet::with_hasher(NoHashBuilder);
|
||||
|
||||
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||
|
||||
let snapped = self.snap_manager.free_snap(&SnapData::new(document, input), &point, SnapTypeConfiguration::default());
|
||||
let snapped = self.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||
let viewport = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
|
||||
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
||||
@@ -1456,6 +1467,7 @@ impl Fsm for PenToolFsmState {
|
||||
input,
|
||||
shape_editor,
|
||||
preferences,
|
||||
viewport,
|
||||
..
|
||||
} = tool_action_data;
|
||||
let selected_nodes = document.network_interface.selected_nodes();
|
||||
@@ -1613,19 +1625,19 @@ impl Fsm for PenToolFsmState {
|
||||
// If not check if there is a closest segment within threshold, if yes then draw overlay
|
||||
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
||||
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input), &point, SnapTypeConfiguration::default());
|
||||
let viewport = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||
let viewport_vec = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
|
||||
let close_to_point = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences).is_some();
|
||||
let close_to_point = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false, preferences).is_some();
|
||||
if preferences.vector_meshes && !close_to_point {
|
||||
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport, tolerance) {
|
||||
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport_vec, tolerance) {
|
||||
let pos = closest_segment.closest_point_to_viewport();
|
||||
let perp = closest_segment.calculate_perp(document);
|
||||
overlay_context.manipulator_anchor(pos, true, None);
|
||||
overlay_context.line(pos - perp * SEGMENT_OVERLAY_SIZE, pos + perp * SEGMENT_OVERLAY_SIZE, Some(COLOR_OVERLAY_BLUE), None);
|
||||
}
|
||||
}
|
||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context);
|
||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
||||
self
|
||||
}
|
||||
(_, PenToolMessage::Overlays { context: mut overlay_context }) => {
|
||||
@@ -1743,7 +1755,7 @@ impl Fsm for PenToolFsmState {
|
||||
if self == PenToolFsmState::PlacingAnchor && preferences.vector_meshes {
|
||||
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
||||
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input), &point, SnapTypeConfiguration::default());
|
||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||
let viewport = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
let close_to_point = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences).is_some();
|
||||
if !close_to_point {
|
||||
@@ -1805,7 +1817,7 @@ impl Fsm for PenToolFsmState {
|
||||
}
|
||||
|
||||
// Draw the overlays that visualize current snapping
|
||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context);
|
||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
||||
|
||||
self
|
||||
}
|
||||
@@ -1822,8 +1834,8 @@ impl Fsm for PenToolFsmState {
|
||||
// Get the closest point and the segment it is on
|
||||
let append = input.keyboard.key(append_to_selected);
|
||||
|
||||
tool_data.store_clicked_endpoint(document, &transform, input, preferences);
|
||||
tool_data.create_initial_point(document, input, responses, tool_options, append, preferences, shape_editor);
|
||||
tool_data.store_clicked_endpoint(document, &transform, input, viewport, preferences);
|
||||
tool_data.create_initial_point(document, input, viewport, responses, tool_options, append, preferences, shape_editor);
|
||||
|
||||
// Enter the dragging handle state while the mouse is held down, allowing the user to move the mouse and position the handle
|
||||
PenToolFsmState::DraggingHandle(tool_data.handle_mode)
|
||||
@@ -1839,16 +1851,16 @@ impl Fsm for PenToolFsmState {
|
||||
}
|
||||
(PenToolFsmState::PlacingAnchor, PenToolMessage::DragStart { append_to_selected }) => {
|
||||
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input), &point, SnapTypeConfiguration::default());
|
||||
let viewport = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||
let viewport_vec = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
|
||||
// Early return if the buffer was started and this message is being run again after the buffer (so that place_anchor updates the state with the newly merged vector)
|
||||
if tool_data.buffering_merged_vector {
|
||||
if let Some(layer) = layer {
|
||||
tool_data.buffering_merged_vector = false;
|
||||
tool_data.handle_mode = HandleMode::ColinearLocked;
|
||||
tool_data.bend_from_previous_point(SnapData::new(document, input), transform, layer, preferences, shape_editor, responses);
|
||||
tool_data.place_anchor(SnapData::new(document, input), transform, input.mouse.position, preferences, responses);
|
||||
tool_data.bend_from_previous_point(SnapData::new(document, input, viewport), transform, layer, preferences, shape_editor, responses);
|
||||
tool_data.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, preferences, responses);
|
||||
}
|
||||
tool_data.buffering_merged_vector = false;
|
||||
PenToolFsmState::DraggingHandle(tool_data.handle_mode)
|
||||
@@ -1863,7 +1875,7 @@ impl Fsm for PenToolFsmState {
|
||||
let layers = LayerNodeIdentifier::ROOT_PARENT
|
||||
.descendants(document.metadata())
|
||||
.filter(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]));
|
||||
if let Some((other_layer, _, _)) = should_extend(document, viewport, crate::consts::SNAP_POINT_TOLERANCE, layers, preferences) {
|
||||
if let Some((other_layer, _, _)) = should_extend(document, viewport_vec, crate::consts::SNAP_POINT_TOLERANCE, layers, preferences) {
|
||||
let selected_nodes = document.network_interface.selected_nodes();
|
||||
let mut selected_layers = selected_nodes.selected_layers(document.metadata());
|
||||
if let Some(current_layer) = selected_layers
|
||||
@@ -1893,7 +1905,7 @@ impl Fsm for PenToolFsmState {
|
||||
(PenToolFsmState::DraggingHandle(_), PenToolMessage::DragStop) => {
|
||||
tool_data.cleanup_target_selections(shape_editor, layer, document, responses);
|
||||
tool_data
|
||||
.finish_placing_handle(SnapData::new(document, input), transform, preferences, responses)
|
||||
.finish_placing_handle(SnapData::new(document, input, viewport), transform, preferences, responses)
|
||||
.unwrap_or(PenToolFsmState::PlacingAnchor)
|
||||
}
|
||||
(
|
||||
@@ -1914,7 +1926,7 @@ impl Fsm for PenToolFsmState {
|
||||
move_anchor_with_handles: input.keyboard.key(move_anchor_with_handles),
|
||||
};
|
||||
|
||||
let snap_data = SnapData::new(document, input);
|
||||
let snap_data = SnapData::new(document, input, viewport);
|
||||
if tool_data.modifiers.colinear && !tool_data.toggle_colinear_debounce {
|
||||
tool_data.handle_mode = match tool_data.handle_mode {
|
||||
HandleMode::Free => {
|
||||
@@ -1962,7 +1974,7 @@ impl Fsm for PenToolFsmState {
|
||||
}
|
||||
|
||||
let state = tool_data
|
||||
.drag_handle(snap_data, transform, input.mouse.position, responses, layer, input)
|
||||
.drag_handle(snap_data, transform, input.mouse.position, responses, layer, input, viewport)
|
||||
.unwrap_or(PenToolFsmState::Ready);
|
||||
|
||||
if tool_data.handle_swapped {
|
||||
@@ -1988,7 +2000,7 @@ impl Fsm for PenToolFsmState {
|
||||
}
|
||||
.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
state
|
||||
}
|
||||
@@ -2012,7 +2024,7 @@ impl Fsm for PenToolFsmState {
|
||||
move_anchor_with_handles: input.keyboard.key(move_anchor_with_handles),
|
||||
};
|
||||
let state = tool_data
|
||||
.place_anchor(SnapData::new(document, input), transform, input.mouse.position, preferences, responses)
|
||||
.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, preferences, responses)
|
||||
.unwrap_or(PenToolFsmState::Ready);
|
||||
|
||||
// Auto-panning
|
||||
@@ -2034,7 +2046,7 @@ impl Fsm for PenToolFsmState {
|
||||
}
|
||||
.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
state
|
||||
}
|
||||
@@ -2063,13 +2075,13 @@ impl Fsm for PenToolFsmState {
|
||||
colinear: input.keyboard.key(colinear),
|
||||
move_anchor_with_handles: input.keyboard.key(move_anchor_with_handles),
|
||||
};
|
||||
tool_data.snap_manager.preview_draw(&SnapData::new(document, input), input.mouse.position);
|
||||
tool_data.snap_manager.preview_draw(&SnapData::new(document, input, viewport), input.mouse.position);
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
self
|
||||
}
|
||||
(PenToolFsmState::DraggingHandle(mode), PenToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, viewport, responses);
|
||||
|
||||
PenToolFsmState::DraggingHandle(mode)
|
||||
}
|
||||
@@ -2078,7 +2090,7 @@ impl Fsm for PenToolFsmState {
|
||||
return self;
|
||||
}
|
||||
// Auto-panning
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, viewport, responses);
|
||||
|
||||
PenToolFsmState::PlacingAnchor
|
||||
}
|
||||
@@ -2119,7 +2131,7 @@ impl Fsm for PenToolFsmState {
|
||||
// Confirm to end path
|
||||
if let Some((vector, layer)) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)).zip(layer) {
|
||||
let single_point_in_layer = vector.point_domain.ids().len() == 1;
|
||||
tool_data.finish_placing_handle(SnapData::new(document, input), transform, preferences, responses);
|
||||
tool_data.finish_placing_handle(SnapData::new(document, input, viewport), transform, preferences, responses);
|
||||
let latest_points = tool_data.latest_points.len() == 1;
|
||||
|
||||
if latest_points && single_point_in_layer {
|
||||
@@ -2166,7 +2178,7 @@ impl Fsm for PenToolFsmState {
|
||||
PenToolFsmState::Ready
|
||||
} else {
|
||||
tool_data
|
||||
.place_anchor(SnapData::new(document, input), transform, input.mouse.position, preferences, responses)
|
||||
.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, preferences, responses)
|
||||
.unwrap_or(PenToolFsmState::Ready)
|
||||
}
|
||||
}
|
||||
@@ -2197,7 +2209,7 @@ impl Fsm for PenToolFsmState {
|
||||
if tool_data.point_index > 0 {
|
||||
tool_data.point_index -= 1;
|
||||
tool_data
|
||||
.place_anchor(SnapData::new(document, input), transform, input.mouse.position, preferences, responses)
|
||||
.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, preferences, responses)
|
||||
.unwrap_or(PenToolFsmState::PlacingAnchor)
|
||||
} else {
|
||||
responses.add(PenToolMessage::Abort);
|
||||
@@ -2206,7 +2218,7 @@ impl Fsm for PenToolFsmState {
|
||||
}
|
||||
(_, PenToolMessage::Redo) => {
|
||||
tool_data.point_index = (tool_data.point_index + 1).min(tool_data.latest_points.len().saturating_sub(1));
|
||||
tool_data.place_anchor(SnapData::new(document, input), transform, input.mouse.position, preferences, responses);
|
||||
tool_data.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, preferences, responses);
|
||||
match tool_data.point_index {
|
||||
0 => PenToolFsmState::Ready,
|
||||
_ => PenToolFsmState::PlacingAnchor,
|
||||
|
||||
@@ -419,11 +419,11 @@ struct SelectToolData {
|
||||
}
|
||||
|
||||
impl SelectToolData {
|
||||
fn get_snap_candidates(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) {
|
||||
fn get_snap_candidates(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, viewport: &ViewportMessageHandler) {
|
||||
self.snap_candidates.clear();
|
||||
for &layer in &self.layers_dragging {
|
||||
if (self.snap_candidates.len() as f64) < document.snapping_state.tolerance {
|
||||
snapping::get_layer_snap_points(layer, &SnapData::new(document, input), &mut self.snap_candidates);
|
||||
snapping::get_layer_snap_points(layer, &SnapData::new(document, input, viewport), &mut self.snap_candidates);
|
||||
}
|
||||
if let Some(bounds) = document.metadata().bounding_box_with_transform(layer, DAffine2::IDENTITY) {
|
||||
let quad = document.metadata().transform_to_document(layer) * Quad::from_box(bounds);
|
||||
@@ -463,20 +463,20 @@ impl SelectToolData {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn intersect_lasso_no_artboards(&self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) -> Vec<LayerNodeIdentifier> {
|
||||
pub fn intersect_lasso_no_artboards(&self, document: &DocumentMessageHandler, viewport: &ViewportMessageHandler) -> Vec<LayerNodeIdentifier> {
|
||||
if self.lasso_polygon.len() < 2 {
|
||||
return Vec::new();
|
||||
}
|
||||
let polygon = Subpath::from_anchors_linear(self.lasso_polygon.clone(), true);
|
||||
document.intersect_polygon_no_artboards(polygon, input).collect()
|
||||
document.intersect_polygon_no_artboards(polygon, viewport).collect()
|
||||
}
|
||||
|
||||
pub fn is_layer_inside_lasso_polygon(&self, layer: &LayerNodeIdentifier, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) -> bool {
|
||||
pub fn is_layer_inside_lasso_polygon(&self, layer: &LayerNodeIdentifier, document: &DocumentMessageHandler, viewport: &ViewportMessageHandler) -> bool {
|
||||
if self.lasso_polygon.len() < 2 {
|
||||
return false;
|
||||
}
|
||||
let polygon = Subpath::from_anchors_linear(self.lasso_polygon.clone(), true);
|
||||
document.is_layer_fully_inside_polygon(layer, input, polygon)
|
||||
document.is_layer_fully_inside_polygon(layer, viewport, polygon)
|
||||
}
|
||||
|
||||
/// Duplicates the currently dragging layers. Called when Alt is pressed and the layers have not yet been duplicated.
|
||||
@@ -598,12 +598,18 @@ impl Fsm for SelectToolFsmState {
|
||||
type ToolOptions = ();
|
||||
|
||||
fn transition(self, event: ToolMessage, tool_data: &mut Self::ToolData, tool_action_data: &mut ToolActionMessageContext, _tool_options: &(), responses: &mut VecDeque<Message>) -> Self {
|
||||
let ToolActionMessageContext { document, input, font_cache, .. } = tool_action_data;
|
||||
let ToolActionMessageContext {
|
||||
document,
|
||||
input,
|
||||
viewport,
|
||||
font_cache,
|
||||
..
|
||||
} = tool_action_data;
|
||||
|
||||
let ToolMessage::Select(event) = event else { return self };
|
||||
match (self, event) {
|
||||
(_, SelectToolMessage::Overlays { context: mut overlay_context }) => {
|
||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context);
|
||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
||||
|
||||
let selected_layers_count = document.network_interface.selected_nodes().selected_unlocked_layers(&document.network_interface).count();
|
||||
tool_data.selected_layers_changed = selected_layers_count != tool_data.selected_layers_count;
|
||||
@@ -661,7 +667,7 @@ impl Fsm for SelectToolFsmState {
|
||||
if !matches!(self, Self::Drawing { .. }) && !input.keyboard.get(Key::MouseMiddle as usize) {
|
||||
// Get the layer the user is hovering over
|
||||
// Artboards are included since they're needed for quick measurement, but will be filtered out for selection later on
|
||||
let click = document.click_list_with_artboards(input).last();
|
||||
let click = document.click_list_with_artboards(input, viewport).last();
|
||||
let not_selected_click = click.filter(|&hovered_layer| !document.network_interface.selected_nodes().selected_layers_contains(hovered_layer, document.metadata()));
|
||||
if let Some(layer) = not_selected_click {
|
||||
if overlay_context.visibility_settings.hover_outline() && !document.network_interface.is_artboard(&layer.to_node(), &[]) {
|
||||
@@ -896,7 +902,7 @@ impl Fsm for SelectToolFsmState {
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let viewport_diagonal = input.viewport_bounds.size().length();
|
||||
let viewport_diagonal = viewport.size().into_dvec2().length();
|
||||
|
||||
let color = if !hover {
|
||||
color
|
||||
@@ -918,7 +924,7 @@ impl Fsm for SelectToolFsmState {
|
||||
|
||||
let extension = tool_data.drag_current - tool_data.drag_start;
|
||||
let origin = compass_center - extension;
|
||||
let viewport_diagonal = input.viewport_bounds.size().length();
|
||||
let viewport_diagonal = viewport.size().into_dvec2().length();
|
||||
|
||||
let edge = DVec2::from_angle(snapped_angle).normalize_or(DVec2::X) * viewport_diagonal;
|
||||
let perp = edge.perp();
|
||||
@@ -949,13 +955,13 @@ impl Fsm for SelectToolFsmState {
|
||||
|
||||
// Draw outline visualizations on the layers to be selected
|
||||
let intersected_layers = match selection_shape {
|
||||
SelectionShapeType::Box => document.intersect_quad_no_artboards(quad, input).collect(),
|
||||
SelectionShapeType::Lasso => tool_data.intersect_lasso_no_artboards(document, input),
|
||||
SelectionShapeType::Box => document.intersect_quad_no_artboards(quad, viewport).collect(),
|
||||
SelectionShapeType::Lasso => tool_data.intersect_lasso_no_artboards(document, viewport),
|
||||
};
|
||||
let layers_to_outline = intersected_layers.into_iter().filter(|layer| match current_selection_mode {
|
||||
SelectionMode::Enclosed => match selection_shape {
|
||||
SelectionShapeType::Box => document.is_layer_fully_inside(layer, quad),
|
||||
SelectionShapeType::Lasso => tool_data.is_layer_inside_lasso_polygon(layer, document, input),
|
||||
SelectionShapeType::Lasso => tool_data.is_layer_inside_lasso_polygon(layer, document, viewport),
|
||||
},
|
||||
SelectionMode::Touched => match tool_data.nested_selection_behavior {
|
||||
NestedSelectionBehavior::Deepest => !layer.has_children(document.metadata()),
|
||||
@@ -1008,7 +1014,7 @@ impl Fsm for SelectToolFsmState {
|
||||
self
|
||||
}
|
||||
(_, SelectToolMessage::EditLayerExec) => {
|
||||
if let Some(intersect) = document.click(input) {
|
||||
if let Some(intersect) = document.click(input, viewport) {
|
||||
match tool_data.nested_selection_behavior {
|
||||
NestedSelectionBehavior::Shallowest => edit_layer_shallowest_manipulation(document, intersect, responses),
|
||||
NestedSelectionBehavior::Deepest => edit_layer_deepest_manipulation(intersect, &document.network_interface, responses),
|
||||
@@ -1031,7 +1037,7 @@ impl Fsm for SelectToolFsmState {
|
||||
tool_data.selection_mode = None;
|
||||
|
||||
let mut selected: Vec<_> = document.network_interface.selected_nodes().selected_visible_and_unlocked_layers(&document.network_interface).collect();
|
||||
let intersection_list = document.click_list(input).collect::<Vec<_>>();
|
||||
let intersection_list = document.click_list(input, viewport).collect::<Vec<_>>();
|
||||
let intersection = document.find_deepest(&intersection_list);
|
||||
|
||||
let position = tool_data.pivot_gizmo().position(document);
|
||||
@@ -1064,10 +1070,10 @@ impl Fsm for SelectToolFsmState {
|
||||
}
|
||||
// Dragging one (or two, forming a corner) of the transform cage bounding box edges
|
||||
else if resize {
|
||||
tool_data.get_snap_candidates(document, input);
|
||||
tool_data.get_snap_candidates(document, input, viewport);
|
||||
SelectToolFsmState::ResizingBounds
|
||||
} else if skew {
|
||||
tool_data.get_snap_candidates(document, input);
|
||||
tool_data.get_snap_candidates(document, input, viewport);
|
||||
SelectToolFsmState::SkewingBounds { skew: Key::Control }
|
||||
}
|
||||
// Dragging the selected layers around to transform them
|
||||
@@ -1081,7 +1087,7 @@ impl Fsm for SelectToolFsmState {
|
||||
}
|
||||
|
||||
tool_data.layers_dragging = selected;
|
||||
tool_data.get_snap_candidates(document, input);
|
||||
tool_data.get_snap_candidates(document, input, viewport);
|
||||
let (axis, using_compass) = {
|
||||
let axis_state = compass_rose_state.axis_type().filter(|_| can_grab_compass_rose);
|
||||
(axis_state.unwrap_or_default(), axis_state.is_some())
|
||||
@@ -1124,7 +1130,7 @@ impl Fsm for SelectToolFsmState {
|
||||
NestedSelectionBehavior::Shallowest if !input.keyboard.key(select_deepest) => drag_shallowest_manipulation(responses, selected, tool_data, document, false, extend),
|
||||
_ => drag_deepest_manipulation(responses, selected, tool_data, document, false),
|
||||
}
|
||||
tool_data.get_snap_candidates(document, input);
|
||||
tool_data.get_snap_candidates(document, input, viewport);
|
||||
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
|
||||
@@ -1177,7 +1183,7 @@ impl Fsm for SelectToolFsmState {
|
||||
let layers_exist = tool_data.layers_dragging.iter().all(|&layer| document.metadata().click_targets(layer).is_some());
|
||||
let ignore = tool_data.non_duplicated_layers.as_ref().filter(|_| !layers_exist).unwrap_or(&tool_data.layers_dragging);
|
||||
|
||||
let snap_data = SnapData::ignore(document, input, ignore);
|
||||
let snap_data = SnapData::ignore(document, input, viewport, ignore);
|
||||
let (start, current) = (tool_data.drag_start, tool_data.drag_current);
|
||||
let e0 = tool_data
|
||||
.bounding_box_manager
|
||||
@@ -1208,7 +1214,7 @@ impl Fsm for SelectToolFsmState {
|
||||
SelectToolMessage::PointerOutsideViewport { modifier_keys: modifier_keys.clone() }.into(),
|
||||
SelectToolMessage::PointerMove { modifier_keys }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
SelectToolFsmState::Dragging {
|
||||
axis,
|
||||
@@ -1228,6 +1234,7 @@ impl Fsm for SelectToolFsmState {
|
||||
&mut tool_data.snap_manager,
|
||||
&mut tool_data.snap_candidates,
|
||||
input,
|
||||
viewport,
|
||||
input.keyboard.key(modifier_keys.center),
|
||||
input.keyboard.key(modifier_keys.axis_align),
|
||||
ToolType::Select,
|
||||
@@ -1236,7 +1243,7 @@ impl Fsm for SelectToolFsmState {
|
||||
SelectToolMessage::PointerOutsideViewport { modifier_keys: modifier_keys.clone() }.into(),
|
||||
SelectToolMessage::PointerMove { modifier_keys }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
}
|
||||
SelectToolFsmState::ResizingBounds
|
||||
}
|
||||
@@ -1283,7 +1290,7 @@ impl Fsm for SelectToolFsmState {
|
||||
SelectToolMessage::PointerOutsideViewport { modifier_keys: modifier_keys.clone() }.into(),
|
||||
SelectToolMessage::PointerMove { modifier_keys }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
SelectToolFsmState::DraggingPivot
|
||||
}
|
||||
@@ -1304,7 +1311,7 @@ impl Fsm for SelectToolFsmState {
|
||||
SelectToolMessage::PointerOutsideViewport { modifier_keys: modifier_keys.clone() }.into(),
|
||||
SelectToolMessage::PointerMove { modifier_keys }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
SelectToolFsmState::Drawing { selection_shape, has_drawn: true }
|
||||
}
|
||||
@@ -1347,7 +1354,7 @@ impl Fsm for SelectToolFsmState {
|
||||
SelectToolMessage::PointerOutsideViewport { .. },
|
||||
) => {
|
||||
// Auto-panning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
|
||||
tool_data.drag_current += shift;
|
||||
tool_data.drag_start += shift;
|
||||
}
|
||||
@@ -1362,7 +1369,7 @@ impl Fsm for SelectToolFsmState {
|
||||
}
|
||||
(SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. }, SelectToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
|
||||
if let Some(bounds) = &mut tool_data.bounding_box_manager {
|
||||
bounds.center_of_transformation += shift;
|
||||
bounds.original_bound_transform.translation += shift;
|
||||
@@ -1373,13 +1380,13 @@ impl Fsm for SelectToolFsmState {
|
||||
}
|
||||
(SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, viewport, responses);
|
||||
|
||||
self
|
||||
}
|
||||
(SelectToolFsmState::Drawing { .. }, SelectToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
|
||||
tool_data.drag_start += shift;
|
||||
}
|
||||
|
||||
@@ -1403,7 +1410,7 @@ impl Fsm for SelectToolFsmState {
|
||||
if !has_dragged && input.keyboard.key(remove_from_selection) && tool_data.layer_selected_on_start.is_none() {
|
||||
// When you click on the layer with remove from selection key (shift) pressed, we deselect all nodes that are children.
|
||||
let quad = tool_data.selection_quad();
|
||||
let intersection = document.intersect_quad_no_artboards(quad, input);
|
||||
let intersection = document.intersect_quad_no_artboards(quad, viewport);
|
||||
|
||||
if let Some(path) = intersection.last() {
|
||||
let replacement_selected_layers: Vec<_> = document
|
||||
@@ -1433,7 +1440,7 @@ impl Fsm for SelectToolFsmState {
|
||||
} else if tool_data.select_single_layer.take().is_some() {
|
||||
// Previously, we may have had many layers selected. If the user clicks without dragging, we should just select the one layer that has been clicked.
|
||||
if !has_dragged {
|
||||
let selected = document.click_list(input).collect::<Vec<_>>();
|
||||
let selected = document.click_list(input, viewport).collect::<Vec<_>>();
|
||||
let intersection = document.find_deepest(&selected);
|
||||
if let Some(intersection) = intersection {
|
||||
tool_data.layer_selected_on_start = Some(intersection);
|
||||
@@ -1449,7 +1456,7 @@ impl Fsm for SelectToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
tool_data.get_snap_candidates(document, input);
|
||||
tool_data.get_snap_candidates(document, input, viewport);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1510,13 +1517,13 @@ impl Fsm for SelectToolFsmState {
|
||||
};
|
||||
|
||||
let intersection: Vec<LayerNodeIdentifier> = match selection_shape {
|
||||
SelectionShapeType::Box => document.intersect_quad_no_artboards(quad, input).collect(),
|
||||
SelectionShapeType::Lasso => tool_data.intersect_lasso_no_artboards(document, input),
|
||||
SelectionShapeType::Box => document.intersect_quad_no_artboards(quad, viewport).collect(),
|
||||
SelectionShapeType::Lasso => tool_data.intersect_lasso_no_artboards(document, viewport),
|
||||
};
|
||||
let new_selected: HashSet<_> = if selection_mode == SelectionMode::Enclosed {
|
||||
let is_inside = |layer: &LayerNodeIdentifier| match selection_shape {
|
||||
SelectionShapeType::Box => document.is_layer_fully_inside(layer, quad),
|
||||
SelectionShapeType::Lasso => tool_data.is_layer_inside_lasso_polygon(layer, document, input),
|
||||
SelectionShapeType::Lasso => tool_data.is_layer_inside_lasso_polygon(layer, document, viewport),
|
||||
};
|
||||
intersection.into_iter().filter(is_inside).collect()
|
||||
} else {
|
||||
|
||||
@@ -501,11 +501,11 @@ pub struct ShapeToolData {
|
||||
}
|
||||
|
||||
impl ShapeToolData {
|
||||
fn get_snap_candidates(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) {
|
||||
fn get_snap_candidates(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, viewport: &ViewportMessageHandler) {
|
||||
self.snap_candidates.clear();
|
||||
for &layer in &self.layers_dragging {
|
||||
if (self.snap_candidates.len() as f64) < document.snapping_state.tolerance {
|
||||
snapping::get_layer_snap_points(layer, &SnapData::new(document, input), &mut self.snap_candidates);
|
||||
snapping::get_layer_snap_points(layer, &SnapData::new(document, input, viewport), &mut self.snap_candidates);
|
||||
}
|
||||
if let Some(bounds) = document.metadata().bounding_box_with_transform(layer, DAffine2::IDENTITY) {
|
||||
let quad = document.metadata().transform_to_document(layer) * Quad::from_box(bounds);
|
||||
@@ -558,6 +558,7 @@ impl Fsm for ShapeToolFsmState {
|
||||
input,
|
||||
preferences,
|
||||
shape_editor,
|
||||
viewport,
|
||||
..
|
||||
}: &mut ToolActionMessageContext,
|
||||
tool_options: &Self::ToolOptions,
|
||||
@@ -596,7 +597,7 @@ impl Fsm for ShapeToolFsmState {
|
||||
let hovering_over_gizmo = tool_data.gizmo_manager.hovering_over_gizmo();
|
||||
|
||||
if !matches!(self, ShapeToolFsmState::ModifyingGizmo) && !modifying_transform_cage && !hovering_over_gizmo {
|
||||
tool_data.data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context);
|
||||
tool_data.data.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
||||
}
|
||||
|
||||
if modifying_transform_cage && !matches!(self, ShapeToolFsmState::ModifyingGizmo) {
|
||||
@@ -783,7 +784,7 @@ impl Fsm for ShapeToolFsmState {
|
||||
|
||||
match (resize, rotate, skew) {
|
||||
(true, false, false) => {
|
||||
tool_data.get_snap_candidates(document, input);
|
||||
tool_data.get_snap_candidates(document, input, viewport);
|
||||
update_cursor_and_pointer(tool_data, responses);
|
||||
|
||||
return ShapeToolFsmState::ResizingBounds;
|
||||
@@ -795,7 +796,7 @@ impl Fsm for ShapeToolFsmState {
|
||||
return ShapeToolFsmState::RotatingBounds;
|
||||
}
|
||||
(false, false, true) => {
|
||||
tool_data.get_snap_candidates(document, input);
|
||||
tool_data.get_snap_candidates(document, input, viewport);
|
||||
update_cursor_and_pointer(tool_data, responses);
|
||||
|
||||
return ShapeToolFsmState::SkewingBounds { skew: Key::Control };
|
||||
@@ -806,11 +807,14 @@ impl Fsm for ShapeToolFsmState {
|
||||
|
||||
match tool_data.current_shape {
|
||||
ShapeType::Polygon | ShapeType::Star | ShapeType::Circle | ShapeType::Arc | ShapeType::Spiral | ShapeType::Grid | ShapeType::Rectangle | ShapeType::Ellipse => {
|
||||
tool_data.data.start(document, input)
|
||||
tool_data.data.start(document, input, viewport);
|
||||
}
|
||||
ShapeType::Line => {
|
||||
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||
let snapped = tool_data.data.snap_manager.free_snap(&SnapData::new(document, input), &point, SnapTypeConfiguration::default());
|
||||
let snapped = tool_data
|
||||
.data
|
||||
.snap_manager
|
||||
.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||
tool_data.data.drag_start = snapped.snapped_point_document;
|
||||
}
|
||||
}
|
||||
@@ -830,7 +834,7 @@ impl Fsm for ShapeToolFsmState {
|
||||
};
|
||||
|
||||
let nodes = vec![(NodeId(0), node)];
|
||||
let layer = graph_modification_utils::new_custom(NodeId::new(), nodes, document.new_layer_bounding_artboard(input), responses);
|
||||
let layer = graph_modification_utils::new_custom(NodeId::new(), nodes, document.new_layer_bounding_artboard(input, viewport), responses);
|
||||
|
||||
let defered_responses = &mut VecDeque::new();
|
||||
|
||||
@@ -868,20 +872,20 @@ impl Fsm for ShapeToolFsmState {
|
||||
};
|
||||
|
||||
match tool_data.current_shape {
|
||||
ShapeType::Polygon => Polygon::update_shape(document, input, layer, tool_data, modifier, responses),
|
||||
ShapeType::Star => Star::update_shape(document, input, layer, tool_data, modifier, responses),
|
||||
ShapeType::Circle => Circle::update_shape(document, input, layer, tool_data, modifier, responses),
|
||||
ShapeType::Arc => Arc::update_shape(document, input, layer, tool_data, modifier, responses),
|
||||
ShapeType::Spiral => Spiral::update_shape(document, input, layer, tool_data, responses),
|
||||
ShapeType::Polygon => Polygon::update_shape(document, input, viewport, layer, tool_data, modifier, responses),
|
||||
ShapeType::Star => Star::update_shape(document, input, viewport, layer, tool_data, modifier, responses),
|
||||
ShapeType::Circle => Circle::update_shape(document, input, viewport, layer, tool_data, modifier, responses),
|
||||
ShapeType::Arc => Arc::update_shape(document, input, viewport, layer, tool_data, modifier, responses),
|
||||
ShapeType::Spiral => Spiral::update_shape(document, input, viewport, layer, tool_data, responses),
|
||||
ShapeType::Grid => Grid::update_shape(document, input, layer, tool_options.grid_type, tool_data, modifier, responses),
|
||||
ShapeType::Rectangle => Rectangle::update_shape(document, input, layer, tool_data, modifier, responses),
|
||||
ShapeType::Ellipse => Ellipse::update_shape(document, input, layer, tool_data, modifier, responses),
|
||||
ShapeType::Line => Line::update_shape(document, input, layer, tool_data, modifier, responses),
|
||||
ShapeType::Rectangle => Rectangle::update_shape(document, input, viewport, layer, tool_data, modifier, responses),
|
||||
ShapeType::Ellipse => Ellipse::update_shape(document, input, viewport, layer, tool_data, modifier, responses),
|
||||
ShapeType::Line => Line::update_shape(document, input, viewport, layer, tool_data, modifier, responses),
|
||||
}
|
||||
|
||||
// Auto-panning
|
||||
let messages = [ShapeToolMessage::PointerOutsideViewport { modifier }.into(), ShapeToolMessage::PointerMove { modifier }.into()];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
self
|
||||
}
|
||||
@@ -890,10 +894,10 @@ impl Fsm for ShapeToolFsmState {
|
||||
return ShapeToolFsmState::Ready(tool_data.current_shape);
|
||||
};
|
||||
|
||||
Line::update_shape(document, input, layer, tool_data, modifier, responses);
|
||||
Line::update_shape(document, input, viewport, layer, tool_data, modifier, responses);
|
||||
// Auto-panning
|
||||
let messages = [ShapeToolMessage::PointerOutsideViewport { modifier }.into(), ShapeToolMessage::PointerMove { modifier }.into()];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
self
|
||||
}
|
||||
@@ -915,11 +919,12 @@ impl Fsm for ShapeToolFsmState {
|
||||
&mut tool_data.data.snap_manager,
|
||||
&mut tool_data.snap_candidates,
|
||||
input,
|
||||
viewport,
|
||||
input.keyboard.key(modifier[0]),
|
||||
input.keyboard.key(modifier[1]),
|
||||
ToolType::Shape,
|
||||
);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
}
|
||||
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
@@ -974,14 +979,14 @@ impl Fsm for ShapeToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor });
|
||||
}
|
||||
|
||||
tool_data.data.snap_manager.preview_draw(&SnapData::new(document, input), input.mouse.position);
|
||||
tool_data.data.snap_manager.preview_draw(&SnapData::new(document, input, viewport), input.mouse.position);
|
||||
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
self
|
||||
}
|
||||
(ShapeToolFsmState::ResizingBounds | ShapeToolFsmState::SkewingBounds { .. }, ShapeToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses)
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses)
|
||||
&& let Some(bounds) = &mut tool_data.bounding_box_manager
|
||||
{
|
||||
bounds.center_of_transformation += shift;
|
||||
@@ -993,7 +998,7 @@ impl Fsm for ShapeToolFsmState {
|
||||
(ShapeToolFsmState::Ready(_), ShapeToolMessage::PointerOutsideViewport { .. }) => self,
|
||||
(_, ShapeToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, viewport, responses);
|
||||
self
|
||||
}
|
||||
(
|
||||
|
||||
@@ -267,12 +267,12 @@ impl SplineToolData {
|
||||
}
|
||||
|
||||
/// Get the snapped point while ignoring current layer
|
||||
fn snapped_point(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) -> SnappedPoint {
|
||||
fn snapped_point(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, viewport: &ViewportMessageHandler) -> SnappedPoint {
|
||||
let metadata = document.metadata();
|
||||
let transform = self.current_layer.map_or(metadata.document_to_viewport, |layer| metadata.transform_to_viewport(layer));
|
||||
let point = SnapCandidatePoint::handle(transform.inverse().transform_point2(input.mouse.position));
|
||||
let ignore = if let Some(layer) = self.current_layer { vec![layer] } else { vec![] };
|
||||
let snap_data = SnapData::ignore(document, input, &ignore);
|
||||
let snap_data = SnapData::ignore(document, input, viewport, &ignore);
|
||||
self.snap_manager.free_snap(&snap_data, &point, SnapTypeConfiguration::default())
|
||||
}
|
||||
}
|
||||
@@ -295,6 +295,7 @@ impl Fsm for SplineToolFsmState {
|
||||
input,
|
||||
shape_editor,
|
||||
preferences,
|
||||
viewport,
|
||||
..
|
||||
} = tool_action_data;
|
||||
|
||||
@@ -303,7 +304,7 @@ impl Fsm for SplineToolFsmState {
|
||||
(_, SplineToolMessage::CanvasTransformed) => self,
|
||||
(_, SplineToolMessage::Overlays { context: mut overlay_context }) => {
|
||||
path_endpoint_overlays(document, shape_editor, &mut overlay_context, preferences);
|
||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context);
|
||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
||||
self
|
||||
}
|
||||
(SplineToolFsmState::MergingEndpoints, SplineToolMessage::MergeEndpoints) => {
|
||||
@@ -342,15 +343,15 @@ impl Fsm for SplineToolFsmState {
|
||||
tool_data.weight = tool_options.line_weight;
|
||||
|
||||
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input), &point, SnapTypeConfiguration::default());
|
||||
let viewport = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||
let viewport_vec = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||
|
||||
let layers = LayerNodeIdentifier::ROOT_PARENT
|
||||
.descendants(document.metadata())
|
||||
.filter(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]));
|
||||
|
||||
// Extend an endpoint of the selected path
|
||||
if let Some((layer, point, position)) = should_extend(document, viewport, SNAP_POINT_TOLERANCE, layers, preferences) {
|
||||
if let Some((layer, point, position)) = should_extend(document, viewport_vec, SNAP_POINT_TOLERANCE, layers, preferences) {
|
||||
if find_spline(document, layer).is_some() {
|
||||
// If the point is the part of Spline then we extend it.
|
||||
tool_data.current_layer = Some(layer);
|
||||
@@ -386,7 +387,7 @@ impl Fsm for SplineToolFsmState {
|
||||
|
||||
responses.add(DocumentMessage::DeselectAllLayers);
|
||||
|
||||
let parent = document.new_layer_bounding_artboard(input);
|
||||
let parent = document.new_layer_bounding_artboard(input, viewport);
|
||||
|
||||
let path_node_type = resolve_document_node_type("Path").expect("Path node does not exist");
|
||||
let path_node = path_node_type.default_node_template();
|
||||
@@ -410,7 +411,7 @@ impl Fsm for SplineToolFsmState {
|
||||
if tool_data.current_layer.is_none() {
|
||||
return SplineToolFsmState::Ready;
|
||||
};
|
||||
tool_data.next_point = tool_data.snapped_point(document, input).snapped_point_document;
|
||||
tool_data.next_point = tool_data.snapped_point(document, input, viewport).snapped_point_document;
|
||||
if tool_data.points.last().is_none_or(|last_pos| last_pos.1.distance(tool_data.next_point) > DRAG_THRESHOLD) {
|
||||
let preview_point = tool_data.preview_point;
|
||||
extend_spline(tool_data, false, responses);
|
||||
@@ -433,7 +434,7 @@ impl Fsm for SplineToolFsmState {
|
||||
tool_data.next_point = point;
|
||||
tool_data.snap_manager.clear_indicator();
|
||||
} else {
|
||||
let snapped_point = tool_data.snapped_point(document, input);
|
||||
let snapped_point = tool_data.snapped_point(document, input, viewport);
|
||||
tool_data.next_point = snapped_point.snapped_point_document;
|
||||
tool_data.snap_manager.update_indicator(snapped_point);
|
||||
}
|
||||
@@ -442,12 +443,12 @@ impl Fsm for SplineToolFsmState {
|
||||
|
||||
// Auto-panning
|
||||
let messages = [SplineToolMessage::PointerOutsideViewport.into(), SplineToolMessage::PointerMove.into()];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
SplineToolFsmState::Drawing
|
||||
}
|
||||
(_, SplineToolMessage::PointerMove) => {
|
||||
tool_data.snap_manager.preview_draw(&SnapData::new(document, input), input.mouse.position);
|
||||
tool_data.snap_manager.preview_draw(&SnapData::new(document, input, viewport), input.mouse.position);
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
self
|
||||
}
|
||||
@@ -456,7 +457,7 @@ impl Fsm for SplineToolFsmState {
|
||||
return self;
|
||||
}
|
||||
// Auto-panning
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, viewport, responses);
|
||||
|
||||
SplineToolFsmState::Drawing
|
||||
}
|
||||
|
||||
@@ -499,6 +499,7 @@ impl Fsm for TextToolFsmState {
|
||||
global_tool_data,
|
||||
input,
|
||||
font_cache,
|
||||
viewport,
|
||||
..
|
||||
} = transition_data;
|
||||
let fill_color = graphene_std::Color::from_rgb_str(COLOR_OVERLAY_BLUE.strip_prefix('#').unwrap())
|
||||
@@ -509,9 +510,8 @@ impl Fsm for TextToolFsmState {
|
||||
let ToolMessage::Text(event) = event else { return self };
|
||||
match (self, event) {
|
||||
(TextToolFsmState::Editing, TextToolMessage::Overlays { context: mut overlay_context }) => {
|
||||
responses.add(FrontendMessage::DisplayEditableTextboxTransform {
|
||||
transform: document.metadata().transform_to_viewport(tool_data.layer).to_cols_array(),
|
||||
});
|
||||
let transform = document.metadata().transform_to_viewport(tool_data.layer).to_cols_array();
|
||||
responses.add(FrontendMessage::DisplayEditableTextboxTransform { transform });
|
||||
if let Some(editing_text) = tool_data.editing_text.as_mut() {
|
||||
let far = graphene_std::text::bounding_box(&tool_data.new_text, &editing_text.font, font_cache, editing_text.typesetting, false);
|
||||
if far.x != 0. && far.y != 0. {
|
||||
@@ -529,7 +529,7 @@ impl Fsm for TextToolFsmState {
|
||||
let quad = Quad::from_box(tool_data.cached_resize_bounds);
|
||||
|
||||
// Draw a bounding box on the layers to be selected
|
||||
for layer in document.intersect_quad_no_artboards(quad, input) {
|
||||
for layer in document.intersect_quad_no_artboards(quad, viewport) {
|
||||
overlay_context.quad(
|
||||
Quad::from_box(document.metadata().bounding_box_viewport(layer).unwrap_or([DVec2::ZERO; 2])),
|
||||
None,
|
||||
@@ -572,7 +572,7 @@ impl Fsm for TextToolFsmState {
|
||||
tool_data.bounding_box_manager.take();
|
||||
}
|
||||
|
||||
tool_data.resize.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context);
|
||||
tool_data.resize.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
||||
|
||||
self
|
||||
}
|
||||
@@ -585,7 +585,7 @@ impl Fsm for TextToolFsmState {
|
||||
state
|
||||
}
|
||||
(TextToolFsmState::Ready, TextToolMessage::DragStart) => {
|
||||
tool_data.resize.start(document, input);
|
||||
tool_data.resize.start(document, input, viewport);
|
||||
tool_data.cached_resize_bounds = [tool_data.resize.viewport_drag_start(document); 2];
|
||||
tool_data.drag_start = input.mouse.position;
|
||||
tool_data.drag_current = input.mouse.position;
|
||||
@@ -659,7 +659,7 @@ impl Fsm for TextToolFsmState {
|
||||
TextToolFsmState::Ready
|
||||
}
|
||||
(TextToolFsmState::Placing, TextToolMessage::PointerMove { center, lock_ratio }) => {
|
||||
tool_data.cached_resize_bounds = tool_data.resize.calculate_points_ignore_layer(document, input, center, lock_ratio, false);
|
||||
tool_data.cached_resize_bounds = tool_data.resize.calculate_points_ignore_layer(document, input, viewport, center, lock_ratio, false);
|
||||
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
|
||||
@@ -668,7 +668,7 @@ impl Fsm for TextToolFsmState {
|
||||
TextToolMessage::PointerOutsideViewport { center, lock_ratio }.into(),
|
||||
TextToolMessage::PointerMove { center, lock_ratio }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
|
||||
TextToolFsmState::Placing
|
||||
}
|
||||
@@ -691,7 +691,7 @@ impl Fsm for TextToolFsmState {
|
||||
TextToolMessage::PointerOutsideViewport { center, lock_ratio }.into(),
|
||||
TextToolMessage::PointerMove { center, lock_ratio }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
}
|
||||
|
||||
TextToolFsmState::Dragging
|
||||
@@ -713,7 +713,7 @@ impl Fsm for TextToolFsmState {
|
||||
let snap = Some(SizeSnapData {
|
||||
manager: &mut tool_data.resize.snap_manager,
|
||||
points: &mut tool_data.snap_candidates,
|
||||
snap_data: SnapData::ignore(document, input, &selected),
|
||||
snap_data: SnapData::ignore(document, input, viewport, &selected),
|
||||
});
|
||||
|
||||
let (position, size) = movement.new_size(input.mouse.position, bounds.original_bound_transform, center_position, constrain, snap);
|
||||
@@ -752,26 +752,26 @@ impl Fsm for TextToolFsmState {
|
||||
TextToolMessage::PointerOutsideViewport { center, lock_ratio }.into(),
|
||||
TextToolMessage::PointerMove { center, lock_ratio }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||
}
|
||||
}
|
||||
TextToolFsmState::ResizingBounds
|
||||
}
|
||||
(_, TextToolMessage::PointerMove { .. }) => {
|
||||
tool_data.resize.snap_manager.preview_draw(&SnapData::new(document, input), input.mouse.position);
|
||||
tool_data.resize.snap_manager.preview_draw(&SnapData::new(document, input, viewport), input.mouse.position);
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
|
||||
self
|
||||
}
|
||||
(TextToolFsmState::Placing, TextToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning setup
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, viewport, responses);
|
||||
|
||||
TextToolFsmState::Placing
|
||||
}
|
||||
(TextToolFsmState::ResizingBounds | TextToolFsmState::Dragging, TextToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
|
||||
if let Some(bounds) = &mut tool_data.bounding_box_manager {
|
||||
bounds.center_of_transformation += shift;
|
||||
bounds.original_bound_transform.translation += shift;
|
||||
|
||||
Reference in New Issue
Block a user