mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-03 21:08:18 +00:00
Node network subgraph editing (#1750)
* Breadcrumb visualization, nested network consistency, create definitions for Merge internal nodes * Add index to network inputs, remove imports usage from flatten network * Replace NodeOutput with NodeInput::Node * Fully remove imports field, remove unnecessary identity nodes, move Output node to encapsulating network * Replace previous_outputs with root_node, fix adding artboard/layer to empty network * Import/Export UI nodes * Display input/output types dynamically from compiled network * Add LayerNodeIdentifer::ROOT_PARENT * Prevent .to_node() on ROOT_PARENT * Separate NodeGraphMessage and GraphOperationMessage * General bug fixes with nested networks * Change layer color, various bug fixes and improvements * Fix disconnect and set node input for proto nodes and UI export node * Dashed line to export for previewed node * Fix deleting proto nodes and nodes that feed into export * Allow modifications to nodes outside of nested network * Get network from Node Id parameter * Change root_node to previous_root_node * Get TaggedValue from proto node implementation type when disconnecting * Improve preview functionality and state * Artboard position and delete children fix * Name inputs/outputs based on DocumentNodeDefinition or type, fix new artboard/layer insertion * replace "Link" with "Wire", adjust previewing * Various bug fixes and improvements * Modify Sample and Poisson-Disk points, fix incorrect input index and deleting currently viewed node * Open demo artwork * Fix opening already upgraded documents and refactor FrontendGraphDataType usages * Fix deleting within network and other bugs * Get default node input from compiled network when copying, fix previews, tests, demo artwork * Code cleanup * Hide EditorApi and add a comment describing unresolved Import node input types * Code review * Replace placeholder ROOT_PARENT NodeId with std::u64::MAX * Breadcrumb padding --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
e4d3faa52a
commit
6d74abb4de
77 changed files with 3924 additions and 2327 deletions
|
@ -85,6 +85,8 @@ impl DynamicExecutor {
|
|||
|
||||
pub fn document_node_types(&self) -> ResolvedDocumentNodeTypes {
|
||||
let mut resolved_document_node_types = ResolvedDocumentNodeTypes::default();
|
||||
// TODO: https://github.com/GraphiteEditor/Graphite/issues/1767
|
||||
// TODO: Non exposed inputs are not added to the inputs_source_map, so they are not included in the resolved_document_node_types. The type is still available in the typing_context. This only affects the UI-only "Import" node.
|
||||
for (source, &(protonode_id, protonode_index)) in self.tree.inputs_source_map() {
|
||||
let Some(node_io) = self.typing_context.type_of(protonode_id) else { continue };
|
||||
let Some(ty) = [&node_io.input].into_iter().chain(&node_io.parameters).nth(protonode_index) else {
|
||||
|
@ -206,7 +208,7 @@ impl BorrowTree {
|
|||
ConstructionArgs::Value(value) => {
|
||||
let upcasted = UpcastNode::new(value.to_owned());
|
||||
let node = Box::new(upcasted) as TypeErasedBox<'_>;
|
||||
let node = NodeContainer::new(node);
|
||||
let node: std::rc::Rc<NodeContainer> = NodeContainer::new(node);
|
||||
self.store_node(node, id);
|
||||
}
|
||||
ConstructionArgs::Inline(_) => unimplemented!("Inline nodes are not supported yet"),
|
||||
|
@ -242,7 +244,7 @@ mod test {
|
|||
let mut tree = BorrowTree::default();
|
||||
let val_1_protonode = ProtoNode::value(ConstructionArgs::Value(TaggedValue::U32(2u32)), vec![]);
|
||||
let context = TypingContext::default();
|
||||
let future = tree.push_node(NodeId(0), val_1_protonode, &context); //.await.unwrap();
|
||||
let future = tree.push_node(NodeId(0), val_1_protonode, &context);
|
||||
futures::executor::block_on(future).unwrap();
|
||||
let _node = tree.get(NodeId(0)).unwrap();
|
||||
let result = futures::executor::block_on(tree.eval(NodeId(0), ()));
|
||||
|
|
|
@ -15,14 +15,13 @@ mod tests {
|
|||
|
||||
fn add_network() -> NodeNetwork {
|
||||
NodeNetwork {
|
||||
imports: vec![NodeId(0), NodeId(0)],
|
||||
exports: vec![NodeOutput::new(NodeId(1), 0)],
|
||||
exports: vec![NodeInput::node(NodeId(1), 0)],
|
||||
nodes: [
|
||||
(
|
||||
NodeId(0),
|
||||
DocumentNode {
|
||||
name: "Cons".into(),
|
||||
inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(&u32))],
|
||||
inputs: vec![NodeInput::network(concrete!(u32), 0), NodeInput::network(concrete!(&u32), 1)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::structural::ConsNode<_, _>")),
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -44,14 +43,13 @@ mod tests {
|
|||
}
|
||||
|
||||
let network = NodeNetwork {
|
||||
imports: vec![NodeId(0)],
|
||||
exports: vec![NodeOutput::new(NodeId(0), 0)],
|
||||
exports: vec![NodeInput::node(NodeId(0), 0)],
|
||||
nodes: [(
|
||||
NodeId(0),
|
||||
DocumentNode {
|
||||
name: "Inc".into(),
|
||||
inputs: vec![
|
||||
NodeInput::Network(concrete!(u32)),
|
||||
NodeInput::network(concrete!(u32), 0),
|
||||
NodeInput::Value {
|
||||
tagged_value: graph_craft::document::value::TaggedValue::U32(1u32),
|
||||
exposed: false,
|
||||
|
@ -84,15 +82,14 @@ mod tests {
|
|||
use graph_craft::*;
|
||||
|
||||
let network = NodeNetwork {
|
||||
imports: vec![NodeId(0)],
|
||||
exports: vec![NodeOutput::new(NodeId(1), 0)],
|
||||
exports: vec![NodeInput::node(NodeId(1), 0)],
|
||||
nodes: [
|
||||
// Simple identity node taking a number as input from outside the graph
|
||||
(
|
||||
NodeId(0),
|
||||
DocumentNode {
|
||||
name: "id".into(),
|
||||
inputs: vec![NodeInput::Network(concrete!(u32))],
|
||||
inputs: vec![NodeInput::network(concrete!(u32), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode")),
|
||||
..Default::default()
|
||||
},
|
||||
|
|
|
@ -100,7 +100,7 @@ macro_rules! async_node {
|
|||
graphene_std::any::PanicNode::<$arg, core::pin::Pin<Box<dyn core::future::Future<Output = $type>>>>::new()
|
||||
),*);
|
||||
// TODO: Propagate the future type through the node graph
|
||||
//let params = vec![$(Type::Fn(Box::new(concrete!(())), Box::new(Type::Future(Box::new(concrete!($type)))))),*];
|
||||
// let params = vec![$(Type::Fn(Box::new(concrete!(())), Box::new(Type::Future(Box::new(concrete!($type)))))),*];
|
||||
let params = vec![$(fn_type!($arg, $type)),*];
|
||||
let mut node_io = NodeIO::<'_, $input>::to_node_io(&node, params);
|
||||
node_io.input = concrete!(<$input as StaticType>::Static);
|
||||
|
@ -177,10 +177,10 @@ macro_rules! raster_node {
|
|||
}};
|
||||
}
|
||||
|
||||
//TODO: turn into hashmap
|
||||
// TODO: turn into hashmap
|
||||
fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeConstructor>> {
|
||||
let node_types: Vec<Vec<(ProtoNodeIdentifier, NodeConstructor, NodeIOTypes)>> = vec![
|
||||
//register_node!(graphene_core::ops::IdentityNode, input: Any<'_>, params: []),
|
||||
// register_node!(graphene_core::ops::IdentityNode, input: Any<'_>, params: []),
|
||||
vec![(
|
||||
ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode"),
|
||||
|_| Box::pin(async move { FutureWrapperNode::new(IdentityNode::new()).into_type_erased() }),
|
||||
|
@ -400,7 +400,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
|||
Box::pin(async move {
|
||||
let document_node: DowncastBothNode<(), graph_craft::document::DocumentNode> = DowncastBothNode::new(args[0].clone());
|
||||
let editor_api: DowncastBothNode<(), WasmEditorApi> = DowncastBothNode::new(args[1].clone());
|
||||
//let document_node = ClonedNode::new(document_node.eval(()));
|
||||
// let document_node = ClonedNode::new(document_node.eval(()));
|
||||
let node = graphene_std::gpu_nodes::MapGpuNode::new(document_node, editor_api);
|
||||
let any: DynAnyNode<ImageFrame<Color>, _, _> = graphene_std::any::DynAnyNode::new(node);
|
||||
any.into_type_erased()
|
||||
|
@ -700,7 +700,6 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
|||
async_node!(graphene_std::wasm_application_io::RenderNode<_, _, _>, input: WasmEditorApi, output: RenderOutput, fn_params: [Footprint => Vec<Color>, () => Arc<WasmSurfaceHandle>]),
|
||||
async_node!(graphene_core::transform::TransformNode<_, _, _, _, _, _>, input: Footprint, output: VectorData, fn_params: [Footprint => VectorData, () => DVec2, () => f64, () => DVec2, () => DVec2, () => DVec2]),
|
||||
async_node!(graphene_core::transform::TransformNode<_, _, _, _, _, _>, input: Footprint, output: WasmSurfaceHandleFrame, fn_params: [Footprint => WasmSurfaceHandleFrame, () => DVec2, () => f64, () => DVec2, () => DVec2, () => DVec2]),
|
||||
async_node!(graphene_core::transform::TransformNode<_, _, _, _, _, _>, input: Footprint, output: WasmSurfaceHandleFrame, fn_params: [Footprint => WasmSurfaceHandleFrame, () => DVec2, () => f64, () => DVec2, () => DVec2, () => DVec2]),
|
||||
async_node!(graphene_core::transform::TransformNode<_, _, _, _, _, _>, input: Footprint, output: ImageFrame<Color>, fn_params: [Footprint => ImageFrame<Color>, () => DVec2, () => f64, () => DVec2, () => DVec2, () => DVec2]),
|
||||
async_node!(graphene_core::transform::TransformNode<_, _, _, _, _, _>, input: Footprint, output: GraphicGroup, fn_params: [Footprint => GraphicGroup, () => DVec2, () => f64, () => DVec2, () => DVec2, () => DVec2]),
|
||||
register_node!(graphene_core::transform::SetTransformNode<_>, input: VectorData, params: [VectorData]),
|
||||
|
@ -800,7 +799,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
|||
register_node!(graphene_core::text::TextGeneratorNode<_, _, _>, input: WasmEditorApi, params: [String, graphene_core::text::Font, f64]),
|
||||
register_node!(graphene_std::brush::VectorPointsNode, input: VectorData, params: []),
|
||||
register_node!(graphene_core::ExtractImageFrame, input: WasmEditorApi, params: []),
|
||||
async_node!(graphene_core::ConstructLayerNode<_, _>, input: Footprint, output: GraphicGroup, fn_params: [Footprint => graphene_core::GraphicElement, Footprint => GraphicGroup]),
|
||||
async_node!(graphene_core::ConstructLayerNode<_, _>, input: Footprint, output: GraphicGroup, fn_params: [Footprint => GraphicGroup, Footprint => graphene_core::GraphicElement]),
|
||||
register_node!(graphene_core::ToGraphicElementNode, input: graphene_core::vector::VectorData, params: []),
|
||||
register_node!(graphene_core::ToGraphicElementNode, input: ImageFrame<Color>, params: []),
|
||||
register_node!(graphene_core::ToGraphicElementNode, input: GraphicGroup, params: []),
|
||||
|
@ -810,7 +809,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
|||
register_node!(graphene_core::ToGraphicGroupNode, input: GraphicGroup, params: []),
|
||||
register_node!(graphene_core::ToGraphicGroupNode, input: Artboard, params: []),
|
||||
async_node!(graphene_core::ConstructArtboardNode<_, _, _, _, _>, input: Footprint, output: Artboard, fn_params: [Footprint => GraphicGroup, () => glam::IVec2, () => glam::IVec2, () => Color, () => bool]),
|
||||
async_node!(graphene_core::AddArtboardNode<_, _>, input: Footprint, output: ArtboardGroup, fn_params: [Footprint => Artboard, Footprint => ArtboardGroup]),
|
||||
async_node!(graphene_core::AddArtboardNode<_, _>, input: Footprint, output: ArtboardGroup, fn_params: [Footprint => ArtboardGroup, Footprint => Artboard]),
|
||||
];
|
||||
let mut map: HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeConstructor>> = HashMap::new();
|
||||
for (id, c, types) in node_types.into_iter().flatten() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue