Skip to content

Commit d672698

Browse files
committed
Refactor Align
1 parent d5f1dcb commit d672698

File tree

5 files changed

+41
-188
lines changed

5 files changed

+41
-188
lines changed

core/document/src/document.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -147,22 +147,12 @@ impl Document {
147147
self.folder_mut(path)?.remove_layer(id)
148148
}
149149

150-
pub fn layer_axis_aligned_bounding_box(&self, path: &[LayerId]) -> Result<Option<[DVec2; 2]>, DocumentError> {
151-
// TODO: Replace with functions of the transform api
152-
if path.is_empty() {
153-
// Special case for root. Root's local is the documents global, so we avoid transforming its transform by itself.
154-
self.layer_local_bounding_box(path)
155-
} else {
156-
let layer = self.layer(path)?;
157-
Ok(layer.data.bounding_box(self.root.transform * layer.transform))
158-
}
159-
}
160-
161-
pub fn layer_local_bounding_box(&self, path: &[LayerId]) -> Result<Option<[DVec2; 2]>, DocumentError> {
162-
// TODO: Replace with functions of the transform api
150+
pub fn viewport_bounding_box(&self, path: &[LayerId]) -> Result<Option<[DVec2; 2]>, DocumentError> {
163151
let layer = self.layer(path)?;
164-
Ok(layer.data.bounding_box(layer.transform))
152+
let transform = self.multiply_transoforms(path)?;
153+
Ok(layer.data.bounding_box(transform))
165154
}
155+
166156
pub fn mark_upstream_as_dirty(&mut self, path: &[LayerId]) -> Result<(), DocumentError> {
167157
let mut root = &mut self.root;
168158
root.cache_dirty = true;
@@ -228,15 +218,13 @@ impl Document {
228218

229219
pub fn transform_in_scope(&mut self, layer: &[LayerId], scope: Option<&[LayerId]>, transform: DAffine2) -> Result<(), DocumentError> {
230220
let to = self.generate_transform(&layer[..layer.len() - 1], scope)?;
231-
log::info!("transform: {:?} to: {:?}, ", transform, to);
232221
let layer = self.layer_mut(layer)?;
233222
layer.transform = to * transform * to.inverse() * layer.transform;
234223
Ok(())
235224
}
236225

237226
pub fn set_transform_in_scope(&mut self, layer: &[LayerId], scope: Option<&[LayerId]>, transform: DAffine2) -> Result<(), DocumentError> {
238227
let to = self.generate_transform(&layer[..layer.len() - 1], scope)?;
239-
log::info!("transform: {:?} to: {:?}, ", transform, to);
240228
let layer = self.layer_mut(layer)?;
241229
layer.transform = to * transform;
242230
Ok(())

core/document/src/layers/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ impl Layer {
126126
return;
127127
}
128128
let transformed_quad = self.transform.inverse() * quad;
129-
log::debug!("{:?} quad: {:?}\n transformed: {:?}", path, quad, transformed_quad);
130129
self.data.intersects_quad(transformed_quad, path, intersections)
131130
}
132131

core/editor/src/document/document_file.rs

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -365,16 +365,10 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
365365
.into(),
366366
),
367367
NudgeSelectedLayers(x, y) => {
368-
let delta = {
369-
let root_layer_rotation = self.layerdata_mut(&[]).rotation;
370-
let rotate_to_viewport_space = DAffine2::from_angle(root_layer_rotation).inverse();
371-
rotate_to_viewport_space.transform_point2((x, y).into())
372-
};
373-
let foo = ();
374368
for path in self.selected_layers().cloned() {
375-
let operation = DocumentOperation::TransformLayer {
369+
let operation = DocumentOperation::TransformLayerInViewport {
376370
path,
377-
transform: DAffine2::from_translation(delta).to_cols_array(),
371+
transform: DAffine2::from_translation((x, y).into()).to_cols_array(),
378372
};
379373
responses.push_back(operation.into());
380374
}
@@ -418,9 +412,9 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
418412
if let Ok(layer) = self.document.layer_mut(&path) {
419413
let scale = DVec2::new(if flip_horizontal { -1. } else { 1. }, if flip_vertical { -1. } else { 1. });
420414
responses.push_back(
421-
DocumentOperation::SetLayerTransform {
415+
DocumentOperation::TransformLayerInViewport {
422416
path,
423-
transform: (layer.transform * DAffine2::from_scale(scale)).to_cols_array(),
417+
transform: DAffine2::from_scale(scale).to_cols_array(),
424418
}
425419
.into(),
426420
);
@@ -477,53 +471,33 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
477471
}
478472
}
479473
AlignSelectedLayers(axis, aggregate) => {
480-
// TODO: Handle folder nested transforms with the transforms API
481-
if self.selected_layers().next().is_none() {
482-
return;
483-
}
474+
let (paths, boxes): (Vec<_>, Vec<_>) = self.selected_layers().filter_map(|path| self.document.viewport_bounding_box(path).ok()?.map(|b| (path, b))).unzip();
484475

485-
let selected_layers = self.selected_layers().cloned().filter_map(|path| {
486-
let layer = self.document.layer(&path).ok()?;
487-
let point = {
488-
let bounding_box = layer.current_bounding_box()?;
489-
match aggregate {
490-
AlignAggregate::Min => bounding_box[0],
491-
AlignAggregate::Max => bounding_box[1],
492-
AlignAggregate::Center => bounding_box[0].lerp(bounding_box[1], 0.5),
493-
AlignAggregate::Average => bounding_box[0].lerp(bounding_box[1], 0.5),
494-
}
495-
};
496-
let (bounding_box_coord, translation_coord) = match axis {
497-
AlignAxis::X => (point.x, layer.transform.translation.x),
498-
AlignAxis::Y => (point.y, layer.transform.translation.y),
499-
};
500-
Some((path, bounding_box_coord, translation_coord))
501-
});
502-
let selected_layers: Vec<_> = selected_layers.collect();
503-
504-
let bounding_box_coords = selected_layers.iter().map(|(_, bounding_box_coord, _)| bounding_box_coord).cloned();
476+
let axis = match axis {
477+
AlignAxis::X => DVec2::X,
478+
AlignAxis::Y => DVec2::Y,
479+
};
480+
let lerp = |bbox: &[DVec2; 2]| bbox[0].lerp(bbox[1], 0.5);
505481
if let Some(aggregated_coord) = match aggregate {
506-
AlignAggregate::Min => bounding_box_coords.reduce(|a, b| a.min(b)),
507-
AlignAggregate::Max => bounding_box_coords.reduce(|a, b| a.max(b)),
508-
AlignAggregate::Center => {
509-
// TODO: Refactor with `reduce` and `merge_bounding_boxes` once the latter is added
510-
self.selected_layers()
511-
.filter_map(|path| self.document.layer(path).ok().map(|layer| layer.current_bounding_box()).flatten())
512-
.map(|bbox| match axis {
513-
AlignAxis::X => (bbox[0].x, bbox[1].x),
514-
AlignAxis::Y => (bbox[0].y, bbox[1].y),
515-
})
516-
.reduce(|(a, b), (c, d)| (a.min(c), b.max(d)))
517-
.map(|(min, max)| (min + max) / 2.)
518-
}
519-
AlignAggregate::Average => Some(bounding_box_coords.sum::<f64>() / selected_layers.len() as f64),
482+
AlignAggregate::Min => boxes.iter().map(|b| b[0]).reduce(|a, b| a.min(b)),
483+
AlignAggregate::Max => boxes.iter().map(|b| b[1]).reduce(|a, b| a.max(b)),
484+
AlignAggregate::Center => boxes.iter().map(|b| (lerp(b), lerp(b))).reduce(|a, b| (a.0.min(b.0), a.1.max(b.1))).map(|(min, max)| (min + max) / 2.),
485+
AlignAggregate::Average => boxes.iter().map(|b| lerp(b)).reduce(|a, b| a + b).map(|b| b / boxes.len() as f64),
520486
} {
521-
for (path, bounding_box_coord, translation_coord) in selected_layers {
522-
let new_coord = aggregated_coord - (bounding_box_coord - translation_coord);
523-
/*match axis {
524-
AlignAxis::X => responses.push_back(DocumentMessage::SetLayerTranslation(path, Some(new_coord), None).into()),
525-
AlignAxis::Y => responses.push_back(DocumentMessage::SetLayerTranslation(path, None, Some(new_coord)).into()),
526-
}*/
487+
for (path, bbox) in paths.into_iter().zip(boxes) {
488+
let center = match aggregate {
489+
AlignAggregate::Min => bbox[0],
490+
AlignAggregate::Max => bbox[1],
491+
_ => lerp(&bbox),
492+
};
493+
let translation = (aggregated_coord - center) * axis;
494+
responses.push_back(
495+
DocumentOperation::TransformLayerInViewport {
496+
path: path.clone(),
497+
transform: DAffine2::from_translation(translation).to_cols_array(),
498+
}
499+
.into(),
500+
);
527501
}
528502
}
529503
}

core/editor/src/tool/tools/eyedropper.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ pub enum EyedropperMessage {
1818
impl<'a> MessageHandler<ToolMessage, ToolActionHandlerData<'a>> for Eyedropper {
1919
fn process_action(&mut self, action: ToolMessage, data: ToolActionHandlerData<'a>, responses: &mut VecDeque<Message>) {
2020
let mouse_pos = data.2.mouse.position;
21-
let (x, y) = (mouse_pos.x as f64, mouse_pos.y as f64);
2221
let tolerance = DVec2::splat(SELECTION_TOLERANCE);
2322
let quad = Quad::from_box([mouse_pos.as_f64() - tolerance, mouse_pos.as_f64() + tolerance]);
2423

core/editor/src/tool/tools/select.rs

Lines changed: 9 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl Fsm for SelectToolFsmState {
9393
self,
9494
event: ToolMessage,
9595
document: &DocumentMessageHandler,
96-
tool_data: &DocumentToolData,
96+
_tool_data: &DocumentToolData,
9797
data: &mut Self::ToolData,
9898
input: &InputPreprocessor,
9999
responses: &mut VecDeque<Message>,
@@ -108,14 +108,19 @@ impl Fsm for SelectToolFsmState {
108108
let mut selected: Vec<_> = document.selected_layers().cloned().collect();
109109
let quad = data.selection_quad();
110110
let intersection = document.document.intersects_quad_root(quad);
111+
// If no layer is currently selected and the user clicks on a shape, select that.
111112
if selected.is_empty() {
112113
if let Some(layer) = intersection.last() {
113114
selected.push(layer.clone());
114115
responses.push_back(DocumentMessage::SelectLayers(selected.clone()).into());
115116
}
116117
}
117-
if !selected.iter().any(|path| intersection.contains(path)) {
118-
log::debug!("drawing stuff");
118+
// If the user clicks on a layer that is in their current selection, go into the dragging mode.
119+
// Otherwise enter the box select mode
120+
if selected.iter().any(|path| intersection.contains(path)) {
121+
data.layers_dragging = selected;
122+
Dragging
123+
} else {
119124
responses.push_back(DocumentMessage::DeselectAllLayers.into());
120125
data.box_id = Some(vec![generate_hash(&*responses, input, document.document.hash())]);
121126
responses.push_back(
@@ -127,14 +132,9 @@ impl Fsm for SelectToolFsmState {
127132
.into(),
128133
);
129134
DrawingBox
130-
} else {
131-
data.layers_dragging = selected;
132-
log::debug!("dragging stuff around: {:?}", data.layers_dragging);
133-
Dragging
134135
}
135136
}
136137
(Dragging, MouseMove) => {
137-
log::debug!("dragging delta: {:?}", input.mouse.position.as_f64() - data.drag_current.as_f64());
138138
for path in data.layers_dragging.iter() {
139139
responses.push_back(
140140
Operation::TransformLayerInViewport {
@@ -152,7 +152,6 @@ impl Fsm for SelectToolFsmState {
152152
let start = data.drag_start.as_f64();
153153
let size = data.drag_current.as_f64() - start;
154154

155-
log::debug!("changing transform {:?} {:?} {:?}", data.box_id, start, size);
156155
responses.push_back(
157156
Operation::SetLayerTransformInViewport {
158157
path: data.box_id.clone().unwrap(),
@@ -173,97 +172,6 @@ impl Fsm for SelectToolFsmState {
173172
responses.push_back(Operation::DeleteLayer { path: data.box_id.take().unwrap() }.into());
174173
Ready
175174
}
176-
/*
177-
let (point_1, point_2) = {
178-
let (x, y) = (data.drag_start.x as f64, data.drag_start.y as f64);
179-
(
180-
DVec2::new(x - SELECTION_TOLERANCE, y - SELECTION_TOLERANCE),
181-
DVec2::new(x + SELECTION_TOLERANCE, y + SELECTION_TOLERANCE),
182-
)
183-
};
184-
185-
let quad = [
186-
DVec2::new(point_1.x, point_1.y),
187-
DVec2::new(point_2.x, point_1.y),
188-
DVec2::new(point_2.x, point_2.y),
189-
DVec2::new(point_1.x, point_2.y),
190-
];
191-
192-
if let Some(intersection) = document.document.intersects_quad_root(quad).last() {
193-
// TODO: Replace root transformations with functions of the transform api
194-
let transformed_start = document.document.root.transform.inverse().transform_vector2(data.drag_start.as_f64());
195-
if document.layer_data.get(intersection).map_or(false, |layer_data| layer_data.selected) {
196-
data.layers_dragging = document
197-
.layer_data
198-
.iter()
199-
.filter_map(|(path, layer_data)| {
200-
layer_data
201-
.selected
202-
.then(|| document.document.layer(path).ok().map(|layer| (path.clone(), layer.transform.translation - transformed_start)))
203-
.flatten()
204-
})
205-
.collect();
206-
} else {
207-
responses.push_back(DocumentMessage::SelectLayers(vec![intersection.clone()]).into());
208-
data.layers_dragging = vec![(intersection.clone(), document.document.layer(intersection).unwrap().transform.translation - transformed_start)]
209-
}
210-
} else {
211-
responses.push_back(DocumentMessage::StartTransaction.into());
212-
data.layers_dragging = Vec::new();
213-
}
214-
215-
Dragging
216-
}
217-
(Dragging, MouseMove) => {
218-
data.drag_current = input.mouse.position;
219-
220-
if data.layers_dragging.is_empty() {
221-
responses.push_back(DocumentMessage::RollbackTransaction.into());
222-
responses.push_back(make_operation(data, tool_data, transform));
223-
} else {
224-
for (path, offset) in &data.layers_dragging {
225-
responses.push_back(DocumentMessage::DragLayer(path.clone(), *offset).into());
226-
}
227-
}
228-
229-
Dragging
230-
}
231-
(Dragging, DragStop) => {
232-
data.drag_current = input.mouse.position;
233-
234-
if data.layers_dragging.is_empty() {
235-
responses.push_back(DocumentMessage::RollbackTransaction.into());
236-
responses.push_back(DocumentMessage::AbortTransaction.into());
237-
238-
if data.drag_start == data.drag_current {
239-
responses.push_back(DocumentMessage::SelectLayers(vec![]).into());
240-
} else {
241-
let (point_1, point_2) = (
242-
DVec2::new(data.drag_start.x as f64, data.drag_start.y as f64),
243-
DVec2::new(data.drag_current.x as f64, data.drag_current.y as f64),
244-
);
245-
246-
let quad = [
247-
DVec2::new(point_1.x, point_1.y),
248-
DVec2::new(point_2.x, point_1.y),
249-
DVec2::new(point_2.x, point_2.y),
250-
DVec2::new(point_1.x, point_2.y),
251-
];
252-
253-
responses.push_back(DocumentMessage::SelectLayers(document.document.intersects_quad_root(quad)).into());
254-
}
255-
} else {
256-
data.layers_dragging = Vec::new();
257-
}
258-
259-
Ready
260-
}
261-
(Dragging, Abort) => {
262-
responses.push_back(DocumentMessage::AbortTransaction.into());
263-
data.layers_dragging = Vec::new();
264-
265-
Ready
266-
}
267175
(_, Align(axis, aggregate)) => {
268176
responses.push_back(DocumentMessage::AlignSelectedLayers(axis, aggregate).into());
269177

@@ -278,26 +186,11 @@ impl Fsm for SelectToolFsmState {
278186
responses.push_back(DocumentMessage::FlipSelectedLayers(FlipAxis::Y).into());
279187

280188
self
281-
}*/
189+
}
282190
_ => self,
283191
}
284192
} else {
285193
self
286194
}
287195
}
288196
}
289-
290-
fn make_operation(data: &SelectToolData, _tool_data: &DocumentToolData, transform: DAffine2) -> Message {
291-
let x0 = data.drag_start.x as f64;
292-
let y0 = data.drag_start.y as f64;
293-
let x1 = data.drag_current.x as f64;
294-
let y1 = data.drag_current.y as f64;
295-
296-
Operation::AddRect {
297-
path: vec![],
298-
insert_index: -1,
299-
transform: (transform.inverse() * glam::DAffine2::from_scale_angle_translation(DVec2::new(x1 - x0, y1 - y0), 0., DVec2::new(x0, y0))).to_cols_array(),
300-
style: style::PathStyle::new(Some(Stroke::new(Color::from_rgb8(0x31, 0x94, 0xD6), 2.0)), Some(Fill::none())),
301-
}
302-
.into()
303-
}

0 commit comments

Comments
 (0)