Clean up DocumentMessageHandler by breaking out several lengthy handlers into helper functions (#3568)
refactor(document): extract large match arms into helper methods Part of #2740 - Code quality refactors. This commit addresses the 'Match statements' section of the tracking issue by extracting three large match arms from process_message() into dedicated helper methods: - handle_group_selected_layers: Handles layer grouping in both artboard and non-artboard workflows (~50 lines extracted) - handle_move_selected_layers_to: Handles layer movement with proper transform preservation (~85 lines extracted) - handle_nudge_selected_layers: Handles keyboard nudging with optional resize mode (~75 lines extracted) The main match statement in DocumentMessageHandler is now ~210 lines shorter and more readable. Logic and behavior remain unchanged.
This commit is contained in:
parent
3571c0d577
commit
f801ed72bb
|
|
@ -623,145 +623,10 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
|||
responses.add(OverlaysMessage::Draw);
|
||||
}
|
||||
DocumentMessage::GroupSelectedLayers { group_folder_type } => {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
|
||||
let mut parent_per_selected_nodes: HashMap<LayerNodeIdentifier, Vec<NodeId>> = HashMap::new();
|
||||
let artboards = LayerNodeIdentifier::ROOT_PARENT
|
||||
.children(self.metadata())
|
||||
.filter(|x| self.network_interface.is_artboard(&x.to_node(), &self.selection_network_path))
|
||||
.collect::<Vec<_>>();
|
||||
let selected_nodes = self.network_interface.selected_nodes();
|
||||
|
||||
// Non-artboard (infinite canvas) workflow
|
||||
if artboards.is_empty() {
|
||||
let Some(parent) = self.network_interface.deepest_common_ancestor(&selected_nodes, &self.selection_network_path, false) else {
|
||||
return;
|
||||
};
|
||||
let Some(selected_nodes) = &self.network_interface.selected_nodes_in_nested_network(&self.selection_network_path) else {
|
||||
return;
|
||||
};
|
||||
let insert_index = DocumentMessageHandler::get_calculated_insert_index(self.metadata(), selected_nodes, parent);
|
||||
|
||||
DocumentMessageHandler::group_layers(responses, insert_index, parent, group_folder_type, &mut self.network_interface);
|
||||
}
|
||||
// Artboard workflow
|
||||
else {
|
||||
for artboard in artboards {
|
||||
let selected_descendants = artboard.descendants(self.metadata()).filter(|x| selected_nodes.selected_layers_contains(*x, self.metadata()));
|
||||
for selected_descendant in selected_descendants {
|
||||
parent_per_selected_nodes.entry(artboard).or_default().push(selected_descendant.to_node());
|
||||
}
|
||||
}
|
||||
|
||||
let mut new_folders: Vec<NodeId> = Vec::new();
|
||||
|
||||
for children in parent_per_selected_nodes.into_values() {
|
||||
let child_selected_nodes = SelectedNodes(children);
|
||||
let Some(parent) = self.network_interface.deepest_common_ancestor(&child_selected_nodes, &self.selection_network_path, false) else {
|
||||
continue;
|
||||
};
|
||||
let insert_index = DocumentMessageHandler::get_calculated_insert_index(self.metadata(), &child_selected_nodes, parent);
|
||||
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: child_selected_nodes.0 });
|
||||
|
||||
new_folders.push(DocumentMessageHandler::group_layers(responses, insert_index, parent, group_folder_type, &mut self.network_interface));
|
||||
}
|
||||
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: new_folders });
|
||||
}
|
||||
self.handle_group_selected_layers(group_folder_type, responses);
|
||||
}
|
||||
DocumentMessage::MoveSelectedLayersTo { parent, insert_index } => {
|
||||
if !self.selection_network_path.is_empty() {
|
||||
log::error!("Moving selected layers is only supported for the Document Network");
|
||||
return;
|
||||
}
|
||||
|
||||
// Disallow trying to insert into self.
|
||||
if self
|
||||
.network_interface
|
||||
.selected_nodes()
|
||||
.selected_layers(self.metadata())
|
||||
.any(|layer| parent.ancestors(self.metadata()).any(|ancestor| ancestor == layer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Artboards can only have `ROOT_PARENT` as the parent.
|
||||
let any_artboards = self
|
||||
.network_interface
|
||||
.selected_nodes()
|
||||
.selected_layers(self.metadata())
|
||||
.any(|layer| self.network_interface.is_artboard(&layer.to_node(), &self.selection_network_path));
|
||||
if any_artboards && parent != LayerNodeIdentifier::ROOT_PARENT {
|
||||
return;
|
||||
}
|
||||
|
||||
// Non-artboards cannot be put at the top level if artboards also exist there
|
||||
let selected_any_non_artboards = self
|
||||
.network_interface
|
||||
.selected_nodes()
|
||||
.selected_layers(self.metadata())
|
||||
.any(|layer| !self.network_interface.is_artboard(&layer.to_node(), &self.selection_network_path));
|
||||
|
||||
let top_level_artboards = LayerNodeIdentifier::ROOT_PARENT
|
||||
.children(self.metadata())
|
||||
.any(|layer| self.network_interface.is_artboard(&layer.to_node(), &self.selection_network_path));
|
||||
|
||||
if selected_any_non_artboards && parent == LayerNodeIdentifier::ROOT_PARENT && top_level_artboards {
|
||||
return;
|
||||
}
|
||||
|
||||
let layers_to_move = self.network_interface.shallowest_unique_layers_sorted(&self.selection_network_path);
|
||||
// Offset the index for layers to move that are below another layer to move. For example when moving 1 and 2 between 3 and 4, 2 should be inserted at the same index as 1 since 1 is moved first.
|
||||
let layers_to_move_with_insert_offset = layers_to_move
|
||||
.iter()
|
||||
.map(|layer| {
|
||||
if layer.parent(self.metadata()) != Some(parent) {
|
||||
return (*layer, 0);
|
||||
}
|
||||
|
||||
let upstream_selected_siblings = layer
|
||||
.downstream_siblings(self.network_interface.document_metadata())
|
||||
.filter(|sibling| {
|
||||
sibling != layer
|
||||
&& layers_to_move.iter().any(|layer| {
|
||||
layer == sibling
|
||||
&& layer
|
||||
.parent(self.metadata())
|
||||
.is_some_and(|parent| parent.children(self.metadata()).position(|child| child == *layer) < Some(insert_index))
|
||||
})
|
||||
})
|
||||
.count();
|
||||
(*layer, upstream_selected_siblings)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
|
||||
for (layer_index, (layer_to_move, insert_offset)) in layers_to_move_with_insert_offset.into_iter().enumerate() {
|
||||
responses.add(NodeGraphMessage::MoveLayerToStack {
|
||||
layer: layer_to_move,
|
||||
parent,
|
||||
insert_index: insert_index + layer_index - insert_offset,
|
||||
});
|
||||
|
||||
if layer_to_move.parent(self.metadata()) != Some(parent) {
|
||||
// TODO: Fix this so it works when dragging a layer into a group parent which has a Transform node, which used to work before #2689 caused this regression by removing the empty vector table row.
|
||||
// TODO: See #2688 for this issue.
|
||||
let layer_local_transform = self.network_interface.document_metadata().transform_to_viewport(layer_to_move);
|
||||
let undo_transform = self.network_interface.document_metadata().transform_to_viewport(parent).inverse();
|
||||
let transform = undo_transform * layer_local_transform;
|
||||
|
||||
responses.add(GraphOperationMessage::TransformSet {
|
||||
layer: layer_to_move,
|
||||
transform,
|
||||
transform_in: TransformIn::Local,
|
||||
skip_rerender: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
self.handle_move_selected_layers_to(parent, insert_index, responses);
|
||||
}
|
||||
DocumentMessage::MoveSelectedLayersToGroup { parent } => {
|
||||
// Group all shallowest unique selected layers in order
|
||||
|
|
@ -786,83 +651,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
|||
resize,
|
||||
resize_opposite_corner,
|
||||
} => {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
|
||||
let resize = ipp.keyboard.key(resize);
|
||||
let resize_opposite_corner = ipp.keyboard.key(resize_opposite_corner);
|
||||
|
||||
let can_move = |layer| {
|
||||
let selected = self.network_interface.selected_nodes();
|
||||
selected.layer_visible(layer, &self.network_interface) && !selected.layer_locked(layer, &self.network_interface)
|
||||
};
|
||||
|
||||
// Nudge translation without resizing
|
||||
if !resize {
|
||||
let transform = DAffine2::from_translation(DVec2::from_angle(-self.document_ptz.tilt()).rotate(DVec2::new(delta_x, delta_y)));
|
||||
responses.add(SelectToolMessage::ShiftSelectedNodes { offset: transform.translation });
|
||||
|
||||
for layer in self.network_interface.shallowest_unique_layers(&[]).filter(|layer| can_move(*layer)) {
|
||||
responses.add(GraphOperationMessage::TransformChange {
|
||||
layer,
|
||||
transform,
|
||||
transform_in: TransformIn::Local,
|
||||
skip_rerender: false,
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let selected_bounding_box = self.network_interface.selected_bounds_document_space(false, &[]);
|
||||
let Some([existing_top_left, existing_bottom_right]) = selected_bounding_box else { return };
|
||||
|
||||
// Swap and negate coordinates as needed to match the resize direction that's closest to the current tilt angle
|
||||
let tilt = (self.document_ptz.tilt() + std::f64::consts::TAU) % std::f64::consts::TAU;
|
||||
let (delta_x, delta_y, opposite_x, opposite_y) = match ((tilt + std::f64::consts::FRAC_PI_4) / std::f64::consts::FRAC_PI_2).floor() as i32 % 4 {
|
||||
0 => (delta_x, delta_y, false, false),
|
||||
1 => (delta_y, -delta_x, false, true),
|
||||
2 => (-delta_x, -delta_y, true, true),
|
||||
3 => (-delta_y, delta_x, true, false),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let size = existing_bottom_right - existing_top_left;
|
||||
// TODO: This is a hacky band-aid. It still results in the shape becoming zero-sized. Properly fix this using the correct math.
|
||||
// If size is zero we clamp it to minimun value to avoid dividing by zero vector to calculate enlargement.
|
||||
let size = size.max(DVec2::ONE);
|
||||
let enlargement = DVec2::new(
|
||||
if resize_opposite_corner != opposite_x { -delta_x } else { delta_x },
|
||||
if resize_opposite_corner != opposite_y { -delta_y } else { delta_y },
|
||||
);
|
||||
let enlargement_factor = (enlargement + size) / size;
|
||||
|
||||
let position = DVec2::new(
|
||||
existing_top_left.x + if resize_opposite_corner != opposite_x { delta_x } else { 0. },
|
||||
existing_top_left.y + if resize_opposite_corner != opposite_y { delta_y } else { 0. },
|
||||
);
|
||||
let mut pivot = (existing_top_left * enlargement_factor - position) / (enlargement_factor - DVec2::ONE);
|
||||
if !pivot.x.is_finite() {
|
||||
pivot.x = 0.;
|
||||
}
|
||||
if !pivot.y.is_finite() {
|
||||
pivot.y = 0.;
|
||||
}
|
||||
let scale = DAffine2::from_scale(enlargement_factor);
|
||||
let pivot = DAffine2::from_translation(pivot);
|
||||
let transformation = pivot * scale * pivot.inverse();
|
||||
let document_to_viewport = self.navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), &self.document_ptz);
|
||||
|
||||
for layer in self.network_interface.shallowest_unique_layers(&[]).filter(|layer| can_move(*layer)) {
|
||||
let to = document_to_viewport.inverse() * self.metadata().downstream_transform_to_viewport(layer);
|
||||
let original_transform = self.metadata().upstream_transform(layer.to_node());
|
||||
let new = to.inverse() * transformation * to * original_transform;
|
||||
responses.add(GraphOperationMessage::TransformSet {
|
||||
layer,
|
||||
transform: new,
|
||||
transform_in: TransformIn::Local,
|
||||
skip_rerender: false,
|
||||
});
|
||||
}
|
||||
self.handle_nudge_selected_layers(delta_x, delta_y, resize, resize_opposite_corner, ipp, viewport, responses);
|
||||
}
|
||||
DocumentMessage::PasteImage {
|
||||
name,
|
||||
|
|
@ -2141,6 +1930,244 @@ impl DocumentMessageHandler {
|
|||
folder_id
|
||||
}
|
||||
|
||||
/// Helper method for GroupSelectedLayers message.
|
||||
/// Handles grouping layers in both artboard and non-artboard workflows.
|
||||
fn handle_group_selected_layers(&mut self, group_folder_type: GroupFolderType, responses: &mut VecDeque<Message>) {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
|
||||
let mut parent_per_selected_nodes: HashMap<LayerNodeIdentifier, Vec<NodeId>> = HashMap::new();
|
||||
let artboards = LayerNodeIdentifier::ROOT_PARENT
|
||||
.children(self.metadata())
|
||||
.filter(|x| self.network_interface.is_artboard(&x.to_node(), &self.selection_network_path))
|
||||
.collect::<Vec<_>>();
|
||||
let selected_nodes = self.network_interface.selected_nodes();
|
||||
|
||||
// Non-artboard (infinite canvas) workflow
|
||||
if artboards.is_empty() {
|
||||
let Some(parent) = self.network_interface.deepest_common_ancestor(&selected_nodes, &self.selection_network_path, false) else {
|
||||
return;
|
||||
};
|
||||
let Some(selected_nodes) = &self.network_interface.selected_nodes_in_nested_network(&self.selection_network_path) else {
|
||||
return;
|
||||
};
|
||||
let insert_index = DocumentMessageHandler::get_calculated_insert_index(self.metadata(), selected_nodes, parent);
|
||||
|
||||
DocumentMessageHandler::group_layers(responses, insert_index, parent, group_folder_type, &mut self.network_interface);
|
||||
}
|
||||
// Artboard workflow
|
||||
else {
|
||||
for artboard in artboards {
|
||||
let selected_descendants = artboard.descendants(self.metadata()).filter(|x| selected_nodes.selected_layers_contains(*x, self.metadata()));
|
||||
for selected_descendant in selected_descendants {
|
||||
parent_per_selected_nodes.entry(artboard).or_default().push(selected_descendant.to_node());
|
||||
}
|
||||
}
|
||||
|
||||
let mut new_folders: Vec<NodeId> = Vec::new();
|
||||
|
||||
for children in parent_per_selected_nodes.into_values() {
|
||||
let child_selected_nodes = SelectedNodes(children);
|
||||
let Some(parent) = self.network_interface.deepest_common_ancestor(&child_selected_nodes, &self.selection_network_path, false) else {
|
||||
continue;
|
||||
};
|
||||
let insert_index = DocumentMessageHandler::get_calculated_insert_index(self.metadata(), &child_selected_nodes, parent);
|
||||
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: child_selected_nodes.0 });
|
||||
|
||||
new_folders.push(DocumentMessageHandler::group_layers(responses, insert_index, parent, group_folder_type, &mut self.network_interface));
|
||||
}
|
||||
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: new_folders });
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper method for MoveSelectedLayersTo message.
|
||||
/// Handles moving selected layers to a new parent with proper transform preservation.
|
||||
fn handle_move_selected_layers_to(&mut self, parent: LayerNodeIdentifier, insert_index: usize, responses: &mut VecDeque<Message>) {
|
||||
if !self.selection_network_path.is_empty() {
|
||||
log::error!("Moving selected layers is only supported for the Document Network");
|
||||
return;
|
||||
}
|
||||
|
||||
// Disallow trying to insert into self.
|
||||
if self
|
||||
.network_interface
|
||||
.selected_nodes()
|
||||
.selected_layers(self.metadata())
|
||||
.any(|layer| parent.ancestors(self.metadata()).any(|ancestor| ancestor == layer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Artboards can only have `ROOT_PARENT` as the parent.
|
||||
let any_artboards = self
|
||||
.network_interface
|
||||
.selected_nodes()
|
||||
.selected_layers(self.metadata())
|
||||
.any(|layer| self.network_interface.is_artboard(&layer.to_node(), &self.selection_network_path));
|
||||
if any_artboards && parent != LayerNodeIdentifier::ROOT_PARENT {
|
||||
return;
|
||||
}
|
||||
|
||||
// Non-artboards cannot be put at the top level if artboards also exist there
|
||||
let selected_any_non_artboards = self
|
||||
.network_interface
|
||||
.selected_nodes()
|
||||
.selected_layers(self.metadata())
|
||||
.any(|layer| !self.network_interface.is_artboard(&layer.to_node(), &self.selection_network_path));
|
||||
|
||||
let top_level_artboards = LayerNodeIdentifier::ROOT_PARENT
|
||||
.children(self.metadata())
|
||||
.any(|layer| self.network_interface.is_artboard(&layer.to_node(), &self.selection_network_path));
|
||||
|
||||
if selected_any_non_artboards && parent == LayerNodeIdentifier::ROOT_PARENT && top_level_artboards {
|
||||
return;
|
||||
}
|
||||
|
||||
let layers_to_move = self.network_interface.shallowest_unique_layers_sorted(&self.selection_network_path);
|
||||
// Offset the index for layers to move that are below another layer to move. For example when moving 1 and 2 between 3 and 4, 2 should be inserted at the same index as 1 since 1 is moved first.
|
||||
let layers_to_move_with_insert_offset = layers_to_move
|
||||
.iter()
|
||||
.map(|layer| {
|
||||
if layer.parent(self.metadata()) != Some(parent) {
|
||||
return (*layer, 0);
|
||||
}
|
||||
|
||||
let upstream_selected_siblings = layer
|
||||
.downstream_siblings(self.network_interface.document_metadata())
|
||||
.filter(|sibling| {
|
||||
sibling != layer
|
||||
&& layers_to_move.iter().any(|layer| {
|
||||
layer == sibling
|
||||
&& layer
|
||||
.parent(self.metadata())
|
||||
.is_some_and(|parent| parent.children(self.metadata()).position(|child| child == *layer) < Some(insert_index))
|
||||
})
|
||||
})
|
||||
.count();
|
||||
(*layer, upstream_selected_siblings)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
|
||||
for (layer_index, (layer_to_move, insert_offset)) in layers_to_move_with_insert_offset.into_iter().enumerate() {
|
||||
responses.add(NodeGraphMessage::MoveLayerToStack {
|
||||
layer: layer_to_move,
|
||||
parent,
|
||||
insert_index: insert_index + layer_index - insert_offset,
|
||||
});
|
||||
|
||||
if layer_to_move.parent(self.metadata()) != Some(parent) {
|
||||
// TODO: Fix this so it works when dragging a layer into a group parent which has a Transform node, which used to work before #2689 caused this regression by removing the empty vector table row.
|
||||
// TODO: See #2688 for this issue.
|
||||
let layer_local_transform = self.network_interface.document_metadata().transform_to_viewport(layer_to_move);
|
||||
let undo_transform = self.network_interface.document_metadata().transform_to_viewport(parent).inverse();
|
||||
let transform = undo_transform * layer_local_transform;
|
||||
|
||||
responses.add(GraphOperationMessage::TransformSet {
|
||||
layer: layer_to_move,
|
||||
transform,
|
||||
transform_in: TransformIn::Local,
|
||||
skip_rerender: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
}
|
||||
|
||||
/// Helper method for NudgeSelectedLayers message.
|
||||
/// Handles keyboard nudging of selected layers with optional resize mode.
|
||||
fn handle_nudge_selected_layers(
|
||||
&mut self,
|
||||
delta_x: f64,
|
||||
delta_y: f64,
|
||||
resize: Key,
|
||||
resize_opposite_corner: Key,
|
||||
ipp: &InputPreprocessorMessageHandler,
|
||||
viewport: &ViewportMessageHandler,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) {
|
||||
responses.add(DocumentMessage::AddTransaction);
|
||||
|
||||
let resize = ipp.keyboard.key(resize);
|
||||
let resize_opposite_corner = ipp.keyboard.key(resize_opposite_corner);
|
||||
|
||||
let can_move = |layer| {
|
||||
let selected = self.network_interface.selected_nodes();
|
||||
selected.layer_visible(layer, &self.network_interface) && !selected.layer_locked(layer, &self.network_interface)
|
||||
};
|
||||
|
||||
// Nudge translation without resizing
|
||||
if !resize {
|
||||
let transform = DAffine2::from_translation(DVec2::from_angle(-self.document_ptz.tilt()).rotate(DVec2::new(delta_x, delta_y)));
|
||||
responses.add(SelectToolMessage::ShiftSelectedNodes { offset: transform.translation });
|
||||
|
||||
for layer in self.network_interface.shallowest_unique_layers(&[]).filter(|layer| can_move(*layer)) {
|
||||
responses.add(GraphOperationMessage::TransformChange {
|
||||
layer,
|
||||
transform,
|
||||
transform_in: TransformIn::Local,
|
||||
skip_rerender: false,
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let selected_bounding_box = self.network_interface.selected_bounds_document_space(false, &[]);
|
||||
let Some([existing_top_left, existing_bottom_right]) = selected_bounding_box else { return };
|
||||
|
||||
// Swap and negate coordinates as needed to match the resize direction that's closest to the current tilt angle
|
||||
let tilt = (self.document_ptz.tilt() + std::f64::consts::TAU) % std::f64::consts::TAU;
|
||||
let (delta_x, delta_y, opposite_x, opposite_y) = match ((tilt + std::f64::consts::FRAC_PI_4) / std::f64::consts::FRAC_PI_2).floor() as i32 % 4 {
|
||||
0 => (delta_x, delta_y, false, false),
|
||||
1 => (delta_y, -delta_x, false, true),
|
||||
2 => (-delta_x, -delta_y, true, true),
|
||||
3 => (-delta_y, delta_x, true, false),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let size = existing_bottom_right - existing_top_left;
|
||||
// TODO: This is a hacky band-aid. It still results in the shape becoming zero-sized. Properly fix this using the correct math.
|
||||
// If size is zero we clamp it to minimun value to avoid dividing by zero vector to calculate enlargement.
|
||||
let size = size.max(DVec2::ONE);
|
||||
let enlargement = DVec2::new(
|
||||
if resize_opposite_corner != opposite_x { -delta_x } else { delta_x },
|
||||
if resize_opposite_corner != opposite_y { -delta_y } else { delta_y },
|
||||
);
|
||||
let enlargement_factor = (enlargement + size) / size;
|
||||
|
||||
let position = DVec2::new(
|
||||
existing_top_left.x + if resize_opposite_corner != opposite_x { delta_x } else { 0. },
|
||||
existing_top_left.y + if resize_opposite_corner != opposite_y { delta_y } else { 0. },
|
||||
);
|
||||
let mut pivot = (existing_top_left * enlargement_factor - position) / (enlargement_factor - DVec2::ONE);
|
||||
if !pivot.x.is_finite() {
|
||||
pivot.x = 0.;
|
||||
}
|
||||
if !pivot.y.is_finite() {
|
||||
pivot.y = 0.;
|
||||
}
|
||||
let scale = DAffine2::from_scale(enlargement_factor);
|
||||
let pivot = DAffine2::from_translation(pivot);
|
||||
let transformation = pivot * scale * pivot.inverse();
|
||||
let document_to_viewport = self.navigation_handler.calculate_offset_transform(viewport.center_in_viewport_space().into(), &self.document_ptz);
|
||||
|
||||
for layer in self.network_interface.shallowest_unique_layers(&[]).filter(|layer| can_move(*layer)) {
|
||||
let to = document_to_viewport.inverse() * self.metadata().downstream_transform_to_viewport(layer);
|
||||
let original_transform = self.metadata().upstream_transform(layer.to_node());
|
||||
let new = to.inverse() * transformation * to * original_transform;
|
||||
responses.add(GraphOperationMessage::TransformSet {
|
||||
layer,
|
||||
transform: new,
|
||||
transform_in: TransformIn::Local,
|
||||
skip_rerender: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads all of the fonts in the document.
|
||||
pub fn load_layer_resources(&self, responses: &mut VecDeque<Message>) {
|
||||
let mut fonts_to_load = HashSet::new();
|
||||
|
|
|
|||
Loading…
Reference in New Issue