From 8a6aa46488052e84790f07c4b343091769756639 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 31 Aug 2025 13:54:15 -0700 Subject: [PATCH] Rewrite FrontendNode --- .../src/messages/frontend/frontend_message.rs | 4 +- .../node_graph/node_graph_message_handler.rs | 6 +- .../document/node_graph/utility_types.rs | 82 +++++++++++++------ frontend/src/components/views/Graph.svelte | 5 +- frontend/src/messages.ts | 68 ++++++++++----- frontend/src/state-providers/node-graph.ts | 6 +- 6 files changed, 118 insertions(+), 53 deletions(-) diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index b8969308c7..d77a115587 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -2,7 +2,7 @@ use super::utility_types::{DocumentDetails, MouseCursorIcon, OpenDocument}; use crate::messages::app_window::app_window_message_handler::AppWindowPlatform; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::node_graph::utility_types::{ - BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendGraphInput, FrontendGraphOutput, FrontendNode, FrontendNodeType, FrontendXY, Transform, + BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendGraphInput, FrontendGraphOutput, FrontendNode, FrontendNodeOrLayer, FrontendNodeType, FrontendXY, FrontendXY, Transform, }; use crate::messages::portfolio::document::utility_types::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer}; use crate::messages::portfolio::document::utility_types::wires::{WirePath, WirePathUpdate}; @@ -276,7 +276,7 @@ pub enum FrontendMessage { }, UpdateNodeGraphNodes { #[serde(rename = "nodesToRender")] - nodes_to_render: Vec, + nodes_to_render: Vec, #[serde(rename = "inSelectedNetwork")] in_selected_network: bool, // Displays a dashed border around the node diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index 7af7cd2ee5..8864d63f0d 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -6,7 +6,9 @@ use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::document_message_handler::navigation_controls; use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext; use crate::messages::portfolio::document::node_graph::document_node_definitions::NodePropertiesContext; -use crate::messages::portfolio::document::node_graph::utility_types::{ContextMenuData, Direction, FrontendGraphDataType, FrontendXY}; +use crate::messages::portfolio::document::node_graph::utility_types::{ + ContextMenuData, Direction, FrontendGraphDataType, FrontendLayer, FrontendNodeMetadata, FrontendNodeOrLayer, FrontendXY, FrontendXY, +}; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::misc::GroupFolderType; use crate::messages::portfolio::document::utility_types::network_interface::{ @@ -22,7 +24,7 @@ use crate::messages::tool::tool_messages::tool_prelude::{Key, MouseMotion}; use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo}; use glam::{DAffine2, DVec2, IVec2}; use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput}; -use graph_craft::proto::GraphErrors; +use graph_craft::proto::{GraphErrors, NodeMetadata}; use graphene_std::math::math_ext::QuadExt; use graphene_std::vector::algorithms::bezpath_algorithms::bezpath_is_inside_bezpath; use graphene_std::*; diff --git a/editor/src/messages/portfolio/document/node_graph/utility_types.rs b/editor/src/messages/portfolio/document/node_graph/utility_types.rs index 45dd0532f2..1adf67902e 100644 --- a/editor/src/messages/portfolio/document/node_graph/utility_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/utility_types.rs @@ -64,9 +64,12 @@ pub struct FrontendGraphInput { pub description: String, #[serde(rename = "resolvedType")] pub resolved_type: String, - #[serde(rename = "connectedTo")] /// Either "nothing", "import index {index}", or "{node name} output {output_index}". + #[serde(rename = "connectedToString")] pub connected_to: String, + /// Used to render the upstream node once this node is rendered + #[serde(rename = "connectedToNode")] + pub connected_to_node: Option, } #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] @@ -83,38 +86,71 @@ pub struct FrontendGraphOutput { pub connected_to: Vec, } +// Metadata that is common to nodes and layers #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] -pub struct FrontendNode { - pub id: graph_craft::document::NodeId, - #[serde(rename = "isLayer")] - pub is_layer: bool, +pub struct FrontendNodeMetadata { + // TODO: Remove and replace with popup manager system #[serde(rename = "canBeLayer")] pub can_be_layer: bool, - pub selected: bool, - pub reference: Option, #[serde(rename = "displayName")] pub display_name: String, - #[serde(rename = "primaryInput")] - pub primary_input: Option, - #[serde(rename = "exposedInputs")] - pub exposed_inputs: Vec, - #[serde(rename = "primaryOutput")] - pub primary_output: Option, - #[serde(rename = "exposedOutputs")] - pub exposed_outputs: Vec, + pub selected: bool, + // Used to get the description, which is stored in a global hashmap + pub reference: Option, + // Reduces opacity of node/hidden eye icon + pub visible: bool, + // The svg string for each input + // pub wires: Vec>, + pub errors: Option, +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] +pub struct FrontendNode { + // pub position: FrontendNodePosition, + pub position: FrontendXY, + pub inputs: Vec>, + pub outputs: Vec>, +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] +pub struct FrontendLayer { + #[serde(rename = "bottomInput")] + pub bottom_input: FrontendGraphInput, + #[serde(rename = "sideInput")] + pub side_input: Option, + pub output: FrontendGraphOutput, + // pub position: FrontendLayerPosition, + pub position: FrontendXY, + pub locked: bool, #[serde(rename = "chainWidth")] pub chain_width: u32, #[serde(rename = "layerHasLeftBorderGap")] - pub layer_has_left_border_gap: bool, - #[serde(rename = "primaryOutputConnectedToLayer")] - pub primary_output_connected_to_layer: bool, + layer_has_left_border_gap: bool, #[serde(rename = "primaryInputConnectedToLayer")] pub primary_input_connected_to_layer: bool, - pub position: FrontendXY, - pub visible: bool, - pub locked: bool, - pub previewed: bool, - pub errors: Option, + #[serde(rename = "primaryOutputConnectedToLayer")] + pub primary_output_connected_to_layer: bool, +} + +// // Should be an enum but those are hard to serialize/deserialize to TS +// #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] +// pub struct FrontendNodePosition { +// pub absolute: Option, +// pub chain: Option, +// } + +// // Should be an enum but those are hard to serialize/deserialize to TS +// #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] +// pub struct FrontendLayerPosition { +// pub absolute: Option, +// pub stack: Option, +// } + +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] +pub struct FrontendNodeOrLayer { + pub metadata: FrontendNodeMetadata, + pub node: Option, + pub layer: Option, } #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] diff --git a/frontend/src/components/views/Graph.svelte b/frontend/src/components/views/Graph.svelte index 210ed69517..0c48a672a2 100644 --- a/frontend/src/components/views/Graph.svelte +++ b/frontend/src/components/views/Graph.svelte @@ -117,10 +117,11 @@ function toggleLayerDisplay(displayAsLayer: boolean, toggleId: bigint) { editor.handle.setToNodeOrLayer(toggleId, displayAsLayer); + editor.handle.setToNodeOrLayer(toggleId, displayAsLayer); } function canBeToggledBetweenNodeAndLayer(toggleDisplayAsLayerNodeId: bigint) { - return $nodeGraph.nodesToRender.get(toggleDisplayAsLayerNodeId)?.canBeLayer || false; + return $nodeGraph.nodesToRender.get(toggleDisplayAsLayerNodeId)?.metadata.canBeLayer || false; } function createNode(nodeType: string) { @@ -199,7 +200,7 @@ } function inputConnectedToText(input: FrontendGraphInput): string { - return `Connected to:\n${input.connectedTo}`; + return `Connected to:\n${input.connectedToString}`; } function zipWithUndefined(arr1: FrontendGraphInput[], arr2: FrontendGraphOutput[]) { diff --git a/frontend/src/messages.ts b/frontend/src/messages.ts index df532396e0..7a76acb655 100644 --- a/frontend/src/messages.ts +++ b/frontend/src/messages.ts @@ -175,13 +175,15 @@ export type FrontendGraphDataType = "General" | "Number" | "Artboard" | "Graphic export class FrontendGraphInput { readonly dataType!: FrontendGraphDataType; + readonly resolvedType!: string; + readonly name!: string; readonly description!: string; - readonly resolvedType!: string; + readonly connectedToString!: string; - readonly connectedTo!: string; + readonly connectedToNode!: bigint | undefined; } export class FrontendGraphOutput { @@ -196,26 +198,42 @@ export class FrontendGraphOutput { readonly connectedTo!: string[]; } -export class FrontendNode { - readonly id!: bigint; - - readonly isLayer!: boolean; - +export class FrontendNodeMetadata { readonly canBeLayer!: boolean; + readonly displayName!: string; + readonly selected!: boolean; readonly reference!: string | undefined; - readonly displayName!: string; + readonly visible!: boolean; - readonly primaryInput!: FrontendGraphInput | undefined; + // readonly wires!: (string | undefined)[]; - readonly exposedInputs!: FrontendGraphInput[]; + readonly errors!: string | undefined; +} - readonly primaryOutput!: FrontendGraphOutput | undefined; +export class FrontendNode { + // readonly position!: FrontendNodePosition; + readonly position!: XY; - readonly exposedOutputs!: FrontendGraphOutput[]; + readonly inputs!: (FrontendGraphInput | undefined)[]; + + readonly outputs!: (FrontendGraphOutput | undefined)[]; +} + +export class FrontendLayer { + // readonly position!: FrontendLayerPosition; + readonly position!: XY; + + readonly bottomInput!: FrontendGraphInput; + + readonly sideInput!: FrontendGraphInput | undefined; + + readonly output!: FrontendGraphOutput; + + readonly locked!: boolean; readonly chainWidth!: number; @@ -224,19 +242,27 @@ export class FrontendNode { readonly primaryInputConnectedToLayer!: boolean; readonly primaryOutputConnectedToLayer!: boolean; +} - @TupleToVec2 - readonly position!: XY; +export class FrontendNodePosition { + readonly absolute!: XY | undefined; + readonly chain!: boolean | undefined; +} - // TODO: Store field for the width of the left node chain +export class FrontendLayerPosition { + readonly absolute!: XY | undefined; + readonly stack!: number | undefined; +} - readonly previewed!: boolean; +export class FrontendNodeOrLayer { + readonly metadata!: FrontendNodeMetadata; + readonly node!: FrontendNode | undefined; + readonly layer!: FrontendLayer | undefined; +} - readonly visible!: boolean; - - readonly unlocked!: boolean; - - readonly errors!: string | undefined; +export class UpdateCentralNodeGraph extends JsMessage { + readonly nodeOrLayer!: FrontendNodeOrLayer[]; + readonly inSelectedNetwork!: boolean; } export class FrontendNodeType { diff --git a/frontend/src/state-providers/node-graph.ts b/frontend/src/state-providers/node-graph.ts index 73e1d436a0..d2f4c693f2 100644 --- a/frontend/src/state-providers/node-graph.ts +++ b/frontend/src/state-providers/node-graph.ts @@ -1,11 +1,11 @@ import { writable } from "svelte/store"; import { type Editor } from "@graphite/editor"; +import type { FrontendNodeOrLayer } from "@graphite/messages"; import { type Box, type FrontendClickTargets, type ContextMenuInformation, - type FrontendNode, type FrontendNodeType, type WirePath, ClearAllNodeGraphWires, @@ -32,8 +32,7 @@ export function createNodeGraphState(editor: Editor) { contextMenuInformation: undefined as ContextMenuInformation | undefined, layerWidths: new Map(), updateImportsExports: undefined as UpdateImportsExports | undefined, - nodesToRender: new Map(), - + nodesToRender: new Map(), visibleNodes: new Set(), /// The index is the exposed input index. The exports have a first key value of u32::MAX. wires: new Map>(), @@ -92,6 +91,7 @@ export function createNodeGraphState(editor: Editor) { return state; }); }); + editor.subscriptions.subscribeJsMessage(UpdateLayerWidths, (updateLayerWidths) => { update((state) => { state.layerWidths = updateLayerWidths.layerWidths;