Fix transforms, Brush tool, and G/R/S (#1473)

* Transform fixes

* Fix the desert artwork

* Change artboard icon

* Better handling when transforming brush strokes

* Code review pass

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube
2023-11-27 04:54:06 +00:00
committed by GitHub
parent 5ee79031ab
commit b2ca643e6e
26 changed files with 308 additions and 238 deletions

View File

@@ -156,6 +156,8 @@ impl Document {
pub fn click(&self, viewport_location: DVec2, network: &NodeNetwork) -> Option<LayerNodeIdentifier> {
self.click_xray(viewport_location).find(|&layer| !is_artboard(layer, network))
}
/// Get the combined bounding box of the click targets of the selected visible layers in viewport space
pub fn selected_visible_layers_bounding_box_viewport(&self) -> Option<[DVec2; 2]> {
self.selected_visible_layers()
.filter_map(|layer| self.metadata.bounding_box_viewport(layer))

View File

@@ -222,7 +222,16 @@ fn sibling_below<'a>(graph: &'a NodeNetwork, node: &DocumentNode) -> Option<(&'a
// transforms
impl DocumentMetadata {
/// Update the cached transforms of the layers
pub fn update_transforms(&mut self, new_transforms: HashMap<LayerNodeIdentifier, DAffine2>, new_upstream_transforms: HashMap<NodeId, DAffine2>) {
pub fn update_transforms(&mut self, mut new_transforms: HashMap<LayerNodeIdentifier, DAffine2>, new_upstream_transforms: HashMap<NodeId, DAffine2>) {
let mut stack = vec![(LayerNodeIdentifier::ROOT, DAffine2::IDENTITY)];
while let Some((layer, transform)) = stack.pop() {
for child in layer.children(self) {
let Some(new_transform) = new_transforms.get_mut(&child) else { continue };
*new_transform = transform * *new_transform;
stack.push((child, *new_transform));
}
}
self.transforms = new_transforms;
self.upstream_transforms = new_upstream_transforms;
}
@@ -235,6 +244,10 @@ impl DocumentMetadata {
})
}
pub fn local_transform(&self, layer: LayerNodeIdentifier) -> DAffine2 {
self.transform_to_document(layer.parent(self).unwrap_or_default()).inverse() * self.transform_to_document(layer)
}
pub fn transform_to_viewport(&self, layer: LayerNodeIdentifier) -> DAffine2 {
self.document_to_viewport * self.transform_to_document(layer)
}
@@ -299,11 +312,16 @@ impl DocumentMetadata {
self.bounding_box_with_transform(layer, self.transform_to_viewport(layer))
}
/// Calculates the document bounds used for scrolling and centring (the layer bounds or the artboard (if applicable))
pub fn document_bounds(&self) -> Option<[DVec2; 2]> {
/// Calculates the document bounds in viewport space
pub fn document_bounds_viewport_space(&self) -> Option<[DVec2; 2]> {
self.all_layers().filter_map(|layer| self.bounding_box_viewport(layer)).reduce(Quad::combine_bounds)
}
/// Calculates the document bounds in document space
pub fn document_bounds_document_space(&self) -> Option<[DVec2; 2]> {
self.all_layers().filter_map(|layer| self.bounding_box_document(layer)).reduce(Quad::combine_bounds)
}
pub fn layer_outline(&self, layer: LayerNodeIdentifier) -> graphene_core::vector::Subpath {
let Some(click_targets) = self.click_targets.get(&layer) else {
return graphene_core::vector::Subpath::new();
@@ -546,8 +564,8 @@ impl From<NodeId> for LayerNodeIdentifier {
}
impl From<LayerNodeIdentifier> for NodeId {
fn from(identifer: LayerNodeIdentifier) -> Self {
identifer.to_node()
fn from(identifier: LayerNodeIdentifier) -> Self {
identifier.to_node()
}
}

View File

@@ -49,6 +49,7 @@ pub enum LayerDataTypeDiscriminant {
Folder,
Shape,
Layer,
Artboard,
}
impl fmt::Display for LayerDataTypeDiscriminant {
@@ -57,6 +58,7 @@ impl fmt::Display for LayerDataTypeDiscriminant {
LayerDataTypeDiscriminant::Folder => write!(f, "Folder"),
LayerDataTypeDiscriminant::Shape => write!(f, "Shape"),
LayerDataTypeDiscriminant::Layer => write!(f, "Layer"),
LayerDataTypeDiscriminant::Artboard => write!(f, "Artboard"),
}
}
}