Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions document-legacy/src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
28 changes: 23 additions & 5 deletions document-legacy/src/document_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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)
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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()
}
}

Expand Down
2 changes: 2 additions & 0 deletions document-legacy/src/layers/layer_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub enum LayerDataTypeDiscriminant {
Folder,
Shape,
Layer,
Artboard,
}

impl fmt::Display for LayerDataTypeDiscriminant {
Expand All @@ -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"),
}
}
}
Expand Down
11 changes: 6 additions & 5 deletions editor/src/dispatcher.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::consts::{DEFAULT_FONT_FAMILY, DEFAULT_FONT_STYLE};
use crate::messages::debug::utility_types::MessageLoggingVerbosity;
use crate::messages::dialog::DialogData;
use crate::messages::prelude::*;

use graphene_core::text::Font;
Expand Down Expand Up @@ -112,11 +113,11 @@ impl Dispatcher {
self.message_handlers.debug_message_handler.process_message(message, &mut queue, ());
}
Dialog(message) => {
self.message_handlers.dialog_message_handler.process_message(
message,
&mut queue,
(&self.message_handlers.portfolio_message_handler, &self.message_handlers.preferences_message_handler),
);
let data = DialogData {
portfolio: &self.message_handlers.portfolio_message_handler,
preferences: &self.message_handlers.preferences_message_handler,
};
self.message_handlers.dialog_message_handler.process_message(message, &mut queue, data);
}
Frontend(message) => {
// Handle these messages immediately by returning early
Expand Down
9 changes: 7 additions & 2 deletions editor/src/messages/dialog/dialog_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ pub struct DialogMessageHandler {
preferences_dialog: PreferencesDialogMessageHandler,
}

impl MessageHandler<DialogMessage, (&PortfolioMessageHandler, &PreferencesMessageHandler)> for DialogMessageHandler {
pub struct DialogData<'a> {
pub portfolio: &'a PortfolioMessageHandler,
pub preferences: &'a PreferencesMessageHandler,
}

impl MessageHandler<DialogMessage, DialogData<'_>> for DialogMessageHandler {
#[remain::check]
fn process_message(&mut self, message: DialogMessage, responses: &mut VecDeque<Message>, (portfolio, preferences): (&PortfolioMessageHandler, &PreferencesMessageHandler)) {
fn process_message(&mut self, message: DialogMessage, responses: &mut VecDeque<Message>, DialogData { portfolio, preferences }: DialogData) {
#[remain::sorted]
match message {
#[remain::unsorted]
Expand Down
2 changes: 1 addition & 1 deletion editor/src/messages/dialog/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ pub mod simple_dialogs;
#[doc(inline)]
pub use dialog_message::{DialogMessage, DialogMessageDiscriminant};
#[doc(inline)]
pub use dialog_message_handler::DialogMessageHandler;
pub use dialog_message_handler::*;
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::consts::VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*;

use graphene_core::uuid::generate_uuid;

use glam::{IVec2, UVec2};
use glam::{DVec2, IVec2, UVec2};

/// A dialog to allow users to set some initial options about a new document.
#[derive(Debug, Clone, Default)]
Expand All @@ -24,13 +25,18 @@ impl MessageHandler<NewDocumentDialogMessage, ()> for NewDocumentDialogMessageHa
NewDocumentDialogMessage::Submit => {
responses.add(PortfolioMessage::NewDocumentWithName { name: self.name.clone() });

if !self.infinite && self.dimensions.x > 0 && self.dimensions.y > 0 {
let create_artboard = !self.infinite && self.dimensions.x > 0 && self.dimensions.y > 0;
if create_artboard {
let id = generate_uuid();
responses.add(GraphOperationMessage::NewArtboard {
id,
artboard: graphene_core::Artboard::new(IVec2::ZERO, self.dimensions.as_ivec2()),
});
responses.add(DocumentMessage::ZoomCanvasToFitAll);
responses.add(NavigationMessage::FitViewportToBounds {
bounds: [DVec2::ZERO, self.dimensions.as_dvec2()],
padding_scale_factor: Some(VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR),
prevent_zoom_past_100: true,
});
}
responses.add(NodeGraphMessage::RunDocumentGraph);
responses.add(NodeGraphMessage::UpdateNewNodeGraph);
Expand Down
22 changes: 11 additions & 11 deletions editor/src/messages/portfolio/document/document_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
}
#[remain::unsorted]
Navigation(message) => {
let document_bounds = self.metadata().document_bounds();
let document_bounds = self.metadata().document_bounds_viewport_space();
self.navigation_handler.process_message(
message,
responses,
Expand Down Expand Up @@ -306,7 +306,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
responses.add(BroadcastEvent::DocumentIsDirty);
}
DeselectAllLayers => {
responses.add_front(SetSelectedLayers { replacement_selected_layers: vec![] });
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![] });
self.layer_range_selection_reference = None;
}
DirtyRenderDocument => {
Expand Down Expand Up @@ -623,7 +623,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand

let viewport_size = ipp.viewport_bounds.size();
let viewport_mid = ipp.viewport_bounds.center();
let [bounds1, bounds2] = self.metadata().document_bounds().unwrap_or([viewport_mid; 2]);
let [bounds1, bounds2] = self.metadata().document_bounds_viewport_space().unwrap_or([viewport_mid; 2]);
let bounds1 = bounds1.min(viewport_mid) - viewport_size * scale;
let bounds2 = bounds2.max(viewport_mid) + viewport_size * scale;
let bounds_length = (bounds2 - bounds1) * (1. + SCROLLBAR_SPACING);
Expand Down Expand Up @@ -657,20 +657,20 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
})
}
SelectAllLayers => {
let all = self.all_layers().map(|path| path.to_vec()).collect();
responses.add_front(SetSelectedLayers { replacement_selected_layers: all });
let all = self.metadata().all_layers().map(|layer| layer.to_node()).collect();
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: all });
}
SelectedLayersLower => {
responses.add_front(DocumentMessage::SelectedLayersReorder { relative_index_offset: -1 });
responses.add(DocumentMessage::SelectedLayersReorder { relative_index_offset: 1 });
}
SelectedLayersLowerToBack => {
responses.add_front(DocumentMessage::SelectedLayersReorder { relative_index_offset: isize::MIN });
responses.add(DocumentMessage::SelectedLayersReorder { relative_index_offset: isize::MAX });
}
SelectedLayersRaise => {
responses.add_front(DocumentMessage::SelectedLayersReorder { relative_index_offset: 1 });
responses.add(DocumentMessage::SelectedLayersReorder { relative_index_offset: -1 });
}
SelectedLayersRaiseToFront => {
responses.add_front(DocumentMessage::SelectedLayersReorder { relative_index_offset: isize::MAX });
responses.add(DocumentMessage::SelectedLayersReorder { relative_index_offset: isize::MIN });
}
SelectedLayersReorder { relative_index_offset } => {
self.selected_layers_reorder(relative_index_offset, responses);
Expand Down Expand Up @@ -813,7 +813,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
}
SetViewMode { view_mode } => {
self.view_mode = view_mode;
responses.add_front(DocumentMessage::DirtyRenderDocument);
responses.add_front(NodeGraphMessage::RunDocumentGraph);
}
StartTransaction => self.backup(responses),
ToggleLayerExpansion { layer } => {
Expand Down Expand Up @@ -876,7 +876,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
responses.add_front(NavigationMessage::SetCanvasZoom { zoom_factor: 2. });
}
ZoomCanvasToFitAll => {
if let Some(bounds) = self.metadata().document_bounds() {
if let Some(bounds) = self.metadata().document_bounds_document_space() {
responses.add(NavigationMessage::FitViewportToBounds {
bounds,
padding_scale_factor: Some(VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,10 @@ impl MessageHandler<NavigationMessage, (&Document, Option<[DVec2; 2]>, &InputPre
responses.add(SetCanvasZoom { zoom_factor: new_scale });
}
FitViewportToBounds {
bounds: [bounds_corner_a, bounds_corner_b],
bounds: [pos1, pos2],
padding_scale_factor,
prevent_zoom_past_100,
} => {
let pos1 = document.metadata.document_to_viewport.inverse().transform_point2(bounds_corner_a);
let pos2 = document.metadata.document_to_viewport.inverse().transform_point2(bounds_corner_b);
let v1 = document.metadata.document_to_viewport.inverse().transform_point2(DVec2::ZERO);
let v2 = document.metadata.document_to_viewport.inverse().transform_point2(ipp.viewport_bounds.size());

Expand All @@ -98,8 +96,9 @@ impl MessageHandler<NavigationMessage, (&Document, Option<[DVec2; 2]>, &InputPre
}
FitViewportToSelection => {
if let Some(bounds) = selection_bounds {
let transform = document.metadata.document_to_viewport.inverse();
responses.add(FitViewportToBounds {
bounds,
bounds: [transform.transform_point2(bounds[0]), transform.transform_point2(bounds[1])],
padding_scale_factor: Some(VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR),
prevent_zoom_past_100: false,
})
Expand Down Expand Up @@ -382,16 +381,18 @@ impl NavigationMessageHandler {
}

pub fn calculate_offset_transform(&self, viewport_center: DVec2) -> DAffine2 {
let scaled_centre = viewport_center / self.snapped_scale();

// Try to avoid fractional coordinates to reduce anti aliasing.
let scale = self.snapped_scale();
let rounded_pan = ((self.pan + viewport_center) * scale).round() / scale - viewport_center;
let rounded_pan = ((self.pan + scaled_centre) * scale).round() / scale - scaled_centre;

// TODO: replace with DAffine2::from_scale_angle_translation and fix the errors
let offset_transform = DAffine2::from_translation(viewport_center);
let offset_transform = DAffine2::from_translation(scaled_centre);
let scale_transform = DAffine2::from_scale(DVec2::splat(scale));
let angle_transform = DAffine2::from_angle(self.snapped_angle());
let translation_transform = DAffine2::from_translation(rounded_pan);
scale_transform * offset_transform * angle_transform * offset_transform.inverse() * translation_transform
scale_transform * offset_transform * angle_transform * translation_transform
}

fn create_document_transform(&self, viewport_center: DVec2, responses: &mut VecDeque<Message>) {
Expand All @@ -403,7 +404,7 @@ impl NavigationMessageHandler {
let new_viewport_bounds = viewport_bounds / zoom_factor;
let delta_size = viewport_bounds - new_viewport_bounds;
let mouse_fraction = mouse / viewport_bounds;
let delta = delta_size * (-mouse_fraction);
let delta = delta_size * (DVec2::splat(0.5) - mouse_fraction);

NavigationMessage::TranslateCanvas { delta }.into()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ impl<'a> ModifyInputsContext<'a> {
};

let metadata = output_node.metadata.clone();
let new_input = output_node.inputs[0].clone();
let new_input = output_node.inputs.first().cloned().filter(|input| input.as_node().is_some());
let node_id = generate_uuid();

output_node.metadata.position.x += 8;
Expand All @@ -292,7 +292,7 @@ impl<'a> ModifyInputsContext<'a> {
warn!("Node type \"{name}\" doesn't exist");
return;
};
let mut new_document_node = node_type.to_document_node_default_inputs([Some(new_input)], metadata);
let mut new_document_node = node_type.to_document_node_default_inputs([new_input], metadata);
update_input(&mut new_document_node.inputs, node_id, self.document_metadata);
self.network.nodes.insert(node_id, new_document_node);
}
Expand Down Expand Up @@ -575,7 +575,10 @@ impl MessageHandler<GraphOperationMessage, (&mut Document, &mut NodeGraphMessage
transform_in,
skip_rerender,
} => {
let parent_transform = document.metadata.document_to_viewport * document.multiply_transforms(&layer[..layer.len() - 1]).unwrap_or_default();
let layer_identifier = LayerNodeIdentifier::new(*layer.last().unwrap(), &document.document_network);
let parent_transform = document
.metadata
.transform_to_viewport(layer_identifier.parent(&document.metadata).unwrap_or(LayerNodeIdentifier::ROOT));
let bounds = LayerBounds::new(document, &layer);
if let Some(mut modify_inputs) = ModifyInputsContext::new_layer(&layer, document, node_graph, responses) {
modify_inputs.transform_change(transform, transform_in, parent_transform, bounds, skip_rerender);
Expand All @@ -597,8 +600,12 @@ impl MessageHandler<GraphOperationMessage, (&mut Document, &mut NodeGraphMessage
transform_in,
skip_rerender,
} => {
let parent_transform = document.metadata.document_to_viewport * document.multiply_transforms(&layer[..layer.len() - 1]).unwrap_or_default();
let current_transform = Some(document.metadata.transform_to_viewport(LayerNodeIdentifier::new(*layer.last().unwrap(), &document.document_network)));
let layer_identifier = LayerNodeIdentifier::new(*layer.last().unwrap(), &document.document_network);
let parent_transform = document
.metadata
.transform_to_viewport(layer_identifier.parent(&document.metadata).unwrap_or(LayerNodeIdentifier::ROOT));

let current_transform = Some(document.metadata.transform_to_viewport(layer_identifier));
let bounds = LayerBounds::new(document, &layer);
if let Some(mut modify_inputs) = ModifyInputsContext::new_layer(&layer, document, node_graph, responses) {
modify_inputs.transform_set(transform, transform_in, parent_transform, current_transform, bounds, skip_rerender);
Expand Down
Loading