Rewrite FrontendNode

This commit is contained in:
Adam
2025-09-08 16:39:22 -07:00
parent 1996dd205a
commit 8a6aa46488
6 changed files with 118 additions and 53 deletions
@@ -2,7 +2,7 @@ use super::utility_types::{DocumentDetails, MouseCursorIcon, OpenDocument};
use crate::messages::app_window::app_window_message_handler::AppWindowPlatform; use crate::messages::app_window::app_window_message_handler::AppWindowPlatform;
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::node_graph::utility_types::{ 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::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer};
use crate::messages::portfolio::document::utility_types::wires::{WirePath, WirePathUpdate}; use crate::messages::portfolio::document::utility_types::wires::{WirePath, WirePathUpdate};
@@ -276,7 +276,7 @@ pub enum FrontendMessage {
}, },
UpdateNodeGraphNodes { UpdateNodeGraphNodes {
#[serde(rename = "nodesToRender")] #[serde(rename = "nodesToRender")]
nodes_to_render: Vec<FrontendNode>, nodes_to_render: Vec<FrontendNodeToRender>,
#[serde(rename = "inSelectedNetwork")] #[serde(rename = "inSelectedNetwork")]
in_selected_network: bool, in_selected_network: bool,
// Displays a dashed border around the node // Displays a dashed border around the node
@@ -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::document_message_handler::navigation_controls;
use crate::messages::portfolio::document::graph_operation::utility_types::ModifyInputsContext; 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::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::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::misc::GroupFolderType; use crate::messages::portfolio::document::utility_types::misc::GroupFolderType;
use crate::messages::portfolio::document::utility_types::network_interface::{ 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 crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
use glam::{DAffine2, DVec2, IVec2}; use glam::{DAffine2, DVec2, IVec2};
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput}; 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::math::math_ext::QuadExt;
use graphene_std::vector::algorithms::bezpath_algorithms::bezpath_is_inside_bezpath; use graphene_std::vector::algorithms::bezpath_algorithms::bezpath_is_inside_bezpath;
use graphene_std::*; use graphene_std::*;
@@ -64,9 +64,12 @@ pub struct FrontendGraphInput {
pub description: String, pub description: String,
#[serde(rename = "resolvedType")] #[serde(rename = "resolvedType")]
pub resolved_type: String, pub resolved_type: String,
#[serde(rename = "connectedTo")]
/// Either "nothing", "import index {index}", or "{node name} output {output_index}". /// Either "nothing", "import index {index}", or "{node name} output {output_index}".
#[serde(rename = "connectedToString")]
pub connected_to: String, pub connected_to: String,
/// Used to render the upstream node once this node is rendered
#[serde(rename = "connectedToNode")]
pub connected_to_node: Option<NodeId>,
} }
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
@@ -83,38 +86,71 @@ pub struct FrontendGraphOutput {
pub connected_to: Vec<String>, pub connected_to: Vec<String>,
} }
// Metadata that is common to nodes and layers
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct FrontendNode { pub struct FrontendNodeMetadata {
pub id: graph_craft::document::NodeId, // TODO: Remove and replace with popup manager system
#[serde(rename = "isLayer")]
pub is_layer: bool,
#[serde(rename = "canBeLayer")] #[serde(rename = "canBeLayer")]
pub can_be_layer: bool, pub can_be_layer: bool,
pub selected: bool,
pub reference: Option<String>,
#[serde(rename = "displayName")] #[serde(rename = "displayName")]
pub display_name: String, pub display_name: String,
#[serde(rename = "primaryInput")] pub selected: bool,
pub primary_input: Option<FrontendGraphInput>, // Used to get the description, which is stored in a global hashmap
#[serde(rename = "exposedInputs")] pub reference: Option<String>,
pub exposed_inputs: Vec<FrontendGraphInput>, // Reduces opacity of node/hidden eye icon
#[serde(rename = "primaryOutput")] pub visible: bool,
pub primary_output: Option<FrontendGraphOutput>, // The svg string for each input
#[serde(rename = "exposedOutputs")] // pub wires: Vec<Option<String>>,
pub exposed_outputs: Vec<FrontendGraphOutput>, pub errors: Option<String>,
}
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct FrontendNode {
// pub position: FrontendNodePosition,
pub position: FrontendXY,
pub inputs: Vec<Option<FrontendGraphInput>>,
pub outputs: Vec<Option<FrontendGraphOutput>>,
}
#[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<FrontendGraphInput>,
pub output: FrontendGraphOutput,
// pub position: FrontendLayerPosition,
pub position: FrontendXY,
pub locked: bool,
#[serde(rename = "chainWidth")] #[serde(rename = "chainWidth")]
pub chain_width: u32, pub chain_width: u32,
#[serde(rename = "layerHasLeftBorderGap")] #[serde(rename = "layerHasLeftBorderGap")]
pub layer_has_left_border_gap: bool, layer_has_left_border_gap: bool,
#[serde(rename = "primaryOutputConnectedToLayer")]
pub primary_output_connected_to_layer: bool,
#[serde(rename = "primaryInputConnectedToLayer")] #[serde(rename = "primaryInputConnectedToLayer")]
pub primary_input_connected_to_layer: bool, pub primary_input_connected_to_layer: bool,
pub position: FrontendXY, #[serde(rename = "primaryOutputConnectedToLayer")]
pub visible: bool, pub primary_output_connected_to_layer: bool,
pub locked: bool, }
pub previewed: bool,
pub errors: Option<String>, // // 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<FrontendXY>,
// pub chain: Option<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 FrontendLayerPosition {
// pub absolute: Option<FrontendXY>,
// pub stack: Option<u32>,
// }
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct FrontendNodeOrLayer {
pub metadata: FrontendNodeMetadata,
pub node: Option<FrontendNode>,
pub layer: Option<FrontendLayer>,
} }
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
+3 -2
View File
@@ -117,10 +117,11 @@
function toggleLayerDisplay(displayAsLayer: boolean, toggleId: bigint) { function toggleLayerDisplay(displayAsLayer: boolean, toggleId: bigint) {
editor.handle.setToNodeOrLayer(toggleId, displayAsLayer); editor.handle.setToNodeOrLayer(toggleId, displayAsLayer);
editor.handle.setToNodeOrLayer(toggleId, displayAsLayer);
} }
function canBeToggledBetweenNodeAndLayer(toggleDisplayAsLayerNodeId: bigint) { function canBeToggledBetweenNodeAndLayer(toggleDisplayAsLayerNodeId: bigint) {
return $nodeGraph.nodesToRender.get(toggleDisplayAsLayerNodeId)?.canBeLayer || false; return $nodeGraph.nodesToRender.get(toggleDisplayAsLayerNodeId)?.metadata.canBeLayer || false;
} }
function createNode(nodeType: string) { function createNode(nodeType: string) {
@@ -199,7 +200,7 @@
} }
function inputConnectedToText(input: FrontendGraphInput): string { function inputConnectedToText(input: FrontendGraphInput): string {
return `Connected to:\n${input.connectedTo}`; return `Connected to:\n${input.connectedToString}`;
} }
function zipWithUndefined(arr1: FrontendGraphInput[], arr2: FrontendGraphOutput[]) { function zipWithUndefined(arr1: FrontendGraphInput[], arr2: FrontendGraphOutput[]) {
+47 -21
View File
@@ -175,13 +175,15 @@ export type FrontendGraphDataType = "General" | "Number" | "Artboard" | "Graphic
export class FrontendGraphInput { export class FrontendGraphInput {
readonly dataType!: FrontendGraphDataType; readonly dataType!: FrontendGraphDataType;
readonly resolvedType!: string;
readonly name!: string; readonly name!: string;
readonly description!: string; readonly description!: string;
readonly resolvedType!: string; readonly connectedToString!: string;
readonly connectedTo!: string; readonly connectedToNode!: bigint | undefined;
} }
export class FrontendGraphOutput { export class FrontendGraphOutput {
@@ -196,26 +198,42 @@ export class FrontendGraphOutput {
readonly connectedTo!: string[]; readonly connectedTo!: string[];
} }
export class FrontendNode { export class FrontendNodeMetadata {
readonly id!: bigint;
readonly isLayer!: boolean;
readonly canBeLayer!: boolean; readonly canBeLayer!: boolean;
readonly displayName!: string;
readonly selected!: boolean; readonly selected!: boolean;
readonly reference!: string | undefined; 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; readonly chainWidth!: number;
@@ -224,19 +242,27 @@ export class FrontendNode {
readonly primaryInputConnectedToLayer!: boolean; readonly primaryInputConnectedToLayer!: boolean;
readonly primaryOutputConnectedToLayer!: boolean; readonly primaryOutputConnectedToLayer!: boolean;
}
@TupleToVec2 export class FrontendNodePosition {
readonly position!: XY; 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; export class UpdateCentralNodeGraph extends JsMessage {
readonly nodeOrLayer!: FrontendNodeOrLayer[];
readonly unlocked!: boolean; readonly inSelectedNetwork!: boolean;
readonly errors!: string | undefined;
} }
export class FrontendNodeType { export class FrontendNodeType {
+3 -3
View File
@@ -1,11 +1,11 @@
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import { type Editor } from "@graphite/editor"; import { type Editor } from "@graphite/editor";
import type { FrontendNodeOrLayer } from "@graphite/messages";
import { import {
type Box, type Box,
type FrontendClickTargets, type FrontendClickTargets,
type ContextMenuInformation, type ContextMenuInformation,
type FrontendNode,
type FrontendNodeType, type FrontendNodeType,
type WirePath, type WirePath,
ClearAllNodeGraphWires, ClearAllNodeGraphWires,
@@ -32,8 +32,7 @@ export function createNodeGraphState(editor: Editor) {
contextMenuInformation: undefined as ContextMenuInformation | undefined, contextMenuInformation: undefined as ContextMenuInformation | undefined,
layerWidths: new Map<bigint, number>(), layerWidths: new Map<bigint, number>(),
updateImportsExports: undefined as UpdateImportsExports | undefined, updateImportsExports: undefined as UpdateImportsExports | undefined,
nodesToRender: new Map<bigint, FrontendNode>(), nodesToRender: new Map<bigint, FrontendNodeToRender>(),
visibleNodes: new Set<bigint>(), visibleNodes: new Set<bigint>(),
/// The index is the exposed input index. The exports have a first key value of u32::MAX. /// The index is the exposed input index. The exports have a first key value of u32::MAX.
wires: new Map<bigint, Map<number, WirePath>>(), wires: new Map<bigint, Map<number, WirePath>>(),
@@ -92,6 +91,7 @@ export function createNodeGraphState(editor: Editor) {
return state; return state;
}); });
}); });
editor.subscriptions.subscribeJsMessage(UpdateLayerWidths, (updateLayerWidths) => { editor.subscriptions.subscribeJsMessage(UpdateLayerWidths, (updateLayerWidths) => {
update((state) => { update((state) => {
state.layerWidths = updateLayerWidths.layerWidths; state.layerWidths = updateLayerWidths.layerWidths;