mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-20 03:18:06 +08:00
Improve native UI network
This commit is contained in:
@@ -1,13 +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, FrontendNodeType, Transform};
|
||||
use crate::messages::portfolio::document::node_graph::utility_types::{BoxSelection, ContextMenuInformation, FrontendClickTargets, FrontendNodeType};
|
||||
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::node_graph_overlay::types::{FrontendExports, FrontendImport, FrontendNodeToRender, FrontendXY, NodeGraphTransform};
|
||||
use graphene_std::raster::Image;
|
||||
use graphene_std::raster::color::Color;
|
||||
use graphene_std::text::{Font, TextAlign};
|
||||
@@ -269,7 +269,7 @@ pub enum FrontendMessage {
|
||||
UpdateMouseCursor {
|
||||
cursor: MouseCursorIcon,
|
||||
},
|
||||
UpdateNodeGraphRender {
|
||||
UpdateNodeGraphSvelteRender {
|
||||
#[serde(rename = "nodesToRender")]
|
||||
nodes_to_render: Vec<FrontendNodeToRender>,
|
||||
open: bool,
|
||||
@@ -280,9 +280,13 @@ pub enum FrontendMessage {
|
||||
#[serde(rename = "previewedNode")]
|
||||
previewed_node: Option<NodeId>,
|
||||
},
|
||||
UpdateNativeNodeGraphRender {
|
||||
#[serde(rename = "nativeNodeGraphRender")]
|
||||
native_node_graph_render: bool,
|
||||
UpdateShouldRenderSvelteNodes {
|
||||
#[serde(rename = "shouldRenderSvelteNodes")]
|
||||
should_render_svelte_nodes: bool,
|
||||
},
|
||||
UpdateNativeNodeGraphSVG {
|
||||
#[serde(rename = "svgString")]
|
||||
svg_string: String,
|
||||
},
|
||||
UpdateVisibleNodes {
|
||||
nodes: Vec<NodeId>,
|
||||
@@ -293,7 +297,7 @@ pub enum FrontendMessage {
|
||||
diff: Vec<WidgetDiff>,
|
||||
},
|
||||
UpdateNodeGraphTransform {
|
||||
transform: Transform,
|
||||
transform: NodeGraphTransform,
|
||||
},
|
||||
UpdateNodeThumbnail {
|
||||
id: NodeId,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use super::node_graph::document_node_definitions;
|
||||
use super::node_graph::utility_types::Transform;
|
||||
use super::overlays::utility_types::Pivot;
|
||||
use super::utility_types::error::EditorError;
|
||||
use super::utility_types::misc::{GroupFolderType, SNAP_FUNCTIONS_FOR_BOUNDING_BOXES, SNAP_FUNCTIONS_FOR_PATHS, SnappingOptions, SnappingState};
|
||||
@@ -31,6 +30,7 @@ use glam::{DAffine2, DVec2, IVec2};
|
||||
use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::{NodeId, NodeInput, NodeNetwork, OldNodeNetwork};
|
||||
use graphene_std::math::quad::Quad;
|
||||
use graphene_std::node_graph_overlay::types::NodeGraphTransform;
|
||||
use graphene_std::path_bool::{boolean_intersect, path_bool_lib};
|
||||
use graphene_std::raster::BlendMode;
|
||||
use graphene_std::raster_types::Raster;
|
||||
@@ -1494,7 +1494,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
|
||||
responses.add(NodeGraphMessage::UpdateImportsExports);
|
||||
|
||||
responses.add(FrontendMessage::UpdateNodeGraphTransform {
|
||||
transform: Transform {
|
||||
transform: NodeGraphTransform {
|
||||
scale: transform.matrix2.x_axis.x,
|
||||
x: transform.translation.x,
|
||||
y: transform.translation.y,
|
||||
|
||||
@@ -3,108 +3,133 @@ use graph_craft::{
|
||||
document::{DocumentNode, DocumentNodeImplementation, NodeInput, NodeNetwork, value::TaggedValue},
|
||||
};
|
||||
use graphene_std::{
|
||||
Context, graphic, memo,
|
||||
node_graph_overlay::{self, types::NodeGraphOverlayData},
|
||||
node_graph_overlay::{types::NodeGraphOverlayData, ui_context::UIContext},
|
||||
table::Table,
|
||||
uuid::NodeId,
|
||||
};
|
||||
|
||||
/// https://excalidraw.com/#json=LgKS6I4lQvGPmke06ZJyp,D9aON9vVZJAjNnZWfwy_SQ
|
||||
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
|
||||
let generate_nodes_id = NodeId::new();
|
||||
let cache_nodes_id = NodeId::new();
|
||||
let transform_nodes_id = NodeId::new();
|
||||
|
||||
let generate_node_graph_bg = NodeId::new();
|
||||
let cache_node_graph_bg = NodeId::new();
|
||||
|
||||
let merge_nodes_and_bg_id = NodeId::new();
|
||||
let render_overlay_id = NodeId::new();
|
||||
let send_overlay_id = NodeId::new();
|
||||
let _cache_output_id = NodeId::new();
|
||||
// TODO: Replace with new cache node
|
||||
let memo_implementation = DocumentNodeImplementation::ProtoNode(graphene_std::ops::identity::IDENTIFIER);
|
||||
|
||||
DocumentNode {
|
||||
inputs: vec![
|
||||
NodeInput::value(TaggedValue::None, true),
|
||||
NodeInput::value(TaggedValue::Vector(Table::new()), 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)],
|
||||
exports: vec![NodeInput::node(send_overlay_id, 0)],
|
||||
nodes: vec![
|
||||
// Merge the overlay on top of the artwork
|
||||
// Create the nodes
|
||||
(
|
||||
NodeId(0),
|
||||
generate_nodes_id,
|
||||
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),
|
||||
call_argument: concrete!(UIContext),
|
||||
inputs: vec![NodeInput::network(concrete!(UIContext), 1)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::node_graph_overlay::GenerateNodesNode".into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
// Cache the nodes
|
||||
(
|
||||
NodeId(6),
|
||||
cache_nodes_id,
|
||||
DocumentNode {
|
||||
call_argument: concrete!(Context),
|
||||
inputs: vec![NodeInput::node(NodeId(7), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(memo::memo::IDENTIFIER),
|
||||
call_argument: concrete!(UIContext),
|
||||
inputs: vec![NodeInput::node(generate_nodes_id, 0)],
|
||||
implementation: memo_implementation.clone(),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
// Create the nodes
|
||||
// Transform the nodes based on the Context
|
||||
(
|
||||
NodeId(7),
|
||||
transform_nodes_id,
|
||||
DocumentNode {
|
||||
call_argument: concrete!(Context),
|
||||
inputs: vec![NodeInput::network(concrete!(Context), 1)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(node_graph_overlay::generate_nodes::IDENTIFIER),
|
||||
call_argument: concrete!(UIContext),
|
||||
inputs: vec![NodeInput::node(cache_nodes_id, 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::node_graph_overlay::TransformNodesNode".into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
// Generate the dot grid background
|
||||
(
|
||||
generate_node_graph_bg,
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::network(concrete!(UIContext), 2)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::node_graph_overlay::DotGridBackgroundNode".into()),
|
||||
call_argument: concrete!(UIContext),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
// Cache the dot grid background
|
||||
(
|
||||
cache_node_graph_bg,
|
||||
DocumentNode {
|
||||
call_argument: concrete!(UIContext),
|
||||
inputs: vec![NodeInput::node(generate_node_graph_bg, 0)],
|
||||
implementation: memo_implementation.clone(),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
// Merge the nodes on top of the dot grid background
|
||||
(
|
||||
merge_nodes_and_bg_id,
|
||||
DocumentNode {
|
||||
call_argument: concrete!(UIContext),
|
||||
inputs: vec![NodeInput::node(transform_nodes_id, 0), NodeInput::node(cache_node_graph_bg, 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::node_graph_overlay::NodeGraphUiExtendNode".into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
// Render the node graph UI graphic to an SVG
|
||||
(
|
||||
render_overlay_id,
|
||||
DocumentNode {
|
||||
call_argument: concrete!(UIContext),
|
||||
inputs: vec![NodeInput::node(merge_nodes_and_bg_id, 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_std::wasm_application_io::RenderNodeGraphUiNode".into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
// Send the overlay to the frontend
|
||||
(
|
||||
send_overlay_id,
|
||||
DocumentNode {
|
||||
call_argument: concrete!(UIContext),
|
||||
inputs: vec![NodeInput::node(render_overlay_id, 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::node_graph_overlay::SendRenderNode".into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
// Cache the full node graph so its not rerendered when the artwork changes
|
||||
// (
|
||||
// cache_nodes_id,
|
||||
// DocumentNode {
|
||||
// call_argument: concrete!(UIContext),
|
||||
// inputs: vec![NodeInput::node(send_overlay_id, 0)],
|
||||
// implementation: memo_implementation.clone(),
|
||||
// ..Default::default()
|
||||
// },
|
||||
// ),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
call_argument: concrete!(Context),
|
||||
call_argument: concrete!(UIContext),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ 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::{DocumentNode, DocumentNodeImplementation, NodeId, NodeInput};
|
||||
use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput};
|
||||
use graph_craft::proto::GraphErrors;
|
||||
use graphene_std::math::math_ext::QuadExt;
|
||||
use graphene_std::node_graph_overlay::types::{FrontendGraphDataType, FrontendXY};
|
||||
@@ -1795,8 +1795,11 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||
}
|
||||
NodeGraphMessage::ToggleNativeNodeGraphRender => {
|
||||
self.native_node_graph_render = !self.native_node_graph_render;
|
||||
self.node_graph_overlay = None;
|
||||
responses.add(FrontendMessage::UpdateShouldRenderSvelteNodes {
|
||||
should_render_svelte_nodes: self.native_node_graph_render,
|
||||
});
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(MenuBarMessage::SendLayout);
|
||||
}
|
||||
NodeGraphMessage::ToggleSelectedLocked => {
|
||||
let Some(selected_nodes) = network_interface.selected_nodes_in_nested_network(selection_network_path) else {
|
||||
|
||||
@@ -214,13 +214,6 @@ pub struct DragStart {
|
||||
pub round_y: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct Transform {
|
||||
pub scale: f64,
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
pub struct BoxSelection {
|
||||
#[serde(rename = "startX")]
|
||||
|
||||
@@ -301,7 +301,7 @@ pub trait FrontendMessageTestUtils {
|
||||
|
||||
impl FrontendMessageTestUtils for FrontendMessage {
|
||||
fn check_node_graph_error(&self) {
|
||||
let FrontendMessage::UpdateNodeGraphRender { nodes_to_render, .. } = self else { return };
|
||||
let FrontendMessage::UpdateNodeGraphSvelteRender { nodes_to_render, .. } = self else { return };
|
||||
|
||||
for node in nodes_to_render {
|
||||
if let Some(error) = &node.metadata.errors {
|
||||
|
||||
Reference in New Issue
Block a user