From 405bd5d36ff5fd251f79f0c61c7774418fba423a Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 3 Sep 2025 10:56:33 -0700 Subject: [PATCH] clean up --- .../src/messages/frontend/frontend_message.rs | 7 +- .../utility_types/widgets/button_widgets.rs | 2 +- .../node_graph/generate_node_graph_overlay.rs | 110 ++++++++++++ .../portfolio/document/node_graph/mod.rs | 1 + .../node_graph/node_graph_message_handler.rs | 36 ++-- .../document/node_graph/node_properties.rs | 7 +- .../document/node_graph/utility_types.rs | 4 +- .../utility_types/network_interface.rs | 2 +- .../network_interface/node_graph.rs | 4 +- .../network_interface/resolved_types.rs | 27 ++- .../portfolio/document/utility_types/nodes.rs | 4 +- .../portfolio/document/utility_types/wires.rs | 1 - editor/src/node_graph_executor.rs | 11 +- frontend/src/messages.ts | 2 + frontend/src/state-providers/node-graph.ts | 8 +- node-graph/gcore/src/lib.rs | 1 + node-graph/gcore/src/node_graph_overlay.rs | 47 +++++ .../gcore/src/node_graph_overlay/types.rs | 170 ++++++++++++++++++ node-graph/gcore/src/types.rs | 4 +- node-graph/graph-craft/src/document/value.rs | 1 + 20 files changed, 416 insertions(+), 33 deletions(-) create mode 100644 editor/src/messages/portfolio/document/node_graph/generate_node_graph_overlay.rs create mode 100644 node-graph/gcore/src/node_graph_overlay.rs create mode 100644 node-graph/gcore/src/node_graph_overlay/types.rs diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index 8fb3b0c3e3..878d6c2ebc 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -1,14 +1,13 @@ 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, FrontendExports, FrontendImport, FrontendNodeToRender, FrontendNodeType, FrontendXY, Transform, -}; +use crate::messages::portfolio::document::node_graph::utility_types::{BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendNodeType, Transform}; use crate::messages::portfolio::document::utility_types::nodes::{JsRawBuffer, LayerPanelEntry, RawBuffer}; use crate::messages::portfolio::document::utility_types::wires::WirePathInProgress; use crate::messages::prelude::*; use crate::messages::tool::utility_types::HintData; use graph_craft::document::NodeId; +use graphene_std::node_graph_overlay::types::{FrontendExports, FrontendImport, FrontendNodeToRender, FrontendXY}; use graphene_std::raster::Image; use graphene_std::raster::color::Color; use graphene_std::text::{Font, TextAlign}; @@ -280,6 +279,8 @@ pub enum FrontendMessage { // Displays a dashed border around the node #[serde(rename = "previewedNode")] previewed_node: Option, + }, + UpdateNativeNodeGraphRender { #[serde(rename = "nativeNodeGraphRender")] native_node_graph_render: bool, }, diff --git a/editor/src/messages/layout/utility_types/widgets/button_widgets.rs b/editor/src/messages/layout/utility_types/widgets/button_widgets.rs index 3698bf3bc0..5f401d08dd 100644 --- a/editor/src/messages/layout/utility_types/widgets/button_widgets.rs +++ b/editor/src/messages/layout/utility_types/widgets/button_widgets.rs @@ -1,8 +1,8 @@ use crate::messages::input_mapper::utility_types::misc::ActionKeys; use crate::messages::layout::utility_types::widget_prelude::*; -use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType; use crate::messages::tool::tool_messages::tool_prelude::WidgetCallback; use derivative::*; +use graphene_std::node_graph_overlay::types::FrontendGraphDataType; use graphene_std::vector::style::FillChoice; use graphite_proc_macros::WidgetBuilder; diff --git a/editor/src/messages/portfolio/document/node_graph/generate_node_graph_overlay.rs b/editor/src/messages/portfolio/document/node_graph/generate_node_graph_overlay.rs new file mode 100644 index 0000000000..6d2decf3d8 --- /dev/null +++ b/editor/src/messages/portfolio/document/node_graph/generate_node_graph_overlay.rs @@ -0,0 +1,110 @@ +use graph_craft::{ + concrete, + document::{DocumentNode, DocumentNodeImplementation, NodeInput, NodeNetwork, value::TaggedValue}, +}; +use graphene_std::{ + Context, graphic, memo, + node_graph_overlay::{self, types::NodeGraphOverlayData}, + uuid::NodeId, +}; + +pub fn generate_node_graph_overlay(node_graph_overlay_data: NodeGraphOverlayData, opacity: f64) -> DocumentNode { + // TODO: Implement as Network and implement finer grained caching for the background, nodes, and exports + DocumentNode { + inputs: vec![ + NodeInput::value(TaggedValue::None, true), + NodeInput::value(TaggedValue::NodeGraphOverlayData(node_graph_overlay_data), true), + NodeInput::value(TaggedValue::F64(opacity), true), + ], + implementation: DocumentNodeImplementation::Network(NodeNetwork { + exports: vec![NodeInput::node(NodeId(0), 0)], + nodes: vec![ + // Merge the overlay on top of the artwork + ( + NodeId(0), + DocumentNode { + call_argument: concrete!(Context), + inputs: vec![NodeInput::node(NodeId(2), 0), NodeInput::node(NodeId(1), 0)], + implementation: DocumentNodeImplementation::ProtoNode(graphic::extend::IDENTIFIER), + ..Default::default() + }, + ), + //Wrap Artwork in a table + ( + NodeId(1), + DocumentNode { + inputs: vec![NodeInput::network(concrete!(Context), 0)], + implementation: DocumentNodeImplementation::ProtoNode(graphic::wrap_graphic::IDENTIFIER), + call_argument: concrete!(Context), + ..Default::default() + }, + ), + // Cache the full node graph so its not rerendered when the artwork changes + ( + NodeId(2), + DocumentNode { + call_argument: concrete!(Context), + inputs: vec![NodeInput::node(NodeId(3), 0)], + implementation: DocumentNodeImplementation::ProtoNode(memo::memo::IDENTIFIER), + ..Default::default() + }, + ), + // Merge the nodes on top of the dot grid background + ( + NodeId(3), + DocumentNode { + call_argument: concrete!(Context), + inputs: vec![NodeInput::node(NodeId(5), 0), NodeInput::node(NodeId(4), 0)], + implementation: DocumentNodeImplementation::ProtoNode(graphic::extend::IDENTIFIER), + ..Default::default() + }, + ), + // Generate the dot grid background + ( + NodeId(4), + DocumentNode { + inputs: vec![NodeInput::network(concrete!(Context), 2)], + implementation: DocumentNodeImplementation::ProtoNode(node_graph_overlay::dot_grid_background::IDENTIFIER), + call_argument: concrete!(Context), + ..Default::default() + }, + ), + // Transform the nodes based on the Context + ( + NodeId(5), + DocumentNode { + call_argument: concrete!(Context), + inputs: vec![NodeInput::node(NodeId(6), 0)], + implementation: DocumentNodeImplementation::ProtoNode(node_graph_overlay::transform_nodes::IDENTIFIER), + ..Default::default() + }, + ), + // Cache the nodes + ( + NodeId(6), + DocumentNode { + call_argument: concrete!(Context), + inputs: vec![NodeInput::node(NodeId(7), 0)], + implementation: DocumentNodeImplementation::ProtoNode(memo::memo::IDENTIFIER), + ..Default::default() + }, + ), + // Create the nodes + ( + NodeId(7), + DocumentNode { + call_argument: concrete!(Context), + inputs: vec![NodeInput::network(concrete!(Context), 1)], + implementation: DocumentNodeImplementation::ProtoNode(node_graph_overlay::generate_nodes::IDENTIFIER), + ..Default::default() + }, + ), + ] + .into_iter() + .collect(), + ..Default::default() + }), + call_argument: concrete!(Context), + ..Default::default() + } +} diff --git a/editor/src/messages/portfolio/document/node_graph/mod.rs b/editor/src/messages/portfolio/document/node_graph/mod.rs index bd25016438..30874339f3 100644 --- a/editor/src/messages/portfolio/document/node_graph/mod.rs +++ b/editor/src/messages/portfolio/document/node_graph/mod.rs @@ -1,4 +1,5 @@ pub mod document_node_definitions; +pub mod generate_node_graph_overlay; mod node_graph_message; mod node_graph_message_handler; pub mod node_properties; 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 e7fe4ad7b2..f0bdde5913 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,7 @@ 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}; 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::{ @@ -21,9 +21,10 @@ use crate::messages::tool::common_functionality::utility_functions::make_path_ed 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::document::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput}; use graph_craft::proto::GraphErrors; use graphene_std::math::math_ext::QuadExt; +use graphene_std::node_graph_overlay::types::{FrontendGraphDataType, FrontendXY}; use graphene_std::vector::algorithms::bezpath_algorithms::bezpath_is_inside_bezpath; use graphene_std::*; use kurbo::{DEFAULT_ACCURACY, Shape}; @@ -875,7 +876,7 @@ impl<'a> MessageHandler> for NodeG }; let Some(output_connector) = output_connector else { return }; self.wire_in_progress_from_connector = network_interface.output_position(&output_connector, selection_network_path); - self.wire_in_progress_type = FrontendGraphDataType::displayed_type(&network_interface.input_type(clicked_input, breadcrumb_network_path)); + self.wire_in_progress_type = network_interface.input_type(clicked_input, breadcrumb_network_path).displayed_type(); return; } @@ -886,7 +887,7 @@ impl<'a> MessageHandler> for NodeG self.wire_in_progress_from_connector = network_interface.output_position(&clicked_output, selection_network_path); let output_type = network_interface.output_type(&clicked_output, breadcrumb_network_path); - self.wire_in_progress_type = FrontendGraphDataType::displayed_type(&output_type); + self.wire_in_progress_type = output_type.displayed_type(); self.update_node_graph_hints(responses); return; @@ -1624,14 +1625,24 @@ impl<'a> MessageHandler> for NodeG let nodes_to_render = network_interface.collect_nodes(&self.node_graph_errors, preferences.graph_wire_style, breadcrumb_network_path); self.frontend_nodes = nodes_to_render.iter().map(|node| node.metadata.node_id).collect(); let previewed_node = network_interface.previewed_node(breadcrumb_network_path); - responses.add(FrontendMessage::UpdateNodeGraphRender { - nodes_to_render, - open: graph_view_overlay_open, - opacity: graph_fade_artwork_percentage, - in_selected_network: selection_network_path == breadcrumb_network_path, - previewed_node, - native_node_graph_render: self.native_node_graph_render, - }); + if self.native_node_graph_render { + let node_graph_render_data = node_graph_overlay::types::NodeGraphOverlayData { + nodes_to_render, + open: graph_view_overlay_open, + in_selected_network: selection_network_path == breadcrumb_network_path, + previewed_node, + }; + self.node_graph_overlay = Some(super::generate_node_graph_overlay::generate_node_graph_overlay(node_graph_render_data, graph_fade_artwork_percentage)); + responses.add(PortfolioMessage::SubmitActiveGraphRender); + } else { + responses.add(FrontendMessage::UpdateNodeGraphRender { + nodes_to_render, + open: graph_view_overlay_open, + opacity: graph_fade_artwork_percentage, + in_selected_network: selection_network_path == breadcrumb_network_path, + previewed_node, + }); + } responses.add(NodeGraphMessage::UpdateVisibleNodes); let layer_widths = network_interface.collect_layer_widths(breadcrumb_network_path); @@ -1784,6 +1795,7 @@ impl<'a> MessageHandler> for NodeG } NodeGraphMessage::ToggleNativeNodeGraphRender => { self.native_node_graph_render = !self.native_node_graph_render; + self.node_graph_overlay = None; responses.add(NodeGraphMessage::SendGraph); } NodeGraphMessage::ToggleSelectedLocked => { diff --git a/editor/src/messages/portfolio/document/node_graph/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_properties.rs index cbc38954bf..2754afa8d4 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_properties.rs @@ -1,7 +1,6 @@ #![allow(clippy::too_many_arguments)] use super::document_node_definitions::{NODE_OVERRIDES, NodePropertiesContext}; -use super::utility_types::FrontendGraphDataType; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::utility_types::network_interface::InputConnector; use crate::messages::prelude::*; @@ -14,6 +13,7 @@ use graph_craft::{Type, concrete}; use graphene_std::NodeInputDecleration; use graphene_std::animation::RealTimeMode; use graphene_std::extract_xy::XY; +use graphene_std::node_graph_overlay::types::FrontendGraphDataType; use graphene_std::path_bool::BooleanOperation; use graphene_std::raster::curve::Curve; use graphene_std::raster::{ @@ -1996,7 +1996,10 @@ pub struct ParameterWidgetsInfo<'a> { impl<'a> ParameterWidgetsInfo<'a> { pub fn new(node_id: NodeId, index: usize, blank_assist: bool, context: &'a mut NodePropertiesContext) -> ParameterWidgetsInfo<'a> { let (name, description) = context.network_interface.displayed_input_name_and_description(&node_id, index, context.selection_network_path); - let input_type = FrontendGraphDataType::displayed_type(&context.network_interface.input_type(&InputConnector::node(node_id, index), context.selection_network_path)); + let input_type = context + .network_interface + .input_type(&InputConnector::node(node_id, index), context.selection_network_path) + .displayed_type(); let document_node = context.network_interface.document_node(&node_id, context.selection_network_path); ParameterWidgetsInfo { 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 7551ad0734..9611c79f8e 100644 --- a/editor/src/messages/portfolio/document/node_graph/utility_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/utility_types.rs @@ -1,6 +1,4 @@ use graph_craft::document::NodeId; -use graph_craft::document::value::TaggedValue; -use graphene_std::Type; use std::borrow::Cow; use crate::messages::portfolio::document::utility_types::network_interface::resolved_types::TypeSource; @@ -208,7 +206,7 @@ impl FrontendNodeType { } } } -#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)] +#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] pub struct DragStart { pub start_x: f64, pub start_y: f64, diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface.rs b/editor/src/messages/portfolio/document/utility_types/network_interface.rs index 2c2482948b..a6c090e84b 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface.rs @@ -5297,7 +5297,7 @@ impl InputConnector { } /// Represents an output connector -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize, specta::Type)] +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub enum OutputConnector { #[serde(rename = "node")] Node { diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface/node_graph.rs b/editor/src/messages/portfolio/document/utility_types/network_interface/node_graph.rs index c06e65d40a..9571658679 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface/node_graph.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface/node_graph.rs @@ -136,7 +136,7 @@ impl NodeNetworkInterface { return None; } let input_type = self.input_type(input_connector, network_path); - let data_type = FrontendGraphDataType::displayed_type(&input_type); + let data_type = input_type.displayed_type(); let resolved_type = input_type.resolved_type_name(); let connected_to = self @@ -239,7 +239,7 @@ impl NodeNetworkInterface { (import_name, description) } }; - let data_type = FrontendGraphDataType::displayed_type(&output_type); + let data_type = output_type.displayed_type(); let resolved_type = output_type.resolved_type_name(); let mut connected_to = self .outward_wires(network_path) diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface/resolved_types.rs b/editor/src/messages/portfolio/document/utility_types/network_interface/resolved_types.rs index 1e099c7ca1..bc04dc1bc7 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface/resolved_types.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface/resolved_types.rs @@ -4,7 +4,7 @@ use graph_craft::{ ProtoNodeIdentifier, Type, concrete, document::{DocumentNodeImplementation, InlineRust, NodeInput, value::TaggedValue}, }; -use graphene_std::uuid::NodeId; +use graphene_std::{node_graph_overlay::types::FrontendGraphDataType, uuid::NodeId}; use interpreted_executor::{ dynamic_executor::{NodeTypes, ResolvedDocumentNodeTypesDelta}, node_registry::NODE_REGISTRY, @@ -45,6 +45,31 @@ pub enum TypeSource { } impl TypeSource { + pub fn displayed_type(&self) -> FrontendGraphDataType { + match self.compiled_nested_type() { + Some(nested_type) => match TaggedValue::from_type_or_none(nested_type) { + TaggedValue::U32(_) + | TaggedValue::U64(_) + | TaggedValue::F32(_) + | TaggedValue::F64(_) + | TaggedValue::DVec2(_) + | TaggedValue::F64Array4(_) + | TaggedValue::VecF64(_) + | TaggedValue::VecDVec2(_) + | TaggedValue::DAffine2(_) => FrontendGraphDataType::Number, + TaggedValue::Artboard(_) => FrontendGraphDataType::Artboard, + TaggedValue::Graphic(_) => FrontendGraphDataType::Graphic, + TaggedValue::Raster(_) => FrontendGraphDataType::Raster, + TaggedValue::Vector(_) => FrontendGraphDataType::Vector, + TaggedValue::Color(_) => FrontendGraphDataType::Color, + TaggedValue::Gradient(_) | TaggedValue::GradientStops(_) | TaggedValue::GradientTable(_) => FrontendGraphDataType::Gradient, + TaggedValue::String(_) => FrontendGraphDataType::Typography, + _ => FrontendGraphDataType::General, + }, + None => FrontendGraphDataType::General, + } + } + pub fn into_compiled_nested_type(self) -> Option { match self { TypeSource::Compiled(compiled_type) => Some(compiled_type.into_nested_type()), diff --git a/editor/src/messages/portfolio/document/utility_types/nodes.rs b/editor/src/messages/portfolio/document/utility_types/nodes.rs index c120938a80..f262e4bdb5 100644 --- a/editor/src/messages/portfolio/document/utility_types/nodes.rs +++ b/editor/src/messages/portfolio/document/utility_types/nodes.rs @@ -62,7 +62,7 @@ pub struct LayerPanelEntry { } /// IMPORTANT: the same node may appear multiple times. -#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize, PartialEq, Eq, specta::Type)] +#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize, PartialEq, Eq)] pub struct SelectedNodes(pub Vec); impl SelectedNodes { @@ -172,5 +172,5 @@ impl SelectedNodes { } } -#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize, PartialEq, Eq, specta::Type)] +#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize, PartialEq, Eq)] pub struct CollapsedLayers(pub Vec); diff --git a/editor/src/messages/portfolio/document/utility_types/wires.rs b/editor/src/messages/portfolio/document/utility_types/wires.rs index 869bcb8890..f8e0559f31 100644 --- a/editor/src/messages/portfolio/document/utility_types/wires.rs +++ b/editor/src/messages/portfolio/document/utility_types/wires.rs @@ -1,4 +1,3 @@ -use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType; use glam::{DVec2, IVec2}; use graphene_std::vector::misc::dvec2_to_point; use kurbo::{BezPath, DEFAULT_ACCURACY, Line, Point, Shape}; diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index 84b0975ac4..8d609d34d2 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -115,10 +115,17 @@ impl NodeGraphExecutor { /// Update the cached network if necessary. fn update_node_graph(&mut self, document: &mut DocumentMessageHandler, node_to_inspect: Option, ignore_hash: bool) -> Result<(), String> { - let network_hash = document.network_interface.document_network().current_hash(); + let mut network = document.network_interface.document_network().clone(); + if let Some(mut node_graph_overlay_node) = document.node_graph_handler.node_graph_overlay.clone() { + let node_graph_overlay_id = NodeId::new(); + let new_export = NodeInput::node(node_graph_overlay_id, 0); + let old_export = std::mem::replace(&mut network.exports[0], new_export); + node_graph_overlay_node.inputs[0] = old_export; + network.nodes.insert(node_graph_overlay_id, node_graph_overlay_node); + } + let network_hash = network.current_hash(); // Refresh the graph when it changes or the inspect node changes if network_hash != self.node_graph_hash || self.previous_node_to_inspect != node_to_inspect || ignore_hash { - let network = document.network_interface.document_network().clone(); self.previous_node_to_inspect = node_to_inspect; self.node_graph_hash = network_hash; diff --git a/frontend/src/messages.ts b/frontend/src/messages.ts index 527c5ee0cc..618d14b150 100644 --- a/frontend/src/messages.ts +++ b/frontend/src/messages.ts @@ -116,7 +116,9 @@ export class UpdateNodeGraphRender extends JsMessage { readonly inSelectedNetwork!: boolean; readonly previewedNode!: bigint | undefined; +} +export class UpdateNativeNodeGraphRender extends JsMessage { readonly nativeNodeGraphRender!: boolean; } diff --git a/frontend/src/state-providers/node-graph.ts b/frontend/src/state-providers/node-graph.ts index 12f5c5a187..74a3584b84 100644 --- a/frontend/src/state-providers/node-graph.ts +++ b/frontend/src/state-providers/node-graph.ts @@ -16,6 +16,7 @@ import { UpdateImportsExports, UpdateLayerWidths, UpdateNodeGraphRender, + UpdateNativeNodeGraphRender, UpdateVisibleNodes, UpdateNodeGraphTransform, UpdateNodeThumbnail, @@ -118,7 +119,12 @@ export function createNodeGraphState(editor: Editor) { state.opacity = updateNodeGraphRender.opacity; state.inSelectedNetwork = updateNodeGraphRender.inSelectedNetwork; state.previewedNode = updateNodeGraphRender.previewedNode; - state.nativeNodeGraphRender = updateNodeGraphRender.nativeNodeGraphRender; + return state; + }); + }); + editor.subscriptions.subscribeJsMessage(UpdateNativeNodeGraphRender, (updateNativeNodeGraphRender) => { + update((state) => { + state.nativeNodeGraphRender = updateNativeNodeGraphRender.nativeNodeGraphRender; return state; }); }); diff --git a/node-graph/gcore/src/lib.rs b/node-graph/gcore/src/lib.rs index 586a76e0b6..c91e7e4fb4 100644 --- a/node-graph/gcore/src/lib.rs +++ b/node-graph/gcore/src/lib.rs @@ -17,6 +17,7 @@ pub mod logic; pub mod math; pub mod memo; pub mod misc; +pub mod node_graph_overlay; pub mod ops; pub mod raster; pub mod raster_types; diff --git a/node-graph/gcore/src/node_graph_overlay.rs b/node-graph/gcore/src/node_graph_overlay.rs new file mode 100644 index 0000000000..01d6e8a32e --- /dev/null +++ b/node-graph/gcore/src/node_graph_overlay.rs @@ -0,0 +1,47 @@ +use graphene_core_shaders::{Ctx, color::Color}; +use kurbo::{BezPath, Point}; + +use crate::{ExtractFootprint, table::Table, vector::Vector}; + +pub mod types; + +#[node_macro::node(category(""))] +pub fn generate_nodes(_: impl Ctx, _node_graph_overlay_data: types::NodeGraphOverlayData) -> Table { + Table::new() +} + +#[node_macro::node(category(""))] +pub fn transform_nodes(_ctx: impl Ctx + ExtractFootprint, nodes: Table) -> Table { + nodes +} + +#[node_macro::node(category(""))] +pub fn dot_grid_background(ctx: impl Ctx + ExtractFootprint, opacity: f64) -> Table { + let Some(footprint) = ctx.try_footprint() else { + log::error!("Could not get footprint from context in dot_grid_background"); + return Table::new(); + }; + // From --color-2-mildblack: --color-2-mildblack-rgb: 34, 34, 34; + let gray = (34. / 255.) as f32; + let Some(bg_color) = Color::from_rgbaf32(gray, gray, gray, opacity as f32) else { + log::error!("Could not create color in dot grid background"); + return Table::new(); + }; + + let mut bez_path = BezPath::new(); + let p0 = Point::new(0., 0.); // bottom-left + let p1 = Point::new(footprint.resolution.x as f64, 0.); // bottom-right + let p2 = Point::new(footprint.resolution.x as f64, footprint.resolution.y as f64); // top-right + let p3 = Point::new(0., footprint.resolution.y as f64); // top-left + + bez_path.move_to(p0); + bez_path.line_to(p1); + bez_path.line_to(p2); + bez_path.line_to(p3); + bez_path.close_path(); + + let mut vector = Vector::from_bezpath(bez_path); + vector.style.fill = crate::vector::style::Fill::Solid(bg_color); + + Table::new_from_element(vector) +} diff --git a/node-graph/gcore/src/node_graph_overlay/types.rs b/node-graph/gcore/src/node_graph_overlay/types.rs new file mode 100644 index 0000000000..db9a293dae --- /dev/null +++ b/node-graph/gcore/src/node_graph_overlay/types.rs @@ -0,0 +1,170 @@ +use crate::uuid::NodeId; + +#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +pub struct NodeGraphOverlayData { + pub nodes_to_render: Vec, + pub open: bool, + pub in_selected_network: bool, + // Displays a dashed border around the node + pub previewed_node: Option, +} + +#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] +pub struct FrontendNodeToRender { + pub metadata: FrontendNodeMetadata, + #[serde(rename = "nodeOrLayer")] + pub node_or_layer: FrontendNodeOrLayer, + //TODO: Remove + pub wires: Vec<(String, bool, FrontendGraphDataType)>, +} + +// Metadata that is common to nodes and layers +#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +pub struct FrontendNodeMetadata { + #[serde(rename = "nodeId")] + pub node_id: NodeId, + // TODO: Remove and replace with popup manager system + #[serde(rename = "canBeLayer")] + pub can_be_layer: bool, + #[serde(rename = "displayName")] + pub display_name: String, + 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, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +pub struct FrontendNode { + // pub position: FrontendNodePosition, + pub position: FrontendXY, + pub inputs: Vec>, + pub outputs: Vec>, +} + +#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, 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 = "primaryInputConnectedToLayer")] + pub primary_input_connected_to_layer: bool, + #[serde(rename = "primaryOutputConnectedToLayer")] + pub primary_output_connected_to_layer: bool, +} + +#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +pub struct FrontendXY { + pub x: i32, + pub y: i32, +} + +// // Should be an enum but those are hard to serialize/deserialize to TS +// #[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, 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, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +// pub struct FrontendLayerPosition { +// pub absolute: Option, +// pub stack: Option, +// } + +#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +pub struct FrontendNodeOrLayer { + pub node: Option, + pub layer: Option, +} + +#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +pub struct FrontendGraphInput { + #[serde(rename = "dataType")] + pub data_type: FrontendGraphDataType, + #[serde(rename = "resolvedType")] + pub resolved_type: String, + pub name: String, + pub description: String, + /// 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, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +pub struct FrontendGraphOutput { + #[serde(rename = "dataType")] + pub data_type: FrontendGraphDataType, + pub name: String, + #[serde(rename = "resolvedType")] + pub resolved_type: String, + pub description: String, + /// If connected to an export, it is "export index {index}". + /// If connected to a node, it is "{node name} input {input_index}". + #[serde(rename = "connectedTo")] + pub connected_to: Vec, +} + +#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +pub struct FrontendExport { + pub port: FrontendGraphInput, + pub wire: Option, +} + +#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +pub struct FrontendExports { + /// If the primary export is not visible, then it is None. + pub exports: Vec>, + #[serde(rename = "previewWire")] + pub preview_wire: Option, +} + +#[derive(Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] + +pub struct FrontendImport { + pub port: FrontendGraphOutput, + pub wires: Vec, +} + +#[derive(Copy, Clone, Debug, Default, PartialEq, Hash, dyn_any::DynAny, serde::Serialize, serde::Deserialize, specta::Type)] +pub enum FrontendGraphDataType { + #[default] + General, + Number, + Artboard, + Graphic, + Raster, + Vector, + Color, + Gradient, + Typography, +} diff --git a/node-graph/gcore/src/types.rs b/node-graph/gcore/src/types.rs index 133cb88c1d..741f1f88b9 100644 --- a/node-graph/gcore/src/types.rs +++ b/node-graph/gcore/src/types.rs @@ -126,7 +126,7 @@ impl std::fmt::Debug for NodeIOTypes { } } -#[derive(Clone, Debug, PartialEq, Eq, Hash, specta::Type, serde::Serialize, serde::Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] pub struct ProtoNodeIdentifier { pub name: Cow<'static, str>, } @@ -230,7 +230,7 @@ impl PartialEq for TypeDescriptor { } /// Graph runtime type information used for type inference. -#[derive(Clone, PartialEq, Eq, Hash, specta::Type, serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] pub enum Type { /// A wrapper for some type variable used within the inference system. Resolved at inference time and replaced with a concrete type. Generic(Cow<'static, str>), diff --git a/node-graph/graph-craft/src/document/value.rs b/node-graph/graph-craft/src/document/value.rs index 2d812cc19b..db57aedbc1 100644 --- a/node-graph/graph-craft/src/document/value.rs +++ b/node-graph/graph-craft/src/document/value.rs @@ -262,6 +262,7 @@ tagged_value! { CentroidType(graphene_core::vector::misc::CentroidType), BooleanOperation(graphene_path_bool::BooleanOperation), TextAlign(graphene_core::text::TextAlign), + NodeGraphOverlayData(graphene_core::node_graph_overlay::types::NodeGraphOverlayData), } impl TaggedValue {