Do not transform layers when transforming a parent folder (#481)

* Modify all message enum data to use named struct values, not tuples (#479)

* Massively reorganize and clean up the whole Rust codebase

* Modify all message enum data to use named struct values, not tuples

* Do not transform layers when transforming parent

* Reduce complexity to O(nlogn)

* Add TODO comment about performance

Co-authored-by: Keavon Chambers <keavon@keavon.com>
Co-authored-by: Dennis <dennis@kobert.dev>
This commit is contained in:
0HyperCube
2022-01-16 08:55:45 -08:00
committed by Keavon Chambers
co-authored by Keavon Chambers Dennis
parent bd3191f16e
commit adcd7cd9a3
4 changed files with 9 additions and 6 deletions
@@ -181,7 +181,7 @@ impl DocumentMessageHandler {
} }
pub fn selected_layers_without_children(&self) -> Vec<&[LayerId]> { pub fn selected_layers_without_children(&self) -> Vec<&[LayerId]> {
let unique_layers = self.graphene_document.shallowest_unique_layers(self.selected_layers()); let unique_layers = GrapheneDocument::shallowest_unique_layers(self.selected_layers());
// We need to maintain layer ordering // We need to maintain layer ordering
self.sort_layers(unique_layers.iter().copied()) self.sort_layers(unique_layers.iter().copied())
+2 -1
View File
@@ -241,7 +241,8 @@ impl<'a> Selected<'a> {
let pivot = DAffine2::from_translation(*self.pivot); let pivot = DAffine2::from_translation(*self.pivot);
let transformation = pivot * delta * pivot.inverse(); let transformation = pivot * delta * pivot.inverse();
for layer_path in &self.selected { // TODO: Cache the result of `shallowest_unique_layers` to avoid this heavy computation every frame of movement, see https://github.com/GraphiteEditor/Graphite/pull/481
for layer_path in Document::shallowest_unique_layers(self.selected.iter().map(|path| path.as_slice())) {
let parent_folder_path = &layer_path[..layer_path.len() - 1]; let parent_folder_path = &layer_path[..layer_path.len() - 1];
let original_layer_transforms = *self.original_transforms.get(layer_path).unwrap(); let original_layer_transforms = *self.original_transforms.get(layer_path).unwrap();
+4 -2
View File
@@ -10,6 +10,7 @@ use crate::misc::{HintData, HintGroup, HintInfo, KeysGroup};
use crate::viewport_tools::snapping::SnapHandler; use crate::viewport_tools::snapping::SnapHandler;
use crate::viewport_tools::tool::{DocumentToolData, Fsm, ToolActionHandlerData}; use crate::viewport_tools::tool::{DocumentToolData, Fsm, ToolActionHandlerData};
use graphene::document::Document;
use graphene::intersection::Quad; use graphene::intersection::Quad;
use graphene::layers::style::{self, Fill, Stroke}; use graphene::layers::style::{self, Fill, Stroke};
use graphene::Operation; use graphene::Operation;
@@ -225,10 +226,11 @@ impl Fsm for SelectToolFsmState {
let mouse_delta = mouse_position - data.drag_current; let mouse_delta = mouse_position - data.drag_current;
let closest_move = data.snap_handler.snap_layers(document, &data.layers_dragging, mouse_delta); let closest_move = data.snap_handler.snap_layers(document, &data.layers_dragging, mouse_delta);
for path in data.layers_dragging.iter() { // TODO: Cache the result of `shallowest_unique_layers` to avoid this heavy computation every frame of movement, see https://github.com/GraphiteEditor/Graphite/pull/481
for path in Document::shallowest_unique_layers(data.layers_dragging.iter().map(|path| path.as_slice())) {
responses.push_front( responses.push_front(
Operation::TransformLayerInViewport { Operation::TransformLayerInViewport {
path: path.clone(), path: path.to_vec(),
transform: DAffine2::from_translation(mouse_delta + closest_move).to_cols_array(), transform: DAffine2::from_translation(mouse_delta + closest_move).to_cols_array(),
} }
.into(), .into(),
+2 -2
View File
@@ -114,11 +114,11 @@ impl Document {
// Return returns all folders that are not contained in any other of the given folders // Return returns all folders that are not contained in any other of the given folders
pub fn shallowest_folders<'a>(&'a self, layers: impl Iterator<Item = &'a [LayerId]>) -> Vec<&[LayerId]> { pub fn shallowest_folders<'a>(&'a self, layers: impl Iterator<Item = &'a [LayerId]>) -> Vec<&[LayerId]> {
self.shallowest_unique_layers(self.folders(layers)) Self::shallowest_unique_layers(self.folders(layers))
} }
// Return returns all layers that are not contained in any other of the given folders // Return returns all layers that are not contained in any other of the given folders
pub fn shallowest_unique_layers<'a>(&'a self, layers: impl Iterator<Item = &'a [LayerId]>) -> Vec<&[LayerId]> { pub fn shallowest_unique_layers<'a>(layers: impl Iterator<Item = &'a [LayerId]>) -> Vec<&'a [LayerId]> {
let mut sorted_layers: Vec<_> = layers.collect(); let mut sorted_layers: Vec<_> = layers.collect();
sorted_layers.sort(); sorted_layers.sort();
// Sorting here creates groups of similar UUID paths // Sorting here creates groups of similar UUID paths