mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-27 09:58:12 +08:00
Change flipping to use the joint bounding box of the selection (#323)
* Change flipping to use the joint bounding box * Fix minor untested changes * Replace unwrap with question mark
This commit is contained in:
committed by
Keavon Chambers
parent
170cda7357
commit
4cf0686801
@@ -58,7 +58,7 @@ pub enum DocumentMessage {
|
|||||||
WheelCanvasZoom,
|
WheelCanvasZoom,
|
||||||
SetCanvasRotation(f64),
|
SetCanvasRotation(f64),
|
||||||
NudgeSelectedLayers(f64, f64),
|
NudgeSelectedLayers(f64, f64),
|
||||||
FlipLayer(Vec<LayerId>, bool, bool),
|
FlipSelectedLayers(FlipAxis),
|
||||||
AlignSelectedLayers(AlignAxis, AlignAggregate),
|
AlignSelectedLayers(AlignAxis, AlignAggregate),
|
||||||
DragLayer(Vec<LayerId>, DVec2),
|
DragLayer(Vec<LayerId>, DVec2),
|
||||||
MoveSelectedLayersTo { path: Vec<LayerId>, insert_index: isize },
|
MoveSelectedLayersTo { path: Vec<LayerId>, insert_index: isize },
|
||||||
@@ -66,6 +66,12 @@ pub enum DocumentMessage {
|
|||||||
SetLayerTranslation(Vec<LayerId>, Option<f64>, Option<f64>),
|
SetLayerTranslation(Vec<LayerId>, Option<f64>, Option<f64>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum FlipAxis {
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
|
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum AlignAxis {
|
pub enum AlignAxis {
|
||||||
X,
|
X,
|
||||||
@@ -652,13 +658,52 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FlipLayer(path, flip_horizontal, flip_vertical) => {
|
FlipSelectedLayers(axis) => {
|
||||||
if let Ok(layer) = self.active_document_mut().document.layer_mut(&path) {
|
// TODO: Handle folder nested transforms with the transforms API
|
||||||
let scale = DVec2::new(if flip_horizontal { -1. } else { 1. }, if flip_vertical { -1. } else { 1. });
|
let selected_paths = self.selected_layers_sorted();
|
||||||
|
if selected_paths.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let selected_layers = selected_paths.iter().filter_map(|path| {
|
||||||
|
let layer = self.active_document().document.layer(path).ok()?;
|
||||||
|
// TODO: Refactor with `reduce` and `merge_bounding_boxes` once the latter is added
|
||||||
|
let (min, max) = {
|
||||||
|
let bounding_box = layer.bounding_box(layer.transform, layer.style)?;
|
||||||
|
match axis {
|
||||||
|
FlipAxis::X => (bounding_box[0].x, bounding_box[1].x),
|
||||||
|
FlipAxis::Y => (bounding_box[0].y, bounding_box[1].y),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some((path.clone(), (min, max)))
|
||||||
|
});
|
||||||
|
|
||||||
|
let (min, max) = selected_layers
|
||||||
|
.clone()
|
||||||
|
.map(|(_, extrema)| extrema)
|
||||||
|
.reduce(|(min_a, max_a), (min_b, max_b)| (min_a.min(min_b), max_a.max(max_b)))
|
||||||
|
.unwrap();
|
||||||
|
let middle = (min + max) / 2.;
|
||||||
|
|
||||||
|
for (path, _) in selected_layers {
|
||||||
|
let layer = self.active_document().document.layer(&path).unwrap();
|
||||||
|
let mut transform = layer.transform;
|
||||||
|
let scale = match axis {
|
||||||
|
FlipAxis::X => DVec2::new(-1., 1.),
|
||||||
|
FlipAxis::Y => DVec2::new(1., -1.),
|
||||||
|
};
|
||||||
|
transform = transform * DAffine2::from_scale(scale);
|
||||||
|
|
||||||
|
let coord = match axis {
|
||||||
|
FlipAxis::X => &mut transform.translation.x,
|
||||||
|
FlipAxis::Y => &mut transform.translation.y,
|
||||||
|
};
|
||||||
|
*coord = *coord - 2. * (*coord - middle);
|
||||||
|
|
||||||
responses.push_back(
|
responses.push_back(
|
||||||
DocumentOperation::SetLayerTransform {
|
DocumentOperation::SetLayerTransform {
|
||||||
path,
|
path,
|
||||||
transform: (layer.transform * DAffine2::from_scale(scale)).to_cols_array(),
|
transform: transform.to_cols_array(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ mod document_message_handler;
|
|||||||
pub use document_file::{Document, LayerData};
|
pub use document_file::{Document, LayerData};
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use document_message_handler::{AlignAggregate, AlignAxis, DocumentMessage, DocumentMessageDiscriminant, DocumentMessageHandler};
|
pub use document_message_handler::{AlignAggregate, AlignAxis, DocumentMessage, DocumentMessageDiscriminant, DocumentMessageHandler, FlipAxis};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use crate::input::{mouse::ViewportPosition, InputPreprocessor};
|
|||||||
use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData};
|
use crate::tool::{DocumentToolData, Fsm, ToolActionHandlerData};
|
||||||
use crate::{
|
use crate::{
|
||||||
consts::SELECTION_TOLERANCE,
|
consts::SELECTION_TOLERANCE,
|
||||||
document::{AlignAggregate, AlignAxis, Document},
|
document::{AlignAggregate, AlignAxis, Document, FlipAxis},
|
||||||
message_prelude::*,
|
message_prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -173,18 +173,12 @@ impl Fsm for SelectToolFsmState {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
(_, FlipHorizontal) => {
|
(_, FlipHorizontal) => {
|
||||||
let selected_layers = document.layer_data.iter().filter_map(|(path, data)| data.selected.then(|| path.clone()));
|
responses.push_back(DocumentMessage::FlipSelectedLayers(FlipAxis::X).into());
|
||||||
for path in selected_layers {
|
|
||||||
responses.push_back(DocumentMessage::FlipLayer(path, true, false).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
(_, FlipVertical) => {
|
(_, FlipVertical) => {
|
||||||
let selected_layers = document.layer_data.iter().filter_map(|(path, data)| data.selected.then(|| path.clone()));
|
responses.push_back(DocumentMessage::FlipSelectedLayers(FlipAxis::Y).into());
|
||||||
for path in selected_layers {
|
|
||||||
responses.push_back(DocumentMessage::FlipLayer(path, false, true).into());
|
|
||||||
}
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user