mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-18 18:38:05 +08:00
Refactor internal shape and reduce reliance on Kurbo (#617)
* Dissolve Points from path * Add handling for removing the first anchor * Add function to turn handles into bez_paths * Created overlay manager, wip * WIP Refactor of VectorShape / Overlays / ShapeEditor * WIP stripping vector shape, anchor, point. * WIP Removed kurbo deps from vector shape, anchor, point * WIP Further work to make vector shapes / anchors / points more standalone. * WIP more pruning * WIP Progress on overlay_renderer * WIP more overlay_renderer work * WIP more pruning, cleared warnings * WIP decided ShapeRenderer wasn't an accurate name, ShapeAdapter now. Error squashing continues. * WIP squashed more errors, now need to decide if anchors should have unique IDs * WIP Errors squashed, now to actually make it work. * WIP Moved vector structs to graphene, beginning to remove bezpath from shape_layer * Refactoring: disentangle kurbo from apply_affine * Refactor internal shape and remove reliance on Kurbo (PR #617) - Disentangle Kurbo (#619) * Refactoring: disentangle kurbo from apply_affine * Broke boolean operations, refactor in state which compiles * "fixed" boolean operation refactor related errors * fixed apply_affine, which would not have applied any type of affine * Small Cleanup, readability * Fix issue with overlay styles no longer showing selection state. * Resolved error with point option * WIP, figuring out how to have one source of truth for VectorShape. Trying to avoid cloning. * WIP work on single source of truth vectorshapes * More steps toward single source of truth VectorShape * Continued wip on making VectorShapes mutably accessible without cloning * Wip using paths to reference vectorshapes instead, need to restructure ShapeEditor * Decided to allow temporary copies of vectorshapes. * Removed HashSet for selected shape indices * Added @TrueDoctor's id_storage.rs with some heavy modification. Added it to VectorShape. Isn't yet used for folders. * Integrated UniqueElements<T> with VectorShape to store VectorAnchors * Improved storage_id.rs perf and cleaned up it's interface * Iterator Implementations and fixes (#637) * Refactoring: disentangle kurbo from apply_affine * Broke boolean operations, refactor in state which compiles * "fixed" boolean operation refactor related errors * fixed apply_affine, which would not have applied any type of affine * implemented transforms for VectorAnchors implemented Not for VectorControlPointType * started adding Vector Shape implementations of shape prototypes * added several useful implemtations to UniqueElements * added another implemnation for UniqueElements to make working with iterators easier, fixed vector-shape errors * package-lock.json * clean up rebase, added back Layer paths * added deref implementation for VectorShape * unnecesary variable * simplify code by removing levels of indirection * fixed errors * merge cleanup * removed package-lock.json * Removed .selected from VectorShape, it isn't needed as layers are selected not shapes specifically. * Removed transform and layer_path from VectorShape * Auto-saving tentitively working. Work toward Overlay transform issues. * Overlays properly hiding and caching. Not clearing cache yet and some tool switching issues remain, but progress. * Putting layers in folders changes their unique ID. This is problematic. Assumed this was not the case. * Removed need for closed bool, changed VectorShape to a tuple struct. * WIP Switched to layer paths as opposed to VectorShapes. Next up add messages for changing VectorShapes. * Added initial messages to edit VectorShape points. * DeleteSelectedPoints messages implemented, selection isn't working currently though. * Selection messages arriving in document, but transform is wrong. * Selection, Deselection working, delete working for first point. * Working towards moving points again * Removed extra vec from UniqueElements, attempting to squash ordering bug. Still appears to occur though. * Delete more stable, clean up, renamed to HandleIn, HandleOut * Further vec_unique cleanup * Further cleanup * Removed Deref / DerefMut from VectorShape * Document version++, will likely revert before merge into master * Seleting / deleting handles tentitively working again. * Version number bump, fixed tests. * Fixed comment in VecUnique * Improved VecUnique descriptor comment * Renamed VecUnique to IdBackedVec to further clarify usage. * Resolved formatting. * WIP Fixing dragging points * Fixed an instance where an OverlayMessage could be sent to the main document incorrectly. * Deleting all of a shapes points now gracefully deletes the layer instead of crashing. * Fixed handle configurations that would panic on deletion * Single anchor dragging restored with multi-dragging next plus handles * sides.into() * Handle and Multi-point dragging working * WIP Handle symmetry working again * Handle mirroring functional again. * Cleaned up warnings * Fixed overlay outline not matching shape * Git branch fix of compatibility with new master * Fixed closed shape bug, replaced kurbo ellipse * Removed unused func, updated comments * Deleting points can undo, multiple shape selection deletes now working * Removed AddOverlay* operations * Partial fix for select drift, added helpers * Don't snap against dragging points * Properly cleanup path outline with multiple shapes * Clear all points in other selected shapes * Actually don't snap against dragging points * Fix path tool & add snap angle and break handle * Fix handle being set to NaN causing render issues * Fix cached overlays not showing line -> curve * Add operations for modifying paths * Remove kurbo from pen tool * Do not snap against handles when anchor selected * Fix overlays not being cleaned up on path tool * Fix handle position after dragging * Use `Anchor` for text & no kurbo in operations * Replace kurbo to_svg function * Ngon no longer center scales by default, still some weird behaviour when holding alt * Cleanup overlays * Fix render and bounding box doctests * Fix fun to_svg error * Fix compile error * Some code review * Remove legacy `SelectPoint` on doubleclick * Remove font from test document * Fix the pen tool selection changed * Reorder imports Co-authored-by: Dennis <dennis@kobert.dev> Co-authored-by: Caleb Dennis <caleb.dennis429@gmail.com> Co-authored-by: caleb <56044292+caleb-ad@users.noreply.github.com> Co-authored-by: Keavon Chambers <keavon@keavon.com> Co-authored-by: 0hypercube <0hypercube@gmail.com> Co-authored-by: 0HyperCube <78500760+0HyperCube@users.noreply.github.com>
This commit is contained in:
committed by
Keavon Chambers
parent
3c2fff4465
commit
58675eb64d
@@ -53,7 +53,9 @@ pub enum DocumentMessage {
|
||||
layer_path: Vec<LayerId>,
|
||||
},
|
||||
DeleteSelectedLayers,
|
||||
DeleteSelectedVectorPoints,
|
||||
DeselectAllLayers,
|
||||
DeselectAllVectorPoints,
|
||||
DirtyRenderDocument,
|
||||
DirtyRenderDocumentInOutlineView,
|
||||
DocumentHistoryBackward,
|
||||
@@ -81,6 +83,11 @@ pub enum DocumentMessage {
|
||||
insert_index: isize,
|
||||
reverse_index: bool,
|
||||
},
|
||||
MoveSelectedVectorPoints {
|
||||
layer_path: Vec<LayerId>,
|
||||
delta: (f64, f64),
|
||||
absolute_position: (f64, f64),
|
||||
},
|
||||
NudgeSelectedLayers {
|
||||
delta_x: f64,
|
||||
delta_y: f64,
|
||||
@@ -144,6 +151,11 @@ pub enum DocumentMessage {
|
||||
ToggleLayerVisibility {
|
||||
layer_path: Vec<LayerId>,
|
||||
},
|
||||
ToggleSelectedHandleMirroring {
|
||||
layer_path: Vec<LayerId>,
|
||||
toggle_distance: bool,
|
||||
toggle_angle: bool,
|
||||
},
|
||||
Undo,
|
||||
UngroupLayers {
|
||||
folder_path: Vec<LayerId>,
|
||||
|
||||
@@ -14,7 +14,6 @@ use crate::layout::widgets::{
|
||||
SeparatorDirection, SeparatorType, Widget, WidgetCallback, WidgetHolder, WidgetLayout,
|
||||
};
|
||||
use crate::message_prelude::*;
|
||||
use crate::viewport_tools::vector_editor::vector_shape::VectorShape;
|
||||
use crate::EditorError;
|
||||
|
||||
use graphene::color::Color;
|
||||
@@ -24,6 +23,7 @@ use graphene::layers::folder_layer::FolderLayer;
|
||||
use graphene::layers::layer_info::{LayerDataType, LayerDataTypeDiscriminant};
|
||||
use graphene::layers::style::{Fill, RenderData, ViewMode};
|
||||
use graphene::layers::text_layer::{Font, FontCache};
|
||||
use graphene::layers::vector::vector_shape::VectorShape;
|
||||
use graphene::{DocumentError, DocumentResponse, LayerId, Operation as DocumentOperation};
|
||||
|
||||
use glam::{DAffine2, DVec2};
|
||||
@@ -158,28 +158,6 @@ impl DocumentMessageHandler {
|
||||
self.artboard_message_handler.artboards_graphene_document.bounding_box_and_transform(path, font_cache).unwrap_or(None)
|
||||
}
|
||||
|
||||
/// Create a new vector shape representation with the underlying kurbo data, VectorManipulatorShape
|
||||
pub fn selected_visible_layers_vector_shapes(&self, responses: &mut VecDeque<Message>, font_cache: &FontCache) -> Vec<VectorShape> {
|
||||
let shapes = self.selected_layers().filter_map(|path_to_shape| {
|
||||
let viewport_transform = self.graphene_document.generate_transform_relative_to_viewport(path_to_shape).ok()?;
|
||||
let layer = self.graphene_document.layer(path_to_shape);
|
||||
|
||||
match &layer {
|
||||
Ok(layer) if layer.visible => {}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
// TODO: Create VectorManipulatorShape when creating a kurbo shape as a stopgap, rather than on each new selection
|
||||
match &layer.ok()?.data {
|
||||
LayerDataType::Shape(shape) => Some(VectorShape::new(path_to_shape.to_vec(), viewport_transform, &shape.path, shape.closed, responses)),
|
||||
LayerDataType::Text(text) => Some(VectorShape::new(path_to_shape.to_vec(), viewport_transform, &text.to_bez_path_nonmut(font_cache), true, responses)),
|
||||
_ => None,
|
||||
}
|
||||
});
|
||||
|
||||
shapes.collect::<Vec<VectorShape>>()
|
||||
}
|
||||
|
||||
pub fn selected_layers(&self) -> impl Iterator<Item = &[LayerId]> {
|
||||
self.layer_metadata.iter().filter_map(|(path, data)| data.selected.then(|| path.as_slice()))
|
||||
}
|
||||
@@ -223,6 +201,22 @@ impl DocumentMessageHandler {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a copy of all the currently selected VectorShapes.
|
||||
pub fn selected_vector_shapes(&self) -> Vec<VectorShape> {
|
||||
self.selected_visible_layers()
|
||||
.flat_map(|layer| self.graphene_document.layer(layer))
|
||||
.flat_map(|layer| layer.as_vector_shape_copy())
|
||||
.collect::<Vec<VectorShape>>()
|
||||
}
|
||||
|
||||
/// Returns references to all the currently selected VectorShapes.
|
||||
pub fn selected_vector_shapes_ref(&self) -> Vec<&VectorShape> {
|
||||
self.selected_visible_layers()
|
||||
.flat_map(|layer| self.graphene_document.layer(layer))
|
||||
.flat_map(|layer| layer.as_vector_shape())
|
||||
.collect::<Vec<&VectorShape>>()
|
||||
}
|
||||
|
||||
/// Returns the bounding boxes for all visible layers and artboards, optionally excluding any paths.
|
||||
pub fn bounding_boxes<'a>(&'a self, ignore_document: Option<&'a Vec<Vec<LayerId>>>, ignore_artboard: Option<LayerId>, font_cache: &'a FontCache) -> impl Iterator<Item = [DVec2; 2]> + 'a {
|
||||
self.visible_layers()
|
||||
@@ -998,14 +992,28 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
|
||||
responses.push_front(BroadcastSignal::SelectionChanged.into());
|
||||
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
|
||||
}
|
||||
DeleteSelectedVectorPoints => {
|
||||
responses.push_back(StartTransaction.into());
|
||||
|
||||
responses.push_front(
|
||||
DocumentOperation::DeleteSelectedVectorPoints {
|
||||
layer_paths: self.selected_layers_without_children().iter().map(|path| path.to_vec()).collect(),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
DeselectAllLayers => {
|
||||
responses.push_front(SetSelectedLayers { replacement_selected_layers: vec![] }.into());
|
||||
self.layer_range_selection_reference.clear();
|
||||
}
|
||||
DeselectAllVectorPoints => {
|
||||
for layer_path in self.selected_layers_without_children() {
|
||||
responses.push_back(DocumentOperation::DeselectAllVectorPoints { layer_path: layer_path.to_vec() }.into());
|
||||
}
|
||||
}
|
||||
DirtyRenderDocument => {
|
||||
// Mark all non-overlay caches as dirty
|
||||
GrapheneDocument::mark_children_as_dirty(&mut self.graphene_document.root);
|
||||
|
||||
responses.push_back(DocumentMessage::RenderDocument.into());
|
||||
}
|
||||
DirtyRenderDocumentInOutlineView => {
|
||||
@@ -1163,6 +1171,12 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
MoveSelectedVectorPoints { layer_path, delta, absolute_position } => {
|
||||
self.backup(responses);
|
||||
if let Ok(_layer) = self.graphene_document.layer(&layer_path) {
|
||||
responses.push_back(DocumentOperation::MoveSelectedVectorPoints { layer_path, delta, absolute_position }.into());
|
||||
}
|
||||
}
|
||||
NudgeSelectedLayers { delta_x, delta_y } => {
|
||||
self.backup(responses);
|
||||
for path in self.selected_layers().map(|path| path.to_vec()) {
|
||||
@@ -1462,6 +1476,20 @@ impl MessageHandler<DocumentMessage, (&InputPreprocessorMessageHandler, &FontCac
|
||||
responses.push_back(DocumentOperation::ToggleLayerVisibility { path: layer_path }.into());
|
||||
responses.push_back(BroadcastSignal::DocumentIsDirty.into());
|
||||
}
|
||||
ToggleSelectedHandleMirroring {
|
||||
layer_path,
|
||||
toggle_distance,
|
||||
toggle_angle,
|
||||
} => {
|
||||
responses.push_back(
|
||||
DocumentOperation::SetSelectedHandleMirroring {
|
||||
layer_path,
|
||||
toggle_distance,
|
||||
toggle_angle,
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
Undo => {
|
||||
responses.push_back(BroadcastSignal::ToolAbort.into());
|
||||
responses.push_back(DocumentHistoryBackward.into());
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use super::clipboards::{CopyBufferEntry, INTERNAL_CLIPBOARD_COUNT};
|
||||
use super::{DocumentMessageHandler, MenuBarMessageHandler};
|
||||
use crate::consts::{DEFAULT_DOCUMENT_NAME, GRAPHITE_DOCUMENT_VERSION};
|
||||
use crate::dialog;
|
||||
use crate::frontend::utility_types::FrontendDocumentDetails;
|
||||
use crate::input::InputPreprocessorMessageHandler;
|
||||
use crate::layout::layout_message::LayoutTarget;
|
||||
use crate::layout::widgets::PropertyHolder;
|
||||
use crate::{dialog, message_prelude::*};
|
||||
use crate::message_prelude::*;
|
||||
|
||||
use graphene::layers::layer_info::LayerDataTypeDiscriminant;
|
||||
use graphene::layers::text_layer::{Font, FontCache};
|
||||
|
||||
Reference in New Issue
Block a user