Retire layer paths used throughout the code (#1531)

* Part 1

* Part 2

* Part 3

* Part 4

* Part 5

* Part 6

* Part 7

* Part 8
This commit is contained in:
Keavon Chambers
2023-12-21 19:32:46 -08:00
committed by GitHub
parent 5c7e04a725
commit 7bfe0ce55b
73 changed files with 532 additions and 798 deletions

View File

@@ -38,10 +38,9 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[
PropertiesPanelMessageDiscriminant::Refresh,
))),
MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::DocumentStructureChanged)),
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerTreeStructure),
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::UpdateDocumentLayerStructure),
MessageDiscriminant::Frontend(FrontendMessageDiscriminant::TriggerFontLoad),
MessageDiscriminant::Broadcast(BroadcastMessageDiscriminant::TriggerEvent(BroadcastEventDiscriminant::DocumentIsDirty)),
MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::InputFrameRasterizeRegionBelowLayer)),
MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::Overlays(OverlaysMessageDiscriminant::Draw))),
];
@@ -262,6 +261,7 @@ mod test {
use crate::messages::tool::tool_messages::tool_prelude::ToolType;
use crate::test_utils::EditorTestUtils;
use graph_craft::document::NodeId;
use graphene_core::raster::color::Color;
fn init_logger() {
@@ -359,7 +359,7 @@ mod test {
fn copy_paste_folder() {
let mut editor = create_editor_with_three_layers();
const FOLDER_ID: u64 = 3;
const FOLDER_ID: NodeId = 3;
editor.handle_message(GraphOperationMessage::NewCustomLayer {
id: FOLDER_ID,

View File

@@ -78,7 +78,7 @@ impl LayoutHolder for ExportDialogMessageHandler {
NumberInput::new(Some(self.scale_factor))
.unit("")
.min(0.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.disabled(self.file_type == FileType::Svg)
.on_update(|number_input: &NumberInput| ExportDialogMessage::ScaleFactor(number_input.value.unwrap()).into())
.min_width(200)

View File

@@ -95,7 +95,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler {
.label("W")
.unit(" px")
.min(0.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.is_integer(true)
.disabled(self.infinite)
.min_width(100)
@@ -106,7 +106,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler {
.label("H")
.unit(" px")
.min(0.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.is_integer(true)
.disabled(self.infinite)
.min_width(100)

View File

@@ -57,7 +57,7 @@ impl PreferencesDialogMessageHandler {
NumberInput::new(Some(preferences.imaginate_refresh_frequency))
.unit(" seconds")
.min(0.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.min_width(200)
.on_update(|number_input: &NumberInput| PreferencesMessage::ImaginateRefreshFrequency { seconds: number_input.value.unwrap() }.into())
.widget_holder(),

View File

@@ -5,7 +5,7 @@ use crate::messages::prelude::*;
/// A dialog for confirming the closing a document with unsaved changes.
pub struct CloseDocumentDialog {
pub document_name: String,
pub document_id: u64,
pub document_id: DocumentId,
}
impl DialogLayoutHolder for CloseDocumentDialog {

View File

@@ -80,7 +80,7 @@ pub enum FrontendMessage {
TriggerImport,
TriggerIndexedDbRemoveDocument {
#[serde(rename = "documentId")]
document_id: u64,
document_id: DocumentId,
},
TriggerIndexedDbWriteDocument {
document: String,
@@ -111,7 +111,7 @@ pub enum FrontendMessage {
// Update prefix: give the frontend a new value or state for it to use
UpdateActiveDocument {
#[serde(rename = "documentId")]
document_id: u64,
document_id: DocumentId,
},
UpdateDialogButtons {
#[serde(rename = "layoutTarget")]
@@ -139,11 +139,11 @@ pub enum FrontendMessage {
UpdateDocumentLayerDetails {
data: LayerPanelEntry,
},
UpdateDocumentLayerTreeStructure {
UpdateDocumentLayerStructure {
#[serde(rename = "dataBuffer")]
data_buffer: RawBuffer,
},
UpdateDocumentLayerTreeStructureJs {
UpdateDocumentLayerStructureJs {
#[serde(rename = "dataBuffer")]
data_buffer: JsRawBuffer,
},
@@ -180,7 +180,7 @@ pub enum FrontendMessage {
},
UpdateImageData {
#[serde(rename = "documentId")]
document_id: u64,
document_id: DocumentId,
#[serde(rename = "imageData")]
image_data: Vec<FrontendImageData>,
},

View File

@@ -1,5 +1,5 @@
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::prelude::*;
use serde::{Deserialize, Serialize};
@@ -10,18 +10,14 @@ pub struct FrontendDocumentDetails {
#[serde(rename = "isSaved")]
pub is_saved: bool,
pub name: String,
pub id: u64,
pub id: DocumentId,
}
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize, specta::Type)]
pub struct FrontendImageData {
pub path: Vec<LayerId>,
pub mime: String,
#[serde(skip)]
pub image_data: std::sync::Arc<Vec<u8>>,
pub transform: Option<[f64; 6]>,
#[serde(rename = "nodeId")]
pub node_id: Option<graph_craft::document::NodeId>,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, specta::Type)]

View File

@@ -1,7 +1,6 @@
use crate::messages::input_mapper::utility_types::input_keyboard::Key;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis};
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::prelude::*;
use graph_craft::document::{NodeId, NodeNetwork};
@@ -42,14 +41,14 @@ pub enum DocumentMessage {
BackupDocument {
network: NodeNetwork,
},
ClearLayerTree,
ClearLayersPanel,
CommitTransaction,
CreateEmptyFolder {
parent: LayerNodeIdentifier,
},
DebugPrintDocument,
DeleteLayer {
layer_path: Vec<LayerId>,
id: NodeId,
},
DeleteSelectedLayers,
DeselectAllLayers,
@@ -61,20 +60,11 @@ pub enum DocumentMessage {
flip_axis: FlipAxis,
},
GroupSelectedLayers,
ImaginateClear {
layer_path: Vec<LayerId>,
},
ImaginateGenerate {
layer_path: Vec<LayerId>,
},
ImaginateGenerate,
ImaginateRandom {
layer_path: Vec<LayerId>,
imaginate_node: Vec<NodeId>,
then_generate: bool,
},
InputFrameRasterizeRegionBelowLayer {
layer_path: Vec<LayerId>,
},
MoveSelectedLayersTo {
parent: LayerNodeIdentifier,
insert_index: isize,
@@ -106,7 +96,7 @@ pub enum DocumentMessage {
relative_index_offset: isize,
},
SelectLayer {
layer_path: Vec<LayerId>,
id: NodeId,
ctrl: bool,
shift: bool,
},
@@ -132,7 +122,7 @@ pub enum DocumentMessage {
},
StartTransaction,
ToggleLayerExpansion {
layer: NodeId,
id: NodeId,
},
Undo,
UndoFinished,

View File

@@ -10,7 +10,6 @@ use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
use crate::messages::portfolio::document::utility_types::document_metadata::{is_artboard, DocumentMetadata, LayerNodeIdentifier};
use crate::messages::portfolio::document::utility_types::layer_panel::RawBuffer;
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, DocumentMode, FlipAxis, PTZ};
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::portfolio::utility_types::PersistentData;
use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::graph_modification_utils::{get_blend_mode, get_opacity};
@@ -224,7 +223,7 @@ fn root_network() -> NodeNetwork {
}
pub struct DocumentInputs<'a> {
pub document_id: u64,
pub document_id: DocumentId,
pub ipp: &'a InputPreprocessorMessageHandler,
pub persistent_data: &'a PersistentData,
pub executor: &'a mut NodeGraphExecutor,
@@ -324,7 +323,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
};
let translation = (aggregated - center) * axis;
responses.add(GraphOperationMessage::TransformChange {
layer: layer.to_path(),
layer,
transform: DAffine2::from_translation(translation),
transform_in: TransformIn::Viewport,
skip_rerender: false,
@@ -333,10 +332,10 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
responses.add(BroadcastEvent::DocumentIsDirty);
}
BackupDocument { network } => self.backup_with_document(network, responses),
ClearLayerTree => {
// Send an empty layer tree
let data_buffer: RawBuffer = Self::default().serialize_root().as_slice().into();
responses.add(FrontendMessage::UpdateDocumentLayerTreeStructure { data_buffer });
ClearLayersPanel => {
// Send an empty layer list
let data_buffer: RawBuffer = Self::default().serialize_root();
responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer });
// Clear the options bar
responses.add(LayoutMessage::SendLayout {
@@ -359,8 +358,8 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
DebugPrintDocument => {
info!("{:#?}", self.network);
}
DeleteLayer { layer_path } => {
responses.add(GraphOperationMessage::DeleteLayer { id: layer_path[0] });
DeleteLayer { id } => {
responses.add(GraphOperationMessage::DeleteLayer { id });
responses.add_front(BroadcastEvent::ToolAbort);
}
DeleteSelectedLayers => {
@@ -368,9 +367,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
responses.add_front(BroadcastEvent::SelectionChanged);
for path in self.metadata().shallowest_unique_layers(self.metadata().selected_layers()) {
responses.add_front(DocumentMessage::DeleteLayer {
layer_path: path.last().unwrap().to_path(),
});
responses.add_front(DocumentMessage::DeleteLayer { id: path.last().unwrap().to_node() });
}
responses.add(BroadcastEvent::DocumentIsDirty);
@@ -384,8 +381,8 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
DocumentStructureChanged => {
self.update_layers_panel_options_bar_widgets(responses);
let data_buffer: RawBuffer = self.serialize_root().as_slice().into();
responses.add(FrontendMessage::UpdateDocumentLayerTreeStructure { data_buffer })
let data_buffer: RawBuffer = self.serialize_root();
responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer })
}
DuplicateSelectedLayers => {
// TODO: Reimplement selected layer duplication
@@ -406,7 +403,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
let bbox_trans = DAffine2::from_translation(-center);
for layer in self.metadata().selected_layers() {
responses.add(GraphOperationMessage::TransformChange {
layer: layer.to_path(),
layer,
transform: DAffine2::from_scale(scale),
transform_in: TransformIn::Scope { scope: bbox_trans },
skip_rerender: false,
@@ -438,13 +435,8 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![folder_id] });
}
ImaginateClear { layer_path } => responses.add(InputFrameRasterizeRegionBelowLayer { layer_path }),
ImaginateGenerate { layer_path } => responses.add(PortfolioMessage::SubmitGraphRender { document_id, layer_path }),
ImaginateRandom {
layer_path,
imaginate_node,
then_generate,
} => {
ImaginateGenerate => responses.add(PortfolioMessage::SubmitGraphRender { document_id }),
ImaginateRandom { imaginate_node, then_generate } => {
// Generate a random seed. We only want values between -2^53 and 2^53, because integer values
// outside of this range can get rounded in f64
let random_bits = generate_uuid();
@@ -459,10 +451,9 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
// Generate the image
if then_generate {
responses.add(DocumentMessage::ImaginateGenerate { layer_path });
responses.add(DocumentMessage::ImaginateGenerate);
}
}
InputFrameRasterizeRegionBelowLayer { layer_path } => responses.add(PortfolioMessage::SubmitGraphRender { document_id, layer_path }),
MoveSelectedLayersTo { parent, insert_index } => {
let selected_layers = self.metadata().selected_layers().collect::<Vec<_>>();
@@ -496,7 +487,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
// Nudge translation
if !ipp.keyboard.key(resize) {
responses.add(GraphOperationMessage::TransformChange {
layer: layer.to_path(),
layer,
transform: DAffine2::from_translation(delta),
transform_in: TransformIn::Local,
skip_rerender: false,
@@ -525,7 +516,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
let original_transform = self.metadata().upstream_transform(layer.to_node());
let new = to.inverse() * transformation * to * original_transform;
responses.add(GraphOperationMessage::TransformSet {
layer: layer.to_path(),
layer,
transform: new,
transform_in: TransformIn::Local,
skip_rerender: false,
@@ -561,7 +552,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![layer.to_node()] });
responses.add(GraphOperationMessage::TransformSet {
layer: layer.to_path(),
layer,
transform,
transform_in: TransformIn::Local,
skip_rerender: false,
@@ -655,16 +646,15 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
SelectedLayersReorder { relative_index_offset } => {
self.selected_layers_reorder(relative_index_offset, responses);
}
SelectLayer { layer_path, ctrl, shift } => {
let clicked_node = *layer_path.last().expect("Cannot select root");
let layer = LayerNodeIdentifier::new(clicked_node, self.network());
SelectLayer { id, ctrl, shift } => {
let layer = LayerNodeIdentifier::new(id, self.network());
let mut nodes = vec![];
// If we have shift pressed and a layer already selected then fill the range
if let Some(last_selected) = self.layer_range_selection_reference.filter(|_| shift) {
nodes.push(last_selected.to_node());
nodes.push(clicked_node);
nodes.push(id);
// Fill the selection range
self.metadata()
@@ -677,13 +667,13 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
if ctrl {
// Toggle selection when holding ctrl
if self.metadata().selected_layers_contains(layer) {
responses.add_front(NodeGraphMessage::SelectedNodesRemove { nodes: vec![clicked_node] });
responses.add_front(NodeGraphMessage::SelectedNodesRemove { nodes: vec![id] });
} else {
responses.add_front(NodeGraphMessage::SelectedNodesAdd { nodes: vec![clicked_node] });
responses.add_front(NodeGraphMessage::SelectedNodesAdd { nodes: vec![id] });
}
responses.add(BroadcastEvent::SelectionChanged);
} else {
nodes.push(clicked_node);
nodes.push(id);
}
// Set our last selection reference
@@ -703,7 +693,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
SetBlendModeForSelectedLayers { blend_mode } => {
self.backup(responses);
for layer in self.metadata().selected_layers_except_artboards() {
responses.add(GraphOperationMessage::BlendModeSet { layer: layer.to_path(), blend_mode });
responses.add(GraphOperationMessage::BlendModeSet { layer, blend_mode });
}
}
SetOpacityForSelectedLayers { opacity } => {
@@ -711,7 +701,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
let opacity = opacity.clamp(0., 1.) as f32;
for layer in self.metadata().selected_layers_except_artboards() {
responses.add(GraphOperationMessage::OpacitySet { layer: layer.to_path(), opacity });
responses.add(GraphOperationMessage::OpacitySet { layer, opacity });
}
}
SetOverlaysVisibility { visible } => {
@@ -742,8 +732,8 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
responses.add_front(NodeGraphMessage::RunDocumentGraph);
}
StartTransaction => self.backup(responses),
ToggleLayerExpansion { layer } => {
let layer = LayerNodeIdentifier::new(layer, self.network());
ToggleLayerExpansion { id } => {
let layer = LayerNodeIdentifier::new(id, self.network());
if self.collapsed.contains(&layer) {
self.collapsed.retain(|&collapsed_layer| collapsed_layer != layer);
} else {
@@ -908,23 +898,23 @@ impl DocumentMessageHandler {
std::iter::empty()
}
fn serialize_structure(&self, folder: LayerNodeIdentifier, structure: &mut Vec<u64>, data: &mut Vec<LayerId>, path: &mut Vec<LayerId>) {
fn serialize_structure(&self, folder: LayerNodeIdentifier, structure: &mut Vec<LayerNodeIdentifier>, data: &mut Vec<LayerNodeIdentifier>, path: &mut Vec<LayerNodeIdentifier>) {
let mut space = 0;
for layer_node in folder.children(self.metadata()) {
data.push(layer_node.to_node());
data.push(layer_node);
space += 1;
if layer_node.has_children(self.metadata()) && !self.collapsed.contains(&layer_node) {
path.push(layer_node.to_node());
path.push(layer_node);
// TODO: Skip if folder is not expanded.
structure.push(space);
structure.push(LayerNodeIdentifier::new_unchecked(space));
self.serialize_structure(layer_node, structure, data, path);
space = 0;
path.pop();
}
}
structure.push(space | 1 << 63);
structure.push(LayerNodeIdentifier::new_unchecked(space | 1 << 63));
}
/// Serializes the layer structure into a condensed 1D structure.
@@ -959,13 +949,15 @@ impl DocumentMessageHandler {
/// [3427872634365736244,18115028555707261608,15878401910454357952]
/// [3427872634365736244,18115028555707261608,449479075714955186]
/// ```
pub fn serialize_root(&self) -> Vec<u64> {
let (mut structure, mut data) = (vec![0], Vec::new());
pub fn serialize_root(&self) -> RawBuffer {
let mut structure = vec![LayerNodeIdentifier::ROOT];
let mut data = Vec::new();
self.serialize_structure(self.metadata().root(), &mut structure, &mut data, &mut vec![]);
structure[0] = structure.len() as u64 - 1;
structure[0] = LayerNodeIdentifier::new_unchecked(structure.len() as NodeId - 1);
structure.extend(data);
structure
structure.iter().map(|id| id.to_node()).collect::<Vec<_>>().as_slice().into()
}
/// Places a document into the history system
@@ -1064,10 +1056,9 @@ impl DocumentMessageHandler {
///
/// This function updates the insert index so that it points to the same place after the specified `layers` are deleted.
fn update_insert_index(&self, layers: &[LayerNodeIdentifier], parent: LayerNodeIdentifier, insert_index: isize) -> isize {
let layer_ids_above = parent.children(self.metadata()).take(if insert_index < 0 { usize::MAX } else { insert_index as usize });
let new_insert_index = layer_ids_above.filter(|layer_id| !layers.contains(layer_id)).count() as isize;
new_insert_index
let take_amount = if insert_index < 0 { usize::MAX } else { insert_index as usize };
let layer_ids_above = parent.children(self.metadata()).take(take_amount);
layer_ids_above.filter(|layer_id| !layers.contains(layer_id)).count() as isize
}
pub fn new_layer_parent(&self) -> LayerNodeIdentifier {

View File

@@ -1,5 +1,4 @@
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::prelude::*;
use bezier_rs::Subpath;
@@ -16,56 +15,54 @@ use graphene_core::{Artboard, Color};
use glam::{DAffine2, DVec2, IVec2};
pub type LayerIdentifier = Vec<LayerId>;
#[impl_message(Message, DocumentMessage, GraphOperation)]
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum GraphOperationMessage {
FillSet {
layer: LayerIdentifier,
layer: LayerNodeIdentifier,
fill: Fill,
},
OpacitySet {
layer: LayerIdentifier,
layer: LayerNodeIdentifier,
opacity: f32,
},
BlendModeSet {
layer: LayerIdentifier,
layer: LayerNodeIdentifier,
blend_mode: BlendMode,
},
UpdateBounds {
layer: LayerIdentifier,
layer: LayerNodeIdentifier,
old_bounds: [DVec2; 2],
new_bounds: [DVec2; 2],
},
StrokeSet {
layer: LayerIdentifier,
layer: LayerNodeIdentifier,
stroke: Stroke,
},
TransformChange {
layer: LayerIdentifier,
layer: LayerNodeIdentifier,
transform: DAffine2,
transform_in: TransformIn,
skip_rerender: bool,
},
TransformSet {
layer: LayerIdentifier,
layer: LayerNodeIdentifier,
transform: DAffine2,
transform_in: TransformIn,
skip_rerender: bool,
},
TransformSetPivot {
layer: LayerIdentifier,
layer: LayerNodeIdentifier,
pivot: DVec2,
},
Vector {
layer: LayerIdentifier,
layer: LayerNodeIdentifier,
modification: VectorDataModification,
},
Brush {
layer: LayerIdentifier,
layer: LayerNodeIdentifier,
strokes: Vec<BrushStroke>,
},

View File

@@ -1,6 +1,5 @@
use super::{resolve_document_node_type, VectorDataModification};
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::prelude::*;
use bezier_rs::Subpath;
@@ -26,7 +25,6 @@ struct ModifyInputsContext<'a> {
document_network: &'a mut NodeNetwork,
node_graph: &'a mut NodeGraphMessageHandler,
responses: &'a mut VecDeque<Message>,
layer: &'a [LayerId],
outwards_links: HashMap<NodeId, Vec<NodeId>>,
layer_node: Option<NodeId>,
}
@@ -38,27 +36,25 @@ impl<'a> ModifyInputsContext<'a> {
document_network,
node_graph,
responses,
layer: &[],
layer_node: None,
document_metadata,
}
}
fn new_with_layer(
layer: &'a [LayerId],
id: NodeId,
document_network: &'a mut NodeNetwork,
document_metadata: &'a mut DocumentMetadata,
node_graph: &'a mut NodeGraphMessageHandler,
responses: &'a mut VecDeque<Message>,
) -> Option<Self> {
let mut document = Self::new(document_network, document_metadata, node_graph, responses);
let Some(mut id) = layer.last().copied() else {
error!("Tried to modify root layer");
return None;
};
let mut id = id;
while !document.document_network.nodes.get(&id)?.is_layer() {
id = document.outwards_links.get(&id)?.first().copied()?;
}
document.layer_node = Some(id);
Some(document)
}
@@ -325,10 +321,9 @@ impl<'a> ModifyInputsContext<'a> {
self.node_graph.network.clear();
self.responses.add(PropertiesPanelMessage::Refresh);
let layer_path = self.layer.to_vec();
if !skip_rerender {
self.responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path });
self.responses.add(NodeGraphMessage::RunDocumentGraph);
} else {
// Code was removed from here which cleared the frame
}
@@ -354,10 +349,9 @@ impl<'a> ModifyInputsContext<'a> {
}
self.responses.add(PropertiesPanelMessage::Refresh);
let layer_path = self.layer.to_vec();
if !skip_rerender {
self.responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path });
self.responses.add(NodeGraphMessage::RunDocumentGraph);
} else {
// Code was removed from here which cleared the frame
}
@@ -509,8 +503,8 @@ impl<'a> ModifyInputsContext<'a> {
self.update_bounds([old_bounds_min, old_bounds_max], [new_bounds_min, new_bounds_max]);
if empty {
if let Some(layer) = self.layer_node {
self.responses.add(DocumentMessage::DeleteLayer { layer_path: vec![layer] })
if let Some(id) = self.layer_node {
self.responses.add(DocumentMessage::DeleteLayer { id })
}
}
}
@@ -594,27 +588,27 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
) {
match message {
GraphOperationMessage::FillSet { layer, fill } => {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
modify_inputs.fill_set(fill);
}
}
GraphOperationMessage::OpacitySet { layer, opacity } => {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
modify_inputs.opacity_set(opacity);
}
}
GraphOperationMessage::BlendModeSet { layer, blend_mode } => {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
modify_inputs.blend_mode_set(blend_mode);
}
}
GraphOperationMessage::UpdateBounds { layer, old_bounds, new_bounds } => {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
modify_inputs.update_bounds(old_bounds, new_bounds);
}
}
GraphOperationMessage::StrokeSet { layer, stroke } => {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
modify_inputs.stroke_set(stroke);
}
}
@@ -624,10 +618,9 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
transform_in,
skip_rerender,
} => {
let layer_identifier = LayerNodeIdentifier::new(*layer.last().unwrap(), document_network);
let parent_transform = document_metadata.downstream_transform_to_viewport(layer_identifier);
let bounds = LayerBounds::new(document_network, document_metadata, &layer);
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) {
let parent_transform = document_metadata.downstream_transform_to_viewport(layer);
let bounds = LayerBounds::new(document_metadata, layer);
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
modify_inputs.transform_change(transform, transform_in, parent_transform, bounds, skip_rerender);
}
}
@@ -637,28 +630,27 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
transform_in,
skip_rerender,
} => {
let layer_identifier = LayerNodeIdentifier::new(*layer.last().unwrap(), document_network);
let parent_transform = document_metadata.downstream_transform_to_viewport(layer_identifier);
let parent_transform = document_metadata.downstream_transform_to_viewport(layer);
let current_transform = Some(document_metadata.transform_to_viewport(layer_identifier));
let bounds = LayerBounds::new(document_network, document_metadata, &layer);
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) {
let current_transform = Some(document_metadata.transform_to_viewport(layer));
let bounds = LayerBounds::new(document_metadata, layer);
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
modify_inputs.transform_set(transform, transform_in, parent_transform, current_transform, bounds, skip_rerender);
}
}
GraphOperationMessage::TransformSetPivot { layer, pivot } => {
let bounds = LayerBounds::new(document_network, document_metadata, &layer);
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) {
let bounds = LayerBounds::new(document_metadata, layer);
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
modify_inputs.pivot_set(pivot, bounds);
}
}
GraphOperationMessage::Vector { layer, modification } => {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
modify_inputs.vector_modify(modification);
}
}
GraphOperationMessage::Brush { layer, strokes } => {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&layer, document_network, document_metadata, node_graph, responses) {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer.to_node(), document_network, document_metadata, node_graph, responses) {
modify_inputs.brush_modify(strokes);
}
}
@@ -744,7 +736,7 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
load_network_structure(document_network, document_metadata, collapsed);
}
GraphOperationMessage::ResizeArtboard { id, location, dimensions } => {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(&[id], document_network, document_metadata, node_graph, responses) {
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(id, document_network, document_metadata, node_graph, responses) {
modify_inputs.resize_artboard(location, dimensions);
}
}

View File

@@ -2,7 +2,6 @@ use crate::messages::portfolio::document::node_graph::VectorDataModification;
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use bezier_rs::{ManipulatorGroup, Subpath};
use graph_craft::document::NodeNetwork;
use graph_craft::document::{value::TaggedValue, NodeInput};
use graphene_core::uuid::ManipulatorGroupId;
use graphene_core::vector::{ManipulatorPointId, SelectedType};
@@ -53,8 +52,7 @@ pub struct LayerBounds {
impl LayerBounds {
/// Extract the layer bounds and their transform for a layer.
pub fn new(document_network: &NodeNetwork, document_metadata: &DocumentMetadata, layer: &[u64]) -> Self {
let layer = LayerNodeIdentifier::new(*layer.last().unwrap(), document_network);
pub fn new(document_metadata: &DocumentMetadata, layer: LayerNodeIdentifier) -> Self {
Self {
bounds: document_metadata.nonzero_bounding_box(layer),
bounds_transform: DAffine2::IDENTITY,

View File

@@ -1,4 +1,3 @@
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::prelude::*;
use graph_craft::document::value::TaggedValue;
@@ -11,14 +10,13 @@ pub enum NodeGraphMessage {
Init,
SelectedNodesUpdated,
ConnectNodesByLink {
output_node: u64,
output_node: NodeId,
output_node_connector_index: usize,
input_node: u64,
input_node: NodeId,
input_node_connector_index: usize,
},
Copy,
CreateNode {
// Having the caller generate the id means that we don't have to return it. This can be a random u64.
node_id: Option<NodeId>,
node_type: String,
x: i32,
@@ -83,7 +81,6 @@ pub enum NodeGraphMessage {
input: NodeInput,
},
SetQualifiedInputValue {
layer_path: Vec<LayerId>,
node_path: Vec<NodeId>,
input_index: usize,
value: TaggedValue,

View File

@@ -3,9 +3,7 @@ use super::load_network_structure;
use crate::messages::input_mapper::utility_types::macros::action_keys;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::prelude::*;
use crate::node_graph_executor::GraphIdentifier;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{DocumentNode, NodeId, NodeInput, NodeNetwork, NodeOutput};
@@ -99,13 +97,13 @@ pub struct FrontendNode {
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct FrontendNodeLink {
#[serde(rename = "linkStart")]
pub link_start: u64,
pub link_start: NodeId,
#[serde(rename = "linkStartOutputIndex")]
pub link_start_output_index: usize,
#[serde(rename = "linkEnd")]
pub link_end: u64,
pub link_end: NodeId,
#[serde(rename = "linkEndInputIndex")]
pub link_end_input_index: u64,
pub link_end_input_index: usize,
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
@@ -124,10 +122,9 @@ impl FrontendNodeType {
#[derive(Debug, Clone, PartialEq)]
pub struct NodeGraphMessageHandler {
pub layer_path: Option<Vec<LayerId>>,
pub network: Vec<NodeId>,
has_selection: bool,
pub widgets: [LayoutGroup; 2],
widgets: [LayoutGroup; 2],
}
impl Default for NodeGraphMessageHandler {
@@ -137,7 +134,6 @@ impl Default for NodeGraphMessageHandler {
let add_nodes_label_row = LayoutGroup::Row { widgets: vec![add_nodes_label] };
Self {
layer_path: None,
network: Vec::new(),
has_selection: false,
widgets: [add_nodes_label_row, LayoutGroup::default()],
@@ -261,15 +257,13 @@ impl NodeGraphMessageHandler {
}
}
fn send_graph(network: &NodeNetwork, layer_path: &Option<Vec<LayerId>>, graph_view_overlay_open: bool, responses: &mut VecDeque<Message>) {
fn send_graph(network: &NodeNetwork, graph_view_overlay_open: bool, responses: &mut VecDeque<Message>) {
responses.add(PropertiesPanelMessage::Refresh);
if !graph_view_overlay_open {
return;
}
let layer_id = layer_path.as_ref().and_then(|path| path.last().copied());
// List of links in format (link_start, link_end, link_end_input_index)
let links = network
.nodes
@@ -278,16 +272,16 @@ impl NodeGraphMessageHandler {
.filter_map(|(input, &link_end, link_end_input_index)| {
if let NodeInput::Node {
node_id: link_start,
output_index: link_start_index,
output_index: link_start_output_index,
// TODO: add ui for lambdas
lambda: _,
} = *input
{
Some(FrontendNodeLink {
link_start,
link_start_output_index: link_start_index,
link_start_output_index,
link_end,
link_end_input_index: link_end_input_index as u64,
link_end_input_index,
})
} else {
None
@@ -318,8 +312,6 @@ impl NodeGraphMessageHandler {
});
let primary_output = if node.has_primary_output { outputs.next() } else { None };
let _graph_identifier = GraphIdentifier::new(layer_id);
nodes.push(FrontendNode {
is_layer: node.is_layer(),
id: *id,
@@ -446,7 +438,7 @@ impl NodeGraphMessageHandler {
pub struct NodeGraphHandlerData<'a> {
pub document_network: &'a mut NodeNetwork,
pub document_metadata: &'a mut DocumentMetadata,
pub document_id: u64,
pub document_id: DocumentId,
pub document_name: &'a str,
pub collapsed: &'a mut Vec<LayerNodeIdentifier>,
pub input: &'a InputPreprocessorMessageHandler,
@@ -495,7 +487,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
error!("No network");
return;
};
let Some(input_node) = network.nodes.get(&input_node) else {
let Some(input_node) = network.nodes.get(&node_id) else {
error!("No to");
return;
};
@@ -569,11 +561,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
if let Some(network) = document_network.nested_network(&self.network) {
// Only generate node graph if one of the selected nodes is connected to the output
if metadata.selected_nodes().any(|&node_id| network.connected_to_output(node_id)) {
if let Some(layer_path) = self.layer_path.clone() {
responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path });
} else {
responses.add(NodeGraphMessage::RunDocumentGraph);
}
responses.add(NodeGraphMessage::RunDocumentGraph);
}
}
}
@@ -612,7 +600,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
}
}
if let Some(network) = document_network.nested_network(&self.network) {
Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses);
Self::send_graph(network, graph_view_overlay_open, responses);
}
self.update_selected(document_network, metadata, responses);
}
@@ -640,7 +628,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::InsertNode { node_id, document_node });
}
Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses);
Self::send_graph(network, graph_view_overlay_open, responses);
self.update_selected(document_network, metadata, responses);
responses.add(NodeGraphMessage::SendGraph { should_rerender: false });
}
@@ -653,7 +641,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
self.network.pop();
}
if let Some(network) = document_network.nested_network(&self.network) {
Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses);
Self::send_graph(network, graph_view_overlay_open, responses);
}
self.update_selected(document_network, metadata, responses);
}
@@ -703,7 +691,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
node.metadata.position += IVec2::new(displacement_x, displacement_y)
}
}
Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses);
Self::send_graph(network, graph_view_overlay_open, responses);
}
NodeGraphMessage::PasteNodes { serialized_nodes } => {
let Some(network) = document_network.nested_network(&self.network) else {
@@ -752,7 +740,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::SendGraph { should_rerender: false });
}
NodeGraphMessage::RunDocumentGraph => responses.add(PortfolioMessage::SubmitGraphRender { document_id, layer_path: Vec::new() }),
NodeGraphMessage::RunDocumentGraph => responses.add(PortfolioMessage::SubmitGraphRender { document_id }),
NodeGraphMessage::SelectedNodesAdd { nodes } => {
metadata.add_selected_nodes(nodes);
responses.add(BroadcastEvent::SelectionChanged);
@@ -768,13 +756,9 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
}
NodeGraphMessage::SendGraph { should_rerender } => {
if let Some(network) = document_network.nested_network(&self.network) {
Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses);
Self::send_graph(network, graph_view_overlay_open, responses);
if should_rerender {
if let Some(layer_path) = self.layer_path.clone() {
responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path });
} else {
responses.add(NodeGraphMessage::RunDocumentGraph);
}
responses.add(NodeGraphMessage::RunDocumentGraph);
}
}
}
@@ -787,11 +771,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::SetNodeInput { node_id, input_index, input });
responses.add(PropertiesPanelMessage::Refresh);
if (node.name != "Imaginate" || input_index == 0) && network.connected_to_output(node_id) {
if let Some(layer_path) = self.layer_path.clone() {
responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path });
} else {
responses.add(NodeGraphMessage::RunDocumentGraph);
}
responses.add(NodeGraphMessage::RunDocumentGraph);
}
}
}
@@ -811,12 +791,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
}
}
}
NodeGraphMessage::SetQualifiedInputValue {
layer_path,
node_path,
input_index,
value,
} => {
NodeGraphMessage::SetQualifiedInputValue { node_path, input_index, value } => {
let Some((node_id, node_path)) = node_path.split_last() else {
error!("Node path is empty");
return;
@@ -832,7 +807,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
}
node.inputs[input_index] = NodeInput::Value { tagged_value: value, exposed: false };
if network.connected_to_output(*node_id) {
responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path });
responses.add(NodeGraphMessage::RunDocumentGraph);
}
}
}
@@ -908,7 +883,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
} else if !network.inputs.contains(&node_id) && !network.original_outputs().iter().any(|output| output.node_id == node_id) {
network.disabled.push(node_id);
}
Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses);
Self::send_graph(network, graph_view_overlay_open, responses);
// Only generate node graph if one of the selected nodes is connected to the output
if network.connected_to_output(node_id) {
@@ -944,21 +919,17 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
} else {
return;
}
Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses);
Self::send_graph(network, graph_view_overlay_open, responses);
}
self.update_selection_action_buttons(document_network, metadata, responses);
if let Some(layer_path) = self.layer_path.clone() {
responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path });
} else {
responses.add(NodeGraphMessage::RunDocumentGraph);
}
responses.add(NodeGraphMessage::RunDocumentGraph);
}
NodeGraphMessage::UpdateNewNodeGraph => {
if let Some(network) = document_network.nested_network(&self.network) {
metadata.clear_selected_nodes();
responses.add(BroadcastEvent::SelectionChanged);
Self::send_graph(network, &self.layer_path, graph_view_overlay_open, responses);
Self::send_graph(network, graph_view_overlay_open, responses);
let node_types = document_node_types::collect_node_types();
responses.add(FrontendMessage::UpdateNodeTypes { node_types });

View File

@@ -2,7 +2,6 @@ use super::{node_properties, FrontendGraphDataType, FrontendNodeType};
use crate::consts::{DEFAULT_FONT_FAMILY, DEFAULT_FONT_STYLE};
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::document_metadata::DocumentMetadata;
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::portfolio::utility_types::PersistentData;
use crate::messages::prelude::Message;
use crate::node_graph_executor::NodeGraphExecutor;
@@ -74,7 +73,6 @@ impl DocumentOutputType {
pub struct NodePropertiesContext<'a> {
pub persistent_data: &'a PersistentData,
pub responses: &'a mut VecDeque<Message>,
pub layer_path: &'a [LayerId],
pub nested_path: &'a [NodeId],
pub executor: &'a mut NodeGraphExecutor,
pub network: &'a NodeNetwork,
@@ -279,7 +277,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Image Frame",
data_type: FrontendGraphDataType::Raster,
}],
properties: node_properties::input_properties,
properties: node_properties::node_no_properties,
..Default::default()
},
DocumentNodeDefinition {
@@ -1069,7 +1067,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "OutputBuffer",
data_type: FrontendGraphDataType::General,
}],
properties: node_properties::input_properties,
properties: node_properties::node_no_properties,
..Default::default()
},
#[cfg(feature = "gpu")]
@@ -1137,7 +1135,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "CommandBuffer",
data_type: FrontendGraphDataType::General,
}],
properties: node_properties::input_properties,
properties: node_properties::node_no_properties,
..Default::default()
},
#[cfg(feature = "gpu")]
@@ -1171,7 +1169,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "PipelineLayout",
data_type: FrontendGraphDataType::General,
}],
properties: node_properties::input_properties,
properties: node_properties::node_no_properties,
..Default::default()
},
#[cfg(feature = "gpu")]
@@ -2377,7 +2375,7 @@ pub static IMAGINATE_NODE: Lazy<DocumentNodeDefinition> = Lazy::new(|| DocumentN
name: "Imaginate",
category: "Image Synthesis",
implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
inputs: vec![0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
outputs: vec![NodeOutput::new(1, 0)],
nodes: [
(
@@ -2404,14 +2402,13 @@ pub static IMAGINATE_NODE: Lazy<DocumentNodeDefinition> = Lazy::new(|| DocumentN
NodeInput::Network(concrete!(String)),
NodeInput::Network(concrete!(bool)),
NodeInput::Network(concrete!(f32)),
NodeInput::Network(concrete!(Option<Vec<u64>>)),
NodeInput::Network(concrete!(bool)),
NodeInput::Network(concrete!(f32)),
NodeInput::Network(concrete!(ImaginateMaskStartingFill)),
NodeInput::Network(concrete!(bool)),
NodeInput::Network(concrete!(bool)),
],
implementation: DocumentNodeImplementation::proto("graphene_std::raster::ImaginateNode<_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _>"),
implementation: DocumentNodeImplementation::proto("graphene_std::raster::ImaginateNode<_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _>"),
..Default::default()
},
),
@@ -2436,7 +2433,6 @@ pub static IMAGINATE_NODE: Lazy<DocumentNodeDefinition> = Lazy::new(|| DocumentN
DocumentInputType::value("Negative Prompt", TaggedValue::String(String::new()), false),
DocumentInputType::value("Adapt Input Image", TaggedValue::Bool(false), false),
DocumentInputType::value("Image Creativity", TaggedValue::F32(66.), false),
DocumentInputType::value("Masking Layer", TaggedValue::LayerPath(None), false),
DocumentInputType::value("Inpaint", TaggedValue::Bool(true), false),
DocumentInputType::value("Mask Blur", TaggedValue::F32(4.), false),
DocumentInputType::value("Mask Starting Fill", TaggedValue::ImaginateMaskStartingFill(ImaginateMaskStartingFill::Fill), false),

View File

@@ -144,16 +144,16 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
NumberInput::new(Some(dvec2.x))
.label(x)
.unit(unit)
.min(min.unwrap_or(-((1u64 << std::f64::MANTISSA_DIGITS) as f64)))
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64)))
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(input.value.unwrap(), dvec2.y)), node_id, index))
.widget_holder(),
Separator::new(SeparatorType::Related).widget_holder(),
NumberInput::new(Some(dvec2.y))
.label(y)
.unit(unit)
.min(min.unwrap_or(-((1u64 << std::f64::MANTISSA_DIGITS) as f64)))
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64)))
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(dvec2.x, input.value.unwrap())), node_id, index))
.widget_holder(),
]);
@@ -170,8 +170,8 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
.int()
.label(x)
.unit(unit)
.min(min.unwrap_or(-((1u64 << std::f64::MANTISSA_DIGITS) as f64)))
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64)))
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(update_x, node_id, index))
.widget_holder(),
Separator::new(SeparatorType::Related).widget_holder(),
@@ -179,8 +179,8 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
.int()
.label(y)
.unit(unit)
.min(min.unwrap_or(-((1u64 << std::f64::MANTISSA_DIGITS) as f64)))
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64)))
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(update_y, node_id, index))
.widget_holder(),
]);
@@ -198,7 +198,7 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
.label(x)
.unit(unit)
.min(min.unwrap_or(0.))
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(update_x, node_id, index))
.widget_holder(),
Separator::new(SeparatorType::Related).widget_holder(),
@@ -207,7 +207,7 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
.label(y)
.unit(unit)
.min(min.unwrap_or(0.))
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(update_y, node_id, index))
.widget_holder(),
]);
@@ -359,7 +359,7 @@ fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, na
}
//TODO Generalize this instead of using a separate function per dropdown menu enum
fn color_channel(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
fn color_channel(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let &NodeInput::Value {
tagged_value: TaggedValue::RedGreenBlue(mode),
@@ -382,7 +382,7 @@ fn color_channel(document_node: &DocumentNode, node_id: u64, index: usize, name:
}
// TODO Generalize this instead of using a separate function per dropdown menu enum
fn noise_type(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
fn noise_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let &NodeInput::Value {
tagged_value: TaggedValue::NoiseType(noise_type),
@@ -403,7 +403,7 @@ fn noise_type(document_node: &DocumentNode, node_id: u64, index: usize, name: &s
}
// TODO Generalize this instead of using a separate function per dropdown menu enum
fn fractal_type(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup {
fn fractal_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let &NodeInput::Value {
tagged_value: TaggedValue::FractalType(fractal_type),
@@ -424,7 +424,7 @@ fn fractal_type(document_node: &DocumentNode, node_id: u64, index: usize, name:
}
// TODO Generalize this instead of using a separate function per dropdown menu enum
fn cellular_distance_function(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup {
fn cellular_distance_function(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let &NodeInput::Value {
tagged_value: TaggedValue::CellularDistanceFunction(cellular_distance_function),
@@ -450,7 +450,7 @@ fn cellular_distance_function(document_node: &DocumentNode, node_id: u64, index:
}
// TODO Generalize this instead of using a separate function per dropdown menu enum
fn cellular_return_type(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup {
fn cellular_return_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let &NodeInput::Value {
tagged_value: TaggedValue::CellularReturnType(cellular_return_type),
@@ -471,7 +471,7 @@ fn cellular_return_type(document_node: &DocumentNode, node_id: u64, index: usize
}
// TODO Generalize this instead of using a separate function per dropdown menu enum
fn domain_warp_type(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup {
fn domain_warp_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool, disabled: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let &NodeInput::Value {
tagged_value: TaggedValue::DomainWarpType(domain_warp_type),
@@ -492,7 +492,7 @@ fn domain_warp_type(document_node: &DocumentNode, node_id: u64, index: usize, na
}
// TODO: Generalize this instead of using a separate function per dropdown menu enum
fn blend_mode(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
fn blend_mode(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let &NodeInput::Value {
tagged_value: TaggedValue::BlendMode(blend_mode),
@@ -520,7 +520,7 @@ fn blend_mode(document_node: &DocumentNode, node_id: u64, index: usize, name: &s
}
// TODO: Generalize this for all dropdowns (also see blend_mode and channel_extration)
fn luminance_calculation(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
fn luminance_calculation(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let &NodeInput::Value {
tagged_value: TaggedValue::LuminanceCalculation(calculation),
@@ -542,7 +542,7 @@ fn luminance_calculation(document_node: &DocumentNode, node_id: u64, index: usiz
LayoutGroup::Row { widgets }.with_tooltip("Formula used to calculate the luminance of a pixel")
}
fn line_cap_widget(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
fn line_cap_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let &NodeInput::Value {
tagged_value: TaggedValue::LineCap(line_cap),
@@ -562,7 +562,7 @@ fn line_cap_widget(document_node: &DocumentNode, node_id: u64, index: usize, nam
LayoutGroup::Row { widgets }
}
fn line_join_widget(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
fn line_join_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let &NodeInput::Value {
tagged_value: TaggedValue::LineJoin(line_join),
@@ -582,7 +582,7 @@ fn line_join_widget(document_node: &DocumentNode, node_id: u64, index: usize, na
LayoutGroup::Row { widgets }
}
fn fill_type_widget(document_node: &DocumentNode, node_id: u64, index: usize) -> LayoutGroup {
fn fill_type_widget(document_node: &DocumentNode, node_id: NodeId, index: usize) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, "Fill Type", FrontendGraphDataType::General, true);
if let &NodeInput::Value {
tagged_value: TaggedValue::FillType(fill_type),
@@ -607,7 +607,7 @@ fn fill_type_widget(document_node: &DocumentNode, node_id: u64, index: usize) ->
LayoutGroup::Row { widgets }
}
fn gradient_type_widget(document_node: &DocumentNode, node_id: u64, index: usize) -> LayoutGroup {
fn gradient_type_widget(document_node: &DocumentNode, node_id: NodeId, index: usize) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, "Gradient Type", FrontendGraphDataType::General, true);
if let &NodeInput::Value {
tagged_value: TaggedValue::GradientType(gradient_type),
@@ -699,7 +699,7 @@ fn gradient_row(row: &mut Vec<WidgetHolder>, positions: &Vec<(f64, Option<Color>
}
}
fn gradient_positions(rows: &mut Vec<LayoutGroup>, document_node: &DocumentNode, name: &str, node_id: u64, input_index: usize) {
fn gradient_positions(rows: &mut Vec<LayoutGroup>, document_node: &DocumentNode, name: &str, node_id: NodeId, input_index: usize) {
let mut widgets = vec![expose_widget(node_id, input_index, FrontendGraphDataType::General, document_node.inputs[input_index].is_exposed())];
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
if let NodeInput::Value {
@@ -742,7 +742,7 @@ fn gradient_positions(rows: &mut Vec<LayoutGroup>, document_node: &DocumentNode,
}
}
fn color_widget(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, color_props: ColorButton, blank_assist: bool) -> LayoutGroup {
fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, color_props: ColorButton, blank_assist: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::Number, blank_assist);
if let NodeInput::Value { tagged_value, exposed: false } = &document_node.inputs[index] {
@@ -767,7 +767,7 @@ fn color_widget(document_node: &DocumentNode, node_id: u64, index: usize, name:
LayoutGroup::Row { widgets }
}
fn curves_widget(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
fn curves_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
if let NodeInput::Value {
@@ -785,17 +785,6 @@ fn curves_widget(document_node: &DocumentNode, node_id: u64, index: usize, name:
LayoutGroup::Row { widgets }
}
/// Properties for the input node, with information describing how frames work and a refresh button
pub fn input_properties(_document_node: &DocumentNode, _node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
let information = TextLabel::new("The graph's input frame is the rasterized artwork under the layer").widget_holder();
let layer_path = context.layer_path.to_vec();
let refresh_button = TextButton::new("Refresh Input")
.tooltip("Refresh the artwork under the layer")
.on_update(move |_| DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path: layer_path.clone() }.into())
.widget_holder();
vec![LayoutGroup::Row { widgets: vec![information] }, LayoutGroup::Row { widgets: vec![refresh_button] }]
}
pub fn levels_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
let input_shadows = number_widget(document_node, node_id, 1, "Shadows", NumberInput::default().min(0.).max(100.).unit("%"), true);
let input_midtones = number_widget(document_node, node_id, 2, "Midtones", NumberInput::default().min(0.).max(100.).unit("%"), true);
@@ -1629,12 +1618,10 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
.tooltip("Generate with a new random seed")
.on_update({
let imaginate_node = imaginate_node.clone();
let layer_path = context.layer_path.to_vec();
let controller = controller.clone();
move |_| {
controller.trigger_regenerate();
DocumentMessage::ImaginateRandom {
layer_path: layer_path.clone(),
imaginate_node: imaginate_node.clone(),
then_generate: true,
}
@@ -1646,11 +1633,10 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
TextButton::new("Generate")
.tooltip("Fill layer frame by generating a new image")
.on_update({
let layer_path = context.layer_path.to_vec();
let controller = controller.clone();
move |_| {
controller.trigger_regenerate();
DocumentMessage::ImaginateGenerate { layer_path: layer_path.clone() }.into()
DocumentMessage::ImaginateGenerate.into()
}
})
.widget_holder(),
@@ -1659,11 +1645,10 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
.tooltip("Remove generated image from the layer frame")
.disabled(!matches!(imaginate_status, ImaginateStatus::ReadyDone))
.on_update({
let layer_path = context.layer_path.to_vec();
let controller = controller.clone();
move |_| {
controller.set_status(ImaginateStatus::Ready);
DocumentMessage::ImaginateClear { layer_path: layer_path.clone() }.into()
DocumentMessage::ImaginateGenerate.into()
}
})
.widget_holder(),
@@ -1687,10 +1672,8 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
.tooltip("Set a new random seed")
.on_update({
let imaginate_node = imaginate_node.clone();
let layer_path = context.layer_path.to_vec();
move |_| {
DocumentMessage::ImaginateRandom {
layer_path: layer_path.clone(),
imaginate_node: imaginate_node.clone(),
then_generate: false,
}
@@ -1701,8 +1684,8 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
Separator::new(SeparatorType::Unrelated).widget_holder(),
NumberInput::new(Some(seed))
.int()
.min(-((1u64 << f64::MANTISSA_DIGITS) as f64))
.max((1u64 << f64::MANTISSA_DIGITS) as f64)
.min(-((1_u64 << f64::MANTISSA_DIGITS) as f64))
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
.on_update(update_value(move |input: &NumberInput| TaggedValue::F64(input.value.unwrap()), node_id, seed_index))
.mode(NumberInputMode::Increment)
.widget_holder(),

View File

@@ -37,7 +37,6 @@ impl<'a> MessageHandler<PropertiesPanelMessage, (&PersistentData, PropertiesPane
persistent_data,
responses,
nested_path: &node_graph_message_handler.network,
layer_path: &[],
executor,
network: document_network,
metadata: document_metadata,

View File

@@ -107,8 +107,9 @@ impl DocumentMetadata {
layer_path
})
.collect::<Vec<_>>();
sorted_layers.sort();
// Sorting here creates groups of similar UUID paths
sorted_layers.sort();
sorted_layers.dedup_by(|a, b| a.starts_with(b));
sorted_layers
}
@@ -386,32 +387,27 @@ impl LayerNodeIdentifier {
u64::from(self.0) - 1
}
/// Convert layer to layer path
pub fn to_path(self) -> Vec<NodeId> {
vec![self.to_node()]
}
/// Access the parent layer if possible
pub fn parent(self, document_metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
document_metadata.get_relations(self).and_then(|relations| relations.parent)
}
/// Access the previous sibling of this layer (up the layer tree)
/// Access the previous sibling of this layer (up the Layers panel)
pub fn previous_sibling(self, document_metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
document_metadata.get_relations(self).and_then(|relations| relations.previous_sibling)
}
/// Access the next sibling of this layer (down the layer tree)
/// Access the next sibling of this layer (down the Layers panel)
pub fn next_sibling(self, document_metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
document_metadata.get_relations(self).and_then(|relations| relations.next_sibling)
}
/// Access the first child of this layer (top most in layer tree)
/// Access the first child of this layer (top most in Layers panel)
pub fn first_child(self, document_metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
document_metadata.get_relations(self).and_then(|relations| relations.first_child)
}
/// Access the last child of this layer (bottom most in layer tree)
/// Access the last child of this layer (bottom most in Layers panel)
pub fn last_child(self, document_metadata: &DocumentMetadata) -> Option<LayerNodeIdentifier> {
document_metadata.get_relations(self).and_then(|relations| relations.last_child)
}
@@ -457,7 +453,7 @@ impl LayerNodeIdentifier {
}
}
/// Add a child towards the top of the layer tree
/// Add a child towards the top of the Layers panel
pub fn push_front_child(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer");
let parent = document_metadata.get_structure_mut(self);
@@ -470,7 +466,7 @@ impl LayerNodeIdentifier {
document_metadata.get_structure_mut(new).parent = Some(self);
}
/// Add a child towards the bottom of the layer tree
/// Add a child towards the bottom of the Layers panel
pub fn push_child(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer");
let parent = document_metadata.get_structure_mut(self);
@@ -483,7 +479,7 @@ impl LayerNodeIdentifier {
document_metadata.get_structure_mut(new).parent = Some(self);
}
/// Add sibling above in the layer tree
/// Add sibling above in the Layers panel
pub fn add_before(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer");
document_metadata.get_structure_mut(new).next_sibling = Some(self);
@@ -501,7 +497,7 @@ impl LayerNodeIdentifier {
}
}
/// Add sibling below in the layer tree
/// Add sibling below in the Layers panel
pub fn add_after(self, document_metadata: &mut DocumentMetadata, new: LayerNodeIdentifier) {
assert!(!document_metadata.structure.contains_key(&new), "Cannot add already existing layer");
document_metadata.get_structure_mut(new).previous_sibling = Some(self);

View File

@@ -1,4 +1,4 @@
use crate::messages::portfolio::document::utility_types::LayerId;
use graph_craft::document::NodeId;
use serde::ser::SerializeStruct;
use serde::{Deserialize, Serialize};
@@ -45,6 +45,9 @@ pub struct LayerPanelEntry {
pub layer_classification: LayerClassification,
pub selected: bool,
pub expanded: bool,
pub path: Vec<LayerId>,
#[serde(rename = "parentId")]
pub parent_id: Option<NodeId>,
pub id: NodeId,
pub depth: usize,
pub thumbnail: String,
}

View File

@@ -1,7 +1,4 @@
pub use super::layer_panel::LayerPanelEntry;
use crate::messages::portfolio::document::utility_types::LayerId;
use graphene_core::raster::color::Color;
use glam::DVec2;
use serde::{Deserialize, Serialize};
@@ -54,12 +51,6 @@ impl DocumentMode {
}
}
pub enum DocumentRenderMode<'a> {
Root,
OnlyBelowLayerInFolder(&'a [LayerId]),
LayerCutout(&'a [LayerId], Color),
}
#[derive(Clone, Debug)]
/// SnappingState determines the current individual snapping states
pub struct SnappingState {

View File

@@ -4,8 +4,3 @@ pub mod error;
pub mod layer_panel;
pub mod misc;
pub mod transformation;
// TODO: Remove this entirely
/// A number that identifies a layer.
/// This does not technically need to be unique globally, only within a folder.
pub type LayerId = u64;

View File

@@ -376,7 +376,7 @@ impl<'a> Selected<'a> {
let to = document_metadata.downstream_transform_to_viewport(layer);
let new = to.inverse() * transformation * to * original_transform;
responses.add(GraphOperationMessage::TransformSet {
layer: layer.to_path(),
layer,
transform: new,
transform_in: TransformIn::Local,
skip_rerender: false,
@@ -404,7 +404,7 @@ impl<'a> Selected<'a> {
let position = new_pos_viewport;
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position },
});
}
@@ -438,17 +438,17 @@ impl<'a> Selected<'a> {
OriginalTransforms::Layer(hash) => {
let Some(matrix) = hash.get(&layer) else { continue };
self.responses.add(GraphOperationMessage::TransformSet {
layer: layer.to_path(),
layer,
transform: *matrix,
transform_in: TransformIn::Local,
skip_rerender: false,
});
}
OriginalTransforms::Path(path) => {
for (layer, points) in path {
for (&layer, points) in path {
for &(point, position) in points {
self.responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position },
});
}

View File

@@ -1,8 +1,8 @@
use super::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::frontend::utility_types::{ExportBounds, FileType};
use crate::messages::portfolio::document::utility_types::clipboards::Clipboard;
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::prelude::*;
use graphene_core::text::Font;
use serde::{Deserialize, Serialize};
@@ -22,21 +22,21 @@ pub enum PortfolioMessage {
// Messages
#[remain::unsorted]
DocumentPassMessage {
document_id: u64,
document_id: DocumentId,
message: DocumentMessage,
},
AutoSaveActiveDocument,
AutoSaveDocument {
document_id: u64,
document_id: DocumentId,
},
CloseActiveDocumentWithConfirmation,
CloseAllDocuments,
CloseAllDocumentsWithConfirmation,
CloseDocument {
document_id: u64,
document_id: DocumentId,
},
CloseDocumentWithConfirmation {
document_id: u64,
document_id: DocumentId,
},
Copy {
clipboard: Clipboard,
@@ -45,7 +45,7 @@ pub enum PortfolioMessage {
clipboard: Clipboard,
},
DeleteDocument {
document_id: u64,
document_id: DocumentId,
},
DestroyAllDocuments,
FontLoaded {
@@ -65,7 +65,7 @@ pub enum PortfolioMessage {
ImaginateServerHostname,
Import,
LoadDocumentResources {
document_id: u64,
document_id: DocumentId,
},
LoadFont {
font: Font,
@@ -81,7 +81,7 @@ pub enum PortfolioMessage {
document_serialized_content: String,
},
OpenDocumentFileWithId {
document_id: u64,
document_id: DocumentId,
document_name: String,
document_is_auto_saved: bool,
document_is_saved: bool,
@@ -97,10 +97,10 @@ pub enum PortfolioMessage {
},
PrevDocument,
SelectDocument {
document_id: u64,
document_id: DocumentId,
},
SetActiveDocument {
document_id: u64,
document_id: DocumentId,
},
SubmitDocumentExport {
file_name: String,
@@ -110,8 +110,7 @@ pub enum PortfolioMessage {
transparent_background: bool,
},
SubmitGraphRender {
document_id: u64,
layer_path: Vec<LayerId>,
document_id: DocumentId,
},
ToggleRulers,
UpdateDocumentWidgets,

View File

@@ -19,9 +19,9 @@ use std::sync::Arc;
#[derive(Debug, Default)]
pub struct PortfolioMessageHandler {
menu_bar_message_handler: MenuBarMessageHandler,
documents: HashMap<u64, DocumentMessageHandler>,
document_ids: Vec<u64>,
active_document_id: Option<u64>,
documents: HashMap<DocumentId, DocumentMessageHandler>,
document_ids: Vec<DocumentId>,
active_document_id: Option<DocumentId>,
graph_view_overlay_open: bool,
copy_buffer: [Vec<CopyBufferEntry>; INTERNAL_CLIPBOARD_COUNT as usize],
pub persistent_data: PersistentData,
@@ -109,7 +109,7 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
// Clear relevant UI layouts if there are no documents
responses.add(PropertiesPanelMessage::Clear);
responses.add(DocumentMessage::ClearLayerTree);
responses.add(DocumentMessage::ClearLayersPanel);
let hint_data = HintData(vec![HintGroup(vec![])]);
responses.add(FrontendMessage::UpdateInputHints { hint_data });
}
@@ -133,7 +133,7 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
if self.documents.len() == 1 && self.document_ids[0] == document_id {
// Clear UI layouts that assume the existence of a document
responses.add(PropertiesPanelMessage::Clear);
responses.add(DocumentMessage::ClearLayerTree);
responses.add(DocumentMessage::ClearLayersPanel);
let hint_data = HintData(vec![HintGroup(vec![])]);
responses.add(FrontendMessage::UpdateInputHints { hint_data });
}
@@ -506,10 +506,9 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
});
}
}
PortfolioMessage::SubmitGraphRender { document_id, layer_path } => {
PortfolioMessage::SubmitGraphRender { document_id } => {
let result = self.executor.submit_node_graph_evaluation(
self.documents.get_mut(&document_id).expect("Tried to render no existent Document"),
layer_path,
ipp.viewport_bounds.size().as_uvec2(),
);
@@ -591,11 +590,11 @@ impl PortfolioMessageHandler {
self.executor.introspect_node(node_path)
}
pub fn document(&self, document_id: u64) -> Option<&DocumentMessageHandler> {
pub fn document(&self, document_id: DocumentId) -> Option<&DocumentMessageHandler> {
self.documents.get(&document_id)
}
pub fn document_mut(&mut self, document_id: u64) -> Option<&mut DocumentMessageHandler> {
pub fn document_mut(&mut self, document_id: DocumentId) -> Option<&mut DocumentMessageHandler> {
self.documents.get_mut(&document_id)
}
@@ -607,7 +606,7 @@ impl PortfolioMessageHandler {
self.active_document_id.and_then(|id| self.documents.get_mut(&id))
}
pub fn active_document_id(&self) -> Option<u64> {
pub fn active_document_id(&self) -> Option<DocumentId> {
self.active_document_id
}
@@ -637,7 +636,7 @@ impl PortfolioMessageHandler {
}
// TODO: Fix how this doesn't preserve tab order upon loading new document from *File > Load*
fn load_document(&mut self, new_document: DocumentMessageHandler, document_id: u64, responses: &mut VecDeque<Message>) {
fn load_document(&mut self, new_document: DocumentMessageHandler, document_id: DocumentId, responses: &mut VecDeque<Message>) {
self.document_ids.push(document_id);
new_document.update_layers_panel_options_bar_widgets(responses);
@@ -667,7 +666,7 @@ impl PortfolioMessageHandler {
self.document_ids.iter().map(|id| self.documents.get(id).expect("document id was not found in the document hashmap"))
}
fn document_index(&self, document_id: u64) -> usize {
fn document_index(&self, document_id: DocumentId) -> usize {
self.document_ids.iter().position(|id| id == &document_id).expect("Active document is missing from document ids")
}

View File

@@ -56,6 +56,9 @@ pub use graphite_proc_macros::*;
pub use std::collections::{HashMap, HashSet, VecDeque};
// TODO: Convert from a type alias to a newtype
pub type DocumentId = u64;
pub trait Responses {
fn add(&mut self, message: impl Into<Message>);

View File

@@ -38,7 +38,7 @@ pub fn new_image_layer(image_frame: ImageFrame<Color>, id: NodeId, parent: Layer
pub fn set_manipulator_mirror_angle(manipulator_groups: &[ManipulatorGroup<ManipulatorGroupId>], layer: LayerNodeIdentifier, mirror_angle: bool, responses: &mut VecDeque<Message>) {
for manipulator_group in manipulator_groups {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorHandleMirroring {
id: manipulator_group.id,
mirror_angle,
@@ -216,7 +216,7 @@ impl<'a> NodeGraphLayer<'a> {
}
/// Return an iterator up the primary flow of the layer
pub fn primary_layer_flow(&self) -> impl Iterator<Item = (&'a DocumentNode, u64)> {
pub fn primary_layer_flow(&self) -> impl Iterator<Item = (&'a DocumentNode, NodeId)> {
self.node_graph.upstream_flow_back_from_nodes(vec![self.layer_node], true)
}

View File

@@ -105,7 +105,6 @@ impl Pivot {
let pivot = transform.inverse().transform_point2(position);
// Only update the pivot when computed position is finite. Infinite can happen when scale is 0.
if pivot.is_finite() {
let layer = layer.to_path();
responses.add(GraphOperationMessage::TransformSetPivot { layer, pivot });
}
}

View File

@@ -17,7 +17,6 @@ impl Resize {
/// Starts a resize, assigning the snap targets and snapping the starting position.
pub fn start(&mut self, responses: &mut VecDeque<Message>, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) {
self.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true);
self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
let root_transform = document.metadata().document_to_viewport;
self.drag_start = root_transform.inverse().transform_point2(self.snap_manager.snap_position(responses, document, input.mouse.position));
}
@@ -25,7 +24,6 @@ impl Resize {
/// Recalculates snap targets without snapping the starting position.
pub fn recalculate_snaps(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) {
self.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true);
self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
}
/// Calculate the drag start position in viewport space.
@@ -65,7 +63,7 @@ impl Resize {
Some(
GraphOperationMessage::TransformSet {
layer: layer.to_path(),
layer,
transform: DAffine2::from_scale_angle_translation(size, 0., start),
transform_in: TransformIn::Viewport,
skip_rerender,

View File

@@ -192,7 +192,7 @@ impl ShapeState {
if point.manipulator_type.is_handle() {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorHandleMirroring { id: group.id, mirror_angle: false },
});
}
@@ -202,7 +202,7 @@ impl ShapeState {
return;
};
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position: (position + delta) },
});
};
@@ -270,7 +270,7 @@ impl ShapeState {
// Mirror the angle but not the distance
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorHandleMirroring {
id: manipulator.id,
mirror_angle: true,
@@ -291,7 +291,7 @@ impl ShapeState {
if let Some(in_handle) = length_previous.map(|length| anchor_position + handle_vector * length) {
let point = ManipulatorPointId::new(manipulator.id, SelectedType::InHandle);
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position: in_handle },
});
}
@@ -299,7 +299,7 @@ impl ShapeState {
if let Some(out_handle) = length_next.map(|length| anchor_position - handle_vector * length) {
let point = ManipulatorPointId::new(manipulator.id, SelectedType::OutHandle);
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position: out_handle },
});
}
@@ -338,7 +338,7 @@ impl ShapeState {
let out_handle = ManipulatorPointId::new(point.group, SelectedType::OutHandle);
if let Some(position) = group.out_handle {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point: out_handle, position },
});
}
@@ -347,7 +347,7 @@ impl ShapeState {
let in_handle = ManipulatorPointId::new(point.group, SelectedType::InHandle);
if let Some(position) = group.in_handle {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point: in_handle, position },
});
}
@@ -391,7 +391,7 @@ impl ShapeState {
let Some(previous_position) = point.manipulator_type.get_position(group) else { return };
let position = previous_position + delta;
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position },
});
};
@@ -410,7 +410,7 @@ impl ShapeState {
// and set angle mirroring to true.
if !mirror && point.manipulator_type.opposite().get_position(group).is_none() {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorHandleMirroring { id: group.id, mirror_angle: true },
});
mirror = true;
@@ -428,7 +428,7 @@ impl ShapeState {
}
let position = group.anchor - (original_handle_position - group.anchor);
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position },
});
}
@@ -471,7 +471,7 @@ impl ShapeState {
if (anchor_position - point_position).length() < DRAG_THRESHOLD {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::RemoveManipulatorPoint { point },
});
@@ -481,7 +481,7 @@ impl ShapeState {
if let Some(lengths) = opposing_handle_lengths {
if lengths.contains_key(&point.group) {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::RemoveManipulatorPoint { point: opposite_point },
});
}
@@ -567,7 +567,7 @@ impl ShapeState {
let Some(opposing_handle_length) = opposing_handle_length else {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::RemoveManipulatorPoint {
point: ManipulatorPointId::new(manipulator_group.id, single_selected_handle.opposite()),
},
@@ -586,7 +586,7 @@ impl ShapeState {
assert!(position.is_finite(), "Opposing handle not finite!");
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position },
});
}
@@ -596,10 +596,10 @@ impl ShapeState {
/// Dissolve the selected points.
pub fn delete_selected_points(&self, responses: &mut VecDeque<Message>) {
for (layer, state) in &self.selected_shape_state {
for (&layer, state) in &self.selected_shape_state {
for &point in &state.selected_points {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::RemoveManipulatorPoint { point },
})
}
@@ -608,10 +608,10 @@ impl ShapeState {
/// Toggle if the handles should mirror angle across the anchor position.
pub fn toggle_handle_mirroring_on_selected(&self, responses: &mut VecDeque<Message>) {
for (layer, state) in &self.selected_shape_state {
for (&layer, state) in &self.selected_shape_state {
for point in &state.selected_points {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::ToggleManipulatorHandleMirroring { id: point.group },
})
}
@@ -620,10 +620,10 @@ impl ShapeState {
/// Toggle if the handles should mirror angle across the anchor position.
pub fn set_handle_mirroring_on_selected(&self, mirror_angle: bool, responses: &mut VecDeque<Message>) {
for (layer, state) in &self.selected_shape_state {
for (&layer, state) in &self.selected_shape_state {
for point in &state.selected_points {
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorHandleMirroring { id: point.group, mirror_angle },
});
}
@@ -732,7 +732,7 @@ impl ShapeState {
let point = ManipulatorPointId::new(start, SelectedType::OutHandle);
let position = first.handle_start().unwrap_or(first.start());
let out_handle = GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position },
};
responses.add(out_handle);
@@ -740,7 +740,7 @@ impl ShapeState {
// Insert a new manipulator group between the existing ones
let manipulator_group = ManipulatorGroup::new(first.end(), first.handle_end(), second.handle_start());
let insert = GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::AddManipulatorGroup { manipulator_group, after_id: start },
};
responses.add(insert);
@@ -749,7 +749,7 @@ impl ShapeState {
let point = ManipulatorPointId::new(end, SelectedType::InHandle);
let position = second.handle_end().unwrap_or(second.end());
let in_handle = GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position },
};
responses.add(in_handle);
@@ -797,16 +797,16 @@ impl ShapeState {
} else {
let point = ManipulatorPointId::new(manipulator.id, SelectedType::InHandle);
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position: anchor_position },
});
let point = ManipulatorPointId::new(manipulator.id, SelectedType::OutHandle);
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position: anchor_position },
});
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorHandleMirroring {
id: manipulator.id,
mirror_angle: false,

View File

@@ -1,6 +1,4 @@
use super::shape_editor::ManipulatorPointInfo;
use crate::consts::{SNAP_AXIS_TOLERANCE, SNAP_POINT_TOLERANCE};
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::prelude::*;
use glam::DVec2;
@@ -100,23 +98,6 @@ impl SnapManager {
}
}
/// Adds all of the shape handles in the document, including bézier handles of the points specified
pub fn add_all_document_handles(
&mut self,
_document_message_handler: &DocumentMessageHandler,
_input: &InputPreprocessorMessageHandler,
_include_handles: &[&[LayerId]],
_exclude: &[&[LayerId]],
_ignore_points: &[ManipulatorPointInfo],
) {
// for path in document_message_handler.all_layers() {
// if !exclude.contains(&path) {
// let layer = document_message_handler.document_legacy.layer(path).expect("Could not get layer for snapping");
// self.add_snap_path(document_message_handler, input, layer, path, include_handles.contains(&path), ignore_points);
// }
// }
}
/// Finds the closest snap from an array of layers to the specified snap targets in viewport coords.
/// Returns 0 for each axis that there is no snap less than the snap tolerance.
pub fn snap_layers(&mut self, responses: &mut VecDeque<Message>, document_message_handler: &DocumentMessageHandler, snap_anchors: Vec<DVec2>, mouse_delta: DVec2) -> DVec2 {

View File

@@ -16,13 +16,13 @@ pub struct ToolMessageHandler {
pub shape_editor: ShapeState,
}
impl MessageHandler<ToolMessage, (&DocumentMessageHandler, u64, &InputPreprocessorMessageHandler, &PersistentData, &NodeGraphExecutor)> for ToolMessageHandler {
impl MessageHandler<ToolMessage, (&DocumentMessageHandler, DocumentId, &InputPreprocessorMessageHandler, &PersistentData, &NodeGraphExecutor)> for ToolMessageHandler {
#[remain::check]
fn process_message(
&mut self,
message: ToolMessage,
responses: &mut VecDeque<Message>,
(document, document_id, input, persistent_data, node_graph): (&DocumentMessageHandler, u64, &InputPreprocessorMessageHandler, &PersistentData, &NodeGraphExecutor),
(document, document_id, input, persistent_data, node_graph): (&DocumentMessageHandler, DocumentId, &InputPreprocessorMessageHandler, &PersistentData, &NodeGraphExecutor),
) {
let font_cache = &persistent_data.font_cache;

View File

@@ -120,7 +120,6 @@ impl ArtboardToolData {
let snap_y = selected_edges.0 || selected_edges.1;
self.snap_manager.start_snap(document, input, document.bounding_boxes(), snap_x, snap_y);
self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
if let Some(bounds) = &mut self.bounding_box_manager {
bounds.center_of_transformation = (bounds.bounds[0] + bounds.bounds[1]) / 2.;
@@ -139,7 +138,6 @@ impl ArtboardToolData {
self.selected_artboard = Some(intersection);
self.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true);
self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
true
} else {
@@ -279,7 +277,6 @@ impl Fsm for ArtboardToolFsmState {
tool_data.selected_artboard = Some(LayerNodeIdentifier::new_unchecked(id));
tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true);
tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
responses.add(GraphOperationMessage::NewArtboard {
id,

View File

@@ -301,7 +301,7 @@ impl BrushToolData {
fn update_strokes(&self, responses: &mut VecDeque<Message>) {
let Some(layer) = self.layer else { return };
let strokes = self.strokes.clone();
responses.add(GraphOperationMessage::Brush { layer: layer.to_path(), strokes });
responses.add(GraphOperationMessage::Brush { layer, strokes });
}
}

View File

@@ -80,7 +80,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
.unit(" px")
.label("Weight")
.min(0.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(|number_input: &NumberInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
.widget_holder()
}
@@ -211,12 +211,12 @@ impl Fsm for EllipseToolFsmState {
let fill_color = tool_options.fill.active_color();
responses.add(GraphOperationMessage::FillSet {
layer: layer.to_path(),
layer,
fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None },
});
responses.add(GraphOperationMessage::StrokeSet {
layer: layer.to_path(),
layer,
stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight),
});

View File

@@ -72,8 +72,6 @@ impl Fsm for FillToolFsmState {
let Some(layer_identifier) = document.click(input.mouse.position, &document.network) else {
return self;
};
let layer = layer_identifier.to_path();
let color = match event {
FillToolMessage::LeftPointerDown => global_tool_data.primary_color,
FillToolMessage::RightPointerDown => global_tool_data.secondary_color,
@@ -81,7 +79,7 @@ impl Fsm for FillToolFsmState {
let fill = Fill::Solid(color);
responses.add(DocumentMessage::StartTransaction);
responses.add(GraphOperationMessage::FillSet { layer, fill });
responses.add(GraphOperationMessage::FillSet { layer: layer_identifier, fill });
responses.add(DocumentMessage::CommitTransaction);
FillToolFsmState::Ready

View File

@@ -87,7 +87,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
.unit(" px")
.label("Weight")
.min(1.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(|number_input: &NumberInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
.widget_holder()
}
@@ -215,12 +215,12 @@ impl Fsm for FreehandToolFsmState {
tool_data.layer = Some(layer);
responses.add(GraphOperationMessage::FillSet {
layer: layer.to_path(),
layer,
fill: if let Some(color) = tool_options.fill.active_color() { Fill::Solid(color) } else { Fill::None },
});
responses.add(GraphOperationMessage::StrokeSet {
layer: layer.to_path(),
layer,
stroke: Stroke::new(tool_options.stroke.active_color(), tool_data.weight),
});
@@ -234,7 +234,7 @@ impl Fsm for FreehandToolFsmState {
if tool_data.last_point != pos {
let manipulator_group = ManipulatorGroup::new_anchor(pos);
let modification = VectorDataModification::AddEndManipulatorGroup { subpath_index: 0, manipulator_group };
responses.add(GraphOperationMessage::Vector { layer: layer.to_path(), modification });
responses.add(GraphOperationMessage::Vector { layer, modification });
tool_data.dragged = true;
tool_data.last_point = pos;
}

View File

@@ -1,5 +1,4 @@
use super::tool_prelude::*;
use crate::application::generate_uuid;
use crate::consts::{LINE_ROTATE_SNAP_ANGLE, MANIPULATOR_GROUP_MARKER_SIZE, SELECTION_THRESHOLD};
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
@@ -235,9 +234,10 @@ impl SelectedGradient {
/// Update the layer fill to the current gradient
pub fn render_gradient(&mut self, responses: &mut VecDeque<Message>) {
self.gradient.transform = self.transform;
let fill = Fill::Gradient(self.gradient.clone());
let layer = self.layer.to_path();
responses.add(GraphOperationMessage::FillSet { layer, fill });
responses.add(GraphOperationMessage::FillSet {
layer: self.layer,
fill: Fill::Gradient(self.gradient.clone()),
});
}
}
@@ -269,7 +269,6 @@ struct GradientToolData {
pub fn start_snap(snap_manager: &mut SnapManager, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) {
snap_manager.start_snap(document, input, document.bounding_boxes(), true, true);
snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
}
impl Fsm for GradientToolFsmState {
@@ -338,9 +337,10 @@ impl Fsm for GradientToolFsmState {
// The gradient has only one point and so should become a fill
if selected_gradient.gradient.positions.len() == 1 {
let fill = Fill::Solid(selected_gradient.gradient.positions[0].1.unwrap_or(Color::BLACK));
let layer = selected_gradient.layer.to_path();
responses.add(GraphOperationMessage::FillSet { layer, fill });
responses.add(GraphOperationMessage::FillSet {
layer: selected_gradient.layer,
fill: Fill::Solid(selected_gradient.gradient.positions[0].1.unwrap_or(Color::BLACK)),
});
return self;
}
@@ -467,7 +467,6 @@ impl Fsm for GradientToolFsmState {
DVec2::ONE,
global_tool_data.primary_color,
DAffine2::IDENTITY,
generate_uuid(),
tool_options.gradient_type,
)
};

View File

@@ -172,10 +172,6 @@ impl Fsm for ImaginateToolFsmState {
state
}
(ImaginateToolFsmState::Drawing, ImaginateToolMessage::DragStop) => {
if let Some(layer) = &shape_data.layer {
responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path: layer.to_path() });
}
input.mouse.finish_transaction(shape_data.viewport_drag_start(document), responses);
shape_data.cleanup(responses);

View File

@@ -81,7 +81,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
.unit(" px")
.label("Weight")
.min(0.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(|number_input: &NumberInput| LineToolMessage::UpdateOptions(LineOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
.widget_holder()
}
@@ -175,7 +175,6 @@ impl Fsm for LineToolFsmState {
match (self, event) {
(LineToolFsmState::Ready, LineToolMessage::DragStart) => {
tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true);
tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
let viewport_start = tool_data.snap_manager.snap_position(responses, document, input.mouse.position);
tool_data.drag_start = document.metadata().document_to_viewport.inverse().transform_point2(viewport_start);
@@ -186,7 +185,7 @@ impl Fsm for LineToolFsmState {
let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), document.new_layer_parent(), responses);
responses.add(GraphOperationMessage::StrokeSet {
layer: layer.to_path(),
layer,
stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight),
});
tool_data.layer = Some(layer);
@@ -280,7 +279,7 @@ fn generate_transform(tool_data: &mut LineToolData, document_to_viewport: DAffin
}
GraphOperationMessage::TransformSet {
layer: tool_data.layer.unwrap().to_path(),
layer: tool_data.layer.unwrap(),
transform: glam::DAffine2::from_scale_angle_translation(DVec2::new(line_length, 1.), angle, start),
transform_in: TransformIn::Viewport,
skip_rerender: false,

View File

@@ -91,8 +91,8 @@ impl LayoutHolder for PathTool {
.label("X")
.min_width(120)
.disabled(x.is_none())
.min(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.min(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64))
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(move |number_input: &NumberInput| {
let new_x = number_input.value.unwrap_or(x.unwrap());
PathToolMessage::SelectedPointXChanged { new_x }.into()
@@ -104,8 +104,8 @@ impl LayoutHolder for PathTool {
.label("Y")
.min_width(120)
.disabled(y.is_none())
.min(-((1u64 << std::f64::MANTISSA_DIGITS) as f64))
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.min(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64))
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(move |number_input: &NumberInput| {
let new_y = number_input.value.unwrap_or(y.unwrap());
PathToolMessage::SelectedPointYChanged { new_y }.into()
@@ -275,9 +275,6 @@ impl PathToolData {
}
selected_points.points.extend(additional_selected_points);
//let include_handles: Vec<_> = selected_layers.iter().map(|x| x.as_slice()).collect();
//self.snap_manager.add_all_document_handles(document, input, &include_handles, &[], &selected_points.points);
self.drag_start_pos = input.mouse.position;
self.previous_mouse_position = input.mouse.position - selected_points.offset;
}

View File

@@ -102,7 +102,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
.unit(" px")
.label("Weight")
.min(0.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(|number_input: &NumberInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
.widget_holder()
}
@@ -226,7 +226,7 @@ impl PenToolData {
};
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorHandleMirroring {
id: last_handle.id,
mirror_angle: false,
@@ -259,12 +259,12 @@ impl PenToolData {
self.layer = Some(layer);
responses.add(GraphOperationMessage::FillSet {
layer: layer.to_path(),
layer,
fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None },
});
responses.add(GraphOperationMessage::StrokeSet {
layer: layer.to_path(),
layer,
stroke: Stroke::new(stroke_color, line_weight),
});
@@ -298,21 +298,21 @@ impl PenToolData {
}
// Remove the point that has just been placed
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::RemoveManipulatorGroup { id: last_manipulator_group.id },
});
// Move the in handle of the previous anchor to on top of the previous position
let point = ManipulatorPointId::new(previous_manipulator_group.id, outwards_handle);
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position: previous_anchor },
});
// Stop the handles on the last point from mirroring
let id = previous_manipulator_group.id;
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle: false },
});
@@ -353,26 +353,26 @@ impl PenToolData {
// Move the in handle of the first point to where the user has placed it
let point = ManipulatorPointId::new(first_manipulator_group.id, inwards_handle);
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position: last_in },
});
// Stop the handles on the first point from mirroring
let id = first_manipulator_group.id;
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle: false },
});
// Remove the point that has just been placed
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::RemoveManipulatorGroup { id: last_manipulator_group.id },
});
// Push a close path node
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetClosed { index: 0, closed: true },
});
@@ -387,7 +387,7 @@ impl PenToolData {
}
// Add a new manipulator for the next anchor that we will place
if let Some(out_handle) = outwards_handle.get_position(last_manipulator_group) {
responses.add(add_manipulator_group(&self.layer, self.from_start, bezier_rs::ManipulatorGroup::new_anchor(out_handle)));
responses.add(add_manipulator_group(self.layer, self.from_start, bezier_rs::ManipulatorGroup::new_anchor(out_handle)));
}
Some(PenToolFsmState::PlacingAnchor)
@@ -419,7 +419,7 @@ impl PenToolData {
// Update points on current segment (to show preview of new handle)
let point = ManipulatorPointId::new(last_manipulator_group.id, outwards_handle);
responses.add(GraphOperationMessage::Vector {
layer: self.layer?.to_path(),
layer: self.layer?,
modification: VectorDataModification::SetManipulatorPosition { point, position: pos },
});
@@ -430,7 +430,7 @@ impl PenToolData {
let pos = last_anchor - (pos - last_anchor);
let point = ManipulatorPointId::new(last_manipulator_group.id, inwards_handle);
responses.add(GraphOperationMessage::Vector {
layer: self.layer?.to_path(),
layer: self.layer?,
modification: VectorDataModification::SetManipulatorPosition { point, position: pos },
});
}
@@ -438,7 +438,7 @@ impl PenToolData {
// Update the mirror status of the currently modifying point
let id = last_manipulator_group.id;
responses.add(GraphOperationMessage::Vector {
layer: self.layer?.to_path(),
layer: self.layer?,
modification: VectorDataModification::SetManipulatorHandleMirroring { id, mirror_angle: should_mirror },
});
@@ -483,7 +483,7 @@ impl PenToolData {
for manipulator_type in [SelectedType::Anchor, SelectedType::InHandle, SelectedType::OutHandle] {
let point = ManipulatorPointId::new(last_manipulator_group.id, manipulator_type);
responses.add(GraphOperationMessage::Vector {
layer: layer.to_path(),
layer,
modification: VectorDataModification::SetManipulatorPosition { point, position: pos },
});
}
@@ -516,7 +516,7 @@ impl PenToolData {
// Remove the unplaced anchor if in anchor placing mode
if fsm == PenToolFsmState::PlacingAnchor {
responses.add(GraphOperationMessage::Vector {
layer: self.layer?.to_path(),
layer: self.layer?,
modification: VectorDataModification::RemoveManipulatorGroup { id: last_manipulator_group.id },
});
last_manipulator_group = previous_manipulator_group;
@@ -526,7 +526,7 @@ impl PenToolData {
let point = ManipulatorPointId::new(last_manipulator_group.id, outwards_handle);
let position = last_manipulator_group.anchor;
responses.add(GraphOperationMessage::Vector {
layer: self.layer?.to_path(),
layer: self.layer?,
modification: VectorDataModification::SetManipulatorPosition { point, position },
});
@@ -591,7 +591,6 @@ impl Fsm for PenToolFsmState {
// Initialize snapping
tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true);
tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
// Disable this tool's mirroring
tool_data.should_mirror = false;
@@ -703,11 +702,10 @@ fn compute_snapped_angle(cached_angle: &mut f64, lock_angle: bool, snap_angle: b
}
/// Pushes a [ManipulatorGroup] to the current layer via a [GraphOperationMessage].
fn add_manipulator_group(layer: &Option<LayerNodeIdentifier>, from_start: bool, manipulator_group: bezier_rs::ManipulatorGroup<ManipulatorGroupId>) -> Message {
fn add_manipulator_group(layer: Option<LayerNodeIdentifier>, from_start: bool, manipulator_group: bezier_rs::ManipulatorGroup<ManipulatorGroupId>) -> Message {
let Some(layer) = layer else {
return Message::NoOp;
};
let layer = layer.to_path();
let modification = if from_start {
VectorDataModification::AddStartManipulatorGroup { subpath_index: 0, manipulator_group }
} else {

View File

@@ -111,7 +111,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
.unit(" px")
.label("Weight")
.min(0.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(|number_input: &NumberInput| PolygonToolMessage::UpdateOptions(PolygonOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
.widget_holder()
}
@@ -251,12 +251,12 @@ impl Fsm for PolygonToolFsmState {
let fill_color = tool_options.fill.active_color();
responses.add(GraphOperationMessage::FillSet {
layer: layer.to_path(),
layer,
fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None },
});
responses.add(GraphOperationMessage::StrokeSet {
layer: layer.to_path(),
layer,
stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight),
});

View File

@@ -68,7 +68,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
.unit(" px")
.label("Weight")
.min(0.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(|number_input: &NumberInput| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
.widget_holder()
}
@@ -220,12 +220,12 @@ impl Fsm for RectangleToolFsmState {
let fill_color = tool_options.fill.active_color();
responses.add(GraphOperationMessage::FillSet {
layer: layer.to_path(),
layer,
fill: if let Some(color) = fill_color { Fill::Solid(color) } else { Fill::None },
});
responses.add(GraphOperationMessage::StrokeSet {
layer: layer.to_path(),
layer,
stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight),
});

View File

@@ -302,10 +302,10 @@ impl SelectToolData {
// Duplicate each previously selected layer and select the new ones.
for layer_ancestors in document.metadata().shallowest_unique_layers(self.layers_dragging.iter().copied()) {
let layer = layer_ancestors.last().unwrap();
let layer = *layer_ancestors.last().unwrap();
// Moves the original back to its starting position.
responses.add_front(GraphOperationMessage::TransformChange {
layer: layer.to_path(),
layer,
transform: DAffine2::from_translation(self.drag_start - self.drag_current),
transform_in: TransformIn::Viewport,
skip_rerender: true,
@@ -336,11 +336,6 @@ impl SelectToolData {
// layer_metadata,
// });
}
// // Since the selected layers have now moved back to their original transforms before the drag began, we rerender them to be displayed as if they weren't touched.
// for layer_path in self.not_duplicated_layers.iter().flatten() {
// responses.add(DocumentMessage::InputFrameRasterizeRegionBelowLayer { layer_path: layer_path.clone() });
// }
}
/// Removes the duplicated layers. Called when Alt is released and the layers have previously been duplicated.
@@ -361,7 +356,7 @@ impl SelectToolData {
// Move the original to under the mouse
for layer_ancestors in document.metadata().shallowest_unique_layers(originals.iter().copied()) {
responses.add_front(GraphOperationMessage::TransformChange {
layer: layer_ancestors.last().unwrap().to_path(),
layer: *layer_ancestors.last().unwrap(),
transform: DAffine2::from_translation(self.drag_current - self.drag_start),
transform_in: TransformIn::Viewport,
skip_rerender: true,
@@ -482,22 +477,11 @@ impl Fsm for SelectToolFsmState {
responses.add(DocumentMessage::StartTransaction);
tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true);
tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
SelectToolFsmState::DraggingPivot
} else if let Some(_selected_edges) = dragging_bounds {
responses.add(DocumentMessage::StartTransaction);
// let snap_x = selected_edges.2 || selected_edges.3;
// let snap_y = selected_edges.0 || selected_edges.1;
//
// tool_data
// .snap_manager
// .start_snap(document, input, document.bounding_boxes(Some(&selected), None, font_cache), snap_x, snap_y);
// tool_data
// .snap_manager
// .add_all_document_handles(document, input, &[], &selected.iter().map(|x| x.as_slice()).collect::<Vec<_>>(), &[]);
tool_data.layers_dragging = selected;
if let Some(bounds) = &mut tool_data.bounding_box_manager {
@@ -606,7 +590,7 @@ impl Fsm for SelectToolFsmState {
// TODO: Cache the result of `shallowest_unique_layers` to avoid this heavy computation every frame of movement, see https://github.com/GraphiteEditor/Graphite/pull/481
for layer_ancestors in document.metadata().shallowest_unique_layers(tool_data.layers_dragging.iter().copied()) {
responses.add_front(GraphOperationMessage::TransformChange {
layer: layer_ancestors.last().unwrap().to_path(),
layer: *layer_ancestors.last().unwrap(),
transform: DAffine2::from_translation(mouse_delta + closest_move),
transform_in: TransformIn::Viewport,
skip_rerender: false,

View File

@@ -89,7 +89,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
.unit(" px")
.label("Weight")
.min(0.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(|number_input: &NumberInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
.widget_holder()
}
@@ -215,7 +215,6 @@ impl Fsm for SplineToolFsmState {
let transform = document.metadata().transform_to_viewport(parent);
tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true);
tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]);
let snapped_position = tool_data.snap_manager.snap_position(responses, document, input.mouse.position);
let pos = transform.inverse().transform_point2(snapped_position);
@@ -228,12 +227,12 @@ impl Fsm for SplineToolFsmState {
let layer = graph_modification_utils::new_vector_layer(vec![], generate_uuid(), parent, responses);
responses.add(GraphOperationMessage::FillSet {
layer: layer.to_path(),
layer,
fill: if let Some(color) = tool_options.fill.active_color() { Fill::Solid(color) } else { Fill::None },
});
responses.add(GraphOperationMessage::StrokeSet {
layer: layer.to_path(),
layer,
stroke: Stroke::new(tool_options.stroke.active_color(), tool_data.weight),
});
tool_data.layer = Some(layer);
@@ -329,5 +328,5 @@ fn update_spline(tool_data: &SplineToolData, show_preview: bool, responses: &mut
graph_modification_utils::set_manipulator_mirror_angle(subpath.manipulator_groups(), layer, true, responses);
let subpaths = vec![subpath];
let modification = VectorDataModification::UpdateSubpaths { subpaths };
responses.add_front(GraphOperationMessage::Vector { layer: layer.to_path(), modification });
responses.add_front(GraphOperationMessage::Vector { layer, modification });
}

View File

@@ -113,7 +113,7 @@ fn create_text_widgets(tool: &TextTool) -> Vec<WidgetHolder> {
.label("Size")
.int()
.min(1.)
.max((1u64 << std::f64::MANTISSA_DIGITS) as f64)
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
.on_update(|number_input: &NumberInput| TextToolMessage::UpdateOptions(TextOptionsUpdate::FontSize(number_input.value.unwrap() as u32)).into())
.widget_holder();
vec![
@@ -298,11 +298,11 @@ impl TextToolData {
insert_index: -1,
});
responses.add(GraphOperationMessage::FillSet {
layer: self.layer.to_path(),
layer: self.layer,
fill: if editing_text.color.is_some() { Fill::Solid(editing_text.color.unwrap()) } else { Fill::None },
});
responses.add(GraphOperationMessage::TransformSet {
layer: self.layer.to_path(),
layer: self.layer,
transform: editing_text.transform,
transform_in: TransformIn::Viewport,
skip_rerender: true,
@@ -310,7 +310,7 @@ impl TextToolData {
self.set_editing(true, font_cache, document, responses);
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: self.layer.to_path() });
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![self.layer.to_node()] });
TextToolFsmState::Editing
} else {
@@ -331,10 +331,11 @@ impl TextToolData {
}
fn fix_text_bounds(&self, new_text: &str, _document: &DocumentMessageHandler, font_cache: &FontCache, responses: &mut VecDeque<Message>) -> Option<()> {
let layer = self.layer.to_path();
let old_bounds = self.get_bounds(&self.editing_text.as_ref()?.text, font_cache)?;
let new_bounds = self.get_bounds(new_text, font_cache)?;
responses.add(GraphOperationMessage::UpdateBounds { layer, old_bounds, new_bounds });
responses.add(GraphOperationMessage::UpdateBounds {
layer: self.layer,
old_bounds: self.get_bounds(&self.editing_text.as_ref()?.text, font_cache)?,
new_bounds: self.get_bounds(new_text, font_cache)?,
});
Some(())
}
@@ -437,7 +438,6 @@ impl Fsm for TextToolFsmState {
(TextToolFsmState::Editing, TextToolMessage::TextChange { new_text }) => {
tool_data.fix_text_bounds(&new_text, document, font_cache, responses);
responses.add(NodeGraphMessage::SetQualifiedInputValue {
layer_path: Vec::new(),
node_path: vec![graph_modification_utils::get_text_id(tool_data.layer, &document.network).unwrap()],
input_index: 1,
value: TaggedValue::String(new_text),

View File

@@ -20,7 +20,7 @@ use std::fmt::{self, Debug};
pub struct ToolActionHandlerData<'a> {
pub document: &'a DocumentMessageHandler,
pub document_id: u64,
pub document_id: DocumentId,
pub global_tool_data: &'a DocumentToolData,
pub input: &'a InputPreprocessorMessageHandler,
pub font_cache: &'a FontCache,
@@ -30,7 +30,7 @@ pub struct ToolActionHandlerData<'a> {
impl<'a> ToolActionHandlerData<'a> {
pub fn new(
document: &'a DocumentMessageHandler,
document_id: u64,
document_id: DocumentId,
global_tool_data: &'a DocumentToolData,
input: &'a InputPreprocessorMessageHandler,
font_cache: &'a FontCache,

View File

@@ -5,23 +5,22 @@ use crate::messages::portfolio::document::node_graph::wrap_network_in_scope;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::layer_panel::LayerClassification;
use crate::messages::portfolio::document::utility_types::misc::LayerPanelEntry;
use crate::messages::portfolio::document::utility_types::LayerId;
use crate::messages::prelude::*;
use graph_craft::concrete;
use graph_craft::document::value::TaggedValue;
use graph_craft::document::{generate_uuid, DocumentNodeImplementation, NodeId, NodeNetwork};
use graph_craft::graphene_compiler::Compiler;
use graph_craft::imaginate_input::ImaginatePreferences;
use graph_craft::{concrete, Type};
use graphene_core::application_io::{ApplicationIo, NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig};
use graphene_core::application_io::{NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig};
use graphene_core::memo::IORecord;
use graphene_core::raster::{Image, ImageFrame};
use graphene_core::renderer::{ClickTarget, GraphicElementRendered, SvgSegment, SvgSegmentList};
use graphene_core::renderer::{ClickTarget, GraphicElementRendered, SvgSegmentList};
use graphene_core::text::FontCache;
use graphene_core::transform::{Footprint, Transform};
use graphene_core::vector::style::ViewMode;
use graphene_core::vector::VectorData;
use graphene_core::{Color, GraphicElement, SurfaceFrame, SurfaceId};
use graphene_core::{Color, GraphicElement, SurfaceFrame};
use graphene_std::wasm_application_io::{WasmApplicationIo, WasmEditorApi};
use interpreted_executor::dynamic_executor::DynamicExecutor;
@@ -31,22 +30,6 @@ use std::rc::Rc;
use std::sync::mpsc::{Receiver, Sender};
use std::sync::Arc;
/// Identifies a node graph, either the document graph or a node graph associated with a legacy layer.
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
pub enum GraphIdentifier {
DocumentGraph,
LayerGraph(LayerId),
}
impl GraphIdentifier {
pub const fn new(layer_id: Option<LayerId>) -> Self {
match layer_id {
Some(layer_id) => Self::LayerGraph(layer_id),
None => Self::DocumentGraph,
}
}
}
pub struct NodeRuntime {
pub(crate) executor: DynamicExecutor,
font_cache: FontCache,
@@ -58,7 +41,6 @@ pub struct NodeRuntime {
pub(crate) click_targets: HashMap<NodeId, Vec<ClickTarget>>,
pub(crate) upstream_transforms: HashMap<NodeId, (Footprint, DAffine2)>,
graph_hash: Option<u64>,
canvas_cache: HashMap<Vec<LayerId>, SurfaceId>,
monitor_nodes: Vec<Vec<NodeId>>,
}
@@ -81,7 +63,6 @@ pub struct ExportConfig {
pub(crate) struct GenerationRequest {
generation_id: u64,
graph: NodeNetwork,
path: Vec<LayerId>,
render_config: RenderConfig,
}
@@ -129,7 +110,6 @@ impl NodeRuntime {
imaginate_preferences: Default::default(),
thumbnails: Default::default(),
wasm_io: None,
canvas_cache: HashMap::new(),
click_targets: HashMap::new(),
graph_hash: None,
upstream_transforms: HashMap::new(),
@@ -142,7 +122,7 @@ impl NodeRuntime {
// This should be avoided in the future.
requests.reverse();
requests.dedup_by_key(|x| match x {
NodeRuntimeMessage::GenerationRequest(x) => Some(x.path.clone()),
NodeRuntimeMessage::GenerationRequest(x) => Some(x.graph.current_hash()),
_ => None,
});
requests.reverse();
@@ -151,17 +131,13 @@ impl NodeRuntime {
NodeRuntimeMessage::FontCacheUpdate(font_cache) => self.font_cache = font_cache,
NodeRuntimeMessage::ImaginatePreferencesUpdate(preferences) => self.imaginate_preferences = preferences,
NodeRuntimeMessage::GenerationRequest(GenerationRequest {
generation_id,
graph,
render_config,
path,
..
generation_id, graph, render_config, ..
}) => {
let transform = render_config.viewport.transform;
let result = self.execute_network(&path, graph, render_config).await;
let result = self.execute_network(graph, render_config).await;
let mut responses = VecDeque::new();
self.update_thumbnails(&path, &mut responses);
self.update_thumbnails(&mut responses);
self.update_upstream_transforms();
let response = GenerationResponse {
@@ -179,7 +155,7 @@ impl NodeRuntime {
}
}
async fn execute_network<'a>(&'a mut self, path: &[LayerId], graph: NodeNetwork, render_config: RenderConfig) -> Result<TaggedValue, String> {
async fn execute_network<'a>(&'a mut self, graph: NodeNetwork, render_config: RenderConfig) -> Result<TaggedValue, String> {
if self.wasm_io.is_none() {
self.wasm_io = Some(WasmApplicationIo::new().await);
}
@@ -245,21 +221,21 @@ impl NodeRuntime {
Err(e) => return Err(e),
};
if let TaggedValue::SurfaceFrame(SurfaceFrame { surface_id, transform: _ }) = result {
let old_id = self.canvas_cache.insert(path.to_vec(), surface_id);
if let Some(old_id) = old_id {
if old_id != surface_id {
if let Some(io) = self.wasm_io.as_ref() {
io.destroy_surface(old_id)
}
}
}
}
// if let TaggedValue::SurfaceFrame(SurfaceFrame { surface_id, transform: _ }) = result {
// let old_id = self.canvas_cache.insert(path.to_vec(), surface_id);
// if let Some(old_id) = old_id {
// if old_id != surface_id {
// if let Some(io) = self.wasm_io.as_ref() {
// io.destroy_surface(old_id)
// }
// }
// }
// }
Ok(result)
}
/// Recomputes the thumbnails for the layers in the graph, modifying the state and updating the UI.
pub fn update_thumbnails(&mut self, layer_path: &[LayerId], responses: &mut VecDeque<Message>) {
pub fn update_thumbnails(&mut self, responses: &mut VecDeque<Message>) {
let mut image_data: Vec<_> = Vec::new();
self.thumbnails.retain(|id, _| self.monitor_nodes.iter().any(|node_path| node_path.contains(id)));
for node_path in &self.monitor_nodes {
@@ -299,8 +275,7 @@ impl NodeRuntime {
}
let resize = Some(DVec2::splat(100.));
let create_image_data = |(node_id, image)| NodeGraphExecutor::to_frontend_image_data(image, None, layer_path, Some(node_id), resize).ok();
image_data.extend(render.image_data.into_iter().filter_map(create_image_data))
image_data.extend(render.image_data.into_iter().filter_map(|(_, image)| NodeGraphExecutor::to_frontend_image_data(image, resize).ok()))
}
if !image_data.is_empty() {
responses.add(FrontendMessage::UpdateImageData { document_id: 0, image_data });
@@ -370,15 +345,11 @@ pub async fn run_node_graph() {
pub struct NodeGraphExecutor {
sender: Sender<NodeRuntimeMessage>,
receiver: Receiver<NodeGraphUpdate>,
// TODO: This is a memory leak since layers are never removed
pub(crate) last_output_type: HashMap<Vec<LayerId>, Option<Type>>,
pub(crate) thumbnails: HashMap<NodeId, SvgSegmentList>,
futures: HashMap<u64, ExecutionContext>,
}
#[derive(Debug, Clone)]
struct ExecutionContext {
layer_path: Vec<LayerId>,
export_config: Option<ExportConfig>,
}
@@ -394,18 +365,15 @@ impl Default for NodeGraphExecutor {
futures: Default::default(),
sender: request_sender,
receiver: response_receiver,
last_output_type: Default::default(),
thumbnails: Default::default(),
}
}
}
impl NodeGraphExecutor {
/// Execute the network by flattening it and creating a borrow stack.
fn queue_execution(&self, network: NodeNetwork, layer_path: Vec<LayerId>, render_config: RenderConfig) -> u64 {
fn queue_execution(&self, network: NodeNetwork, render_config: RenderConfig) -> u64 {
let generation_id = generate_uuid();
let request = GenerationRequest {
path: layer_path,
graph: network,
generation_id,
render_config,
@@ -470,23 +438,17 @@ impl NodeGraphExecutor {
}
/// Generate a new [`FrontendImageData`] from the [`Image`].
fn to_frontend_image_data(image: Image<Color>, transform: Option<[f64; 6]>, layer_path: &[LayerId], node_id: Option<u64>, resize: Option<DVec2>) -> Result<FrontendImageData, String> {
fn to_frontend_image_data(image: Image<Color>, resize: Option<DVec2>) -> Result<FrontendImageData, String> {
let (image_data, _size) = Self::encode_img(image, resize, image::ImageOutputFormat::Bmp)?;
let mime = "image/bmp".to_string();
let image_data = std::sync::Arc::new(image_data);
Ok(FrontendImageData {
path: layer_path.to_vec(),
node_id,
image_data,
mime,
transform,
})
Ok(FrontendImageData { image_data, mime })
}
/// Evaluates a node graph, computing the entire graph
pub fn submit_node_graph_evaluation(&mut self, document: &mut DocumentMessageHandler, layer_path: Vec<LayerId>, viewport_resolution: UVec2) -> Result<(), String> {
pub fn submit_node_graph_evaluation(&mut self, document: &mut DocumentMessageHandler, viewport_resolution: UVec2) -> Result<(), String> {
// Get the node graph layer
let network = document.network().clone();
@@ -506,9 +468,9 @@ impl NodeGraphExecutor {
};
// Execute the node graph
let generation_id = self.queue_execution(network, layer_path.clone(), render_config);
let generation_id = self.queue_execution(network, render_config);
self.futures.insert(generation_id, ExecutionContext { layer_path, export_config: None });
self.futures.insert(generation_id, ExecutionContext { export_config: None });
Ok(())
}
@@ -541,11 +503,8 @@ impl NodeGraphExecutor {
export_config.size = size;
// Execute the node graph
let generation_id = self.queue_execution(network, Vec::new(), render_config);
let execution_context = ExecutionContext {
layer_path: Vec::new(),
export_config: Some(export_config),
};
let generation_id = self.queue_execution(network, render_config);
let execution_context = ExecutionContext { export_config: Some(export_config) };
self.futures.insert(generation_id, execution_context);
Ok(())
@@ -626,16 +585,17 @@ impl NodeGraphExecutor {
},
expanded: layer.has_children(document_metadata) && !collapsed.contains(&layer),
selected: document_metadata.selected_layers_contains(layer),
path: vec![node_id],
parent_id: layer.parent(document_metadata).map(|parent| parent.to_node()),
id: node_id,
depth: layer.ancestors(document_metadata).count() - 1,
thumbnail: svg.to_string(),
},
});
}
self.thumbnails = new_thumbnails;
document_metadata.update_transforms(new_upstream_transforms);
document_metadata.update_click_targets(new_click_targets);
responses.extend(updates);
self.process_node_graph_output(node_graph_output, execution_context.layer_path.clone(), transform, responses)?;
self.process_node_graph_output(node_graph_output, transform, responses)?;
responses.add(DocumentMessage::RenderDocument);
responses.add(DocumentMessage::DocumentStructureChanged);
responses.add(BroadcastEvent::DocumentIsDirty);
@@ -665,8 +625,7 @@ impl NodeGraphExecutor {
responses.add(FrontendMessage::UpdateDocumentArtwork { svg });
}
fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, layer_path: Vec<LayerId>, transform: DAffine2, responses: &mut VecDeque<Message>) -> Result<(), String> {
self.last_output_type.insert(layer_path.clone(), Some(node_graph_output.ty()));
fn process_node_graph_output(&mut self, node_graph_output: TaggedValue, transform: DAffine2, responses: &mut VecDeque<Message>) -> Result<(), String> {
match node_graph_output {
TaggedValue::SurfaceFrame(SurfaceFrame { surface_id: _, transform: _ }) => {
// TODO: Reimplement this now that document-legacy is gone
@@ -709,19 +668,4 @@ impl NodeGraphExecutor {
};
Ok(())
}
/// When a blob url for a thumbnail is loaded, update the state and the UI.
pub fn insert_thumbnail_blob_url(&mut self, blob_url: String, node_id: NodeId, responses: &mut VecDeque<Message>) {
for segment_list in self.thumbnails.values_mut() {
if let Some(segment) = segment_list.iter_mut().find(|segment| **segment == SvgSegment::BlobUrl(node_id)) {
*segment = SvgSegment::String(blob_url);
responses.add(FrontendMessage::UpdateNodeThumbnail {
id: node_id,
value: segment_list.to_string(),
});
return;
}
}
warn!("Received blob url for invalid segment")
}
}