mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-03 21:08:18 +00:00
Fix path tool
This commit is contained in:
parent
4cd72edb64
commit
0d6bec837b
8 changed files with 164 additions and 210 deletions
|
@ -180,7 +180,7 @@ pub fn default_mapping() -> Mapping {
|
|||
//
|
||||
// PathToolMessage
|
||||
entry!(KeyDown(Lmb); action_dispatch=PathToolMessage::DragStart { add_to_selection: Shift }),
|
||||
entry!(PointerMove; refresh_keys=[Alt, Shift], action_dispatch=PathToolMessage::PointerMove { alt_mirror_angle: Alt, shift_mirror_distance: Shift }),
|
||||
entry!(PointerMove; refresh_keys=[Alt, Shift], action_dispatch=PathToolMessage::PointerMove { alt: Alt, shift: Shift }),
|
||||
entry!(KeyDown(Delete); action_dispatch=PathToolMessage::Delete),
|
||||
entry!(KeyDown(KeyA); modifiers=[Control], action_dispatch=PathToolMessage::SelectAllPoints),
|
||||
entry!(KeyDown(Backspace); action_dispatch=PathToolMessage::Delete),
|
||||
|
|
|
@ -130,18 +130,15 @@ impl OverlayRenderer {
|
|||
responses.add(OverlaysMessage::Rerender);
|
||||
}
|
||||
|
||||
pub fn clear_subpath_overlays(&mut self, _document: &Document, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>) {
|
||||
// Remove the shape outline overlays
|
||||
if let Some(overlay_path) = self.shape_overlay_cache.get(&layer) {
|
||||
Self::remove_outline_overlays(overlay_path.clone(), responses)
|
||||
/// Delete all cached overlays
|
||||
pub fn clear_all_overlays(&mut self, responses: &mut VecDeque<Message>) {
|
||||
for (_, overlay_path) in self.shape_overlay_cache.drain() {
|
||||
Self::remove_outline_overlays(overlay_path, responses)
|
||||
}
|
||||
self.shape_overlay_cache.remove(&layer);
|
||||
|
||||
// Remove the ManipulatorGroup overlays
|
||||
let Some(layer_cache) = self.manipulator_group_overlay_cache.remove(&layer) else { return };
|
||||
|
||||
for manipulator_group_overlays in layer_cache.values() {
|
||||
Self::remove_manipulator_group_overlays(manipulator_group_overlays, responses);
|
||||
for (_, layer_cache) in self.manipulator_group_overlay_cache.drain() {
|
||||
for manipulator_group_overlays in layer_cache.values() {
|
||||
Self::remove_manipulator_group_overlays(manipulator_group_overlays, responses);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ impl ShapeState {
|
|||
pub fn set_selected_layers(&mut self, target_layers: Vec<LayerNodeIdentifier>) {
|
||||
self.selected_shape_state.retain(|layer_path, _| target_layers.contains(layer_path));
|
||||
for layer in target_layers {
|
||||
self.selected_shape_state.entry(layer).or_insert_with(SelectedLayerState::default);
|
||||
self.selected_shape_state.entry(layer).or_default();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,11 +142,6 @@ impl ShapeState {
|
|||
self.selected_shape_state.keys()
|
||||
}
|
||||
|
||||
/// Clear all of the shapes we can modify.
|
||||
pub fn clear_selected_layers(&mut self) {
|
||||
self.selected_shape_state.clear();
|
||||
}
|
||||
|
||||
pub fn has_selected_layers(&self) -> bool {
|
||||
!self.selected_shape_state.is_empty()
|
||||
}
|
||||
|
|
|
@ -164,6 +164,23 @@ pub fn add_bounding_box(responses: &mut VecDeque<Message>) -> Vec<LayerId> {
|
|||
path
|
||||
}
|
||||
|
||||
/// Update the location of a bounding box with no handles
|
||||
pub fn update_bounding_box(pos1: DVec2, pos2: DVec2, layer: &Option<Vec<LayerId>>, responses: &mut VecDeque<Message>) {
|
||||
if let Some(path) = layer.as_ref().cloned() {
|
||||
let transform = transform_from_box(pos1, pos2, DAffine2::IDENTITY).to_cols_array();
|
||||
let operation = Operation::SetLayerTransformInViewport { path, transform };
|
||||
responses.add_front(DocumentMessage::Overlays(operation.into()));
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the bounding box overlay with no transform handles
|
||||
pub fn remove_bounding_box(layer_path: Option<Vec<LayerId>>, responses: &mut VecDeque<Message>) {
|
||||
if let Some(path) = layer_path {
|
||||
let operation = Operation::DeleteLayer { path };
|
||||
responses.add(DocumentMessage::Overlays(operation.into()));
|
||||
}
|
||||
}
|
||||
|
||||
/// Add the transform handle overlay
|
||||
fn add_transform_handles(responses: &mut VecDeque<Message>) -> [Vec<LayerId>; 8] {
|
||||
const EMPTY_VEC: Vec<LayerId> = Vec::new();
|
||||
|
|
|
@ -3,14 +3,12 @@ use std::vec;
|
|||
use super::tool_prelude::*;
|
||||
use crate::consts::{DRAG_THRESHOLD, SELECTION_THRESHOLD, SELECTION_TOLERANCE};
|
||||
use crate::messages::tool::common_functionality::overlay_renderer::OverlayRenderer;
|
||||
use crate::messages::tool::common_functionality::shape_editor::{ManipulatorAngle, ManipulatorPointInfo, OpposingHandleLengths, ShapeState};
|
||||
use crate::messages::tool::common_functionality::shape_editor::{ManipulatorAngle, ManipulatorPointInfo, OpposingHandleLengths, SelectedPointsInfo, ShapeState};
|
||||
use crate::messages::tool::common_functionality::snapping::SnapManager;
|
||||
use crate::messages::tool::common_functionality::transformation_cage::{add_bounding_box, transform_from_box};
|
||||
use crate::messages::tool::common_functionality::transformation_cage::{add_bounding_box, remove_bounding_box, update_bounding_box};
|
||||
|
||||
use document_legacy::document::Document;
|
||||
use document_legacy::document_metadata::LayerNodeIdentifier;
|
||||
use document_legacy::intersection::Quad;
|
||||
use document_legacy::{LayerId, Operation};
|
||||
use document_legacy::LayerId;
|
||||
use graphene_core::vector::{ManipulatorPointId, SelectedType};
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -50,8 +48,8 @@ pub enum PathToolMessage {
|
|||
delta_y: f64,
|
||||
},
|
||||
PointerMove {
|
||||
alt_mirror_angle: Key,
|
||||
shift_mirror_distance: Key,
|
||||
alt: Key,
|
||||
shift: Key,
|
||||
},
|
||||
SelectAllPoints,
|
||||
SelectedPointUpdated,
|
||||
|
@ -212,8 +210,7 @@ struct PathToolData {
|
|||
impl PathToolData {
|
||||
fn refresh_overlays(&mut self, document: &DocumentMessageHandler, shape_editor: &mut ShapeState, shape_overlay: &mut OverlayRenderer, responses: &mut VecDeque<Message>) {
|
||||
// Set the previously selected layers to invisible
|
||||
for layer_path in document.all_layers() {
|
||||
let layer = LayerNodeIdentifier::from_path(layer_path, document.network());
|
||||
for layer in document.document_legacy.metadata.all_layers() {
|
||||
shape_overlay.layer_overlay_visibility(&document.document_legacy, layer, false, responses);
|
||||
}
|
||||
|
||||
|
@ -224,6 +221,106 @@ impl PathToolData {
|
|||
|
||||
self.opposing_handle_lengths = None;
|
||||
}
|
||||
|
||||
fn mouse_down(
|
||||
&mut self,
|
||||
shift: bool,
|
||||
shape_editor: &mut ShapeState,
|
||||
document: &DocumentMessageHandler,
|
||||
input: &InputPreprocessorMessageHandler,
|
||||
shape_overlay: &mut OverlayRenderer,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> PathToolFsmState {
|
||||
self.opposing_handle_lengths = None;
|
||||
let _selected_layers = shape_editor.selected_layers().cloned().collect::<Vec<_>>();
|
||||
|
||||
// Select the first point within the threshold (in pixels)
|
||||
if let Some(selected_points) = shape_editor.select_point(&document.document_legacy, input.mouse.position, SELECTION_THRESHOLD, shift) {
|
||||
self.start_dragging_point(selected_points, input, document, responses);
|
||||
self.refresh_overlays(document, shape_editor, shape_overlay, responses);
|
||||
|
||||
PathToolFsmState::Dragging
|
||||
}
|
||||
// We didn't find a point nearby, so consider selecting the nearest shape instead
|
||||
else if let Some((layer, _)) = document.document_legacy.metadata.click(input.mouse.position) {
|
||||
// TODO: Actual selection
|
||||
let layer_list = vec![layer.to_path()];
|
||||
if shift {
|
||||
responses.add(DocumentMessage::AddSelectedLayers { additional_layers: layer_list });
|
||||
} else {
|
||||
responses.add(DocumentMessage::SetSelectedLayers {
|
||||
replacement_selected_layers: layer_list,
|
||||
});
|
||||
}
|
||||
self.drag_start_pos = input.mouse.position;
|
||||
self.previous_mouse_position = input.mouse.position;
|
||||
shape_editor.select_all_anchors(&document.document_legacy, layer);
|
||||
|
||||
PathToolFsmState::Dragging
|
||||
} else {
|
||||
// Start drawing a box
|
||||
self.drag_start_pos = input.mouse.position;
|
||||
self.previous_mouse_position = input.mouse.position;
|
||||
self.drag_box_overlay_layer = Some(add_bounding_box(responses));
|
||||
|
||||
PathToolFsmState::DrawingBox
|
||||
}
|
||||
}
|
||||
|
||||
fn start_dragging_point(&mut self, mut selected_points: SelectedPointsInfo, input: &InputPreprocessorMessageHandler, _document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
|
||||
// TODO: enable snapping
|
||||
|
||||
//self
|
||||
// .snap_manager
|
||||
// .start_snap(document, input, document.bounding_boxes(Some(&selected_layers), None, render_data), true, true);
|
||||
|
||||
// Do not snap against handles when anchor is selected
|
||||
let mut additional_selected_points = Vec::new();
|
||||
for point in selected_points.points.iter() {
|
||||
if point.point_id.manipulator_type == SelectedType::Anchor {
|
||||
additional_selected_points.push(ManipulatorPointInfo {
|
||||
layer: point.layer,
|
||||
point_id: ManipulatorPointId::new(point.point_id.group, SelectedType::InHandle),
|
||||
});
|
||||
additional_selected_points.push(ManipulatorPointInfo {
|
||||
layer: point.layer,
|
||||
point_id: ManipulatorPointId::new(point.point_id.group, SelectedType::OutHandle),
|
||||
});
|
||||
}
|
||||
}
|
||||
selected_points.points.extend(additional_selected_points);
|
||||
|
||||
//let include_handles: Vec<_> = selected_layers.iter().map(|x| x.as_slice()).collect();
|
||||
//self.snap_manager.add_all_document_handles(document, input, &include_handles, &[], &selected_points.points);
|
||||
|
||||
self.drag_start_pos = input.mouse.position;
|
||||
self.previous_mouse_position = input.mouse.position - selected_points.offset;
|
||||
}
|
||||
|
||||
fn drag(&mut self, shift: bool, alt: bool, shape_editor: &mut ShapeState, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) {
|
||||
// Check if the alt key has just been pressed
|
||||
if alt && !self.alt_debounce {
|
||||
self.opposing_handle_lengths = None;
|
||||
shape_editor.toggle_handle_mirroring_on_selected(responses);
|
||||
}
|
||||
self.alt_debounce = alt;
|
||||
|
||||
if shift {
|
||||
if self.opposing_handle_lengths.is_none() {
|
||||
self.opposing_handle_lengths = Some(shape_editor.opposing_handle_lengths(&document.document_legacy));
|
||||
}
|
||||
} else if let Some(opposing_handle_lengths) = &self.opposing_handle_lengths {
|
||||
shape_editor.reset_opposing_handle_lengths(&document.document_legacy, opposing_handle_lengths, responses);
|
||||
self.opposing_handle_lengths = None;
|
||||
}
|
||||
|
||||
// Move the selected points with the mouse
|
||||
let snapped_position = self.snap_manager.snap_position(responses, document, input.mouse.position);
|
||||
shape_editor.move_selected_points(&document.document_legacy, snapped_position - self.previous_mouse_position, shift, responses);
|
||||
self.previous_mouse_position = snapped_position;
|
||||
}
|
||||
}
|
||||
|
||||
impl Fsm for PathToolFsmState {
|
||||
|
@ -234,7 +331,6 @@ impl Fsm for PathToolFsmState {
|
|||
let ToolActionHandlerData {
|
||||
document,
|
||||
input,
|
||||
render_data,
|
||||
shape_editor,
|
||||
shape_overlay,
|
||||
..
|
||||
|
@ -242,14 +338,12 @@ impl Fsm for PathToolFsmState {
|
|||
let ToolMessage::Path(event) = event else {
|
||||
return self;
|
||||
};
|
||||
|
||||
match (self, event) {
|
||||
(_, PathToolMessage::SelectionChanged) => {
|
||||
// Set the newly targeted layers to visible
|
||||
let layer_paths = document
|
||||
.selected_visible_layers()
|
||||
.map(|layer_path| LayerNodeIdentifier::from_path(layer_path, document.network()))
|
||||
.collect();
|
||||
shape_editor.set_selected_layers(layer_paths);
|
||||
let target_layers = document.document_legacy.metadata.selected_layers().collect();
|
||||
shape_editor.set_selected_layers(target_layers);
|
||||
|
||||
tool_data.refresh_overlays(document, shape_editor, shape_overlay, responses);
|
||||
|
||||
|
@ -260,8 +354,7 @@ impl Fsm for PathToolFsmState {
|
|||
(_, PathToolMessage::DocumentIsDirty) => {
|
||||
// When the document has moved / needs to be redraw, re-render the overlays
|
||||
// TODO the overlay system should probably receive this message instead of the tool
|
||||
for layer_path in document.selected_visible_layers() {
|
||||
let layer = LayerNodeIdentifier::from_path(layer_path, document.network());
|
||||
for layer in document.document_legacy.metadata.selected_layers() {
|
||||
shape_overlay.render_subpath_overlays(&shape_editor.selected_shape_state, &document.document_legacy, layer, responses);
|
||||
}
|
||||
|
||||
|
@ -271,128 +364,21 @@ impl Fsm for PathToolFsmState {
|
|||
}
|
||||
// Mouse down
|
||||
(_, PathToolMessage::DragStart { add_to_selection }) => {
|
||||
let shift_pressed = input.keyboard.get(add_to_selection as usize);
|
||||
let shift = input.keyboard.get(add_to_selection as usize);
|
||||
|
||||
tool_data.opposing_handle_lengths = None;
|
||||
let _selected_layers = shape_editor.selected_layers().cloned().collect::<Vec<_>>();
|
||||
|
||||
// Select the first point within the threshold (in pixels)
|
||||
if let Some(mut selected_points) = shape_editor.select_point(&document.document_legacy, input.mouse.position, SELECTION_THRESHOLD, shift_pressed) {
|
||||
responses.add(DocumentMessage::StartTransaction);
|
||||
|
||||
//tool_data
|
||||
// .snap_manager
|
||||
// .start_snap(document, input, document.bounding_boxes(Some(&selected_layers), None, render_data), true, true);
|
||||
|
||||
// Do not snap against handles when anchor is selected
|
||||
let mut additional_selected_points = Vec::new();
|
||||
for point in selected_points.points.iter() {
|
||||
if point.point_id.manipulator_type == SelectedType::Anchor {
|
||||
additional_selected_points.push(ManipulatorPointInfo {
|
||||
layer: point.layer,
|
||||
point_id: ManipulatorPointId::new(point.point_id.group, SelectedType::InHandle),
|
||||
});
|
||||
additional_selected_points.push(ManipulatorPointInfo {
|
||||
layer: point.layer,
|
||||
point_id: ManipulatorPointId::new(point.point_id.group, SelectedType::OutHandle),
|
||||
});
|
||||
}
|
||||
}
|
||||
selected_points.points.extend(additional_selected_points);
|
||||
|
||||
//let include_handles: Vec<_> = selected_layers.iter().map(|x| x.as_slice()).collect();
|
||||
//tool_data.snap_manager.add_all_document_handles(document, input, &include_handles, &[], &selected_points.points);
|
||||
|
||||
tool_data.drag_start_pos = input.mouse.position;
|
||||
tool_data.previous_mouse_position = input.mouse.position - selected_points.offset;
|
||||
|
||||
tool_data.refresh_overlays(document, shape_editor, shape_overlay, responses);
|
||||
|
||||
responses.add(PathToolMessage::SelectedPointUpdated);
|
||||
PathToolFsmState::Dragging
|
||||
}
|
||||
// We didn't find a point nearby, so consider selecting the nearest shape instead
|
||||
else {
|
||||
let selection_size = DVec2::new(2.0, 2.0);
|
||||
// Select shapes directly under our mouse
|
||||
let intersection = document
|
||||
.document_legacy
|
||||
.intersects_quad_root(Quad::from_box([input.mouse.position - selection_size, input.mouse.position + selection_size]), render_data);
|
||||
if !intersection.is_empty() {
|
||||
if shift_pressed {
|
||||
responses.add(DocumentMessage::AddSelectedLayers { additional_layers: intersection });
|
||||
} else {
|
||||
// Selects the topmost layer when selecting intersecting shapes
|
||||
let top_most_intersection = intersection[intersection.len() - 1].clone();
|
||||
responses.add(DocumentMessage::SetSelectedLayers {
|
||||
replacement_selected_layers: vec![top_most_intersection.clone()],
|
||||
});
|
||||
tool_data.drag_start_pos = input.mouse.position;
|
||||
tool_data.previous_mouse_position = input.mouse.position;
|
||||
// Selects all the anchor points when clicking in a filled area of shape. If two shapes intersect we pick the topmost layer.
|
||||
let layer = LayerNodeIdentifier::from_path(&top_most_intersection, document.network());
|
||||
shape_editor.select_all_anchors(&document.document_legacy, layer);
|
||||
return PathToolFsmState::Dragging;
|
||||
}
|
||||
} else {
|
||||
// an empty intersection means that the user is drawing a box
|
||||
tool_data.drag_start_pos = input.mouse.position;
|
||||
tool_data.previous_mouse_position = input.mouse.position;
|
||||
|
||||
tool_data.drag_box_overlay_layer = Some(add_bounding_box(responses));
|
||||
return PathToolFsmState::DrawingBox;
|
||||
}
|
||||
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
tool_data.mouse_down(shift, shape_editor, document, input, shape_overlay, responses)
|
||||
}
|
||||
(PathToolFsmState::DrawingBox, PathToolMessage::PointerMove { .. }) => {
|
||||
tool_data.previous_mouse_position = input.mouse.position;
|
||||
update_bounding_box(tool_data.drag_start_pos, input.mouse.position, &tool_data.drag_box_overlay_layer, responses);
|
||||
|
||||
responses.add_front(DocumentMessage::Overlays(
|
||||
Operation::SetLayerTransformInViewport {
|
||||
path: tool_data.drag_box_overlay_layer.clone().unwrap(),
|
||||
transform: transform_from_box(tool_data.drag_start_pos, tool_data.previous_mouse_position, DAffine2::IDENTITY).to_cols_array(),
|
||||
}
|
||||
.into(),
|
||||
));
|
||||
PathToolFsmState::DrawingBox
|
||||
}
|
||||
(PathToolFsmState::Dragging, PathToolMessage::PointerMove { alt, shift }) => {
|
||||
let alt = input.keyboard.get(alt as usize);
|
||||
let shift = input.keyboard.get(shift as usize);
|
||||
tool_data.drag(shift, alt, shape_editor, document, input, responses);
|
||||
|
||||
// Dragging
|
||||
(
|
||||
PathToolFsmState::Dragging,
|
||||
PathToolMessage::PointerMove {
|
||||
alt_mirror_angle,
|
||||
shift_mirror_distance,
|
||||
},
|
||||
) => {
|
||||
// Determine when alt state changes
|
||||
let alt_pressed = input.keyboard.get(alt_mirror_angle as usize);
|
||||
|
||||
// Only on alt down
|
||||
if alt_pressed && !tool_data.alt_debounce {
|
||||
tool_data.opposing_handle_lengths = None;
|
||||
shape_editor.toggle_handle_mirroring_on_selected(responses);
|
||||
}
|
||||
tool_data.alt_debounce = alt_pressed;
|
||||
|
||||
// Determine when shift state changes
|
||||
let shift_pressed = input.keyboard.get(shift_mirror_distance as usize);
|
||||
|
||||
if shift_pressed {
|
||||
if tool_data.opposing_handle_lengths.is_none() {
|
||||
tool_data.opposing_handle_lengths = Some(shape_editor.opposing_handle_lengths(&document.document_legacy));
|
||||
}
|
||||
} else if let Some(opposing_handle_lengths) = &tool_data.opposing_handle_lengths {
|
||||
shape_editor.reset_opposing_handle_lengths(&document.document_legacy, opposing_handle_lengths, responses);
|
||||
tool_data.opposing_handle_lengths = None;
|
||||
}
|
||||
|
||||
// Move the selected points by the mouse position
|
||||
let snapped_position = tool_data.snap_manager.snap_position(responses, document, input.mouse.position);
|
||||
shape_editor.move_selected_points(&document.document_legacy, snapped_position - tool_data.previous_mouse_position, shift_pressed, responses);
|
||||
tool_data.previous_mouse_position = snapped_position;
|
||||
PathToolFsmState::Dragging
|
||||
}
|
||||
|
||||
|
@ -405,16 +391,10 @@ impl Fsm for PathToolFsmState {
|
|||
shape_editor.select_all_in_quad(&document.document_legacy, [tool_data.drag_start_pos, tool_data.previous_mouse_position], !shift_pressed);
|
||||
tool_data.refresh_overlays(document, shape_editor, shape_overlay, responses);
|
||||
};
|
||||
remove_bounding_box(tool_data.drag_box_overlay_layer.take(), responses);
|
||||
|
||||
responses.add_front(DocumentMessage::Overlays(
|
||||
Operation::DeleteLayer {
|
||||
path: tool_data.drag_box_overlay_layer.take().unwrap(),
|
||||
}
|
||||
.into(),
|
||||
));
|
||||
PathToolFsmState::Ready
|
||||
|
||||
responses.add(PathToolMessage::SelectedPointUpdated);
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
|
||||
// Mouse up
|
||||
|
@ -427,17 +407,11 @@ impl Fsm for PathToolFsmState {
|
|||
shape_editor.select_all_in_quad(&document.document_legacy, [tool_data.drag_start_pos, tool_data.previous_mouse_position], !shift_pressed);
|
||||
tool_data.refresh_overlays(document, shape_editor, shape_overlay, responses);
|
||||
};
|
||||
|
||||
responses.add_front(DocumentMessage::Overlays(
|
||||
Operation::DeleteLayer {
|
||||
path: tool_data.drag_box_overlay_layer.take().unwrap(),
|
||||
}
|
||||
.into(),
|
||||
));
|
||||
remove_bounding_box(tool_data.drag_box_overlay_layer.take(), responses);
|
||||
|
||||
responses.add(PathToolMessage::SelectedPointUpdated);
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
}
|
||||
|
||||
(_, PathToolMessage::DragStop { shift_mirror_distance }) => {
|
||||
let shift_pressed = input.keyboard.get(shift_mirror_distance as usize);
|
||||
|
||||
|
@ -467,10 +441,7 @@ impl Fsm for PathToolFsmState {
|
|||
responses.add(DocumentMessage::StartTransaction);
|
||||
shape_editor.delete_selected_points(responses);
|
||||
responses.add(PathToolMessage::SelectionChanged);
|
||||
for layer_path in document.all_layers() {
|
||||
let layer = LayerNodeIdentifier::from_path(layer_path, document.network());
|
||||
shape_overlay.clear_subpath_overlays(&document.document_legacy, layer, responses);
|
||||
}
|
||||
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
(_, PathToolMessage::InsertPoint) => {
|
||||
|
@ -485,21 +456,15 @@ impl Fsm for PathToolFsmState {
|
|||
}
|
||||
(_, PathToolMessage::Abort) => {
|
||||
// TODO Tell overlay manager to remove the overlays
|
||||
for layer_path in document.all_layers() {
|
||||
let layer = LayerNodeIdentifier::from_path(layer_path, document.network());
|
||||
shape_overlay.clear_subpath_overlays(&document.document_legacy, layer, responses);
|
||||
}
|
||||
shape_overlay.clear_all_overlays(responses);
|
||||
remove_bounding_box(tool_data.drag_box_overlay_layer.take(), responses);
|
||||
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
(
|
||||
_,
|
||||
PathToolMessage::PointerMove {
|
||||
alt_mirror_angle: _,
|
||||
shift_mirror_distance: _,
|
||||
},
|
||||
) => self,
|
||||
(_, PathToolMessage::PointerMove { .. }) => self,
|
||||
(_, PathToolMessage::NudgeSelectedPoints { delta_x, delta_y }) => {
|
||||
shape_editor.move_selected_points(&document.document_legacy, (delta_x, delta_y).into(), true, responses);
|
||||
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
(_, PathToolMessage::SelectAllPoints) => {
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::consts::LINE_ROTATE_SNAP_ANGLE;
|
|||
use crate::messages::portfolio::document::node_graph::VectorDataModification;
|
||||
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
|
||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||
use crate::messages::tool::common_functionality::overlay_renderer::OverlayRenderer;
|
||||
use crate::messages::tool::common_functionality::snapping::SnapManager;
|
||||
use crate::messages::tool::tool_messages::pen_tool::graph_modification_utils::NodeGraphLayer;
|
||||
|
||||
|
@ -275,7 +274,7 @@ impl PenToolData {
|
|||
|
||||
// TODO: tooltip / user documentation?
|
||||
/// If you place the anchor on top of the previous anchor then you break the mirror
|
||||
fn check_break(&mut self, document: &DocumentMessageHandler, transform: DAffine2, shape_overlay: &mut OverlayRenderer, responses: &mut VecDeque<Message>) -> Option<()> {
|
||||
fn check_break(&mut self, document: &DocumentMessageHandler, transform: DAffine2, responses: &mut VecDeque<Message>) -> Option<()> {
|
||||
// Get subpath
|
||||
let layer_path = self.path.as_ref()?;
|
||||
let subpath = &get_subpaths(LayerNodeIdentifier::from_path(layer_path, document.network()), &document.document_legacy)?[self.subpath_index];
|
||||
|
@ -317,16 +316,11 @@ impl PenToolData {
|
|||
modification: VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle: false },
|
||||
});
|
||||
|
||||
// The overlay system cannot detect deleted points so we must just delete all the overlays
|
||||
for layer_path in document.all_layers() {
|
||||
shape_overlay.clear_subpath_overlays(&document.document_legacy, LayerNodeIdentifier::from_path(layer_path, document.network()), responses);
|
||||
}
|
||||
|
||||
self.should_mirror = false;
|
||||
None
|
||||
}
|
||||
|
||||
fn finish_placing_handle(&mut self, document: &DocumentMessageHandler, transform: DAffine2, shape_overlay: &mut OverlayRenderer, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
|
||||
fn finish_placing_handle(&mut self, document: &DocumentMessageHandler, transform: DAffine2, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
|
||||
// Get subpath
|
||||
let layer_path = self.path.as_ref()?;
|
||||
let subpath = &get_subpaths(LayerNodeIdentifier::from_path(layer_path, document.network()), &document.document_legacy)?[self.subpath_index];
|
||||
|
@ -384,11 +378,6 @@ impl PenToolData {
|
|||
|
||||
responses.add(DocumentMessage::CommitTransaction);
|
||||
|
||||
// Clean up overlays
|
||||
for layer_path in document.all_layers() {
|
||||
shape_overlay.clear_subpath_overlays(&document.document_legacy, LayerNodeIdentifier::from_path(layer_path, document.network()), responses);
|
||||
}
|
||||
|
||||
// Clean up tool data
|
||||
self.path = None;
|
||||
self.snap_manager.cleanup(responses);
|
||||
|
@ -643,12 +632,12 @@ impl Fsm for PenToolFsmState {
|
|||
PenToolFsmState::DraggingHandle
|
||||
}
|
||||
(PenToolFsmState::PlacingAnchor, PenToolMessage::DragStart) => {
|
||||
tool_data.check_break(document, transform, shape_overlay, responses);
|
||||
tool_data.check_break(document, transform, responses);
|
||||
PenToolFsmState::DraggingHandle
|
||||
}
|
||||
(PenToolFsmState::DraggingHandle, PenToolMessage::DragStop) => {
|
||||
tool_data.should_mirror = true;
|
||||
tool_data.finish_placing_handle(document, transform, shape_overlay, responses).unwrap_or(PenToolFsmState::PlacingAnchor)
|
||||
tool_data.finish_placing_handle(document, transform, responses).unwrap_or(PenToolFsmState::PlacingAnchor)
|
||||
}
|
||||
(PenToolFsmState::DraggingHandle, PenToolMessage::PointerMove { snap_angle, break_handle, lock_angle }) => {
|
||||
let modifiers = ModifierState {
|
||||
|
@ -673,10 +662,6 @@ impl Fsm for PenToolFsmState {
|
|||
let message = tool_data.finish_transaction(self, document, responses).unwrap_or(DocumentMessage::AbortTransaction);
|
||||
responses.add(message);
|
||||
|
||||
// Clean up overlays
|
||||
for layer_path in document.all_layers() {
|
||||
shape_overlay.clear_subpath_overlays(&document.document_legacy, LayerNodeIdentifier::from_path(layer_path, document.network()), responses);
|
||||
}
|
||||
tool_data.path = None;
|
||||
tool_data.snap_manager.cleanup(responses);
|
||||
|
||||
|
@ -684,9 +669,8 @@ impl Fsm for PenToolFsmState {
|
|||
}
|
||||
(_, PenToolMessage::Abort) => {
|
||||
// Clean up overlays
|
||||
for layer_path in document.all_layers() {
|
||||
shape_overlay.clear_subpath_overlays(&document.document_legacy, LayerNodeIdentifier::from_path(layer_path, document.network()), responses);
|
||||
}
|
||||
shape_overlay.clear_all_overlays(responses);
|
||||
|
||||
self
|
||||
}
|
||||
_ => self,
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::messages::prelude::*;
|
|||
use crate::messages::tool::common_functionality::shape_editor::ShapeState;
|
||||
use crate::messages::tool::utility_types::{ToolData, ToolType};
|
||||
|
||||
use document_legacy::document_metadata::LayerNodeIdentifier;
|
||||
use document_legacy::layers::style::RenderData;
|
||||
use graphene_core::vector::ManipulatorPointId;
|
||||
|
||||
|
@ -229,11 +228,8 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformL
|
|||
self.mouse_position = ipp.mouse.position;
|
||||
}
|
||||
SelectionChanged => {
|
||||
let layer_paths = document
|
||||
.selected_visible_layers()
|
||||
.map(|layer_path| LayerNodeIdentifier::from_path(layer_path, document.network()))
|
||||
.collect();
|
||||
shape_editor.set_selected_layers(layer_paths);
|
||||
let target_layers = document.document_legacy.metadata.selected_layers().collect();
|
||||
shape_editor.set_selected_layers(target_layers);
|
||||
}
|
||||
TypeBackspace => self.transform_operation.grs_typed(self.typing.type_backspace(), &mut selected, self.snap),
|
||||
TypeDecimalPoint => self.transform_operation.grs_typed(self.typing.type_decimal_point(), &mut selected, self.snap),
|
||||
|
|
|
@ -44,7 +44,7 @@ impl WasmApplicationIo {
|
|||
let executor = if let Some(gpu) = web_sys::window().map(|w| w.navigator().gpu()) {
|
||||
let request_adapter = || {
|
||||
let request_adapter = js_sys::Reflect::get(&gpu, &wasm_bindgen::JsValue::from_str("requestAdapter")).ok()?;
|
||||
let function = js_sys::Function::try_from(&request_adapter)?;
|
||||
let function = request_adapter.dyn_ref::<js_sys::Function>()?;
|
||||
Some(function.call0(&gpu).ok())
|
||||
};
|
||||
let result = request_adapter();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue