Add dragging of layers with the select tool (#293)

* Add dragging of layers with the select tool

* Transform mouse positions based on root transform

* Add TODOs regarding root inverse transforms
This commit is contained in:
Henry Sloan 2021-07-23 21:51:14 -04:00 committed by GitHub
parent ac7b5dd06e
commit d15d7d0fab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 28 deletions

View file

@ -57,6 +57,7 @@ pub enum DocumentMessage {
SetCanvasRotation(f64),
NudgeSelectedLayers(f64, f64),
FlipLayer(Vec<LayerId>, bool, bool),
DragLayer(Vec<LayerId>, DVec2),
MoveSelectedLayersTo { path: Vec<LayerId>, insert_index: isize },
ReorderSelectedLayers(i32), // relatve_position,
}
@ -647,6 +648,20 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
);
}
}
DragLayer(path, offset) => {
// TODO: Replace root transformations with functions of the transform api
// and do the same with all instances of `root.transform.inverse()` in other messages
let transformed_mouse_pos = self.active_document().document.root.transform.inverse().transform_vector2(ipp.mouse.position.as_dvec2());
let translation = offset + transformed_mouse_pos;
if let Ok(layer) = self.active_document_mut().document.layer_mut(&path) {
let transform = {
let mut transform = layer.transform;
transform.translation = translation;
transform.to_cols_array()
};
responses.push_back(DocumentOperation::SetLayerTransform { path, transform }.into());
}
}
message => todo!("document_action_handler does not implement: {}", message.to_discriminant().global_name()),
}
}

View file

@ -57,6 +57,7 @@ impl Default for SelectToolFsmState {
struct SelectToolData {
drag_start: ViewportPosition,
drag_current: ViewportPosition,
layers_dragging: Vec<(Vec<LayerId>, DVec2)>, // Paths and offsets
}
impl Fsm for SelectToolFsmState {
@ -71,33 +72,13 @@ impl Fsm for SelectToolFsmState {
(Ready, DragStart) => {
data.drag_start = input.mouse.position;
data.drag_current = input.mouse.position;
responses.push_back(Operation::MountWorkingFolder { path: vec![] }.into());
Dragging
}
(Dragging, MouseMove) => {
data.drag_current = input.mouse.position;
responses.push_back(Operation::ClearWorkingFolder.into());
responses.push_back(make_operation(data, tool_data, transform));
Dragging
}
(Dragging, DragStop) => {
data.drag_current = input.mouse.position;
responses.push_back(Operation::ClearWorkingFolder.into());
let (point_1, point_2) = if data.drag_start == data.drag_current {
let (x, y) = (data.drag_current.x as f64, data.drag_current.y as f64);
let (point_1, point_2) = {
let (x, y) = (data.drag_start.x as f64, data.drag_start.y as f64);
(
DVec2::new(x - SELECTION_TOLERANCE, y - SELECTION_TOLERANCE),
DVec2::new(x + SELECTION_TOLERANCE, y + SELECTION_TOLERANCE),
)
} else {
(
DVec2::new(data.drag_start.x as f64, data.drag_start.y as f64),
DVec2::new(data.drag_current.x as f64, data.drag_current.y as f64),
)
};
let quad = [
@ -107,21 +88,77 @@ impl Fsm for SelectToolFsmState {
DVec2::new(point_1.x, point_2.y),
];
responses.push_back(Operation::DiscardWorkingFolder.into());
if data.drag_start == data.drag_current {
if let Some(intersection) = document.document.intersects_quad_root(quad).last() {
responses.push_back(DocumentMessage::SelectLayers(vec![intersection.clone()]).into());
if let Some(intersection) = document.document.intersects_quad_root(quad).last() {
// TODO: Replace root transformations with functions of the transform api
let transformed_start = document.document.root.transform.inverse().transform_vector2(data.drag_start.as_dvec2());
if document.layer_data.get(intersection).map_or(false, |layer_data| layer_data.selected) {
data.layers_dragging = document
.layer_data
.iter()
.filter_map(|(path, layer_data)| {
layer_data
.selected
.then(|| (path.clone(), document.document.layer(path).unwrap().transform.translation - transformed_start))
})
.collect();
} else {
responses.push_back(DocumentMessage::SelectLayers(vec![]).into());
responses.push_back(DocumentMessage::SelectLayers(vec![intersection.clone()]).into());
data.layers_dragging = vec![(intersection.clone(), document.document.layer(intersection).unwrap().transform.translation - transformed_start)]
}
} else {
responses.push_back(DocumentMessage::SelectLayers(document.document.intersects_quad_root(quad)).into());
responses.push_back(Operation::MountWorkingFolder { path: vec![] }.into());
data.layers_dragging = Vec::new();
}
Dragging
}
(Dragging, MouseMove) => {
data.drag_current = input.mouse.position;
if data.layers_dragging.is_empty() {
responses.push_back(Operation::ClearWorkingFolder.into());
responses.push_back(make_operation(data, tool_data, transform));
} else {
for (path, offset) in &data.layers_dragging {
responses.push_back(DocumentMessage::DragLayer(path.clone(), offset.clone()).into());
}
}
Dragging
}
(Dragging, DragStop) => {
data.drag_current = input.mouse.position;
if data.layers_dragging.is_empty() {
responses.push_back(Operation::ClearWorkingFolder.into());
responses.push_back(Operation::DiscardWorkingFolder.into());
if data.drag_start == data.drag_current {
responses.push_back(DocumentMessage::SelectLayers(vec![]).into());
} else {
let (point_1, point_2) = (
DVec2::new(data.drag_start.x as f64, data.drag_start.y as f64),
DVec2::new(data.drag_current.x as f64, data.drag_current.y as f64),
);
let quad = [
DVec2::new(point_1.x, point_1.y),
DVec2::new(point_2.x, point_1.y),
DVec2::new(point_2.x, point_2.y),
DVec2::new(point_1.x, point_2.y),
];
responses.push_back(DocumentMessage::SelectLayers(document.document.intersects_quad_root(quad)).into());
}
} else {
data.layers_dragging = Vec::new();
}
Ready
}
(Dragging, Abort) => {
responses.push_back(Operation::DiscardWorkingFolder.into());
data.layers_dragging = Vec::new();
Ready
}