mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-30 10:28:12 +08:00
Add invalid type
This commit is contained in:
+8
@@ -7,10 +7,12 @@ use crate::messages::portfolio::document::utility_types::nodes::CollapsedLayers;
|
|||||||
use crate::messages::prelude::*;
|
use crate::messages::prelude::*;
|
||||||
use crate::messages::tool::common_functionality::graph_modification_utils::get_clip_mode;
|
use crate::messages::tool::common_functionality::graph_modification_utils::get_clip_mode;
|
||||||
use glam::{DAffine2, DVec2, IVec2};
|
use glam::{DAffine2, DVec2, IVec2};
|
||||||
|
use graph_craft::document::value::TaggedValue;
|
||||||
use graph_craft::document::{NodeId, NodeInput};
|
use graph_craft::document::{NodeId, NodeInput};
|
||||||
use graphene_std::Color;
|
use graphene_std::Color;
|
||||||
use graphene_std::renderer::Quad;
|
use graphene_std::renderer::Quad;
|
||||||
use graphene_std::renderer::convert_usvg_path::convert_usvg_path;
|
use graphene_std::renderer::convert_usvg_path::convert_usvg_path;
|
||||||
|
use graphene_std::table::Table;
|
||||||
use graphene_std::text::{Font, TypesettingConfig};
|
use graphene_std::text::{Font, TypesettingConfig};
|
||||||
use graphene_std::vector::style::{Fill, Gradient, GradientStops, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
use graphene_std::vector::style::{Fill, Gradient, GradientStops, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
||||||
|
|
||||||
@@ -140,10 +142,16 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
|
|||||||
skip_rerender: true,
|
skip_rerender: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Set the bottom input of the artboard back to artboard
|
||||||
|
let bottom_input = NodeInput::value(TaggedValue::Artboard(Table::new()), true);
|
||||||
|
network_interface.set_input(&InputConnector::node(artboard_layer.to_node(), 0), bottom_input, &[]);
|
||||||
} else {
|
} else {
|
||||||
// We have some non layers (e.g. just a rectangle node). We disconnect the bottom input and connect it to the left input.
|
// We have some non layers (e.g. just a rectangle node). We disconnect the bottom input and connect it to the left input.
|
||||||
network_interface.disconnect_input(&InputConnector::node(artboard_layer.to_node(), 0), &[]);
|
network_interface.disconnect_input(&InputConnector::node(artboard_layer.to_node(), 0), &[]);
|
||||||
network_interface.set_input(&InputConnector::node(artboard_layer.to_node(), 1), primary_input, &[]);
|
network_interface.set_input(&InputConnector::node(artboard_layer.to_node(), 1), primary_input, &[]);
|
||||||
|
// Set the bottom input of the artboard back to artboard
|
||||||
|
let bottom_input = NodeInput::value(TaggedValue::Artboard(Table::new()), true);
|
||||||
|
network_interface.set_input(&InputConnector::node(artboard_layer.to_node(), 0), bottom_input, &[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
responses.add_front(NodeGraphMessage::SelectedNodesSet { nodes: vec![id] });
|
responses.add_front(NodeGraphMessage::SelectedNodesSet { nodes: vec![id] });
|
||||||
|
|||||||
+39
-2
@@ -6,7 +6,39 @@ use graphene_std::registry::*;
|
|||||||
use graphene_std::*;
|
use graphene_std::*;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
/// Traverses a document node template and metadata in parallel to link the protonodes to their reference
|
||||||
|
fn traverse_node(node: &DocumentNode, node_metadata: &mut DocumentNodePersistentMetadata) {
|
||||||
|
match &node.implementation {
|
||||||
|
DocumentNodeImplementation::Network(node_network) => {
|
||||||
|
for (nested_node_id, nested_node) in node_network.nodes.iter() {
|
||||||
|
let nested_metadata = node_metadata
|
||||||
|
.network_metadata
|
||||||
|
.as_mut()
|
||||||
|
.expect("Network node must have network metadata")
|
||||||
|
.persistent_metadata
|
||||||
|
.node_metadata
|
||||||
|
.get_mut(nested_node_id)
|
||||||
|
.expect("Network metadata must have corresponding node id");
|
||||||
|
traverse_node(nested_node, &mut nested_metadata.persistent_metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DocumentNodeImplementation::ProtoNode(proto_node_identifier) => {
|
||||||
|
if let Some(metadata) = NODE_METADATA.lock().unwrap().get(&proto_node_identifier) {
|
||||||
|
node_metadata.reference = Some(metadata.display_name.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DocumentNodeImplementation::Extract => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn post_process_nodes(mut custom: Vec<DocumentNodeDefinition>) -> Vec<DocumentNodeDefinition> {
|
pub(super) fn post_process_nodes(mut custom: Vec<DocumentNodeDefinition>) -> Vec<DocumentNodeDefinition> {
|
||||||
|
NODE_METADATA.lock().unwrap().keys().for_each(|key| log::debug!("{key:?}"));
|
||||||
|
|
||||||
|
// Link the protonodes with custom networks to their reference
|
||||||
|
for node in custom.iter_mut() {
|
||||||
|
traverse_node(&node.node_template.document_node, &mut node.node_template.persistent_node_metadata);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove struct generics
|
// Remove struct generics
|
||||||
for DocumentNodeDefinition { node_template, .. } in custom.iter_mut() {
|
for DocumentNodeDefinition { node_template, .. } in custom.iter_mut() {
|
||||||
let NodeTemplate {
|
let NodeTemplate {
|
||||||
@@ -20,7 +52,6 @@ pub(super) fn post_process_nodes(mut custom: Vec<DocumentNodeDefinition>) -> Vec
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let node_registry = NODE_REGISTRY.lock().unwrap();
|
let node_registry = NODE_REGISTRY.lock().unwrap();
|
||||||
'outer: for (id, metadata) in NODE_METADATA.lock().unwrap().iter() {
|
'outer: for (id, metadata) in NODE_METADATA.lock().unwrap().iter() {
|
||||||
for node in custom.iter() {
|
for node in custom.iter() {
|
||||||
@@ -32,7 +63,10 @@ pub(super) fn post_process_nodes(mut custom: Vec<DocumentNodeDefinition>) -> Vec
|
|||||||
..
|
..
|
||||||
} = node;
|
} = node;
|
||||||
match implementation {
|
match implementation {
|
||||||
DocumentNodeImplementation::ProtoNode(name) if name == id => continue 'outer,
|
DocumentNodeImplementation::ProtoNode(name) if name == id => {
|
||||||
|
log::debug!("skipping defintion {name}");
|
||||||
|
continue 'outer;
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,6 +89,8 @@ pub(super) fn post_process_nodes(mut custom: Vec<DocumentNodeDefinition>) -> Vec
|
|||||||
let output_type = &first_node_io.return_value;
|
let output_type = &first_node_io.return_value;
|
||||||
|
|
||||||
let inputs = preprocessor::node_inputs(fields, first_node_io);
|
let inputs = preprocessor::node_inputs(fields, first_node_io);
|
||||||
|
log::debug!("generating definition for {display_name:?}");
|
||||||
|
|
||||||
let node = DocumentNodeDefinition {
|
let node = DocumentNodeDefinition {
|
||||||
identifier: display_name,
|
identifier: display_name,
|
||||||
node_template: NodeTemplate {
|
node_template: NodeTemplate {
|
||||||
@@ -91,5 +127,6 @@ pub(super) fn post_process_nodes(mut custom: Vec<DocumentNodeDefinition>) -> Vec
|
|||||||
custom.push(node);
|
custom.push(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom.iter().for_each(|def| log::debug!("{:?}", def.identifier));
|
||||||
custom
|
custom
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
|
|||||||
use crate::messages::viewport::{Position, Rect};
|
use crate::messages::viewport::{Position, Rect};
|
||||||
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 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::*;
|
||||||
@@ -51,7 +50,6 @@ pub struct NodeGraphMessageContext<'a> {
|
|||||||
pub struct NodeGraphMessageHandler {
|
pub struct NodeGraphMessageHandler {
|
||||||
// TODO: Remove network and move to NodeNetworkInterface
|
// TODO: Remove network and move to NodeNetworkInterface
|
||||||
pub network: Vec<NodeId>,
|
pub network: Vec<NodeId>,
|
||||||
pub node_graph_errors: GraphErrors,
|
|
||||||
has_selection: bool,
|
has_selection: bool,
|
||||||
widgets: [LayoutGroup; 2],
|
widgets: [LayoutGroup; 2],
|
||||||
/// Used to add a transaction for the first node move when dragging.
|
/// Used to add a transaction for the first node move when dragging.
|
||||||
@@ -1623,7 +1621,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
|||||||
if node_bbox[1].x >= document_bbox[0].x && node_bbox[0].x <= document_bbox[1].x && node_bbox[1].y >= document_bbox[0].y && node_bbox[0].y <= document_bbox[1].y {
|
if node_bbox[1].x >= document_bbox[0].x && node_bbox[0].x <= document_bbox[1].x && node_bbox[1].y >= document_bbox[0].y && node_bbox[0].y <= document_bbox[1].y {
|
||||||
nodes.push(*node_id);
|
nodes.push(*node_id);
|
||||||
}
|
}
|
||||||
for error in &self.node_graph_errors {
|
for error in &network_interface.resolved_types.node_graph_errors {
|
||||||
if error.node_path.contains(node_id) {
|
if error.node_path.contains(node_id) {
|
||||||
nodes.push(*node_id);
|
nodes.push(*node_id);
|
||||||
}
|
}
|
||||||
@@ -1995,8 +1993,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
|||||||
responses.add(NodeGraphMessage::SendGraph);
|
responses.add(NodeGraphMessage::SendGraph);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::UpdateTypes { resolved_types, node_graph_errors } => {
|
NodeGraphMessage::UpdateTypes { resolved_types, node_graph_errors } => {
|
||||||
network_interface.resolved_types.update(resolved_types);
|
network_interface.resolved_types.update(resolved_types, node_graph_errors);
|
||||||
self.node_graph_errors = node_graph_errors;
|
|
||||||
}
|
}
|
||||||
NodeGraphMessage::UpdateActionButtons => {
|
NodeGraphMessage::UpdateActionButtons => {
|
||||||
if selection_network_path == breadcrumb_network_path {
|
if selection_network_path == breadcrumb_network_path {
|
||||||
@@ -2557,13 +2554,14 @@ impl NodeGraphMessageHandler {
|
|||||||
|
|
||||||
let locked = network_interface.is_locked(&node_id, breadcrumb_network_path);
|
let locked = network_interface.is_locked(&node_id, breadcrumb_network_path);
|
||||||
|
|
||||||
let errors = self
|
let errors = network_interface
|
||||||
|
.resolved_types
|
||||||
.node_graph_errors
|
.node_graph_errors
|
||||||
.iter()
|
.iter()
|
||||||
.find(|error| error.node_path == node_id_path)
|
.find(|error| error.node_path == node_id_path)
|
||||||
.map(|error| format!("{:?}", error.error.clone()))
|
.map(|error| format!("{:?}", error.error.clone()))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
if self.node_graph_errors.iter().any(|error| error.node_path.starts_with(&node_id_path)) {
|
if network_interface.resolved_types.node_graph_errors.iter().any(|error| error.node_path.starts_with(&node_id_path)) {
|
||||||
Some("Node graph type error within this node".to_string())
|
Some("Node graph type error within this node".to_string())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -2746,7 +2744,6 @@ impl Default for NodeGraphMessageHandler {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
network: Vec::new(),
|
network: Vec::new(),
|
||||||
node_graph_errors: Vec::new(),
|
|
||||||
has_selection: false,
|
has_selection: false,
|
||||||
widgets: [LayoutGroup::Row { widgets: Vec::new() }, LayoutGroup::Row { widgets: Vec::new() }],
|
widgets: [LayoutGroup::Row { widgets: Vec::new() }, LayoutGroup::Row { widgets: Vec::new() }],
|
||||||
drag_start: None,
|
drag_start: None,
|
||||||
@@ -2778,7 +2775,6 @@ impl Default for NodeGraphMessageHandler {
|
|||||||
impl PartialEq for NodeGraphMessageHandler {
|
impl PartialEq for NodeGraphMessageHandler {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.network == other.network
|
self.network == other.network
|
||||||
&& self.node_graph_errors == other.node_graph_errors
|
|
||||||
&& self.has_selection == other.has_selection
|
&& self.has_selection == other.has_selection
|
||||||
&& self.widgets == other.widgets
|
&& self.widgets == other.widgets
|
||||||
&& self.drag_start == other.drag_start
|
&& self.drag_start == other.drag_start
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ pub enum FrontendGraphDataType {
|
|||||||
Color,
|
Color,
|
||||||
Gradient,
|
Gradient,
|
||||||
Typography,
|
Typography,
|
||||||
|
Invalid,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FrontendGraphDataType {
|
impl FrontendGraphDataType {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use super::nodes::SelectedNodes;
|
|||||||
use crate::consts::{EXPORTS_TO_RIGHT_EDGE_PIXEL_GAP, EXPORTS_TO_TOP_EDGE_PIXEL_GAP, GRID_SIZE, IMPORTS_TO_LEFT_EDGE_PIXEL_GAP, IMPORTS_TO_TOP_EDGE_PIXEL_GAP};
|
use crate::consts::{EXPORTS_TO_RIGHT_EDGE_PIXEL_GAP, EXPORTS_TO_TOP_EDGE_PIXEL_GAP, GRID_SIZE, IMPORTS_TO_LEFT_EDGE_PIXEL_GAP, IMPORTS_TO_TOP_EDGE_PIXEL_GAP};
|
||||||
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::{DocumentNodeDefinition, resolve_document_node_type};
|
use crate::messages::portfolio::document::node_graph::document_node_definitions::{DocumentNodeDefinition, resolve_document_node_type};
|
||||||
use crate::messages::portfolio::document::node_graph::utility_types::{Direction, FrontendClickTargets, FrontendGraphInput, FrontendGraphOutput};
|
use crate::messages::portfolio::document::node_graph::utility_types::{Direction, FrontendClickTargets, FrontendGraphDataType, FrontendGraphInput, FrontendGraphOutput};
|
||||||
use crate::messages::portfolio::document::utility_types::network_interface::resolved_types::ResolvedDocumentNodeTypes;
|
use crate::messages::portfolio::document::utility_types::network_interface::resolved_types::ResolvedDocumentNodeTypes;
|
||||||
use crate::messages::portfolio::document::utility_types::wires::{GraphWireStyle, WirePath, WirePathUpdate, build_vector_wire};
|
use crate::messages::portfolio::document::utility_types::wires::{GraphWireStyle, WirePath, WirePathUpdate, build_vector_wire};
|
||||||
use crate::messages::tool::common_functionality::graph_modification_utils;
|
use crate::messages::tool::common_functionality::graph_modification_utils;
|
||||||
@@ -625,7 +625,7 @@ impl NodeNetworkInterface {
|
|||||||
}
|
}
|
||||||
let input_type = self.input_type(input_connector, network_path);
|
let input_type = self.input_type(input_connector, network_path);
|
||||||
let data_type = input_type.displayed_type();
|
let data_type = input_type.displayed_type();
|
||||||
let resolved_type = input_type.resolved_type_name();
|
let resolved_type = input_type.resolved_type_node_string();
|
||||||
|
|
||||||
let connected_to = self
|
let connected_to = self
|
||||||
.upstream_output_connector(input_connector, network_path)
|
.upstream_output_connector(input_connector, network_path)
|
||||||
@@ -656,7 +656,7 @@ impl NodeNetworkInterface {
|
|||||||
|
|
||||||
let export_name = if !export_name.is_empty() {
|
let export_name = if !export_name.is_empty() {
|
||||||
export_name
|
export_name
|
||||||
} else if let Some(export_type_name) = input_type.compiled_nested_type_name() {
|
} else if let Some(export_type_name) = input_type.compiled_nested_type().map(|nested| nested.to_string()) {
|
||||||
export_type_name
|
export_type_name
|
||||||
} else {
|
} else {
|
||||||
format!("Export index {}", export_index)
|
format!("Export index {}", export_index)
|
||||||
@@ -690,7 +690,7 @@ impl NodeNetworkInterface {
|
|||||||
let node_metadata = self.node_metadata(node_id, network_path)?;
|
let node_metadata = self.node_metadata(node_id, network_path)?;
|
||||||
let output_name = node_metadata.persistent_metadata.output_names.get(*output_index).cloned().unwrap_or_default();
|
let output_name = node_metadata.persistent_metadata.output_names.get(*output_index).cloned().unwrap_or_default();
|
||||||
|
|
||||||
let output_name = if !output_name.is_empty() { output_name } else { output_type.resolved_type_name() };
|
let output_name = if !output_name.is_empty() { output_name } else { output_type.resolved_type_node_string() };
|
||||||
(output_name, String::new())
|
(output_name, String::new())
|
||||||
}
|
}
|
||||||
OutputConnector::Import(import_index) => {
|
OutputConnector::Import(import_index) => {
|
||||||
@@ -707,7 +707,7 @@ impl NodeNetworkInterface {
|
|||||||
|
|
||||||
let import_name = if !import_name.is_empty() {
|
let import_name = if !import_name.is_empty() {
|
||||||
import_name
|
import_name
|
||||||
} else if let Some(import_type_name) = output_type.compiled_nested_type_name() {
|
} else if let Some(import_type_name) = output_type.compiled_nested_type().map(|nested| nested.to_string()) {
|
||||||
import_type_name
|
import_type_name
|
||||||
} else {
|
} else {
|
||||||
format!("Import index {}", import_index)
|
format!("Import index {}", import_index)
|
||||||
@@ -717,7 +717,7 @@ impl NodeNetworkInterface {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let data_type = output_type.displayed_type();
|
let data_type = output_type.displayed_type();
|
||||||
let resolved_type = output_type.resolved_type_name();
|
let resolved_type = output_type.resolved_type_node_string();
|
||||||
let mut connected_to = self
|
let mut connected_to = self
|
||||||
.outward_wires(network_path)
|
.outward_wires(network_path)
|
||||||
.and_then(|outward_wires| outward_wires.get(output_connector))
|
.and_then(|outward_wires| outward_wires.get(output_connector))
|
||||||
@@ -977,7 +977,7 @@ impl NodeNetworkInterface {
|
|||||||
};
|
};
|
||||||
let description = input_metadata.input_description.to_string();
|
let description = input_metadata.input_description.to_string();
|
||||||
let name = if input_metadata.input_name.is_empty() {
|
let name = if input_metadata.input_name.is_empty() {
|
||||||
self.input_type(&InputConnector::node(*node_id, input_index), network_path).resolved_type_name()
|
self.input_type(&InputConnector::node(*node_id, input_index), network_path).resolved_type_node_string()
|
||||||
} else {
|
} else {
|
||||||
input_metadata.input_name.to_string()
|
input_metadata.input_name.to_string()
|
||||||
};
|
};
|
||||||
@@ -2520,7 +2520,10 @@ impl NodeNetworkInterface {
|
|||||||
pub fn wire_path_from_input(&mut self, input: &InputConnector, graph_wire_style: GraphWireStyle, dashed: bool, network_path: &[NodeId]) -> Option<WirePath> {
|
pub fn wire_path_from_input(&mut self, input: &InputConnector, graph_wire_style: GraphWireStyle, dashed: bool, network_path: &[NodeId]) -> Option<WirePath> {
|
||||||
let (vector_wire, thick) = self.vector_wire_from_input(input, graph_wire_style, network_path)?;
|
let (vector_wire, thick) = self.vector_wire_from_input(input, graph_wire_style, network_path)?;
|
||||||
let path_string = vector_wire.to_svg();
|
let path_string = vector_wire.to_svg();
|
||||||
let data_type = self.input_type(input, network_path).displayed_type();
|
let data_type = self
|
||||||
|
.upstream_output_connector(input, network_path)
|
||||||
|
.map(|output| self.output_type(&output, network_path).displayed_type())
|
||||||
|
.unwrap_or(FrontendGraphDataType::General);
|
||||||
Some(WirePath {
|
Some(WirePath {
|
||||||
path_string,
|
path_string,
|
||||||
data_type,
|
data_type,
|
||||||
|
|||||||
+86
-105
@@ -2,7 +2,8 @@ use std::collections::{HashMap, HashSet};
|
|||||||
|
|
||||||
use graph_craft::document::value::TaggedValue;
|
use graph_craft::document::value::TaggedValue;
|
||||||
use graph_craft::document::{DocumentNodeImplementation, InlineRust, NodeInput};
|
use graph_craft::document::{DocumentNodeImplementation, InlineRust, NodeInput};
|
||||||
use graph_craft::{ProtoNodeIdentifier, Type, concrete};
|
use graph_craft::proto::GraphErrors;
|
||||||
|
use graph_craft::{Type, concrete};
|
||||||
use graphene_std::uuid::NodeId;
|
use graphene_std::uuid::NodeId;
|
||||||
use interpreted_executor::dynamic_executor::{NodeTypes, ResolvedDocumentNodeTypesDelta};
|
use interpreted_executor::dynamic_executor::{NodeTypes, ResolvedDocumentNodeTypesDelta};
|
||||||
use interpreted_executor::node_registry::NODE_REGISTRY;
|
use interpreted_executor::node_registry::NODE_REGISTRY;
|
||||||
@@ -14,37 +15,42 @@ use crate::messages::portfolio::document::utility_types::network_interface::{Inp
|
|||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ResolvedDocumentNodeTypes {
|
pub struct ResolvedDocumentNodeTypes {
|
||||||
pub types: HashMap<Vec<NodeId>, NodeTypes>,
|
pub types: HashMap<Vec<NodeId>, NodeTypes>,
|
||||||
|
pub node_graph_errors: GraphErrors,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResolvedDocumentNodeTypes {
|
impl ResolvedDocumentNodeTypes {
|
||||||
pub fn update(&mut self, delta: ResolvedDocumentNodeTypesDelta) {
|
pub fn update(&mut self, delta: ResolvedDocumentNodeTypesDelta, errors: GraphErrors) {
|
||||||
for (path, node_type) in delta.add {
|
for (path, node_type) in delta.add {
|
||||||
self.types.insert(path.to_vec(), node_type);
|
self.types.insert(path.to_vec(), node_type);
|
||||||
}
|
}
|
||||||
for path in delta.remove {
|
for path in delta.remove {
|
||||||
self.types.remove(&path.to_vec());
|
self.types.remove(&path.to_vec());
|
||||||
}
|
}
|
||||||
|
self.node_graph_errors = errors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the result of a type query for an input or output connector.
|
/// Represents the result of a type query for an input or output connector.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum TypeSource {
|
pub enum TypeSource {
|
||||||
// A type that has been compiled based on all upstream types
|
/// A type that has been compiled based on all upstream types.
|
||||||
Compiled(Type),
|
Compiled(Type),
|
||||||
// The type of value inputs
|
/// The type of value inputs.
|
||||||
TaggedValue(Type),
|
TaggedValue(Type),
|
||||||
// A type that is guessed from the document node definition
|
/// When the input/output is not compiled. The Type is from the document node definition, or () if it doesn't exist.
|
||||||
DocumentNodeDefinition(Type),
|
|
||||||
// When the input is not compiled, the type is unknown and must be guessed from the valid types
|
|
||||||
Unknown,
|
Unknown,
|
||||||
|
/// When there is a node graph error for the inputs to a node. The Type is from the document node definition, or () if it doesn't exist.
|
||||||
|
Invalid,
|
||||||
|
/// When there is an error in the algorithm for determining the input/output type (indicates a bug in the editor).
|
||||||
Error(&'static str),
|
Error(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeSource {
|
impl TypeSource {
|
||||||
/// The reduced set of frontend types for displaying color.
|
/// The reduced set of frontend types for displaying color.
|
||||||
pub fn displayed_type(&self) -> FrontendGraphDataType {
|
pub fn displayed_type(&self) -> FrontendGraphDataType {
|
||||||
|
if matches!(self, TypeSource::Invalid) {
|
||||||
|
return FrontendGraphDataType::Invalid;
|
||||||
|
};
|
||||||
match self.compiled_nested_type() {
|
match self.compiled_nested_type() {
|
||||||
Some(nested_type) => match TaggedValue::from_type_or_none(nested_type) {
|
Some(nested_type) => match TaggedValue::from_type_or_none(nested_type) {
|
||||||
TaggedValue::U32(_)
|
TaggedValue::U32(_)
|
||||||
@@ -77,29 +83,60 @@ impl TypeSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If Some, the type should be displayed in the imports/exports, if None it should be replaced with "import/export index _".
|
|
||||||
pub fn compiled_nested_type_name(&self) -> Option<String> {
|
|
||||||
self.compiled_nested_type().map(|ty| ty.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Used when searching for nodes in the add Node popup.
|
/// Used when searching for nodes in the add Node popup.
|
||||||
pub fn add_node_string(self) -> Option<String> {
|
pub fn add_node_string(self) -> Option<String> {
|
||||||
self.compiled_nested_type().map(|ty| format!("type:{}", ty.to_string()))
|
self.compiled_nested_type().map(|ty| format!("type:{}", ty.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type to display in the tooltip.
|
/// The type to display in the tooltip.
|
||||||
pub fn resolved_type_name(&self) -> String {
|
pub fn resolved_type_tooltip_string(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
TypeSource::Compiled(compiled_type) => compiled_type.nested_type().to_string(),
|
TypeSource::Compiled(compiled_type) => format!("Data Type: {:?}", compiled_type.nested_type_name().to_string()),
|
||||||
TypeSource::TaggedValue(value_type) => value_type.nested_type().to_string(),
|
TypeSource::TaggedValue(value_type) => format!("Data Type: {:?}", value_type.nested_type_name().to_string()),
|
||||||
TypeSource::DocumentNodeDefinition(_) => "Unknown".to_string(),
|
TypeSource::Unknown => "Unknown Data Type".to_string(),
|
||||||
|
TypeSource::Invalid => "Invalid Type Combination".to_string(),
|
||||||
|
TypeSource::Error(_) => "Error Getting Data Type".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The type to display in the node row.
|
||||||
|
pub fn resolved_type_node_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
TypeSource::Compiled(compiled_type) => compiled_type.nested_type_name().to_string(),
|
||||||
|
TypeSource::TaggedValue(value_type) => value_type.nested_type_name().to_string(),
|
||||||
TypeSource::Unknown => "Unknown".to_string(),
|
TypeSource::Unknown => "Unknown".to_string(),
|
||||||
|
TypeSource::Invalid => "Invalid".to_string(),
|
||||||
TypeSource::Error(_) => "Error".to_string(),
|
TypeSource::Error(_) => "Error".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeNetworkInterface {
|
impl NodeNetworkInterface {
|
||||||
|
fn input_has_error(&mut self, input_connector: &InputConnector, network_path: &[NodeId]) -> bool {
|
||||||
|
match input_connector {
|
||||||
|
InputConnector::Node { node_id, input_index } => {
|
||||||
|
let Some(implementation) = self.implementation(node_id, network_path) else {
|
||||||
|
log::error!("Could not get implementation in input_has_error");
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let node_path = [network_path, &[*node_id]].concat();
|
||||||
|
match implementation {
|
||||||
|
DocumentNodeImplementation::Network(_) => {
|
||||||
|
let Some(map) = self.outward_wires(&node_path) else { return false };
|
||||||
|
let Some(outward_wires) = map.get(&OutputConnector::Import(*input_index)) else { return false };
|
||||||
|
outward_wires.clone().iter().any(|connector| match connector {
|
||||||
|
InputConnector::Node { node_id, input_index } => self.input_has_error(&InputConnector::node(*node_id, *input_index), &node_path),
|
||||||
|
InputConnector::Export(_) => false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
DocumentNodeImplementation::ProtoNode(_) => self.resolved_types.node_graph_errors.iter().any(|error| error.node_path == node_path),
|
||||||
|
DocumentNodeImplementation::Extract => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InputConnector::Export(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the [`TypeSource`] for any InputConnector.
|
/// Get the [`TypeSource`] for any InputConnector.
|
||||||
/// If the input is not compiled, then an Unknown or default from the definition is returned.
|
/// If the input is not compiled, then an Unknown or default from the definition is returned.
|
||||||
pub fn input_type(&mut self, input_connector: &InputConnector, network_path: &[NodeId]) -> TypeSource {
|
pub fn input_type(&mut self, input_connector: &InputConnector, network_path: &[NodeId]) -> TypeSource {
|
||||||
@@ -109,25 +146,19 @@ impl NodeNetworkInterface {
|
|||||||
|
|
||||||
match input {
|
match input {
|
||||||
NodeInput::Node { node_id, output_index } => {
|
NodeInput::Node { node_id, output_index } => {
|
||||||
let input_type = self.output_type(&OutputConnector::node(*node_id, *output_index), network_path);
|
let output_connector = OutputConnector::node(*node_id, *output_index);
|
||||||
if input_type == TypeSource::Unknown {
|
// First check if there is an error with this node or any protonodes it is connected to
|
||||||
// If we are trying to get the input type of an unknown node, check if it has a reference to its definition and use that input type
|
if self.input_has_error(input_connector, network_path) {
|
||||||
if let InputConnector::Node { node_id, input_index } = input_connector {
|
return TypeSource::Invalid;
|
||||||
if let Some(definition) = self.get_node_definition(node_id, network_path) {
|
|
||||||
if let Some(value) = definition.node_template.document_node.inputs.get(*input_index).and_then(|input| input.as_value()) {
|
|
||||||
return TypeSource::DocumentNodeDefinition(value.ty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
input_type
|
self.output_type(&output_connector, network_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeInput::Value { tagged_value, .. } => TypeSource::TaggedValue(tagged_value.ty()),
|
NodeInput::Value { tagged_value, .. } => TypeSource::TaggedValue(tagged_value.ty()),
|
||||||
NodeInput::Import { import_index, .. } => {
|
NodeInput::Import { import_index, .. } => {
|
||||||
// Get the input type of the encapsulating node input
|
// Get the input type of the encapsulating node input
|
||||||
let Some((encapsulating_node, encapsulating_path)) = network_path.split_last() else {
|
let Some((encapsulating_node, encapsulating_path)) = network_path.split_last() else {
|
||||||
return TypeSource::Error("Could not get type of import in document network");
|
return TypeSource::Error("Could not get type of import in document network since it has no imports");
|
||||||
};
|
};
|
||||||
self.input_type(&InputConnector::node(*encapsulating_node, *import_index), encapsulating_path)
|
self.input_type(&InputConnector::node(*encapsulating_node, *import_index), encapsulating_path)
|
||||||
}
|
}
|
||||||
@@ -142,20 +173,16 @@ impl NodeNetworkInterface {
|
|||||||
let guaranteed_type = match self.input_type(input_connector, network_path) {
|
let guaranteed_type = match self.input_type(input_connector, network_path) {
|
||||||
TypeSource::Compiled(compiled) => compiled,
|
TypeSource::Compiled(compiled) => compiled,
|
||||||
TypeSource::TaggedValue(value) => value,
|
TypeSource::TaggedValue(value) => value,
|
||||||
TypeSource::DocumentNodeDefinition(definition) => definition,
|
TypeSource::Unknown | TypeSource::Invalid => {
|
||||||
TypeSource::Unknown => {
|
let mut ret = concrete!(());
|
||||||
let mut valid_types = self.potential_valid_input_types(input_connector, network_path);
|
if let InputConnector::Node { node_id, input_index } = input_connector {
|
||||||
|
if let Some(definition) = self.get_node_definition(node_id, network_path) {
|
||||||
match valid_types.pop() {
|
if let Some(value) = definition.node_template.document_node.inputs.get(*input_index).and_then(|input| input.as_value()) {
|
||||||
Some(valid_type) => valid_type,
|
ret = value.ty();
|
||||||
None => {
|
|
||||||
match self.random_type_for_connector(input_connector, network_path) {
|
|
||||||
Some(random_type) => random_type,
|
|
||||||
// If there are no connected protonodes then we give up and return the empty type
|
|
||||||
None => concrete!(()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
TypeSource::Error(e) => {
|
TypeSource::Error(e) => {
|
||||||
log::error!("Error getting tagged_value_from_input for {input_connector:?} {e}");
|
log::error!("Error getting tagged_value_from_input for {input_connector:?} {e}");
|
||||||
@@ -172,18 +199,18 @@ impl NodeNetworkInterface {
|
|||||||
return vec![graph_craft::generic!(T)];
|
return vec![graph_craft::generic!(T)];
|
||||||
};
|
};
|
||||||
let Some(implementation) = self.implementation(node_id, network_path) else {
|
let Some(implementation) = self.implementation(node_id, network_path) else {
|
||||||
log::error!("Could not get node implementation in valid_input_types");
|
log::error!("Could not get node implementation in potential_valid_input_types");
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
};
|
};
|
||||||
match implementation {
|
match implementation {
|
||||||
DocumentNodeImplementation::Network(_) => {
|
DocumentNodeImplementation::Network(_) => {
|
||||||
let nested_path = [network_path, &[*node_id]].concat();
|
let nested_path = [network_path, &[*node_id]].concat();
|
||||||
let Some(outward_wires) = self.outward_wires(&nested_path) else {
|
let Some(outward_wires) = self.outward_wires(&nested_path) else {
|
||||||
log::error!("Could not get outward wires in valid_input_types");
|
log::error!("Could not get outward wires in potential_valid_input_types");
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
};
|
};
|
||||||
let Some(inputs_from_import) = outward_wires.get(&OutputConnector::Import(*input_index)) else {
|
let Some(inputs_from_import) = outward_wires.get(&OutputConnector::Import(*input_index)) else {
|
||||||
log::error!("Could not get inputs from import in valid_input_types");
|
log::error!("Could not get inputs from import in potential_valid_input_types");
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -201,7 +228,7 @@ impl NodeNetworkInterface {
|
|||||||
}
|
}
|
||||||
DocumentNodeImplementation::ProtoNode(proto_node_identifier) => {
|
DocumentNodeImplementation::ProtoNode(proto_node_identifier) => {
|
||||||
let Some(implementations) = NODE_REGISTRY.get(proto_node_identifier) else {
|
let Some(implementations) = NODE_REGISTRY.get(proto_node_identifier) else {
|
||||||
log::error!("Protonode {proto_node_identifier:?} not found in registry");
|
log::error!("Protonode {proto_node_identifier:?} not found in registry in potential_valid_input_types");
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
};
|
};
|
||||||
let number_of_inputs = self.number_of_inputs(node_id, network_path);
|
let number_of_inputs = self.number_of_inputs(node_id, network_path);
|
||||||
@@ -230,13 +257,13 @@ impl NodeNetworkInterface {
|
|||||||
match input_connector {
|
match input_connector {
|
||||||
InputConnector::Node { node_id, input_index } => {
|
InputConnector::Node { node_id, input_index } => {
|
||||||
let Some(implementation) = self.implementation(node_id, network_path) else {
|
let Some(implementation) = self.implementation(node_id, network_path) else {
|
||||||
return Err(format!("Could not get node implementation for {:?} {} in valid_input_types", network_path, *node_id));
|
return Err(format!("Could not get node implementation for {:?} {} in complete_valid_input_types", network_path, *node_id));
|
||||||
};
|
};
|
||||||
match implementation {
|
match implementation {
|
||||||
DocumentNodeImplementation::Network(_) => self.valid_output_types(&OutputConnector::Import(input_connector.input_index()), &[network_path, &[*node_id]].concat()),
|
DocumentNodeImplementation::Network(_) => self.valid_output_types(&OutputConnector::Import(input_connector.input_index()), &[network_path, &[*node_id]].concat()),
|
||||||
DocumentNodeImplementation::ProtoNode(proto_node_identifier) => {
|
DocumentNodeImplementation::ProtoNode(proto_node_identifier) => {
|
||||||
let Some(implementations) = NODE_REGISTRY.get(proto_node_identifier) else {
|
let Some(implementations) = NODE_REGISTRY.get(proto_node_identifier) else {
|
||||||
return Err(format!("Protonode {proto_node_identifier:?} not found in registry"));
|
return Err(format!("Protonode {proto_node_identifier:?} not found in registry in complete_valid_input_types"));
|
||||||
};
|
};
|
||||||
let valid_output_types = match self.valid_output_types(&OutputConnector::node(*node_id, 0), network_path) {
|
let valid_output_types = match self.valid_output_types(&OutputConnector::node(*node_id, 0), network_path) {
|
||||||
Ok(valid_types) => valid_types,
|
Ok(valid_types) => valid_types,
|
||||||
@@ -273,9 +300,8 @@ impl NodeNetworkInterface {
|
|||||||
Some((encapsulating_node, encapsulating_path)) => self.valid_output_types(&OutputConnector::node(*encapsulating_node, *export_index), encapsulating_path),
|
Some((encapsulating_node, encapsulating_path)) => self.valid_output_types(&OutputConnector::node(*encapsulating_node, *export_index), encapsulating_path),
|
||||||
None => {
|
None => {
|
||||||
// Valid types for the export are all types that can be fed into the render node
|
// Valid types for the export are all types that can be fed into the render node
|
||||||
// TODO: Use ::IDENTIFIER
|
let render_node = graphene_std::render_node::render::IDENTIFIER;
|
||||||
let render_node = "graphene_std::wasm_application_io::RenderNode";
|
let Some(implementations) = NODE_REGISTRY.get(&render_node) else {
|
||||||
let Some(implementations) = NODE_REGISTRY.get(&ProtoNodeIdentifier::new(render_node)) else {
|
|
||||||
return Err(format!("Protonode {render_node:?} not found in registry"));
|
return Err(format!("Protonode {render_node:?} not found in registry"));
|
||||||
};
|
};
|
||||||
Ok(implementations.iter().map(|(types, _)| types.inputs[1].clone()).collect())
|
Ok(implementations.iter().map(|(types, _)| types.inputs[1].clone()).collect())
|
||||||
@@ -303,19 +329,24 @@ impl NodeNetworkInterface {
|
|||||||
}
|
}
|
||||||
OutputConnector::Import(import_index) => {
|
OutputConnector::Import(import_index) => {
|
||||||
let Some((encapsulating_node, encapsulating_path)) = network_path.split_last() else {
|
let Some((encapsulating_node, encapsulating_path)) = network_path.split_last() else {
|
||||||
return TypeSource::Error("Cannot get import type in document network");
|
return TypeSource::Error("Cannot get import type in document network since it has no imports");
|
||||||
};
|
};
|
||||||
self.input_type(&InputConnector::node(*encapsulating_node, *import_index), encapsulating_path)
|
let mut input_type = self.input_type(&InputConnector::node(*encapsulating_node, *import_index), encapsulating_path);
|
||||||
|
if matches!(input_type, TypeSource::Invalid) {
|
||||||
|
input_type = TypeSource::Unknown
|
||||||
|
}
|
||||||
|
return input_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The valid output types are all types that are valid for each downstream connection
|
|
||||||
pub fn valid_output_types(&mut self, output_connector: &OutputConnector, network_path: &[NodeId]) -> Result<Vec<Type>, String> {
|
/// The valid output types are all types that are valid for each downstream connection.
|
||||||
|
fn valid_output_types(&mut self, output_connector: &OutputConnector, network_path: &[NodeId]) -> Result<Vec<Type>, String> {
|
||||||
let Some(outward_wires) = self.outward_wires(&network_path) else {
|
let Some(outward_wires) = self.outward_wires(&network_path) else {
|
||||||
return Err("Could not get outward wires in valid_input_types".to_string());
|
return Err("Could not get outward wires in valid_output_types".to_string());
|
||||||
};
|
};
|
||||||
let Some(inputs_from_import) = outward_wires.get(output_connector) else {
|
let Some(inputs_from_import) = outward_wires.get(output_connector) else {
|
||||||
return Err("Could not get inputs from import in valid_input_types".to_string());
|
return Err("Could not get inputs from import in valid_output_types".to_string());
|
||||||
};
|
};
|
||||||
|
|
||||||
let intersection = inputs_from_import
|
let intersection = inputs_from_import
|
||||||
@@ -330,54 +361,4 @@ impl NodeNetworkInterface {
|
|||||||
|
|
||||||
Ok(intersection.into_iter().collect::<Vec<_>>())
|
Ok(intersection.into_iter().collect::<Vec<_>>())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs a downstream iteration from an input connector to the next protonode and selects a random type from its implementations.
|
|
||||||
pub fn random_type_for_connector(&mut self, input_connector: &InputConnector, network_path: &[NodeId]) -> Option<Type> {
|
|
||||||
match input_connector {
|
|
||||||
InputConnector::Node { node_id, input_index } => {
|
|
||||||
let Some(implementation) = self.implementation(node_id, network_path) else {
|
|
||||||
log::error!("Could not get node {node_id} in random_downstream_protonode_from_connector");
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
match implementation {
|
|
||||||
DocumentNodeImplementation::Network(_) => {
|
|
||||||
let Some(outward_wires) = self.outward_wires(&network_path) else {
|
|
||||||
log::error!("Could not get outward wires in random_downstream_protonode_from_connector");
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
let Some(inputs_from_import) = outward_wires.get(&OutputConnector::Import(*input_index)) else {
|
|
||||||
log::error!("Could not get inputs from import in valid_input_types");
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
let Some(first_input) = inputs_from_import.first().cloned() else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
self.random_type_for_connector(&first_input, &[network_path, &[*node_id]].concat())
|
|
||||||
}
|
|
||||||
DocumentNodeImplementation::ProtoNode(proto_node_identifier) => {
|
|
||||||
let Some(implementations) = NODE_REGISTRY.get(proto_node_identifier) else {
|
|
||||||
log::error!("Protonode {proto_node_identifier:?} not found in registry");
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
implementations.keys().min().and_then(|node_io| node_io.inputs.get(input_connector.input_index())).cloned()
|
|
||||||
}
|
|
||||||
DocumentNodeImplementation::Extract => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InputConnector::Export(export_index) => network_path.split_last().and_then(|(encapsulating_node, encapsulating_path)| {
|
|
||||||
let Some(outward_wires) = self.outward_wires(&encapsulating_path) else {
|
|
||||||
log::error!("Could not get outward wires in random_downstream_protonode_from_connector export");
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
let Some(inputs_from_import) = outward_wires.get(&OutputConnector::node(*encapsulating_node, *export_index)) else {
|
|
||||||
log::error!("Could not get inputs from import in valid_input_types");
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
let Some(first_input) = inputs_from_import.first().cloned() else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
self.random_type_for_connector(&first_input, encapsulating_path)
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,6 +129,8 @@
|
|||||||
--color-data-gradient-dim: #6c489b;
|
--color-data-gradient-dim: #6c489b;
|
||||||
--color-data-typography: #eea7a7;
|
--color-data-typography: #eea7a7;
|
||||||
--color-data-typography-dim: #955252;
|
--color-data-typography-dim: #955252;
|
||||||
|
--color-data-invalid: var(--color-error-red);
|
||||||
|
--color-data-invalid-dim: color-mix(in srgb, var(--color-error-red) 75%, black);
|
||||||
|
|
||||||
--color-none: white;
|
--color-none: white;
|
||||||
--color-none-repeat: no-repeat;
|
--color-none-repeat: no-repeat;
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ export type ContextMenuInformation = {
|
|||||||
contextMenuData: "CreateNode" | { type: "CreateNode"; compatibleType: string } | { nodeId: bigint; currentlyIsNode: boolean };
|
contextMenuData: "CreateNode" | { type: "CreateNode"; compatibleType: string } | { nodeId: bigint; currentlyIsNode: boolean };
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FrontendGraphDataType = "General" | "Number" | "Artboard" | "Graphic" | "Raster" | "Vector" | "Color";
|
export type FrontendGraphDataType = "General" | "Number" | "Artboard" | "Graphic" | "Raster" | "Vector" | "Color" | "Invalid";
|
||||||
|
|
||||||
export class FrontendGraphInput {
|
export class FrontendGraphInput {
|
||||||
readonly dataType!: FrontendGraphDataType;
|
readonly dataType!: FrontendGraphDataType;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ macro_rules! fn_type_fut {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Default, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Hash, Default, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct NodeIOTypes {
|
pub struct NodeIOTypes {
|
||||||
pub call_argument: Type,
|
pub call_argument: Type,
|
||||||
pub return_value: Type,
|
pub return_value: Type,
|
||||||
@@ -229,20 +229,8 @@ impl PartialEq for TypeDescriptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for TypeDescriptor {
|
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
||||||
self.name.cmp(&other.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for TypeDescriptor {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Graph runtime type information used for type inference.
|
/// Graph runtime type information used for type inference.
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, specta::Type, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Hash, specta::Type, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
/// A wrapper for some type variable used within the inference system. Resolved at inference time and replaced with a concrete 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>),
|
Generic(Cow<'static, str>),
|
||||||
@@ -364,6 +352,15 @@ impl Type {
|
|||||||
_ => Cow::Owned(self.to_string()),
|
_ => Cow::Owned(self.to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn nested_type_name(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Type::Generic(name) => name.as_ref(),
|
||||||
|
Type::Concrete(type_descriptor) => type_descriptor.name.as_ref(),
|
||||||
|
Type::Fn(_, nested) => nested.nested_type_name(),
|
||||||
|
Type::Future(nested) => nested.nested_type_name(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_type(ty: &str) -> String {
|
fn format_type(ty: &str) -> String {
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc<WasmEdito
|
|||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
// Keep this in sync with the protonode in valid_input_types
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
call_argument: concrete!(Context),
|
call_argument: concrete!(Context),
|
||||||
inputs: vec![NodeInput::scope("editor-api"), NodeInput::node(NodeId(2), 0), NodeInput::node(NodeId(1), 0)],
|
inputs: vec![NodeInput::scope("editor-api"), NodeInput::node(NodeId(2), 0), NodeInput::node(NodeId(1), 0)],
|
||||||
@@ -61,7 +62,6 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc<WasmEdito
|
|||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
// Keep this in sync with the protonode id in valid_input_types for the document network export
|
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
call_argument: concrete!(graphene_std::application_io::RenderConfig),
|
call_argument: concrete!(graphene_std::application_io::RenderConfig),
|
||||||
inputs: vec![NodeInput::node(NodeId(3), 0)],
|
inputs: vec![NodeInput::node(NodeId(3), 0)],
|
||||||
|
|||||||
Reference in New Issue
Block a user