From 6d1e8d1b48f5a60d702632179aa06cc965200d97 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Mon, 12 Oct 2026 12:49:34 -0700 Subject: [PATCH 1/4] Rename the Properties panel to the Inspector throughout the code --- demo-artwork/marbled-mandelbrot.graphite | 2 +- editor/src/dispatcher.rs | 6 +- .../messages/layout/layout_message_handler.rs | 2 +- .../layout/utility_types/layout_widget.rs | 36 +-- .../utility_types/widgets/button_widgets.rs | 2 +- .../menu_bar/menu_bar_message_handler.rs | 12 +- .../portfolio/document/document_message.rs | 8 +- .../document/document_message_handler.rs | 86 +++--- .../graph_operation_message_handler.rs | 2 +- .../document/graph_operation/utility_types.rs | 10 +- .../inspector_message.rs} | 4 +- .../inspector/inspector_message_handler.rs | 77 ++++++ .../portfolio/document/inspector/mod.rs | 7 + editor/src/messages/portfolio/document/mod.rs | 2 +- .../node_graph/document_node_definitions.rs | 261 +++++++++--------- .../document_node_derive.rs | 4 +- .../portfolio/document/node_graph/mod.rs | 2 +- .../node_graph/node_graph_message_handler.rs | 74 ++--- .../{node_properties.rs => node_inspector.rs} | 246 ++++++++--------- .../document/properties_panel/mod.rs | 7 - .../properties_panel_message_handler.rs | 77 ------ .../network_interface/frontend.rs | 2 +- .../network_interface/mutations.rs | 2 +- .../network_interface/queries.rs | 2 +- .../network_interface/store/cursor.rs | 4 +- .../network_interface/template.rs | 6 +- .../utility_types/network_interface/types.rs | 44 +-- .../utility_types/network_interface/view.rs | 2 +- .../messages/portfolio/document_migration.rs | 20 +- .../portfolio/fonts/fonts_message_handler.rs | 2 +- .../portfolio/portfolio_message_handler.rs | 12 +- .../src/messages/portfolio/utility_types.rs | 19 +- .../portfolio/workspace/workspace_message.rs | 2 +- .../workspace/workspace_message_handler.rs | 20 +- editor/src/messages/prelude.rs | 2 +- .../tool/tool_messages/artboard_tool.rs | 2 +- .../tool/tool_messages/gradient_tool.rs | 18 +- frontend/src/components/Editor.svelte | 2 +- frontend/src/components/README.md | 2 +- .../{Properties.svelte => Inspector.svelte} | 18 +- ...idgetSection.svelte => NodeSection.svelte} | 36 +-- .../components/widgets/WidgetLayout.svelte | 6 +- frontend/src/components/window/Panel.svelte | 4 +- frontend/src/stores/portfolio.ts | 8 +- frontend/src/utility-functions/widgets.ts | 2 +- frontend/wrapper/src/editor_commands.rs | 12 +- node-graph/README.md | 12 +- node-graph/graph-craft/src/document.rs | 2 +- .../libraries/core-types/src/registry.rs | 2 +- node-graph/node-macro/src/codegen.rs | 4 +- node-graph/node-macro/src/parsing.rs | 38 +-- node-graph/nodes/gcore/src/memo.rs | 2 +- node-graph/nodes/raster/src/adjustments.rs | 28 +- node-graph/nodes/raster/src/std_nodes.rs | 26 +- node-graph/nodes/repeat/src/repeat_nodes.rs | 2 +- node-graph/nodes/text/src/lib.rs | 4 +- .../nodes/vector/src/generator_nodes.rs | 6 +- node-graph/nodes/vector/src/vector_nodes.rs | 8 +- node-graph/preprocessor/src/lib.rs | 2 +- website/content/features.md | 4 +- website/content/learn/_outline_draft.md | 6 +- website/content/learn/interface/_index.md | 2 +- website/content/learn/interface/menu-bar.md | 2 +- .../introduction/features-and-limitations.md | 2 +- 64 files changed, 673 insertions(+), 655 deletions(-) rename editor/src/messages/portfolio/document/{properties_panel/properties_panel_message.rs => inspector/inspector_message.rs} (60%) create mode 100644 editor/src/messages/portfolio/document/inspector/inspector_message_handler.rs create mode 100644 editor/src/messages/portfolio/document/inspector/mod.rs rename editor/src/messages/portfolio/document/node_graph/{node_properties.rs => node_inspector.rs} (94%) delete mode 100644 editor/src/messages/portfolio/document/properties_panel/mod.rs delete mode 100644 editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs rename frontend/src/components/panels/{Properties.svelte => Inspector.svelte} (91%) rename frontend/src/components/widgets/{WidgetSection.svelte => NodeSection.svelte} (91%) diff --git a/demo-artwork/marbled-mandelbrot.graphite b/demo-artwork/marbled-mandelbrot.graphite index f94a5cbe23e..9c81ad2aa91 100644 --- a/demo-artwork/marbled-mandelbrot.graphite +++ b/demo-artwork/marbled-mandelbrot.graphite @@ -1 +1 @@ -{"network_interface":{"network":{"exports":[{"Node":{"node_id":12241147352993594415,"output_index":0}}],"nodes":[[80924370013313595,{"inputs":[{"Node":{"node_id":6029481207635803402,"output_index":0}},{"Value":{"tagged_value":{"GradientRamp":{"stops":{"color":[{"red":0.06469504,"green":0.0,"blue":0.0755814,"alpha":1.0,"linear":true},{"red":0.016644126,"green":0.13212071,"blue":0.62523156,"alpha":1.0,"linear":true},{"red":1.0,"green":0.8708812,"blue":0.3485102,"alpha":1.0,"linear":true},{"red":0.30054384,"green":0.8468733,"blue":0.8468733,"alpha":0.01,"linear":true}],"position":[0.0,0.12704918032786883,0.5,1.0],"midpoint":[0.5,0.5,0.5,0.5]},"gradient_space":"RgbGamma"}},"exposed":false}},{"Value":{"tagged_value":{"Bool":false},"exposed":false}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"raster_nodes::adjustments::GradientMapNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[3606681156406984991,{"inputs":[{"Node":{"node_id":6323350524796370485,"output_index":0}},{"Value":{"tagged_value":{"GradientRamp":{"stops":{"color":[{"red":0.0,"green":0.0,"blue":0.0,"alpha":1.0,"linear":true},{"red":0.04631017,"green":0.0,"blue":0.0076861563,"alpha":1.0,"linear":true},{"red":0.83939683,"green":0.7249875,"blue":0.27055356,"alpha":1.0,"linear":true},{"red":0.025397457,"green":0.3485102,"blue":0.3485102,"alpha":1.0,"linear":true},{"red":0.01102731,"green":0.09231063,"blue":0.09231063,"alpha":1.0,"linear":true}],"position":[0.0,0.3237704918032787,0.5655737704918032,0.8155737704918032,1.0],"midpoint":[0.5,0.5,0.5,0.5,0.5]},"gradient_space":"RgbGamma"}},"exposed":false}},{"Value":{"tagged_value":{"Bool":true},"exposed":false}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"raster_nodes::adjustments::GradientMapNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[4388711862172196665,{"inputs":[],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"raster_nodes::std_nodes::MandelbrotNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"FOOTPRINT","inject":""}}],[6029481207635803402,{"inputs":[{"Node":{"node_id":4388711862172196665,"output_index":0}},{"Value":{"tagged_value":{"DVec2":[0.0,0.0]},"exposed":false}},{"Value":{"tagged_value":{"Number":0.0},"exposed":false}},{"Value":{"tagged_value":{"DVec2":[1000.0,1000.0]},"exposed":false}},{"Value":{"tagged_value":{"DVec2":[0.0,0.0]},"exposed":false}},{"Value":{"tagged_value":{"DVec2":[0.0,0.0]},"exposed":false}},{"Value":{"tagged_value":{"Bool":true},"exposed":false}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":1,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[1,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Import":{"import_type":{"Concrete":{"name":"glam::f64::dvec2::DVec2"}},"import_index":1}},{"Import":{"import_type":{"Concrete":{"name":"f64"}},"import_index":2}},{"Import":{"import_type":{"Concrete":{"name":"glam::f64::dvec2::DVec2"}},"import_index":3}},{"Import":{"import_type":{"Concrete":{"name":"glam::f64::dvec2::DVec2"}},"import_index":4}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"transform_nodes::transform_nodes::TransformNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[6323350524796370485,{"inputs":[{"Value":{"tagged_value":"None","exposed":false}},{"Value":{"tagged_value":{"Bool":false},"exposed":false}},{"Value":{"tagged_value":{"Integer":0},"exposed":false}},{"Value":{"tagged_value":{"Number":35.0},"exposed":false}},{"Value":{"tagged_value":{"NoiseType":"OpenSimplex2"},"exposed":false}},{"Value":{"tagged_value":{"DomainWarpType":"OpenSimplex2"},"exposed":false}},{"Value":{"tagged_value":{"Number":100.0},"exposed":false}},{"Value":{"tagged_value":{"FractalType":"PingPong"},"exposed":false}},{"Value":{"tagged_value":{"Integer":3},"exposed":false}},{"Value":{"tagged_value":{"Number":2.0},"exposed":false}},{"Value":{"tagged_value":{"Number":0.5},"exposed":false}},{"Value":{"tagged_value":{"Number":0.0},"exposed":false}},{"Value":{"tagged_value":{"Number":2.0},"exposed":false}},{"Value":{"tagged_value":{"CellularDistanceFunction":"Hybrid"},"exposed":false}},{"Value":{"tagged_value":{"CellularReturnType":"CellValue"},"exposed":false}},{"Value":{"tagged_value":{"Number":1.0},"exposed":false}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"raster_nodes::std_nodes::NoisePatternNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"FOOTPRINT","inject":""}}],[6565638614909771142,{"inputs":[{"Node":{"node_id":7624113397561636853,"output_index":0}},{"Node":{"node_id":80924370013313595,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":5,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::AsGraphicNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[1,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":1}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::IntoGroupNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::PathOfSubgraphNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[3,{"inputs":[{"Node":{"node_id":1,"output_index":0}},{"Value":{"tagged_value":{"String":"editor:layer_path"},"exposed":false}},{"Node":{"node_id":2,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::WriteAttributeNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[4,{"inputs":[{"Node":{"node_id":3,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[5,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Node":{"node_id":4,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::ExtendNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[7624113397561636853,{"inputs":[{"Value":{"tagged_value":{"TypeDefault":{"List":{"Concrete":{"name":"graphic_types::graphic::Graphic"}}}},"exposed":true}},{"Node":{"node_id":3606681156406984991,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":5,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::AsGraphicNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[1,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":1}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::IntoGroupNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::PathOfSubgraphNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[3,{"inputs":[{"Node":{"node_id":1,"output_index":0}},{"Value":{"tagged_value":{"String":"editor:layer_path"},"exposed":false}},{"Node":{"node_id":2,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::WriteAttributeNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[4,{"inputs":[{"Node":{"node_id":3,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[5,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Node":{"node_id":4,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::ExtendNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[12241147352993594415,{"inputs":[{"Value":{"tagged_value":{"TypeDefault":{"List":{"Concrete":{"name":"graphic_types::artboard::Artboard"}}}},"exposed":true}},{"Node":{"node_id":6565638614909771142,"output_index":0}},{"Value":{"tagged_value":{"DVec2":[0.0,0.0]},"exposed":false}},{"Value":{"tagged_value":{"DVec2":[1000.0,1000.0]},"exposed":false}},{"Value":{"tagged_value":{"Color":{"red":0.0,"green":0.0,"blue":0.0,"alpha":1.0,"linear":true}},"exposed":false}},{"Value":{"tagged_value":{"Bool":true},"exposed":false}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":4,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Fn":[{"Concrete":{"name":"core::option::Option>"}},{"Generic":"T"}]},"import_index":1}},{"Import":{"import_type":{"Item":{"Concrete":{"name":"graph_craft::document::value::TaggedValue"}}},"import_index":2}},{"Import":{"import_type":{"Item":{"Concrete":{"name":"graph_craft::document::value::TaggedValue"}}},"import_index":3}},{"Import":{"import_type":{"Item":{"Concrete":{"name":"graph_craft::document::value::TaggedValue"}}},"import_index":4}},{"Import":{"import_type":{"Item":{"Concrete":{"name":"graph_craft::document::value::TaggedValue"}}},"import_index":5}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphic_nodes::artboard::CreateArtboardNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[1,{"inputs":[{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::PathOfSubgraphNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Value":{"tagged_value":{"String":"editor:layer_path"},"exposed":false}},{"Node":{"node_id":1,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::WriteAttributeNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[3,{"inputs":[{"Node":{"node_id":2,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[4,{"inputs":[{"Import":{"import_type":{"Fn":[{"Concrete":{"name":"core::option::Option>"}},{"List":{"Concrete":{"name":"graphic_types::artboard::Artboard"}}}]},"import_index":0}},{"Node":{"node_id":3,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::ExtendNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]},"network_metadata":{"persistent_metadata":{"reference":null,"node_metadata":[[80924370013313595,{"persistent_metadata":{"storage_id":null,"display_name":"Gradient Map","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Image","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Gradient","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Reverse","input_description":""}}],"output_names":["Image"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":null}}],[3606681156406984991,{"persistent_metadata":{"storage_id":null,"display_name":"Gradient Map","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Image","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Gradient","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Reverse","input_description":""}}],"output_names":["Image"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":null}}],[4388711862172196665,{"persistent_metadata":{"storage_id":null,"display_name":"Mandelbrot","input_metadata":[],"output_names":["Raster"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":null}}],[6029481207635803402,{"persistent_metadata":{"storage_id":null,"display_name":"Transform","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"is_integer":false,"unit":" px","x":"X","y":"Y"},"widget_override":"vec2","input_name":"Translation","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"transform_rotation","input_name":"Rotation","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"is_integer":false,"unit":"x","x":"W","y":"H"},"widget_override":"vec2","input_name":"Scale","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"transform_skew","input_name":"Skew","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"hidden","input_name":"Origin Offset","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":"hidden","input_name":"Scale Appearance","input_description":""}}],"output_names":["Data"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":{"persistent_metadata":{"reference":null,"node_metadata":[[0,{"persistent_metadata":{"storage_id":null,"display_name":"Monitor","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,0]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"storage_id":null,"display_name":"Transform","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[7,0]}}},"network_metadata":null}}]],"pinned_node_order":[],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[0.0,0.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,0.0,0.0],"node_graph_width":0.0}}}}}],[6323350524796370485,{"persistent_metadata":{"storage_id":null,"display_name":"Noise Pattern","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Spacer","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Clip","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Seed","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_scale","input_name":"Scale","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_noise_type","input_name":"Noise Type","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_domain_warp_type","input_name":"Domain Warp Type","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_domain_warp_amplitude","input_name":"Domain Warp Amplitude","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_fractal_type","input_name":"Fractal Type","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_fractal_octaves","input_name":"Fractal Octaves","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_fractal_lacunarity","input_name":"Fractal Lacunarity","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_fractal_gain","input_name":"Fractal Gain","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_fractal_weighted_strength","input_name":"Fractal Weighted Strength","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_ping_pong_strength","input_name":"Fractal Ping Pong Strength","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_cellular_distance_function","input_name":"Cellular Distance Function","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_cellular_return_type","input_name":"Cellular Return Type","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_properties_cellular_jitter","input_name":"Cellular Jitter","input_description":"TODO"}}],"output_names":["Image"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":null}}],[6565638614909771142,{"persistent_metadata":{"storage_id":null,"display_name":"Mandelbrot Set","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Graphical Data","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Over","input_description":"TODO"}}],"output_names":["Out"],"locked":false,"pinned":false,"node_type_metadata":{"Layer":{"position":{"Absolute":[-16,6]}}},"network_metadata":{"persistent_metadata":{"reference":"Merge","node_metadata":[[0,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-2]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-1]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Node Path","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,0]}}},"network_metadata":null}}],[3,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":"The list to set the named attribute on (one value per item).\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Name","input_description":"The attribute name (key) to write or replace.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":"The node that produces the attribute value for each item. Called once per item with the item's index in context.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-14,-1]}}},"network_metadata":null}}],[4,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-7,-1]}}},"network_metadata":null}}],[5,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Base","input_description":"The list whose items will appear at the start of the extended list.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"New","input_description":"The list whose items will appear at the end of the extended list.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,-2]}}},"network_metadata":null}}]],"pinned_node_order":[],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[0.0,0.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,0.0,0.0],"node_graph_width":0.0}}}}}],[7624113397561636853,{"persistent_metadata":{"storage_id":null,"display_name":"Swirly Noise","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Graphical Data","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Over","input_description":"TODO"}}],"output_names":["Out"],"locked":false,"pinned":false,"node_type_metadata":{"Layer":{"position":{"Stack":0}}},"network_metadata":{"persistent_metadata":{"reference":"Merge","node_metadata":[[0,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-2]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-1]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Node Path","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,0]}}},"network_metadata":null}}],[3,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":"The list to set the named attribute on (one value per item).\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Name","input_description":"The attribute name (key) to write or replace.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":"The node that produces the attribute value for each item. Called once per item with the item's index in context.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-14,-1]}}},"network_metadata":null}}],[4,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-7,-1]}}},"network_metadata":null}}],[5,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Base","input_description":"The list whose items will appear at the start of the extended list.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"New","input_description":"The list whose items will appear at the end of the extended list.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,-2]}}},"network_metadata":null}}]],"pinned_node_order":[],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[0.0,0.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,0.0,0.0],"node_graph_width":0.0}}}}}],[12241147352993594415,{"persistent_metadata":{"storage_id":null,"display_name":"Artboard","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Artboards","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"hidden","input_name":"Contents","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"is_integer":true,"unit":" px","x":"X","y":"Y"},"widget_override":"vec2","input_name":"Location","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"is_integer":true,"unit":" px","x":"W","y":"H"},"widget_override":"vec2","input_name":"Dimensions","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"artboard_background","input_name":"Background","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Clip","input_description":"TODO"}}],"output_names":["Out"],"locked":false,"pinned":false,"node_type_metadata":{"Layer":{"position":{"Absolute":[-8,3]}}},"network_metadata":{"persistent_metadata":{"reference":"Artboard","node_metadata":[[0,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":"Graphics to include within the artboard.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Location","input_description":"Coordinate of the top-left corner of the artboard within the document.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Dimensions","input_description":"Width and height of the artboard within the document.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Background","input_description":"Color of the artboard background.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Clip","input_description":"Whether to cut off the contained content that extends outside the artboard, or keep it visible.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-3]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Node Path","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,3]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":"The list to set the named attribute on (one value per item).\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Name","input_description":"The attribute name (key) to write or replace.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":"The node that produces the attribute value for each item. Called once per item with the item's index in context.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-14,-3]}}},"network_metadata":null}}],[3,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-7,-3]}}},"network_metadata":null}}],[4,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Base","input_description":"The list whose items will appear at the start of the extended list.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"New","input_description":"The list whose items will appear at the end of the extended list.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,-4]}}},"network_metadata":null}}]],"pinned_node_order":[],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[0.0,0.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,0.0,0.0],"node_graph_width":0.0}}}}}]],"pinned_node_order":[],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[345.0,-187.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,1335.0,393.0],"node_graph_width":1980.0}}}},"collapsed":[],"properties_panel_collapsed_sections":[],"commit_hash":"","document_ptz":{"pan":[-339.3903349049215,-502.62390663267854],"tilt":0.0,"zoom":4.0,"flip":false},"render_mode":"Normal","overlays_visibility_settings":{"all":true,"artboard_name":true,"compass_rose":true,"quick_measurement":true,"transform_measurement":true,"transform_cage":true,"hover_outline":true,"selection_outline":true,"layer_origin_cross":true,"pivot":true,"origin":true,"path":true,"anchors":true,"handles":true},"rulers_visible":true,"snapping_state":{"snapping_enabled":true,"grid_snapping":false,"artboards":true,"tolerance":8.0,"bounding_box":{"center_point":true,"corner_point":true,"edge_midpoint":true,"align_with_edges":true,"distribute_evenly":true},"path":{"anchor_point":true,"line_midpoint":true,"along_path":true,"normal_to_path":true,"tangent_to_path":true,"path_intersection_point":true,"align_with_anchor_point":true,"perpendicular_from_endpoint":true},"grid":{"origin":[0.0,0.0],"grid_type":{"Rectangular":{"spacing":[1.0,1.0]}},"rectangular_spacing":[1.0,1.0],"isometric_y_spacing":1.0,"isometric_angle_a":30.0,"isometric_angle_b":30.0,"color":"#cccccc","dot_display":false}},"graph_view_overlay_open":false,"graph_fade_artwork_percentage":80.0} \ No newline at end of file +{"network_interface":{"network":{"exports":[{"Node":{"node_id":12241147352993594415,"output_index":0}}],"nodes":[[80924370013313595,{"inputs":[{"Node":{"node_id":6029481207635803402,"output_index":0}},{"Value":{"tagged_value":{"GradientRamp":{"stops":{"color":[{"red":0.06469504,"green":0.0,"blue":0.0755814,"alpha":1.0,"linear":true},{"red":0.016644126,"green":0.13212071,"blue":0.62523156,"alpha":1.0,"linear":true},{"red":1.0,"green":0.8708812,"blue":0.3485102,"alpha":1.0,"linear":true},{"red":0.30054384,"green":0.8468733,"blue":0.8468733,"alpha":0.01,"linear":true}],"position":[0.0,0.12704918032786883,0.5,1.0],"midpoint":[0.5,0.5,0.5,0.5]},"gradient_space":"RgbGamma"}},"exposed":false}},{"Value":{"tagged_value":{"Bool":false},"exposed":false}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"raster_nodes::adjustments::GradientMapNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[3606681156406984991,{"inputs":[{"Node":{"node_id":6323350524796370485,"output_index":0}},{"Value":{"tagged_value":{"GradientRamp":{"stops":{"color":[{"red":0.0,"green":0.0,"blue":0.0,"alpha":1.0,"linear":true},{"red":0.04631017,"green":0.0,"blue":0.0076861563,"alpha":1.0,"linear":true},{"red":0.83939683,"green":0.7249875,"blue":0.27055356,"alpha":1.0,"linear":true},{"red":0.025397457,"green":0.3485102,"blue":0.3485102,"alpha":1.0,"linear":true},{"red":0.01102731,"green":0.09231063,"blue":0.09231063,"alpha":1.0,"linear":true}],"position":[0.0,0.3237704918032787,0.5655737704918032,0.8155737704918032,1.0],"midpoint":[0.5,0.5,0.5,0.5,0.5]},"gradient_space":"RgbGamma"}},"exposed":false}},{"Value":{"tagged_value":{"Bool":true},"exposed":false}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"raster_nodes::adjustments::GradientMapNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[4388711862172196665,{"inputs":[],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"raster_nodes::std_nodes::MandelbrotNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"FOOTPRINT","inject":""}}],[6029481207635803402,{"inputs":[{"Node":{"node_id":4388711862172196665,"output_index":0}},{"Value":{"tagged_value":{"DVec2":[0.0,0.0]},"exposed":false}},{"Value":{"tagged_value":{"Number":0.0},"exposed":false}},{"Value":{"tagged_value":{"DVec2":[1000.0,1000.0]},"exposed":false}},{"Value":{"tagged_value":{"DVec2":[0.0,0.0]},"exposed":false}},{"Value":{"tagged_value":{"DVec2":[0.0,0.0]},"exposed":false}},{"Value":{"tagged_value":{"Bool":true},"exposed":false}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":1,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[1,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Import":{"import_type":{"Concrete":{"name":"glam::f64::dvec2::DVec2"}},"import_index":1}},{"Import":{"import_type":{"Concrete":{"name":"f64"}},"import_index":2}},{"Import":{"import_type":{"Concrete":{"name":"glam::f64::dvec2::DVec2"}},"import_index":3}},{"Import":{"import_type":{"Concrete":{"name":"glam::f64::dvec2::DVec2"}},"import_index":4}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"transform_nodes::transform_nodes::TransformNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[6323350524796370485,{"inputs":[{"Value":{"tagged_value":"None","exposed":false}},{"Value":{"tagged_value":{"Bool":false},"exposed":false}},{"Value":{"tagged_value":{"Integer":0},"exposed":false}},{"Value":{"tagged_value":{"Number":35.0},"exposed":false}},{"Value":{"tagged_value":{"NoiseType":"OpenSimplex2"},"exposed":false}},{"Value":{"tagged_value":{"DomainWarpType":"OpenSimplex2"},"exposed":false}},{"Value":{"tagged_value":{"Number":100.0},"exposed":false}},{"Value":{"tagged_value":{"FractalType":"PingPong"},"exposed":false}},{"Value":{"tagged_value":{"Integer":3},"exposed":false}},{"Value":{"tagged_value":{"Number":2.0},"exposed":false}},{"Value":{"tagged_value":{"Number":0.5},"exposed":false}},{"Value":{"tagged_value":{"Number":0.0},"exposed":false}},{"Value":{"tagged_value":{"Number":2.0},"exposed":false}},{"Value":{"tagged_value":{"CellularDistanceFunction":"Hybrid"},"exposed":false}},{"Value":{"tagged_value":{"CellularReturnType":"CellValue"},"exposed":false}},{"Value":{"tagged_value":{"Number":1.0},"exposed":false}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"raster_nodes::std_nodes::NoisePatternNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"FOOTPRINT","inject":""}}],[6565638614909771142,{"inputs":[{"Node":{"node_id":7624113397561636853,"output_index":0}},{"Node":{"node_id":80924370013313595,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":5,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::AsGraphicNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[1,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":1}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::IntoGroupNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::PathOfSubgraphNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[3,{"inputs":[{"Node":{"node_id":1,"output_index":0}},{"Value":{"tagged_value":{"String":"editor:layer_path"},"exposed":false}},{"Node":{"node_id":2,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::WriteAttributeNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[4,{"inputs":[{"Node":{"node_id":3,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[5,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Node":{"node_id":4,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::ExtendNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[7624113397561636853,{"inputs":[{"Value":{"tagged_value":{"TypeDefault":{"List":{"Concrete":{"name":"graphic_types::graphic::Graphic"}}}},"exposed":true}},{"Node":{"node_id":3606681156406984991,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":5,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::AsGraphicNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[1,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":1}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::IntoGroupNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::PathOfSubgraphNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[3,{"inputs":[{"Node":{"node_id":1,"output_index":0}},{"Value":{"tagged_value":{"String":"editor:layer_path"},"exposed":false}},{"Node":{"node_id":2,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::WriteAttributeNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[4,{"inputs":[{"Node":{"node_id":3,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[5,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Node":{"node_id":4,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::ExtendNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[12241147352993594415,{"inputs":[{"Value":{"tagged_value":{"TypeDefault":{"List":{"Concrete":{"name":"graphic_types::artboard::Artboard"}}}},"exposed":true}},{"Node":{"node_id":6565638614909771142,"output_index":0}},{"Value":{"tagged_value":{"DVec2":[0.0,0.0]},"exposed":false}},{"Value":{"tagged_value":{"DVec2":[1000.0,1000.0]},"exposed":false}},{"Value":{"tagged_value":{"Color":{"red":0.0,"green":0.0,"blue":0.0,"alpha":1.0,"linear":true}},"exposed":false}},{"Value":{"tagged_value":{"Bool":true},"exposed":false}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":4,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Fn":[{"Concrete":{"name":"core::option::Option>"}},{"Generic":"T"}]},"import_index":1}},{"Import":{"import_type":{"Item":{"Concrete":{"name":"graph_craft::document::value::TaggedValue"}}},"import_index":2}},{"Import":{"import_type":{"Item":{"Concrete":{"name":"graph_craft::document::value::TaggedValue"}}},"import_index":3}},{"Import":{"import_type":{"Item":{"Concrete":{"name":"graph_craft::document::value::TaggedValue"}}},"import_index":4}},{"Import":{"import_type":{"Item":{"Concrete":{"name":"graph_craft::document::value::TaggedValue"}}},"import_index":5}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphic_nodes::artboard::CreateArtboardNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[1,{"inputs":[{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::PathOfSubgraphNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Value":{"tagged_value":{"String":"editor:layer_path"},"exposed":false}},{"Node":{"node_id":1,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::WriteAttributeNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[3,{"inputs":[{"Node":{"node_id":2,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[4,{"inputs":[{"Import":{"import_type":{"Fn":[{"Concrete":{"name":"core::option::Option>"}},{"List":{"Concrete":{"name":"graphic_types::artboard::Artboard"}}}]},"import_index":0}},{"Node":{"node_id":3,"output_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>"}},"implementation":{"ProtoNode":{"name":"graphic_nodes::graphic::ExtendNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]},"network_metadata":{"persistent_metadata":{"reference":null,"node_metadata":[[80924370013313595,{"persistent_metadata":{"storage_id":null,"display_name":"Gradient Map","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Image","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Gradient","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Reverse","input_description":""}}],"output_names":["Image"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":null}}],[3606681156406984991,{"persistent_metadata":{"storage_id":null,"display_name":"Gradient Map","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Image","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Gradient","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Reverse","input_description":""}}],"output_names":["Image"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":null}}],[4388711862172196665,{"persistent_metadata":{"storage_id":null,"display_name":"Mandelbrot","input_metadata":[],"output_names":["Raster"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":null}}],[6029481207635803402,{"persistent_metadata":{"storage_id":null,"display_name":"Transform","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"is_integer":false,"unit":" px","x":"X","y":"Y"},"widget_override":"vec2","input_name":"Translation","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"transform_rotation","input_name":"Rotation","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"is_integer":false,"unit":"x","x":"W","y":"H"},"widget_override":"vec2","input_name":"Scale","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"transform_skew","input_name":"Skew","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"hidden","input_name":"Origin Offset","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":"hidden","input_name":"Scale Appearance","input_description":""}}],"output_names":["Data"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":{"persistent_metadata":{"reference":null,"node_metadata":[[0,{"persistent_metadata":{"storage_id":null,"display_name":"Monitor","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,0]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"storage_id":null,"display_name":"Transform","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[7,0]}}},"network_metadata":null}}]],"pinned_node_order":[],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[0.0,0.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,0.0,0.0],"node_graph_width":0.0}}}}}],[6323350524796370485,{"persistent_metadata":{"storage_id":null,"display_name":"Noise Pattern","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Spacer","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Clip","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Seed","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_scale","input_name":"Scale","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_noise_type","input_name":"Noise Type","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_domain_warp_type","input_name":"Domain Warp Type","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_domain_warp_amplitude","input_name":"Domain Warp Amplitude","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_fractal_type","input_name":"Fractal Type","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_fractal_octaves","input_name":"Fractal Octaves","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_fractal_lacunarity","input_name":"Fractal Lacunarity","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_fractal_gain","input_name":"Fractal Gain","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_fractal_weighted_strength","input_name":"Fractal Weighted Strength","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_ping_pong_strength","input_name":"Fractal Ping Pong Strength","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_cellular_distance_function","input_name":"Cellular Distance Function","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_cellular_return_type","input_name":"Cellular Return Type","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"noise_inspector_cellular_jitter","input_name":"Cellular Jitter","input_description":"TODO"}}],"output_names":["Image"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":null}}],[6565638614909771142,{"persistent_metadata":{"storage_id":null,"display_name":"Mandelbrot Set","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Graphical Data","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Over","input_description":"TODO"}}],"output_names":["Out"],"locked":false,"pinned":false,"node_type_metadata":{"Layer":{"position":{"Absolute":[-16,6]}}},"network_metadata":{"persistent_metadata":{"reference":"Merge","node_metadata":[[0,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-2]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-1]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Node Path","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,0]}}},"network_metadata":null}}],[3,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":"The list to set the named attribute on (one value per item).\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Name","input_description":"The attribute name (key) to write or replace.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":"The node that produces the attribute value for each item. Called once per item with the item's index in context.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-14,-1]}}},"network_metadata":null}}],[4,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-7,-1]}}},"network_metadata":null}}],[5,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Base","input_description":"The list whose items will appear at the start of the extended list.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"New","input_description":"The list whose items will appear at the end of the extended list.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,-2]}}},"network_metadata":null}}]],"pinned_node_order":[],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[0.0,0.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,0.0,0.0],"node_graph_width":0.0}}}}}],[7624113397561636853,{"persistent_metadata":{"storage_id":null,"display_name":"Swirly Noise","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Graphical Data","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Over","input_description":"TODO"}}],"output_names":["Out"],"locked":false,"pinned":false,"node_type_metadata":{"Layer":{"position":{"Stack":0}}},"network_metadata":{"persistent_metadata":{"reference":"Merge","node_metadata":[[0,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-2]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-1]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Node Path","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,0]}}},"network_metadata":null}}],[3,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":"The list to set the named attribute on (one value per item).\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Name","input_description":"The attribute name (key) to write or replace.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":"The node that produces the attribute value for each item. Called once per item with the item's index in context.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-14,-1]}}},"network_metadata":null}}],[4,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-7,-1]}}},"network_metadata":null}}],[5,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Base","input_description":"The list whose items will appear at the start of the extended list.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"New","input_description":"The list whose items will appear at the end of the extended list.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,-2]}}},"network_metadata":null}}]],"pinned_node_order":[],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[0.0,0.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,0.0,0.0],"node_graph_width":0.0}}}}}],[12241147352993594415,{"persistent_metadata":{"storage_id":null,"display_name":"Artboard","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Artboards","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"hidden","input_name":"Contents","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"is_integer":true,"unit":" px","x":"X","y":"Y"},"widget_override":"vec2","input_name":"Location","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"is_integer":true,"unit":" px","x":"W","y":"H"},"widget_override":"vec2","input_name":"Dimensions","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":"artboard_background","input_name":"Background","input_description":"TODO"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Clip","input_description":"TODO"}}],"output_names":["Out"],"locked":false,"pinned":false,"node_type_metadata":{"Layer":{"position":{"Absolute":[-8,3]}}},"network_metadata":{"persistent_metadata":{"reference":"Artboard","node_metadata":[[0,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":"Graphics to include within the artboard.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Location","input_description":"Coordinate of the top-left corner of the artboard within the document.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Dimensions","input_description":"Width and height of the artboard within the document.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Background","input_description":"Color of the artboard background.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Clip","input_description":"Whether to cut off the contained content that extends outside the artboard, or keep it visible.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-3]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Node Path","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,3]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":"The list to set the named attribute on (one value per item).\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Name","input_description":"The attribute name (key) to write or replace.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":"The node that produces the attribute value for each item. Called once per item with the item's index in context.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-14,-3]}}},"network_metadata":null}}],[3,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Content","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-7,-3]}}},"network_metadata":null}}],[4,{"persistent_metadata":{"storage_id":null,"display_name":"","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Base","input_description":"The list whose items will appear at the start of the extended list.\n"}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"New","input_description":"The list whose items will appear at the end of the extended list.\n"}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,-4]}}},"network_metadata":null}}]],"pinned_node_order":[],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[0.0,0.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,0.0,0.0],"node_graph_width":0.0}}}}}]],"pinned_node_order":[],"previewing":"No","navigation_metadata":{"node_graph_ptz":{"pan":[345.0,-187.0],"tilt":0.0,"zoom":1.0,"flip":false},"node_graph_to_viewport":[1.0,0.0,0.0,1.0,1335.0,393.0],"node_graph_width":1980.0}}}},"collapsed":[],"properties_panel_collapsed_sections":[],"commit_hash":"","document_ptz":{"pan":[-339.3903349049215,-502.62390663267854],"tilt":0.0,"zoom":4.0,"flip":false},"render_mode":"Normal","overlays_visibility_settings":{"all":true,"artboard_name":true,"compass_rose":true,"quick_measurement":true,"transform_measurement":true,"transform_cage":true,"hover_outline":true,"selection_outline":true,"layer_origin_cross":true,"pivot":true,"origin":true,"path":true,"anchors":true,"handles":true},"rulers_visible":true,"snapping_state":{"snapping_enabled":true,"grid_snapping":false,"artboards":true,"tolerance":8.0,"bounding_box":{"center_point":true,"corner_point":true,"edge_midpoint":true,"align_with_edges":true,"distribute_evenly":true},"path":{"anchor_point":true,"line_midpoint":true,"along_path":true,"normal_to_path":true,"tangent_to_path":true,"path_intersection_point":true,"align_with_anchor_point":true,"perpendicular_from_endpoint":true},"grid":{"origin":[0.0,0.0],"grid_type":{"Rectangular":{"spacing":[1.0,1.0]}},"rectangular_spacing":[1.0,1.0],"isometric_y_spacing":1.0,"isometric_angle_a":30.0,"isometric_angle_b":30.0,"color":"#cccccc","dot_display":false}},"graph_view_overlay_open":false,"graph_fade_artwork_percentage":80.0} \ No newline at end of file diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index afd6c0108d7..3950a3ab862 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -85,9 +85,7 @@ const SIDE_EFFECT_FREE_MESSAGES: &[MessageDiscriminant] = &[ /// Since we don't need to update the frontend multiple times per frame, /// we have a set of messages which we will buffer until the next frame is requested. const FRONTEND_UPDATE_MESSAGES: &[MessageDiscriminant] = &[ - MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::PropertiesPanel( - PropertiesPanelMessageDiscriminant::Refresh, - ))), + MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::Inspector(InspectorMessageDiscriminant::Refresh))), MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::UpdateDocumentWidgets), MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::Overlays(OverlaysMessageDiscriminant::Draw))), MessageDiscriminant::Portfolio(PortfolioMessageDiscriminant::Document(DocumentMessageDiscriminant::RenderRulers)), @@ -288,7 +286,7 @@ impl Dispatcher { let layout = &self.message_handlers.portfolio_message_handler.workspace.panel_layout; menu_bar_message_handler.data_panel_open = layout.is_panel_present(PanelType::Data); menu_bar_message_handler.layers_panel_open = layout.is_panel_present(PanelType::Layers); - menu_bar_message_handler.properties_panel_open = layout.is_panel_present(PanelType::Properties); + menu_bar_message_handler.inspector_open = layout.is_panel_present(PanelType::Inspector); menu_bar_message_handler.message_logging_verbosity = self.message_handlers.debug_message_handler.message_logging_verbosity; menu_bar_message_handler.reset_node_definitions_on_open = self.message_handlers.portfolio_message_handler.reset_node_definitions_on_open; menu_bar_message_handler.show_storage_preferences = self.message_handlers.preferences_message_handler.show_storage_preferences; diff --git a/editor/src/messages/layout/layout_message_handler.rs b/editor/src/messages/layout/layout_message_handler.rs index 10be404a277..afd26eda4b8 100644 --- a/editor/src/messages/layout/layout_message_handler.rs +++ b/editor/src/messages/layout/layout_message_handler.rs @@ -165,7 +165,7 @@ impl LayoutMessageHandler { } } // A section contains more LayoutGroups which we add to the stack. - LayoutGroup::Section(WidgetSection { layout, .. }) => { + LayoutGroup::NodeSection(NodeSection { layout, .. }) => { stack.extend(layout.0.iter().enumerate().map(|(index, val)| ([widget_path.as_slice(), &[index]].concat(), val))); } LayoutGroup::Table(WidgetTable { rows, .. }) => { diff --git a/editor/src/messages/layout/utility_types/layout_widget.rs b/editor/src/messages/layout/utility_types/layout_widget.rs index 2f8e177cb07..549cb4628dc 100644 --- a/editor/src/messages/layout/utility_types/layout_widget.rs +++ b/editor/src/messages/layout/utility_types/layout_widget.rs @@ -70,8 +70,8 @@ define_layout_target!( MenuBar, /// Bar at the top of the node graph containing the location and the "Preview" and "Hide" buttons. NodeGraphControlBar, - /// The body of the Properties panel containing many collapsable sections. - PropertiesPanel, + /// The body of the Inspector containing many collapsable sections. + Inspector, /// The contextual input key/mouse combination shortcuts shown in the status bar at the bottom of the window. StatusBarHints, /// The version information shown in the status bar at the bottom right of the window. @@ -295,7 +295,7 @@ impl<'a> Iterator for WidgetIter<'a> { self.table.extend(rows.iter().flatten().flatten().rev()); self.next() } - Some(LayoutGroup::Section(WidgetSection { layout, .. })) => { + Some(LayoutGroup::NodeSection(NodeSection { layout, .. })) => { for layout_row in &layout.0 { self.stack.push(layout_row); } @@ -347,7 +347,7 @@ impl<'a> Iterator for WidgetIterMut<'a> { self.table.extend(rows.iter_mut().flatten().flatten().rev()); self.next() } - Some(LayoutGroup::Section(WidgetSection { layout, .. })) => { + Some(LayoutGroup::NodeSection(NodeSection { layout, .. })) => { for layout_row in &mut layout.0 { self.stack.push(layout_row); } @@ -364,7 +364,7 @@ pub enum LayoutGroup { Column(WidgetColumn), Row(WidgetRow), Table(WidgetTable), - Section(WidgetSection), + NodeSection(NodeSection), } #[cfg_attr(feature = "wasm", derive(tsify::Tsify))] @@ -390,7 +390,7 @@ pub struct WidgetTable { pub unstyled: bool, } -/// A wire drawn between Properties panel sections, styled like the graph's wire carrying the same data. +/// A wire drawn between Inspector sections, styled like the graph's wire carrying the same data. #[cfg_attr(feature = "wasm", derive(tsify::Tsify))] #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct SectionWire { @@ -401,10 +401,10 @@ pub struct SectionWire { pub is_list: bool, } -/// A collapsible Properties panel section for a single node: a header with its name and pin, delete, and visibility controls, above its input parameter widgets. +/// A collapsible Inspector section for a single node: a header with its name and pin, delete, and visibility controls, above its input parameter widgets. #[cfg_attr(feature = "wasm", derive(tsify::Tsify), tsify(large_number_types_as_bigints))] #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct WidgetSection { +pub struct NodeSection { /// The node's name shown in the section header: its implementation name, followed in parentheses by its given alias if it has one. pub name: String, /// The node definition's icon, shown before the name in the section header (none when it has no icon). @@ -413,7 +413,7 @@ pub struct WidgetSection { pub description: String, /// Whether the node is visible rather than hidden (shown as the eye icon). pub visible: bool, - /// Whether the node is pinned, keeping its section shown in the Properties panel when nothing is selected (shown as the pin icon). + /// Whether the node is pinned, keeping its section shown in the Inspector when nothing is selected (shown as the pin icon). pub pinned: bool, /// Whether this section can be dragged to reorder it within its layer's chain of nodes (true for a layer chain's nodes, but not its terminal layer node). pub draggable: bool, @@ -428,9 +428,9 @@ pub struct WidgetSection { pub node_reference: bool, /// Whether this section is expanded to show its contents, as opposed to being collapsed down to just its header. pub expanded: bool, - /// The ID of the node whose properties this section displays. + /// The ID of the node whose Inspector section this is. pub id: u64, - /// The node's properties content, rendered as the section's body when expanded, followed by the sections of any chain it shows (those with an `output_wire`). + /// The node's Inspector content, rendered as the section's body when expanded, followed by the sections of any chain it shows (those with an `output_wire`). pub layout: Layout, } @@ -467,7 +467,7 @@ impl LayoutGroup { #[allow(clippy::too_many_arguments)] pub fn section(name: impl Into, icon: Option, description: impl Into, visible: bool, pinned: bool, expanded: bool, id: u64, layout: Layout) -> Self { - Self::Section(WidgetSection { + Self::NodeSection(NodeSection { name: name.into(), icon, description: description.into(), @@ -572,7 +572,7 @@ impl Diffable for LayoutGroup { } } ( - Self::Section(WidgetSection { + Self::NodeSection(NodeSection { name: current_name, icon: current_icon, description: current_description, @@ -586,7 +586,7 @@ impl Diffable for LayoutGroup { id: current_id, layout: current_layout, }), - Self::Section(WidgetSection { + Self::NodeSection(NodeSection { name: new_name, icon: new_icon, description: new_description, @@ -631,7 +631,7 @@ impl Diffable for LayoutGroup { current_layout.clone_from(&new_layout); // Push an update layout group to the diff - let new_value = Self::Section(WidgetSection { + let new_value = Self::NodeSection(NodeSection { name: new_name, icon: new_icon, description: new_description, @@ -691,7 +691,7 @@ impl Diffable for LayoutGroup { } } } - Self::Section(WidgetSection { layout, .. }) => { + Self::NodeSection(NodeSection { layout, .. }) => { layout.collect_checkbox_ids(layout_target, widget_path, checkbox_map); } } @@ -721,7 +721,7 @@ impl Diffable for LayoutGroup { } } } - Self::Section(WidgetSection { layout, .. }) => { + Self::NodeSection(NodeSection { layout, .. }) => { layout.replace_widget_ids(layout_target, widget_path, checkbox_map); } } @@ -973,7 +973,7 @@ impl WidgetSizing { #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct WidgetDiff { /// A path to the change - /// e.g. [0, 1, 2] in the Properties panel is the first section, second row and third widget. + /// e.g. [0, 1, 2] in the Inspector is the first section, second row and third widget. /// An empty path [] shows that the entire panel has changed and is sent when the UI is first created. #[serde(rename = "widgetPath")] pub widget_path: Vec, 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 a4fb48f5970..984a81f5b54 100644 --- a/editor/src/messages/layout/utility_types/widgets/button_widgets.rs +++ b/editor/src/messages/layout/utility_types/widgets/button_widgets.rs @@ -130,7 +130,7 @@ pub struct ParameterExposeButton { pub on_commit: WidgetCallback<()>, } -/// A parameter's name, for an input fed by a chain of nodes, that shows or hides that chain's sections within its node's Properties panel section. +/// A parameter's name, for an input fed by a chain of nodes, that shows or hides that chain's sections within its node's Inspector section. #[cfg_attr(feature = "wasm", derive(tsify::Tsify))] #[derive(Clone, serde::Serialize, serde::Deserialize, Derivative, Default, WidgetBuilder)] #[derivative(Debug, PartialEq)] diff --git a/editor/src/messages/menu_bar/menu_bar_message_handler.rs b/editor/src/messages/menu_bar/menu_bar_message_handler.rs index e257bdf45d0..d118f58621f 100644 --- a/editor/src/messages/menu_bar/menu_bar_message_handler.rs +++ b/editor/src/messages/menu_bar/menu_bar_message_handler.rs @@ -25,7 +25,7 @@ pub struct MenuBarMessageHandler { pub make_path_editable_is_allowed: bool, pub data_panel_open: bool, pub layers_panel_open: bool, - pub properties_panel_open: bool, + pub inspector_open: bool, pub focus_document: bool, } @@ -669,11 +669,11 @@ impl LayoutHolder for MenuBarMessageHandler { .on_commit(|_| WorkspaceMessage::ResetWorkspaceLayout.into()), ], vec![ - MenuListEntry::new("Properties") - .label("Properties") - .icon(if self.properties_panel_open { "CheckboxChecked" } else { "CheckboxUnchecked" }) - .tooltip_shortcut(action_shortcut!(WorkspaceMessageDiscriminant::TogglePropertiesPanelOpen)) - .on_commit(|_| WorkspaceMessage::TogglePropertiesPanelOpen.into()) + MenuListEntry::new("Inspector") + .label("Inspector") + .icon(if self.inspector_open { "CheckboxChecked" } else { "CheckboxUnchecked" }) + .tooltip_shortcut(action_shortcut!(WorkspaceMessageDiscriminant::ToggleInspectorOpen)) + .on_commit(|_| WorkspaceMessage::ToggleInspectorOpen.into()) .disabled(self.focus_document), MenuListEntry::new("Layers") .label("Layers") diff --git a/editor/src/messages/portfolio/document/document_message.rs b/editor/src/messages/portfolio/document/document_message.rs index ca1652f063b..8d68c5983b4 100644 --- a/editor/src/messages/portfolio/document/document_message.rs +++ b/editor/src/messages/portfolio/document/document_message.rs @@ -34,7 +34,7 @@ pub enum DocumentMessage { #[child] Overlays(OverlaysMessage), #[child] - PropertiesPanel(PropertiesPanelMessage), + Inspector(InspectorMessage), #[child] DataPanel(DataPanelMessage), #[child] @@ -104,7 +104,7 @@ pub enum DocumentMessage { parent: LayerNodeIdentifier, insert_index: usize, }, - ReorderPropertiesSection { + ReorderInspectorSection { node_id: NodeId, insert_index: usize, duplicate: bool, @@ -249,11 +249,11 @@ pub enum DocumentMessage { tree_path: Vec, recursive: bool, }, - ToggleNodePropertiesSectionExpanded { + ToggleNodeInspectorSectionExpanded { node_id: NodeId, recursive: bool, }, - ToggleNodePropertiesInputChain { + ToggleNodeInspectorInputChain { node_id: NodeId, input_index: usize, }, diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 0cb4225dcab..714e1379329 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -1,5 +1,5 @@ use super::document_diff::diff_networks; -use super::node_graph::{document_node_definitions, node_properties}; +use super::node_graph::{document_node_definitions, node_inspector}; use super::utility_types::error::EditorError; use super::utility_types::misc::{GroupFolderType, SNAP_FUNCTIONS_FOR_BOUNDING_BOXES, SNAP_FUNCTIONS_FOR_PATHS, SnappingOptions, SnappingState}; use super::utility_types::network_interface::{self, NodeNetworkInterface, TransactionStatus}; @@ -15,12 +15,12 @@ use crate::messages::input_mapper::utility_types::macros::action_shortcut; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::data_panel::{DataPanelMessageContext, DataPanelMessageHandler}; use crate::messages::portfolio::document::graph_operation::utility_types::{ModifyInputsContext, TransformIn}; +use crate::messages::portfolio::document::inspector::inspector_message_handler::InspectorMessageContext; use crate::messages::portfolio::document::node_graph::NodeGraphMessageContext; use crate::messages::portfolio::document::node_graph::document_node_definitions::DefinitionIdentifier; use crate::messages::portfolio::document::node_graph::utility_types::FrontendGraphDataType; use crate::messages::portfolio::document::overlays::grid_overlays::{grid_overlay, overlay_options}; use crate::messages::portfolio::document::overlays::utility_types::{OverlaysType, OverlaysVisibilitySettings, Pivot}; -use crate::messages::portfolio::document::properties_panel::properties_panel_message_handler::PropertiesPanelMessageContext; use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis, PTZ}; use crate::messages::portfolio::document::utility_types::network_interface::{ChainInsertionPoint, FlowType, InputConnector, NodeTemplate, OutputConnector}; @@ -66,7 +66,7 @@ pub struct DocumentMessageContext<'a> { pub preferences: &'a PreferencesMessageHandler, pub data_panel_open: bool, pub layers_panel_open: bool, - pub properties_panel_open: bool, + pub inspector_open: bool, pub viewport: &'a ViewportMessageHandler, pub resource_storage: &'a ResourceStorageMessageHandler, pub fonts: &'a FontsMessageHandler, @@ -97,7 +97,7 @@ pub struct DocumentMessageHandler { #[serde(skip)] pub overlays_message_handler: OverlaysMessageHandler, #[serde(skip)] - pub properties_panel_message_handler: PropertiesPanelMessageHandler, + pub inspector_message_handler: InspectorMessageHandler, #[serde(skip)] pub data_panel_message_handler: DataPanelMessageHandler, @@ -113,12 +113,12 @@ pub struct DocumentMessageHandler { /// Tracks which layer occurrences are collapsed in the Layers panel, keyed by tree path. #[serde(deserialize_with = "deserialize_collapsed_layers", default)] pub collapsed: CollapsedLayers, - /// The node IDs whose section is collapsed in the Properties panel. + /// The node IDs whose section is collapsed in the Inspector. + #[serde(default, alias = "properties_panel_collapsed_sections")] + pub inspector_collapsed_sections: Vec, + /// The input (if any) whose feeding chain a node's Inspector section shows within it, for each node where that differs from the default of a layer's chain input. #[serde(default)] - pub properties_panel_collapsed_sections: Vec, - /// The input (if any) whose feeding chain a node's Properties panel section shows within it, for each node where that differs from the default of a layer's chain input. - #[serde(default)] - pub properties_panel_expanded_input_chains: Vec<(NodeId, Option)>, + pub inspector_expanded_input_chains: Vec<(NodeId, Option)>, /// The layer node IDs whose chain is expanded into a row per node in the Layers panel. #[serde(default)] pub layers_panel_expanded_chains: Vec, @@ -202,7 +202,7 @@ impl Default for DocumentMessageHandler { navigation_handler: NavigationMessageHandler::default(), node_graph_handler: NodeGraphMessageHandler::default(), overlays_message_handler: OverlaysMessageHandler::default(), - properties_panel_message_handler: PropertiesPanelMessageHandler::default(), + inspector_message_handler: InspectorMessageHandler::default(), data_panel_message_handler: DataPanelMessageHandler::default(), // ============================================ // Fields that are saved in the document format @@ -210,8 +210,8 @@ impl Default for DocumentMessageHandler { network_interface: default_document_network_interface(), resources: ResourceMessageHandler::default(), collapsed: CollapsedLayers::default(), - properties_panel_collapsed_sections: Vec::new(), - properties_panel_expanded_input_chains: Vec::new(), + inspector_collapsed_sections: Vec::new(), + inspector_expanded_input_chains: Vec::new(), layers_panel_expanded_chains: Vec::new(), commit_hash: GRAPHITE_GIT_COMMIT_HASH.to_string(), document_ptz: PTZ::default(), @@ -255,7 +255,7 @@ impl MessageHandler> for DocumentMes preferences, data_panel_open, layers_panel_open, - properties_panel_open, + inspector_open, resource_storage, fonts, } = context; @@ -282,19 +282,19 @@ impl MessageHandler> for DocumentMes self.overlays_message_handler .process_message(message, responses, OverlaysMessageContext { visibility_settings, viewport }); } - DocumentMessage::PropertiesPanel(message) => { - let context = PropertiesPanelMessageContext { + DocumentMessage::Inspector(message) => { + let context = InspectorMessageContext { executor, document_id, network_interface: &mut self.network_interface, resources: &self.resources, selection_network_path: &self.selection_network_path, fonts, - properties_panel_open, - properties_panel_collapsed_sections: &self.properties_panel_collapsed_sections, - properties_panel_expanded_input_chains: &self.properties_panel_expanded_input_chains, + inspector_open, + inspector_collapsed_sections: &self.inspector_collapsed_sections, + inspector_expanded_input_chains: &self.inspector_expanded_input_chains, }; - self.properties_panel_message_handler.process_message(message, responses, context); + self.inspector_message_handler.process_message(message, responses, context); } DocumentMessage::DataPanel(message) => { self.data_panel_message_handler.process_message( @@ -317,8 +317,8 @@ impl MessageHandler> for DocumentMes breadcrumb_network_path: &self.breadcrumb_network_path, document_id, collapsed: &mut self.collapsed, - properties_panel_collapsed_sections: &mut self.properties_panel_collapsed_sections, - properties_panel_expanded_input_chains: &mut self.properties_panel_expanded_input_chains, + inspector_collapsed_sections: &mut self.inspector_collapsed_sections, + inspector_expanded_input_chains: &mut self.inspector_expanded_input_chains, layers_panel_expanded_chains: &mut self.layers_panel_expanded_chains, ipp, graph_view_overlay_open: self.graph_view_overlay_open, @@ -549,7 +549,7 @@ impl MessageHandler> for DocumentMes responses.add(NodeGraphMessage::RunDocumentGraph); responses.add(NodeGraphMessage::SendGraph); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); } DocumentMessage::DuplicateSelectedLayersTo { parent, insert_index } => { if !self.selection_network_path.is_empty() { @@ -819,8 +819,8 @@ impl MessageHandler> for DocumentMes DocumentMessage::MoveSelectedLayersTo { parent, insert_index } => { self.move_selected_layers_to(parent, insert_index, responses); } - DocumentMessage::ReorderPropertiesSection { node_id, insert_index, duplicate } => { - // The Properties panel shows draggable sections in two cases, disambiguated by the current selection: + DocumentMessage::ReorderInspectorSection { node_id, insert_index, duplicate } => { + // The Inspector shows draggable sections in two cases, disambiguated by the current selection: // a single selected layer (reorder within its node chain) or no selection (reorder the pinned nodes). let selected_nodes = self.network_interface.selected_nodes_in_nested_network(&self.selection_network_path); let Some(selected_nodes) = selected_nodes else { return }; @@ -851,10 +851,10 @@ impl MessageHandler> for DocumentMes responses.add(DocumentMessage::MoveChainNodes { node_ids, layer, insert_index }); } } else if layers.is_empty() && nodes.is_empty() { - // Reorder a pinned node, which is purely a Properties panel display order (no graph rerender needed, and nothing to duplicate into) + // Reorder a pinned node, which is purely a Inspector display order (no graph rerender needed, and nothing to duplicate into) responses.add(DocumentMessage::AddTransaction); responses.add(NodeGraphMessage::ReorderPinnedNode { node_id, insert_index }); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); } } DocumentMessage::MoveChainNodes { node_ids, layer, insert_index } => { @@ -863,7 +863,7 @@ impl MessageHandler> for DocumentMes responses.add(NodeGraphMessage::MoveChainNodes { node_ids, layer, insert_index }); responses.add(NodeGraphMessage::RunDocumentGraph); responses.add(NodeGraphMessage::SendGraph); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); } DocumentMessage::DuplicateChainNodes { node_ids, @@ -883,7 +883,7 @@ impl MessageHandler> for DocumentMes }); responses.add(NodeGraphMessage::RunDocumentGraph); responses.add(NodeGraphMessage::SendGraph); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); } DocumentMessage::PasteChainNodes { copies } => { // Layers and their chains live in the document network, so a nested one open in the graph has no chain to paste into @@ -925,7 +925,7 @@ impl MessageHandler> for DocumentMes } responses.add(NodeGraphMessage::RunDocumentGraph); responses.add(NodeGraphMessage::SendGraph); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); } DocumentMessage::PasteNodes { nodes } => { // Over the same selection they were copied from, nodes are duplicated into their flow, and otherwise they're pasted loose into the graph and shown there @@ -1472,7 +1472,7 @@ impl MessageHandler> for DocumentMes PanelType::Layers => self.selection_network_path = vec![], _ => {} } - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); responses.add(NodeGraphMessage::UpdateLayerPanel); responses.add(NodeGraphMessage::UpdateInSelectedNetwork); } @@ -1664,39 +1664,39 @@ impl MessageHandler> for DocumentMes responses.add(NodeGraphMessage::SendGraph); } - DocumentMessage::ToggleNodePropertiesSectionExpanded { node_id, recursive } => { - let expand = self.properties_panel_collapsed_sections.contains(&node_id); + DocumentMessage::ToggleNodeInspectorSectionExpanded { node_id, recursive } => { + let expand = self.inspector_collapsed_sections.contains(&node_id); // Recursively, every section nested within this one follows along let node_ids = if recursive { - node_properties::nested_section_nodes(node_id, &self.properties_panel_expanded_input_chains, &self.network_interface, &self.selection_network_path) + node_inspector::nested_section_nodes(node_id, &self.inspector_expanded_input_chains, &self.network_interface, &self.selection_network_path) } else { vec![node_id] }; for node_id in node_ids { if expand { - self.properties_panel_collapsed_sections.retain(|id| *id != node_id); - } else if !self.properties_panel_collapsed_sections.contains(&node_id) { - self.properties_panel_collapsed_sections.push(node_id); + self.inspector_collapsed_sections.retain(|id| *id != node_id); + } else if !self.inspector_collapsed_sections.contains(&node_id) { + self.inspector_collapsed_sections.push(node_id); } } - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); } - DocumentMessage::ToggleNodePropertiesInputChain { node_id, input_index } => { + DocumentMessage::ToggleNodeInspectorInputChain { node_id, input_index } => { // A section shows at most one input's chain, so showing this one hides any other let network_path = &self.selection_network_path; - let default = node_properties::default_expanded_input_chain(&node_id, &self.network_interface, network_path); - let current = node_properties::expanded_input_chain(&node_id, &self.properties_panel_expanded_input_chains, &self.network_interface, network_path); + let default = node_inspector::default_expanded_input_chain(&node_id, &self.network_interface, network_path); + let current = node_inspector::expanded_input_chain(&node_id, &self.inspector_expanded_input_chains, &self.network_interface, network_path); let expanded = (current != Some(input_index)).then_some(input_index); - self.properties_panel_expanded_input_chains.retain(|(id, _)| *id != node_id); + self.inspector_expanded_input_chains.retain(|(id, _)| *id != node_id); if expanded != default { - self.properties_panel_expanded_input_chains.push((node_id, expanded)); + self.inspector_expanded_input_chains.push((node_id, expanded)); } - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); } DocumentMessage::ToggleLayerChainExpanded { layer_id } => { if self.layers_panel_expanded_chains.contains(&layer_id) { diff --git a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs index 5f93b391d9e..4c867ee2321 100644 --- a/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs +++ b/editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs @@ -138,7 +138,7 @@ impl MessageHandler> for return; }; if set_stroke_paint_order(network_interface, &[], stroke_node_id, paint_order) { - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); responses.add(NodeGraphMessage::RunDocumentGraph); responses.add(NodeGraphMessage::SendGraph); } diff --git a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs index c760211bc8e..d5eb57eedc5 100644 --- a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs +++ b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs @@ -752,7 +752,7 @@ impl<'a> ModifyInputsContext<'a> { }; transform_utils::update_transform(self.network_interface, &transform_node_id, last_transform_value); - self.responses.add(PropertiesPanelMessage::Refresh); + self.responses.add(InspectorMessage::Refresh); self.responses.add(NodeGraphMessage::RunDocumentGraph); } @@ -959,7 +959,7 @@ impl<'a> ModifyInputsContext<'a> { transform_utils::update_transform(self.network_interface, &transform_node_id, transform); // Refresh the render and editor UI - self.responses.add(PropertiesPanelMessage::Refresh); + self.responses.add(InspectorMessage::Refresh); if !skip_rerender { self.responses.add(NodeGraphMessage::RunDocumentGraph); } @@ -970,7 +970,7 @@ impl<'a> ModifyInputsContext<'a> { return; }; self.network_interface.vector_modify(&path_node_id, modification_type); - self.responses.add(PropertiesPanelMessage::Refresh); + self.responses.add(InspectorMessage::Refresh); self.responses.add(NodeGraphMessage::RunDocumentGraph); } @@ -1002,10 +1002,10 @@ impl<'a> ModifyInputsContext<'a> { ); } - /// Set the input, refresh the Properties panel, and run the document graph if skip_rerender is false + /// Set the input, refresh the Inspector, and run the document graph if skip_rerender is false pub fn set_input_with_refresh(&mut self, input_connector: InputConnector, input: NodeInput, skip_rerender: bool) { self.network_interface.set_input(&input_connector, input, &[]); - self.responses.add(PropertiesPanelMessage::Refresh); + self.responses.add(InspectorMessage::Refresh); if !skip_rerender { self.responses.add(NodeGraphMessage::RunDocumentGraph); } diff --git a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message.rs b/editor/src/messages/portfolio/document/inspector/inspector_message.rs similarity index 60% rename from editor/src/messages/portfolio/document/properties_panel/properties_panel_message.rs rename to editor/src/messages/portfolio/document/inspector/inspector_message.rs index a87d8fb07d7..95cce6f0342 100644 --- a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message.rs +++ b/editor/src/messages/portfolio/document/inspector/inspector_message.rs @@ -1,8 +1,8 @@ use crate::messages::prelude::*; -#[impl_message(Message, DocumentMessage, PropertiesPanel)] +#[impl_message(Message, DocumentMessage, Inspector)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] -pub enum PropertiesPanelMessage { +pub enum InspectorMessage { // Messages Clear, Refresh, diff --git a/editor/src/messages/portfolio/document/inspector/inspector_message_handler.rs b/editor/src/messages/portfolio/document/inspector/inspector_message_handler.rs new file mode 100644 index 00000000000..9ca30ace526 --- /dev/null +++ b/editor/src/messages/portfolio/document/inspector/inspector_message_handler.rs @@ -0,0 +1,77 @@ +use graphene_std::uuid::NodeId; + +use crate::messages::layout::utility_types::widget_prelude::*; +use crate::messages::portfolio::document::node_graph::document_node_definitions::NodeInspectorContext; +use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface; +use crate::messages::prelude::*; +use crate::node_graph_executor::NodeGraphExecutor; + +#[derive(ExtractField)] +pub struct InspectorMessageContext<'a> { + pub executor: &'a mut NodeGraphExecutor, + pub document_id: DocumentId, + pub network_interface: &'a mut NodeNetworkInterface, + pub resources: &'a ResourceMessageHandler, + pub selection_network_path: &'a [NodeId], + pub fonts: &'a FontsMessageHandler, + pub inspector_open: bool, + pub inspector_collapsed_sections: &'a [NodeId], + pub inspector_expanded_input_chains: &'a [(NodeId, Option)], +} + +#[derive(Debug, Clone, Default, ExtractField)] +pub struct InspectorMessageHandler {} + +#[message_handler_data] +impl MessageHandler> for InspectorMessageHandler { + fn process_message(&mut self, message: InspectorMessage, responses: &mut VecDeque, context: InspectorMessageContext) { + let InspectorMessageContext { + executor, + document_id, + network_interface, + resources, + selection_network_path, + fonts, + inspector_open, + inspector_collapsed_sections, + inspector_expanded_input_chains, + } = context; + + match message { + InspectorMessage::Clear => { + responses.add(LayoutMessage::SendLayout { + layout: Layout::default(), + layout_target: LayoutTarget::Inspector, + }); + } + InspectorMessage::Refresh => { + if !inspector_open { + responses.add(InspectorMessage::Clear); + return; + } + + let mut node_inspector_context = NodeInspectorContext { + responses, + executor, + document_id, + network_interface, + resources, + selection_network_path, + fonts, + inspector_collapsed_sections, + inspector_expanded_input_chains, + }; + let layout = Layout(NodeGraphMessageHandler::collate_inspector_sections(&mut node_inspector_context)); + + node_inspector_context.responses.add(LayoutMessage::SendLayout { + layout, + layout_target: LayoutTarget::Inspector, + }); + } + } + } + + fn actions(&self) -> ActionList { + actions!(InspectorMessageDiscriminant;) + } +} diff --git a/editor/src/messages/portfolio/document/inspector/mod.rs b/editor/src/messages/portfolio/document/inspector/mod.rs new file mode 100644 index 00000000000..8f8bc3ecb52 --- /dev/null +++ b/editor/src/messages/portfolio/document/inspector/mod.rs @@ -0,0 +1,7 @@ +mod inspector_message; +pub mod inspector_message_handler; + +#[doc(inline)] +pub use inspector_message::{InspectorMessage, InspectorMessageDiscriminant}; +#[doc(inline)] +pub use inspector_message_handler::InspectorMessageHandler; diff --git a/editor/src/messages/portfolio/document/mod.rs b/editor/src/messages/portfolio/document/mod.rs index 6bf4a921c57..a3318acbc7f 100644 --- a/editor/src/messages/portfolio/document/mod.rs +++ b/editor/src/messages/portfolio/document/mod.rs @@ -7,10 +7,10 @@ pub(crate) mod storage_tests; pub mod data_panel; pub mod graph_operation; +pub mod inspector; pub mod navigation; pub mod node_graph; pub mod overlays; -pub mod properties_panel; pub mod resource; pub mod utility_types; diff --git a/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs b/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs index d77ceb76d00..dd340b46fab 100644 --- a/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs +++ b/editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs @@ -1,7 +1,7 @@ mod document_node_derive; -use super::node_properties::choice::enum_choice; -use super::node_properties::{self, ParameterWidgetsInfo, SliderRange}; +use super::node_inspector::choice::enum_choice; +use super::node_inspector::{self, ParameterWidgetsInfo, SliderRange}; use super::utility_types::{FrontendNodeType, InputTypeConstraint}; use crate::messages::frontend::IconName; use crate::messages::layout::utility_types::widget_prelude::*; @@ -23,7 +23,7 @@ use graphene_std::vector::Vector; use graphene_std::*; use std::collections::{HashMap, VecDeque}; -pub struct NodePropertiesContext<'a> { +pub struct NodeInspectorContext<'a> { pub responses: &'a mut VecDeque, pub executor: &'a mut NodeGraphExecutor, pub document_id: DocumentId, @@ -31,19 +31,19 @@ pub struct NodePropertiesContext<'a> { pub resources: &'a ResourceMessageHandler, pub fonts: &'a FontsMessageHandler, pub selection_network_path: &'a [NodeId], - /// The node IDs whose Properties panel sections the user has collapsed. - pub properties_panel_collapsed_sections: &'a [NodeId], + /// The node IDs whose Inspector sections the user has collapsed. + pub inspector_collapsed_sections: &'a [NodeId], /// The input (if any) whose feeding chain a node's section shows, for each node where that differs from the default. - pub properties_panel_expanded_input_chains: &'a [(NodeId, Option)], + pub inspector_expanded_input_chains: &'a [(NodeId, Option)], } -impl NodePropertiesContext<'_> { +impl NodeInspectorContext<'_> { pub fn call_widget_override(&mut self, node_id: &NodeId, index: usize) -> Option> { - let input_properties_row = self.network_interface.persistent_input_metadata(node_id, index, self.selection_network_path)?; + let input_inspector_row = self.network_interface.persistent_input_metadata(node_id, index, self.selection_network_path)?; // The stored override wins, falling back to the definition's own so documents saved before it gained one still // pick it up. Only `Custom` is recovered, since the other kinds also need input data stored at insertion time. - let widget_override = input_properties_row.widget_override.clone().or_else(|| { + let widget_override = input_inspector_row.widget_override.clone().or_else(|| { let implementation = self.network_interface.implementation(node_id, self.selection_network_path)?; let DocumentNodeImplementation::ProtoNode(proto_node_identifier) = implementation else { return None; @@ -138,8 +138,8 @@ pub struct DocumentNodeDefinition { /// Node level overrides are stored based on the reference, not the instance. If the node is modified such that it becomes a local version /// (for example an input is added), the reference is no longer to the definition, and the overrides are lost. - /// Most nodes should not use node based properties, since they are less flexible than input level properties. - pub properties: Option<&'static str>, + /// Most nodes should not use a node-level Inspector override, since it is less flexible than an input-level override. + pub inspector: Option<&'static str>, } // We use the once_cell to use the document node definitions throughout the editor without passing a reference @@ -161,7 +161,7 @@ fn document_node_definitions() -> HashMap HashMap HashMap HashMap HashMap HashMap HashMap HashMap HashMap HashMap Vec + Send + Sync>>; +type NodeInspector = HashMap Vec + Send + Sync>>; // TODO: Replace with `core::cell::LazyCell` () or similar -pub static NODE_OVERRIDES: once_cell::sync::Lazy = once_cell::sync::Lazy::new(static_node_properties); - -/// Defines the logic for inputs to display a custom Properties panel widget. -fn static_node_properties() -> NodeProperties { - let mut map: NodeProperties = HashMap::new(); - map.insert("brightness_contrast_properties".to_string(), Box::new(node_properties::brightness_contrast_properties)); - map.insert("channel_mixer_properties".to_string(), Box::new(node_properties::channel_mixer_properties)); - map.insert("levels_properties".to_string(), Box::new(node_properties::levels_properties)); - map.insert("transfer_curves_properties".to_string(), Box::new(node_properties::transfer_curves_properties)); - map.insert("hue_saturation_properties".to_string(), Box::new(node_properties::hue_saturation_properties)); - map.insert("black_and_white_properties".to_string(), Box::new(node_properties::black_and_white_properties)); - map.insert("threshold_properties".to_string(), Box::new(node_properties::threshold_properties)); - map.insert("vibrance_properties".to_string(), Box::new(node_properties::vibrance_properties)); - map.insert("color_balance_properties".to_string(), Box::new(node_properties::color_balance_properties)); - map.insert("fill_properties".to_string(), Box::new(node_properties::fill_properties)); - map.insert("stroke_properties".to_string(), Box::new(node_properties::stroke_properties)); - map.insert("offset_path_properties".to_string(), Box::new(node_properties::offset_path_properties)); - map.insert("selective_color_properties".to_string(), Box::new(node_properties::selective_color_properties)); - map.insert("exposure_properties".to_string(), Box::new(node_properties::exposure_properties)); - map.insert("format_number_properties".to_string(), Box::new(node_properties::format_number_properties)); - map.insert("string_capitalization_properties".to_string(), Box::new(node_properties::string_capitalization_properties)); - map.insert("rectangle_properties".to_string(), Box::new(node_properties::rectangle_properties)); - map.insert("grid_properties".to_string(), Box::new(node_properties::grid_properties)); - map.insert("spiral_properties".to_string(), Box::new(node_properties::spiral_properties)); - map.insert("sample_polyline_properties".to_string(), Box::new(node_properties::sample_polyline_properties)); +pub static NODE_OVERRIDES: once_cell::sync::Lazy = once_cell::sync::Lazy::new(static_node_inspector); + +/// Defines the logic for inputs to display a custom Inspector widget. +fn static_node_inspector() -> NodeInspector { + let mut map: NodeInspector = HashMap::new(); + map.insert("brightness_contrast_inspector".to_string(), Box::new(node_inspector::brightness_contrast_inspector)); + map.insert("channel_mixer_inspector".to_string(), Box::new(node_inspector::channel_mixer_inspector)); + map.insert("levels_inspector".to_string(), Box::new(node_inspector::levels_inspector)); + map.insert("transfer_curves_inspector".to_string(), Box::new(node_inspector::transfer_curves_inspector)); + map.insert("hue_saturation_inspector".to_string(), Box::new(node_inspector::hue_saturation_inspector)); + map.insert("black_and_white_inspector".to_string(), Box::new(node_inspector::black_and_white_inspector)); + map.insert("threshold_inspector".to_string(), Box::new(node_inspector::threshold_inspector)); + map.insert("vibrance_inspector".to_string(), Box::new(node_inspector::vibrance_inspector)); + map.insert("color_balance_inspector".to_string(), Box::new(node_inspector::color_balance_inspector)); + map.insert("fill_inspector".to_string(), Box::new(node_inspector::fill_inspector)); + map.insert("stroke_inspector".to_string(), Box::new(node_inspector::stroke_inspector)); + map.insert("offset_path_inspector".to_string(), Box::new(node_inspector::offset_path_inspector)); + map.insert("selective_color_inspector".to_string(), Box::new(node_inspector::selective_color_inspector)); + map.insert("exposure_inspector".to_string(), Box::new(node_inspector::exposure_inspector)); + map.insert("format_number_inspector".to_string(), Box::new(node_inspector::format_number_inspector)); + map.insert("string_capitalization_inspector".to_string(), Box::new(node_inspector::string_capitalization_inspector)); + map.insert("rectangle_inspector".to_string(), Box::new(node_inspector::rectangle_inspector)); + map.insert("grid_inspector".to_string(), Box::new(node_inspector::grid_inspector)); + map.insert("spiral_inspector".to_string(), Box::new(node_inspector::spiral_inspector)); + map.insert("sample_polyline_inspector".to_string(), Box::new(node_inspector::sample_polyline_inspector)); map.insert( - "monitor_properties".to_string(), - Box::new(|_node_id, _context| node_properties::string_properties("Used internally by the editor to obtain a layer thumbnail.")), + "monitor_inspector".to_string(), + Box::new(|_node_id, _context| node_inspector::string_inspector("Used internally by the editor to obtain a layer thumbnail.")), ); map } -type InputProperties = HashMap Result, String> + Send + Sync>>; +type InputInspector = HashMap Result, String> + Send + Sync>>; // TODO: Replace with `core::cell::LazyCell` () or similar -static INPUT_OVERRIDES: once_cell::sync::Lazy = once_cell::sync::Lazy::new(static_input_properties); +static INPUT_OVERRIDES: once_cell::sync::Lazy = once_cell::sync::Lazy::new(static_input_inspector); -/// Defines the logic for inputs to display a custom Properties panel widget. -fn static_input_properties() -> InputProperties { - let mut map: InputProperties = HashMap::new(); +/// Defines the logic for inputs to display a custom Inspector widget. +fn static_input_inspector() -> InputInspector { + let mut map: InputInspector = HashMap::new(); map.insert("hidden".to_string(), Box::new(|_node_id, _index, _context| Ok(Vec::new()))); map.insert( "string".to_string(), Box::new(|node_id, index, context| { - let Some(value) = context.network_interface.input_data(&node_id, index, "string_properties", context.selection_network_path) else { - return Err(format!("Could not get string properties for node {node_id}")); + // Falls back to the legacy key + let network_interface = &context.network_interface; + let Some(value) = network_interface + .input_data(&node_id, index, "string_inspector", context.selection_network_path) + .or_else(|| network_interface.input_data(&node_id, index, "string_properties", context.selection_network_path)) + else { + return Err(format!("Could not get string Inspector input data for node {node_id}")); }; let Some(string) = value.as_str() else { - return Err(format!("Could not downcast string properties for node {node_id}")); + return Err(format!("Could not downcast string Inspector input data for node {node_id}")); }; - Ok(node_properties::string_properties(string)) + Ok(node_inspector::string_inspector(string)) }), ); map.insert( @@ -947,7 +952,7 @@ fn static_input_properties() -> InputProperties { true }); - Ok(vec![LayoutGroup::row(node_properties::number_widget( + Ok(vec![LayoutGroup::row(node_inspector::number_widget( ParameterWidgetsInfo::at_index(node_id, index, blank_assist, context), number_input, ))]) @@ -969,7 +974,7 @@ fn static_input_properties() -> InputProperties { if let Some(unit) = field.unit { number_input = number_input.unit(unit); } - // Typing is clamped only by the hard bounds; the slider extent prefers the soft bounds (see `property_from_type`) + // Typing is clamped only by the hard bounds; the slider extent prefers the soft bounds (see `inspector_row_from_type`) if let Some(hard_min) = field.number_hard_min { number_input = number_input.min(hard_min); } @@ -988,7 +993,7 @@ fn static_input_properties() -> InputProperties { } }; // NOTE: The bool input MUST be at the input index directly before the f64 input! - Ok(vec![LayoutGroup::row(node_properties::optional_f64_widget( + Ok(vec![LayoutGroup::row(node_inspector::optional_f64_widget( ParameterWidgetsInfo::at_index(node_id, index, false, context), index - 1, number_input, @@ -1007,7 +1012,7 @@ fn static_input_properties() -> InputProperties { max: 100., default: Some(100.), }; - Ok(vec![LayoutGroup::row(node_properties::optional_f64_widget( + Ok(vec![LayoutGroup::row(node_inspector::optional_f64_widget( ParameterWidgetsInfo::at_index(node_id, index, false, context), index - 1, number_input, @@ -1018,7 +1023,7 @@ fn static_input_properties() -> InputProperties { map.insert( // A type-witness input, whose stored value's type selects the node's row: the dropdown lists the types the rows accept there "type_choice".to_string(), - Box::new(|node_id, index, context| Ok(vec![node_properties::type_choice_widget(ParameterWidgetsInfo::at_index(node_id, index, true, context))])), + Box::new(|node_id, index, context| Ok(vec![node_inspector::type_choice_widget(ParameterWidgetsInfo::at_index(node_id, index, true, context))])), ); map.insert( "vec2".to_string(), @@ -1060,7 +1065,7 @@ fn static_input_properties() -> InputProperties { .and_then(|value| value.as_bool()) .unwrap_or_default(); - Ok(vec![node_properties::vec2_widget( + Ok(vec![node_inspector::vec2_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), &x, &y, @@ -1071,10 +1076,10 @@ fn static_input_properties() -> InputProperties { }), ); map.insert( - "noise_properties_scale".to_string(), + "noise_inspector_scale".to_string(), Box::new(|node_id, index, context| { - let (_, coherent_noise_active, _, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; - let scale = node_properties::number_widget( + let (_, coherent_noise_active, _, _, _, _) = node_inspector::query_noise_pattern_state(node_id, context)?; + let scale = node_inspector::number_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), NumberInput::default().min(0.).disabled(!coherent_noise_active), ); @@ -1082,28 +1087,28 @@ fn static_input_properties() -> InputProperties { }), ); map.insert( - "noise_properties_noise_type".to_string(), + "noise_inspector_noise_type".to_string(), Box::new(|node_id, index, context| { - let noise_type_row = enum_choice::().for_socket(ParameterWidgetsInfo::at_index(node_id, index, true, context)).property_row(); + let noise_type_row = enum_choice::().for_socket(ParameterWidgetsInfo::at_index(node_id, index, true, context)).inspector_row(); Ok(vec![noise_type_row, LayoutGroup::row(Vec::new())]) }), ); map.insert( - "noise_properties_domain_warp_type".to_string(), + "noise_inspector_domain_warp_type".to_string(), Box::new(|node_id, index, context| { - let (_, coherent_noise_active, _, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; + let (_, coherent_noise_active, _, _, _, _) = node_inspector::query_noise_pattern_state(node_id, context)?; let domain_warp_type = enum_choice::() .for_socket(ParameterWidgetsInfo::at_index(node_id, index, true, context)) .disabled(!coherent_noise_active) - .property_row(); + .inspector_row(); Ok(vec![domain_warp_type]) }), ); map.insert( - "noise_properties_domain_warp_amplitude".to_string(), + "noise_inspector_domain_warp_amplitude".to_string(), Box::new(|node_id, index, context| { - let (_, coherent_noise_active, _, _, domain_warp_active, _) = node_properties::query_noise_pattern_state(node_id, context)?; - let domain_warp_amplitude = node_properties::number_widget( + let (_, coherent_noise_active, _, _, domain_warp_active, _) = node_inspector::query_noise_pattern_state(node_id, context)?; + let domain_warp_amplitude = node_inspector::number_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), NumberInput::default().min(0.).disabled(!coherent_noise_active || !domain_warp_active), ); @@ -1111,21 +1116,21 @@ fn static_input_properties() -> InputProperties { }), ); map.insert( - "noise_properties_fractal_type".to_string(), + "noise_inspector_fractal_type".to_string(), Box::new(|node_id, index, context| { - let (_, coherent_noise_active, _, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; + let (_, coherent_noise_active, _, _, _, _) = node_inspector::query_noise_pattern_state(node_id, context)?; let fractal_type_row = enum_choice::() .for_socket(ParameterWidgetsInfo::at_index(node_id, index, true, context)) .disabled(!coherent_noise_active) - .property_row(); + .inspector_row(); Ok(vec![fractal_type_row]) }), ); map.insert( - "noise_properties_fractal_octaves".to_string(), + "noise_inspector_fractal_octaves".to_string(), Box::new(|node_id, index, context| { - let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_properties::query_noise_pattern_state(node_id, context)?; - let fractal_octaves = node_properties::number_widget( + let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_inspector::query_noise_pattern_state(node_id, context)?; + let fractal_octaves = node_inspector::number_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), NumberInput::default() .mode_range() @@ -1139,10 +1144,10 @@ fn static_input_properties() -> InputProperties { }), ); map.insert( - "noise_properties_fractal_lacunarity".to_string(), + "noise_inspector_fractal_lacunarity".to_string(), Box::new(|node_id, index, context| { - let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_properties::query_noise_pattern_state(node_id, context)?; - let fractal_lacunarity = node_properties::number_widget( + let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_inspector::query_noise_pattern_state(node_id, context)?; + let fractal_lacunarity = node_inspector::number_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), NumberInput::default() .mode_range() @@ -1154,10 +1159,10 @@ fn static_input_properties() -> InputProperties { }), ); map.insert( - "noise_properties_fractal_gain".to_string(), + "noise_inspector_fractal_gain".to_string(), Box::new(|node_id, index, context| { - let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_properties::query_noise_pattern_state(node_id, context)?; - let fractal_gain = node_properties::number_widget( + let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_inspector::query_noise_pattern_state(node_id, context)?; + let fractal_gain = node_inspector::number_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), NumberInput::default() .mode_range() @@ -1169,10 +1174,10 @@ fn static_input_properties() -> InputProperties { }), ); map.insert( - "noise_properties_fractal_weighted_strength".to_string(), + "noise_inspector_fractal_weighted_strength".to_string(), Box::new(|node_id, index, context| { - let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_properties::query_noise_pattern_state(node_id, context)?; - let fractal_weighted_strength = node_properties::range_slider_widget( + let (fractal_active, coherent_noise_active, _, _, _, domain_warp_only_fractal_type_wrongly_active) = node_inspector::query_noise_pattern_state(node_id, context)?; + let fractal_weighted_strength = node_inspector::range_slider_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), NumberInput::default() .min(0.) @@ -1184,10 +1189,10 @@ fn static_input_properties() -> InputProperties { }), ); map.insert( - "noise_properties_ping_pong_strength".to_string(), + "noise_inspector_ping_pong_strength".to_string(), Box::new(|node_id, index, context| { - let (fractal_active, coherent_noise_active, _, ping_pong_active, _, domain_warp_only_fractal_type_wrongly_active) = node_properties::query_noise_pattern_state(node_id, context)?; - let fractal_ping_pong_strength = node_properties::number_widget( + let (fractal_active, coherent_noise_active, _, ping_pong_active, _, domain_warp_only_fractal_type_wrongly_active) = node_inspector::query_noise_pattern_state(node_id, context)?; + let fractal_ping_pong_strength = node_inspector::number_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), NumberInput::default() .mode_range() @@ -1199,32 +1204,32 @@ fn static_input_properties() -> InputProperties { }), ); map.insert( - "noise_properties_cellular_distance_function".to_string(), + "noise_inspector_cellular_distance_function".to_string(), Box::new(|node_id, index, context| { - let (_, coherent_noise_active, cellular_noise_active, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; + let (_, coherent_noise_active, cellular_noise_active, _, _, _) = node_inspector::query_noise_pattern_state(node_id, context)?; let cellular_distance_function_row = enum_choice::() .for_socket(ParameterWidgetsInfo::at_index(node_id, index, true, context)) .disabled(!coherent_noise_active || !cellular_noise_active) - .property_row(); + .inspector_row(); Ok(vec![cellular_distance_function_row]) }), ); map.insert( - "noise_properties_cellular_return_type".to_string(), + "noise_inspector_cellular_return_type".to_string(), Box::new(|node_id, index, context| { - let (_, coherent_noise_active, cellular_noise_active, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; + let (_, coherent_noise_active, cellular_noise_active, _, _, _) = node_inspector::query_noise_pattern_state(node_id, context)?; let cellular_return_type = enum_choice::() .for_socket(ParameterWidgetsInfo::at_index(node_id, index, true, context)) .disabled(!coherent_noise_active || !cellular_noise_active) - .property_row(); + .inspector_row(); Ok(vec![cellular_return_type]) }), ); map.insert( - "noise_properties_cellular_jitter".to_string(), + "noise_inspector_cellular_jitter".to_string(), Box::new(|node_id, index, context| { - let (_, coherent_noise_active, cellular_noise_active, _, _, _) = node_properties::query_noise_pattern_state(node_id, context)?; - let cellular_jitter = node_properties::number_widget( + let (_, coherent_noise_active, cellular_noise_active, _, _, _) = node_inspector::query_noise_pattern_state(node_id, context)?; + let cellular_jitter = node_inspector::number_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), NumberInput::default() .mode_range() @@ -1238,15 +1243,15 @@ fn static_input_properties() -> InputProperties { map.insert( "assign_colors_gradient".to_string(), Box::new(|node_id, index, context| { - let gradient_row = node_properties::color_widget(ParameterWidgetsInfo::at_index(node_id, index, true, context), ColorInput::default().allow_none(false)); + let gradient_row = node_inspector::color_widget(ParameterWidgetsInfo::at_index(node_id, index, true, context), ColorInput::default().allow_none(false)); Ok(vec![gradient_row]) }), ); map.insert( "assign_colors_seed".to_string(), Box::new(|node_id, index, context| { - let randomize_enabled = node_properties::query_assign_colors_randomize(node_id, context)?; - let seed_row = node_properties::number_widget( + let randomize_enabled = node_inspector::query_assign_colors_randomize(node_id, context)?; + let seed_row = node_inspector::number_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), NumberInput::default().min(0.).int().disabled(!randomize_enabled), ); @@ -1256,8 +1261,8 @@ fn static_input_properties() -> InputProperties { map.insert( "assign_colors_repeat_every".to_string(), Box::new(|node_id, index, context| { - let randomize_enabled = node_properties::query_assign_colors_randomize(node_id, context)?; - let repeat_every_row = node_properties::number_widget( + let randomize_enabled = node_inspector::query_assign_colors_randomize(node_id, context)?; + let repeat_every_row = node_inspector::number_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), NumberInput::default().min(0.).int().disabled(randomize_enabled), ); @@ -1267,9 +1272,9 @@ fn static_input_properties() -> InputProperties { map.insert( "transform_rotation".to_string(), Box::new(|node_id, index, context| { - let mut widgets = node_properties::start_widgets(&ParameterWidgetsInfo::at_index(node_id, index, true, context)); + let mut widgets = node_inspector::start_widgets(&ParameterWidgetsInfo::at_index(node_id, index, true, context)); - let document_node = node_properties::get_document_node(node_id, context)?; + let document_node = node_inspector::get_document_node(node_id, context)?; let Some(input) = document_node.inputs.get(index) else { return Err("Input not found in transform rotation input override".to_string()); }; @@ -1281,12 +1286,12 @@ fn static_input_properties() -> InputProperties { .mode(NumberInputMode::Range) .range_min(Some(-180.)) .range_max(Some(180.)) - .on_update(node_properties::update_value_at_index( + .on_update(node_inspector::update_value_at_index( |number_input: &NumberInput| TaggedValue::Number(number_input.value.unwrap()), node_id, index, )) - .on_commit(node_properties::commit_value) + .on_commit(node_inspector::commit_value) .widget_instance(), ]); } @@ -1298,7 +1303,7 @@ fn static_input_properties() -> InputProperties { map.insert( "transform_translation".to_string(), Box::new(|node_id, index, context| { - Ok(vec![node_properties::vec2_widget( + Ok(vec![node_inspector::vec2_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), "X", "Y", @@ -1312,7 +1317,7 @@ fn static_input_properties() -> InputProperties { map.insert( "transform_scale".to_string(), Box::new(|node_id, index, context| { - Ok(vec![node_properties::vec2_widget( + Ok(vec![node_inspector::vec2_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), "W", "H", @@ -1326,9 +1331,9 @@ fn static_input_properties() -> InputProperties { map.insert( "transform_skew".to_string(), Box::new(|node_id, index, context| { - let mut widgets = node_properties::start_widgets(&ParameterWidgetsInfo::at_index(node_id, index, true, context)); + let mut widgets = node_inspector::start_widgets(&ParameterWidgetsInfo::at_index(node_id, index, true, context)); - let document_node = node_properties::get_document_node(node_id, context)?; + let document_node = node_inspector::get_document_node(node_id, context)?; let Some(input) = document_node.inputs.get(index) else { return Err("Input not found in transform skew input override".to_string()); }; @@ -1340,12 +1345,12 @@ fn static_input_properties() -> InputProperties { .unit("°") .min(-89.9) .max(89.9) - .on_update(node_properties::update_value_at_index( + .on_update(node_inspector::update_value_at_index( move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(input.value.unwrap(), val.y)), node_id, index, )) - .on_commit(node_properties::commit_value) + .on_commit(node_inspector::commit_value) .widget_instance(), Separator::new(SeparatorStyle::Related).widget_instance(), NumberInput::new(Some(val.y)) @@ -1353,12 +1358,12 @@ fn static_input_properties() -> InputProperties { .unit("°") .min(-89.9) .max(89.9) - .on_update(node_properties::update_value_at_index( + .on_update(node_inspector::update_value_at_index( move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(val.x, input.value.unwrap())), node_id, index, )) - .on_commit(node_properties::commit_value) + .on_commit(node_inspector::commit_value) .widget_instance(), ]); } @@ -1368,14 +1373,14 @@ fn static_input_properties() -> InputProperties { ); map.insert( "text_area".to_string(), - Box::new(|node_id, index, context| Ok(vec![LayoutGroup::row(node_properties::text_area_widget(ParameterWidgetsInfo::at_index(node_id, index, true, context)))])), + Box::new(|node_id, index, context| Ok(vec![LayoutGroup::row(node_inspector::text_area_widget(ParameterWidgetsInfo::at_index(node_id, index, true, context)))])), ); map.insert( // A math expression, flagged with a warning icon while it fails to parse "math_expression".to_string(), Box::new(|node_id, index, context| { let info = ParameterWidgetsInfo::at_index(node_id, index, true, context); - Ok(vec![LayoutGroup::row(node_properties::math_expression_widget(info, false))]) + Ok(vec![LayoutGroup::row(node_inspector::math_expression_widget(info, false))]) }), ); map.insert( @@ -1383,7 +1388,7 @@ fn static_input_properties() -> InputProperties { "math_expression_or_reducer".to_string(), Box::new(|node_id, index, context| { let info = ParameterWidgetsInfo::at_index(node_id, index, true, context); - Ok(vec![LayoutGroup::row(node_properties::math_expression_widget(info, true))]) + Ok(vec![LayoutGroup::row(node_inspector::math_expression_widget(info, true))]) }), ); map.insert( @@ -1393,7 +1398,7 @@ fn static_input_properties() -> InputProperties { if context.fonts.font_catalog.is_empty() { context.responses.add(FontsMessage::LoadCatalog); } - let (font, style) = node_properties::font_inputs(ParameterWidgetsInfo::at_index(node_id, index, true, context)); + let (font, style) = node_inspector::font_inputs(ParameterWidgetsInfo::at_index(node_id, index, true, context)); let mut result = vec![LayoutGroup::row(font)]; if let Some(style) = style { result.push(LayoutGroup::row(style)); @@ -1404,21 +1409,21 @@ fn static_input_properties() -> InputProperties { map.insert( "image_file".to_string(), Box::new(|node_id, index, context| { - let widgets = node_properties::resource_widget(ParameterWidgetsInfo::at_index(node_id, index, true, context), vec![TypeFilter::raster()]); + let widgets = node_inspector::resource_widget(ParameterWidgetsInfo::at_index(node_id, index, true, context), vec![TypeFilter::raster()]); Ok(vec![LayoutGroup::row(widgets)]) }), ); map.insert( "lut_file".to_string(), Box::new(|node_id, index, context| { - let widgets = node_properties::resource_widget(ParameterWidgetsInfo::at_index(node_id, index, true, context), vec![TypeFilter::lut()]); + let widgets = node_inspector::resource_widget(ParameterWidgetsInfo::at_index(node_id, index, true, context), vec![TypeFilter::lut()]); Ok(vec![LayoutGroup::row(widgets)]) }), ); map.insert( "artboard_background".to_string(), Box::new(|node_id, index, context| { - Ok(vec![node_properties::color_widget( + Ok(vec![node_inspector::color_widget( ParameterWidgetsInfo::at_index(node_id, index, true, context), ColorInput::default().allow_none(false), )]) @@ -1429,7 +1434,7 @@ fn static_input_properties() -> InputProperties { Box::new(|node_id, index, context| { let choices = enum_choice::() .for_socket(ParameterWidgetsInfo::at_index(node_id, index, true, context)) - .property_row(); + .inspector_row(); Ok(vec![choices]) }), ); @@ -1626,7 +1631,7 @@ impl DocumentNodeDefinition { } }); - // Ensure that the input properties are initialized for every input of every node + // Ensure that the input metadata is initialized for every input of every node template.normalize_input_metadata(); template diff --git a/editor/src/messages/portfolio/document/node_graph/document_node_definitions/document_node_derive.rs b/editor/src/messages/portfolio/document/node_graph/document_node_definitions/document_node_derive.rs index a59351751df..0a6c87069ce 100644 --- a/editor/src/messages/portfolio/document/node_graph/document_node_definitions/document_node_derive.rs +++ b/editor/src/messages/portfolio/document/node_graph/document_node_definitions/document_node_derive.rs @@ -41,7 +41,7 @@ pub(super) fn post_process_nodes(custom: Vec) -> HashMap icon, fields, description, - properties, + inspector, context_features, output_fields, .. @@ -107,7 +107,7 @@ pub(super) fn post_process_nodes(custom: Vec) -> HashMap category, icon: *icon, description: Cow::Borrowed(description), - properties: *properties, + inspector: *inspector, }, ); } diff --git a/editor/src/messages/portfolio/document/node_graph/mod.rs b/editor/src/messages/portfolio/document/node_graph/mod.rs index bd250164380..6f1f4803197 100644 --- a/editor/src/messages/portfolio/document/node_graph/mod.rs +++ b/editor/src/messages/portfolio/document/node_graph/mod.rs @@ -1,7 +1,7 @@ pub mod document_node_definitions; mod node_graph_message; mod node_graph_message_handler; -pub mod node_properties; +pub mod node_inspector; pub mod utility_types; #[doc(inline)] 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 c3df9ff0f7a..e0dfcb9c4da 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 @@ -1,4 +1,4 @@ -use super::node_properties; +use super::node_inspector; use super::utility_types::{BoxSelection, ContextMenuInformation, DragStart, FrontendNode}; use crate::consts::GRID_SIZE; use crate::messages::input_mapper::utility_types::macros::{action_shortcut, action_shortcut_manual}; @@ -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::{ - DefinitionIdentifier, NodePropertiesContext, resolve_document_node_type, resolve_network_node_type, resolve_proto_node_type, + DefinitionIdentifier, NodeInspectorContext, resolve_document_node_type, resolve_network_node_type, resolve_proto_node_type, }; use crate::messages::portfolio::document::node_graph::utility_types::{ContextMenuData, Direction, FrontendGraphDataType, NodeGraphErrorDiagnostic}; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; @@ -39,8 +39,8 @@ pub struct NodeGraphMessageContext<'a> { pub breadcrumb_network_path: &'a [NodeId], pub document_id: DocumentId, pub collapsed: &'a mut CollapsedLayers, - pub properties_panel_collapsed_sections: &'a mut Vec, - pub properties_panel_expanded_input_chains: &'a mut Vec<(NodeId, Option)>, + pub inspector_collapsed_sections: &'a mut Vec, + pub inspector_expanded_input_chains: &'a mut Vec<(NodeId, Option)>, pub layers_panel_expanded_chains: &'a mut Vec, pub ipp: &'a InputPreprocessorMessageHandler, pub graph_view_overlay_open: bool, @@ -116,8 +116,8 @@ impl<'a> MessageHandler> for NodeG breadcrumb_network_path, document_id, collapsed, - properties_panel_collapsed_sections, - properties_panel_expanded_input_chains, + inspector_collapsed_sections, + inspector_expanded_input_chains, layers_panel_expanded_chains, ipp, graph_view_overlay_open, @@ -202,12 +202,12 @@ impl<'a> MessageHandler> for NodeG // Prune the Layers panel collapsed state for any layer tree paths whose nodes no longer exist, so it doesn't accumulate across loads collapsed.0.retain(|path| path.iter().all(|&node_id| network_interface.document_network().nodes.contains_key(&node_id))); - // Prune the Properties panel node section collapsed state for any nodes (in any nested network) that no longer exist, so it doesn't accumulate across loads + // Prune the Inspector node section collapsed state for any nodes (in any nested network) that no longer exist, so it doesn't accumulate across loads let existing_nodes = network_interface.document_network().recursive_nodes().map(|(node_id, ..)| *node_id).collect::>(); - properties_panel_collapsed_sections.retain(|node_id| existing_nodes.contains(node_id)); + inspector_collapsed_sections.retain(|node_id| existing_nodes.contains(node_id)); - // Likewise for the Properties panel's expanded input chains and the Layers panel's expanded layer chains - properties_panel_expanded_input_chains.retain(|(node_id, _)| existing_nodes.contains(node_id)); + // Likewise for the Inspector's expanded input chains and the Layers panel's expanded layer chains + inspector_expanded_input_chains.retain(|(node_id, _)| existing_nodes.contains(node_id)); layers_panel_expanded_chains.retain(|node_id| existing_nodes.contains(node_id)); } NodeGraphMessage::SelectedNodesUpdated => { @@ -219,7 +219,7 @@ impl<'a> MessageHandler> for NodeG } responses.add(MenuBarMessage::SendLayout); responses.add(NodeGraphMessage::UpdateLayerPanel); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); responses.add(NodeGraphMessage::SendSelectedNodes); responses.add(ArtboardToolMessage::UpdateSelectedArtboard); responses.add(DocumentMessage::DocumentStructureChanged); @@ -272,7 +272,7 @@ impl<'a> MessageHandler> for NodeG NodeGraphMessage::CreateNodeInLayerWithTransaction { node_type, layer } => { responses.add(DocumentMessage::AddTransaction); responses.add(NodeGraphMessage::CreateNodeInLayerNoTransaction { node_type, layer }); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); responses.add(NodeGraphMessage::RunDocumentGraph); } NodeGraphMessage::CreateNodeFromContextMenu { @@ -493,7 +493,7 @@ impl<'a> MessageHandler> for NodeG // Update the graph UI and re-render if graph_view_overlay_open { - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); responses.add(NodeGraphMessage::SendGraph); } else { responses.add(DocumentMessage::GraphViewOverlay { open: true }); @@ -1793,7 +1793,7 @@ impl<'a> MessageHandler> for NodeG NodeGraphMessage::SendGraph => { responses.add(NodeGraphMessage::UpdateLayerPanel); responses.add(DocumentMessage::DocumentStructureChanged); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); responses.add(EventMessage::GraphChanged); if breadcrumb_network_path == selection_network_path && graph_view_overlay_open { let nodes = self.collect_nodes(network_interface, breadcrumb_network_path); @@ -1833,7 +1833,7 @@ impl<'a> MessageHandler> for NodeG input_connector: InputConnector::node_at_index(node_id, input_index), input, }); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); if is_fill_input { responses.add(OverlaysMessage::Draw); } @@ -2099,7 +2099,7 @@ impl<'a> MessageHandler> for NodeG responses.add(NodeGraphMessage::UpdateActionButtons); responses.add(NodeGraphMessage::SendGraph); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); responses.add(DataPanelMessage::Refresh); } NodeGraphMessage::UpdateBoxSelection => { @@ -2555,17 +2555,17 @@ impl NodeGraphMessageHandler { self.widgets[1] = LayoutGroup::row(widgets); } - /// Collate the Properties panel sections for a node graph - pub fn collate_properties(context: &mut NodePropertiesContext) -> Vec { + /// Collate the Inspector sections for a node graph + pub fn collate_inspector_sections(context: &mut NodeInspectorContext) -> Vec { // If the selected nodes are in the document network, use the document network. Otherwise, use the nested network let Some(selected_nodes) = context.network_interface.selected_nodes_in_nested_network(context.selection_network_path) else { - warn!("No selected nodes in collate_properties"); + warn!("No selected nodes in collate_inspector_sections"); return Vec::new(); }; // We want: - // - If only nodes (no layers) are selected: display each node's properties - // - If one layer is selected, and zero or more of its (primary flow) upstream nodes: display the properties for the layer and all its upstream nodes + // - If only nodes (no layers) are selected: display each node's Inspector section + // - If one layer is selected, and zero or more of its (primary flow) upstream nodes: display the Inspector sections for the layer and all its upstream nodes // - If multiple layers are selected, or one node plus other non-upstream nodes: display nothing // - If nothing is selected, display any pinned nodes/layers @@ -2587,30 +2587,30 @@ impl NodeGraphMessageHandler { // Next, we decide what to display based on the number of layers and nodes selected match *layers.as_slice() { - // If no layers are selected, show properties for all selected nodes + // If no layers are selected, show Inspector sections for all selected nodes [] => { - let selected_nodes = nodes.iter().map(|node_id| node_properties::generate_node_properties(*node_id, context)).collect::>(); + let selected_nodes = nodes.iter().map(|node_id| node_inspector::generate_node_inspector(*node_id, context)).collect::>(); if !selected_nodes.is_empty() { return selected_nodes; } - // TODO: Display properties for encapsulating node when no nodes are selected in a nested network - // This may require store a separate path for the Properties panel - // And if no nodes are selected, show properties for all pinned nodes (in the user's saved order, each draggable to reorder) - let mut pinned_node_properties = context + // TODO: Display Inspector sections for encapsulating node when no nodes are selected in a nested network + // This may require store a separate path for the Inspector + // And if no nodes are selected, show Inspector sections for all pinned nodes (in the user's saved order, each draggable to reorder) + let mut pinned_node_inspector = context .network_interface .ordered_pinned_nodes(context.selection_network_path) .into_iter() - .map(|node_id| node_properties::generate_node_properties(node_id, context)) + .map(|node_id| node_inspector::generate_node_inspector(node_id, context)) .collect::>(); - for pinned_section in pinned_node_properties.iter_mut() { - if let LayoutGroup::Section(section) = pinned_section { + for pinned_section in pinned_node_inspector.iter_mut() { + if let LayoutGroup::NodeSection(section) = pinned_section { section.draggable = true; } } // With nothing pinned either, explain what can appear here - if pinned_node_properties.is_empty() { + if pinned_node_inspector.is_empty() { return vec![LayoutGroup::row(vec![ Separator::new(SeparatorStyle::Unrelated).widget_instance(), TextLabel::new("Select layers or nodes to inspect their parameters. Pin them for quick access here when nothing is selected.") @@ -2621,9 +2621,9 @@ impl NodeGraphMessageHandler { ])]; } - pinned_node_properties + pinned_node_inspector } - // If one layer is selected, filter out all selected nodes that are not upstream of it. If there are no nodes left, show properties for the layer. Otherwise, show nothing. + // If one layer is selected, filter out all selected nodes that are not upstream of it. If there are no nodes left, show the Inspector section for the layer. Otherwise, show nothing. [layer] => { let nodes_not_upstream_of_layer = nodes.into_iter().filter(|&selected_node_id| { !context @@ -2635,15 +2635,15 @@ impl NodeGraphMessageHandler { } // The layer's section, containing its chain's sections unless another input's chain is shown instead - let mut layer_section = node_properties::generate_node_properties(layer, context); + let mut layer_section = node_inspector::generate_node_inspector(layer, context); // The sections of the layer's own chain can be dragged to reorder it, except a node without a primary input (e.g. a generator) - let expanded_input_chain = node_properties::expanded_input_chain(&layer, context.properties_panel_expanded_input_chains, context.network_interface, context.selection_network_path); + let expanded_input_chain = node_inspector::expanded_input_chain(&layer, context.inspector_expanded_input_chains, context.network_interface, context.selection_network_path); if expanded_input_chain == Some(network_interface::LAYER_SECONDARY_INPUT_INDEX) - && let LayoutGroup::Section(section) = &mut layer_section + && let LayoutGroup::NodeSection(section) = &mut layer_section { for layout_group in section.layout.0.iter_mut() { - if let LayoutGroup::Section(chain_section) = layout_group + if let LayoutGroup::NodeSection(chain_section) = layout_group && chain_section.output_wire.is_some() && !chain_section.node_reference { diff --git a/editor/src/messages/portfolio/document/node_graph/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_inspector.rs similarity index 94% rename from editor/src/messages/portfolio/document/node_graph/node_properties.rs rename to editor/src/messages/portfolio/document/node_graph/node_inspector.rs index 4728c880c58..a408f9018c0 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_inspector.rs @@ -1,6 +1,6 @@ #![allow(clippy::too_many_arguments)] -use super::document_node_definitions::{NODE_OVERRIDES, NodePropertiesContext}; +use super::document_node_definitions::{NODE_OVERRIDES, NodeInspectorContext}; use super::utility_types::FrontendGraphDataType; use crate::messages::layout::utility_types::math_expression::{MathExpressionTokens, math_expression_error, math_expression_error_ranges, math_expression_tokens}; use crate::messages::layout::utility_types::tooltip_markdown::{escape_markdown, markdown_code_span}; @@ -45,7 +45,7 @@ use graphene_std::{NodeParameter, ParameterRef}; use math_parser::parser::{MessagePart, ParseError}; use std::path::PathBuf; -pub(crate) fn string_properties(text: &str) -> Vec { +pub(crate) fn string_inspector(text: &str) -> Vec { let widget = TextLabel::new(text).widget_instance(); vec![LayoutGroup::row(vec![widget])] } @@ -106,7 +106,7 @@ pub fn expose_widget(node_id: NodeId, index: usize, data_type: FrontendGraphData // TODO: Remove this when we have proper entry row formatting that includes room for Assists. pub fn add_blank_assist(widgets: &mut Vec) { widgets.extend_from_slice(&[ - // Custom CSS specific to the Properties panel converts this Section separator into the width of an assist (24px). + // Custom CSS specific to the Inspector converts this Section separator into the width of an assist (24px). Separator::new(SeparatorStyle::Section).widget_instance(), // This last one is the separator after the 24px assist. Separator::new(SeparatorStyle::Unrelated).widget_instance(), @@ -204,7 +204,7 @@ pub fn start_widgets(parameter_widgets_info: &ParameterWidgetsInfo) -> Vec O } } -pub(crate) fn property_from_type(node_id: NodeId, index: usize, ty: &Type, options: ParameterOptions, context: &mut NodePropertiesContext) -> Result, Vec> { +pub(crate) fn inspector_row_from_type(node_id: NodeId, index: usize, ty: &Type, options: ParameterOptions, context: &mut NodeInspectorContext) -> Result, Vec> { let ParameterOptions { soft_min, soft_max, @@ -396,54 +396,54 @@ pub(crate) fn property_from_type(node_id: NodeId, index: usize, ty: &Type, optio // ========================= // AUTO-GENERATED ENUM TYPES // ========================= - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), - Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).property_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).disabled(false).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), + Some(x) if id_is::(x) => enum_choice::().for_socket(default_info).inspector_row(), // ===== // OTHER // ===== _ => return Err(unsupported_widgets(default_info, concrete_type.to_string())), } } - Type::Item(element) => return property_from_type(node_id, index, element, options, context), + Type::Item(element) => return inspector_row_from_type(node_id, index, element, options, context), Type::List(element) => match element.as_ref() { Type::Concrete(element_type) if element_type.name == std::any::type_name::() => array_of_number_widget(default_info, TextInput::default()).into(), _ => return Err(unsupported_widgets(default_info, ty.to_string())), }, Type::Generic(_) => vec![TextLabel::new("Generic Type (Not Supported)").widget_instance()].into(), - Type::Fn(_, out) => return property_from_type(node_id, index, out, options, context), - Type::Future(out) => return property_from_type(node_id, index, out, options, context), + Type::Fn(_, out) => return inspector_row_from_type(node_id, index, out, options, context), + Type::Future(out) => return inspector_row_from_type(node_id, index, out, options, context), }; extra_widgets.push(widgets); @@ -1369,7 +1369,7 @@ fn type_choice_sections(offered: &[Type]) -> Vec> { pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button: ColorInput) -> LayoutGroup { let mut widgets = start_widgets(¶meter_widgets_info); - // Return early with just the label if the input is exposed to the graph, meaning we don't want to show the color picker widget in the Properties panel + // Return early with just the label if the input is exposed to the graph, meaning we don't want to show the color picker widget in the Inspector let Some(NodeInput::Value { tagged_value, exposed: false }) = parameter_widgets_info.input() else { return LayoutGroup::row(widgets); }; @@ -1570,7 +1570,7 @@ pub fn resource_widget(parameter_widgets_info: ParameterWidgetsInfo, filters: Ve widgets } -pub fn get_document_node<'a>(node_id: NodeId, context: &'a NodePropertiesContext<'a>) -> Result<&'a DocumentNode, String> { +pub fn get_document_node<'a>(node_id: NodeId, context: &'a NodeInspectorContext<'a>) -> Result<&'a DocumentNode, String> { let network = context .network_interface .nested_network(context.selection_network_path) @@ -1578,14 +1578,14 @@ pub fn get_document_node<'a>(node_id: NodeId, context: &'a NodePropertiesContext network.nodes.get(&node_id).ok_or(format!("node {node_id} not found in get_document_node")) } -pub fn query_node_and_input_info<'a>(node_id: NodeId, input_index: usize, context: &'a mut NodePropertiesContext<'a>) -> Result<(&'a DocumentNode, String, String), String> { +pub fn query_node_and_input_info<'a>(node_id: NodeId, input_index: usize, context: &'a mut NodeInspectorContext<'a>) -> Result<(&'a DocumentNode, String, String), String> { let (name, description) = context.network_interface.displayed_input_name_and_description(&node_id, input_index, context.selection_network_path); let document_node = get_document_node(node_id, context)?; Ok((document_node, name, description)) } -pub fn query_noise_pattern_state(node_id: NodeId, context: &NodePropertiesContext) -> Result<(bool, bool, bool, bool, bool, bool), String> { +pub fn query_noise_pattern_state(node_id: NodeId, context: &NodeInspectorContext) -> Result<(bool, bool, bool, bool, bool, bool), String> { let document_node = get_document_node(node_id, context)?; let current_noise_type = document_node.inputs.iter().find_map(|input| match input.as_value() { Some(&TaggedValue::NoiseType(noise_type)) => Some(noise_type), @@ -1617,7 +1617,7 @@ pub fn query_noise_pattern_state(node_id: NodeId, context: &NodePropertiesContex )) } -pub fn query_assign_colors_randomize(node_id: NodeId, context: &NodePropertiesContext) -> Result { +pub fn query_assign_colors_randomize(node_id: NodeId, context: &NodeInspectorContext) -> Result { use graphene_std::vector::assign_colors::*; let document_node = get_document_node(node_id, context)?; @@ -1638,7 +1638,7 @@ fn color_track(color: Color) -> Gradient { Gradient::from(vec![Color::BLACK, color, Color::WHITE]) } -pub(crate) fn brightness_contrast_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn brightness_contrast_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::brightness_contrast::*; // Use Classic toggle changes the brightness range @@ -1690,12 +1690,12 @@ pub(crate) fn brightness_contrast_properties(node_id: NodeId, context: &mut Node layout } -pub(crate) fn transfer_curves_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn transfer_curves_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::curves::*; let mut channel_info = ParameterWidgetsInfo::new(node_id, ChannelInput, true, context); channel_info.exposable = false; - let channel = enum_choice::().for_socket(channel_info).property_row(); + let channel = enum_choice::().for_socket(channel_info).inspector_row(); let channel_value = match get_document_node(node_id, context).ok().and_then(|document_node| document_node.input_value(ChannelInput).cloned()) { Some(TaggedValue::AdjustmentChannel(channel)) => channel, @@ -1713,12 +1713,12 @@ pub(crate) fn transfer_curves_properties(node_id: NodeId, context: &mut NodeProp vec![channel, transfer_curve] } -pub(crate) fn levels_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn levels_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::levels::*; let mut channel_info = ParameterWidgetsInfo::new(node_id, ChannelInput, true, context); channel_info.exposable = false; - let channel = enum_choice::().for_socket(channel_info).property_row(); + let channel = enum_choice::().for_socket(channel_info).inspector_row(); let channel_value = match get_document_node(node_id, context).ok().and_then(|document_node| document_node.input_value(ChannelInput).cloned()) { Some(TaggedValue::AdjustmentChannel(channel)) => channel, @@ -1874,7 +1874,7 @@ impl SliderSectionParam { /// Append a section of related parameters as rows: a shared slider over `track` (with one marker per non-exposed parameter) sits on the first non-exposed row /// alongside its 60px number input, and the remaining non-exposed rows show only their 60px number input. Exposed parameters render as the standard exposed-row display. /// Marker positions are clamped to non-decreasing display order so they never visually cross even if the underlying values do. -fn build_shared_slider_section(node_id: NodeId, context: &mut NodePropertiesContext, track: &Gradient, params: &[SliderSectionParam], layout: &mut Vec) { +fn build_shared_slider_section(node_id: NodeId, context: &mut NodeInspectorContext, track: &Gradient, params: &[SliderSectionParam], layout: &mut Vec) { // Snapshot exposure and values before the mutable-borrow loop let exposure_and_value: Vec<(bool, f64)> = match get_document_node(node_id, context) { Ok(document_node) => params @@ -2051,13 +2051,13 @@ fn build_shared_slider_section(node_id: NodeId, context: &mut NodePropertiesCont } } -pub(crate) fn hue_saturation_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn hue_saturation_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::hue_saturation::*; let document_node = match get_document_node(node_id, context) { Ok(document_node) => document_node, Err(err) => { - log::error!("Could not get document node in hue_saturation_properties: {err}"); + log::error!("Could not get document node in hue_saturation_inspector: {err}"); return Vec::new(); } }; @@ -2172,7 +2172,7 @@ pub(crate) fn hue_saturation_properties(node_id: NodeId, context: &mut NodePrope // Colorize replaces the ranges, so while it is on the selector stays but grayed out and the selected range's edges hide let mut range_info = ParameterWidgetsInfo::new(node_id, RangeInput, true, context); range_info.exposable = false; - let mut layout = vec![enum_choice::().for_socket(range_info).disabled(colorize_value).property_row()]; + let mut layout = vec![enum_choice::().for_socket(range_info).disabled(colorize_value).inspector_row()]; layout.extend([ gradient_slider_row( @@ -2326,7 +2326,7 @@ pub(crate) fn range_slider_widget(parameter_widgets_info: ParameterWidgetsInfo, /// Build a row with a single-marker `SliderInput` over `track` and a 60px `NumberInput`. The marker maps `value_min..value_max` to position 0..1, and double-click resets to `default_value`. fn gradient_slider_row( node_id: NodeId, - context: &mut NodePropertiesContext, + context: &mut NodeInspectorContext, parameter: impl Into, track: Gradient, handle_color: Color, @@ -2382,7 +2382,7 @@ fn gradient_slider_row( LayoutGroup::row(row) } -pub(crate) fn threshold_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn threshold_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::threshold::*; let params = [ @@ -2396,7 +2396,7 @@ pub(crate) fn threshold_properties(node_id: NodeId, context: &mut NodeProperties layout } -pub(crate) fn vibrance_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn vibrance_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::vibrance::*; let number_input = NumberInput::default().mode_increment().unit("%").min(-100.).max(100.); @@ -2411,25 +2411,25 @@ pub(crate) fn vibrance_properties(node_id: NodeId, context: &mut NodePropertiesC vec![LayoutGroup::row(vibrance), LayoutGroup::row(saturation)] } -pub(crate) fn color_balance_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn color_balance_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::color_balance::*; let mut tone_info = ParameterWidgetsInfo::new(node_id, ToneInput, true, context); tone_info.exposable = false; - let tone = enum_choice::().for_socket(tone_info).property_row(); + let tone = enum_choice::().for_socket(tone_info).inspector_row(); let preserve_luminosity = bool_widget(ParameterWidgetsInfo::new(node_id, PreserveLuminosityInput, true, context), CheckboxInput::default()); let document_node = match get_document_node(node_id, context) { Ok(document_node) => document_node, Err(err) => { - log::error!("Could not get document node in color_balance_properties: {err}"); + log::error!("Could not get document node in color_balance_inspector: {err}"); return Vec::new(); } }; let tone_choice = match document_node.input_value(ToneInput) { Some(TaggedValue::TonalRange(choice)) => *choice, _ => { - warn!("Color Balance node properties panel could not be displayed."); + warn!("Color Balance node Inspector could not be displayed."); return vec![]; } }; @@ -2456,7 +2456,7 @@ pub(crate) fn color_balance_properties(node_id: NodeId, context: &mut NodeProper layout } -pub(crate) fn black_and_white_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn black_and_white_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::black_and_white::*; let number_input = NumberInput::default().mode_increment().unit("%").min(-200.).max(300.); @@ -2490,18 +2490,18 @@ pub(crate) fn black_and_white_properties(node_id: NodeId, context: &mut NodeProp layout } -pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn channel_mixer_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::channel_mixer::*; let is_monochrome = bool_widget(ParameterWidgetsInfo::new(node_id, MonochromeInput, true, context), CheckboxInput::default()); let mut parameter_info = ParameterWidgetsInfo::new(node_id, OutputChannelInput, true, context); parameter_info.exposable = false; - let output_channel = enum_choice::().for_socket(parameter_info).property_row(); + let output_channel = enum_choice::().for_socket(parameter_info).inspector_row(); let document_node = match get_document_node(node_id, context) { Ok(document_node) => document_node, Err(err) => { - log::error!("Could not get document node in channel_mixer_properties: {err}"); + log::error!("Could not get document node in channel_mixer_inspector: {err}"); return Vec::new(); } }; @@ -2514,7 +2514,7 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper let output_channel_value = match &document_node.input_value(OutputChannelInput) { Some(TaggedValue::RedGreenBlue(choice)) => choice, _ => { - warn!("Channel Mixer node properties panel could not be displayed."); + warn!("Channel Mixer node Inspector could not be displayed."); return vec![]; } }; @@ -2554,17 +2554,17 @@ pub(crate) fn channel_mixer_properties(node_id: NodeId, context: &mut NodeProper layout } -pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn selective_color_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::selective_color::*; let mut default_info = ParameterWidgetsInfo::new(node_id, ColorsInput, true, context); default_info.exposable = false; - let colors = enum_choice::().for_socket(default_info).property_row(); + let colors = enum_choice::().for_socket(default_info).inspector_row(); let document_node = match get_document_node(node_id, context) { Ok(document_node) => document_node, Err(err) => { - log::error!("Could not get document node in selective_color_properties: {err}"); + log::error!("Could not get document node in selective_color_inspector: {err}"); return Vec::new(); } }; @@ -2572,7 +2572,7 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp let colors_choice = match &document_node.input_value(ColorsInput) { Some(TaggedValue::SelectiveColorChoice(choice)) => choice, _ => { - warn!("Selective Color node properties panel could not be displayed."); + warn!("Selective Color node Inspector could not be displayed."); return vec![]; } }; @@ -2595,7 +2595,7 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp // Mode let mode = enum_choice::() .for_socket(ParameterWidgetsInfo::new(node_id, ModeInput, true, context)) - .property_row(); + .inspector_row(); let mut layout = vec![colors]; for (i, parameter) in parameters.into_iter().enumerate() { @@ -2606,17 +2606,17 @@ pub(crate) fn selective_color_properties(node_id: NodeId, context: &mut NodeProp layout } -pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn grid_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::vector::generator_nodes::grid::*; - let grid_type = enum_choice::().for_socket(ParameterWidgetsInfo::new(node_id, GridTypeInput, true, context)).property_row(); + let grid_type = enum_choice::().for_socket(ParameterWidgetsInfo::new(node_id, GridTypeInput, true, context)).inspector_row(); let mut widgets = vec![grid_type]; let document_node = match get_document_node(node_id, context) { Ok(document_node) => document_node, Err(err) => { - log::error!("Could not get document node in grid_properties: {err}"); + log::error!("Could not get document node in grid_inspector: {err}"); return Vec::new(); } }; @@ -2651,12 +2651,12 @@ pub(crate) fn grid_properties(node_id: NodeId, context: &mut NodePropertiesConte widgets } -pub(crate) fn spiral_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn spiral_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::vector::generator_nodes::spiral::*; let spiral_type = enum_choice::() .for_socket(ParameterWidgetsInfo::new(node_id, SpiralTypeInput, true, context)) - .property_row(); + .inspector_row(); let turns = number_widget(ParameterWidgetsInfo::new(node_id, TurnsInput, true, context), NumberInput::default().min(0.1)); let start_angle = number_widget(ParameterWidgetsInfo::new(node_id, StartAngleInput, true, context), NumberInput::default().unit("°")); @@ -2665,7 +2665,7 @@ pub(crate) fn spiral_properties(node_id: NodeId, context: &mut NodePropertiesCon let document_node = match get_document_node(node_id, context) { Ok(document_node) => document_node, Err(err) => { - log::error!("Could not get document node in exposure_properties: {err}"); + log::error!("Could not get document node in exposure_inspector: {err}"); return Vec::new(); } }; @@ -2719,13 +2719,13 @@ pub(crate) const SAMPLE_POLYLINE_DESCRIPTION_START_OFFSET: &str = "Exclude some pub(crate) const SAMPLE_POLYLINE_DESCRIPTION_STOP_OFFSET: &str = "Exclude some distance from the end of the path after the last point."; pub(crate) const SAMPLE_POLYLINE_DESCRIPTION_ADAPTIVE_SPACING: &str = "Round 'Separation' to a nearby value that divides into the path length evenly."; -pub(crate) fn sample_polyline_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn sample_polyline_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::vector::sample_polyline::*; let document_node = match get_document_node(node_id, context) { Ok(document_node) => document_node, Err(err) => { - log::error!("Could not get document node in sample_polyline_properties: {err}"); + log::error!("Could not get document node in sample_polyline_inspector: {err}"); return Vec::new(); } }; @@ -2735,7 +2735,7 @@ pub(crate) fn sample_polyline_properties(node_id: NodeId, context: &mut NodeProp let spacing = enum_choice::() .for_socket(ParameterWidgetsInfo::new(node_id, SpacingInput, true, context)) - .property_row(); + .inspector_row(); let separation = number_widget(ParameterWidgetsInfo::new(node_id, SeparationInput, true, context), NumberInput::default().min(0.).unit(" px")); let quantity = number_widget(ParameterWidgetsInfo::new(node_id, QuantityInput, true, context), NumberInput::default().min(2.).int()); let start_offset = number_widget(ParameterWidgetsInfo::new(node_id, StartOffsetInput, true, context), NumberInput::default().min(0.).unit(" px")); @@ -2755,7 +2755,7 @@ pub(crate) fn sample_polyline_properties(node_id: NodeId, context: &mut NodeProp ] } -pub(crate) fn exposure_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn exposure_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::raster::exposure::*; let exposure = range_slider_widget( @@ -2788,7 +2788,7 @@ pub(crate) fn exposure_properties(node_id: NodeId, context: &mut NodePropertiesC vec![LayoutGroup::row(exposure), LayoutGroup::row(offset), LayoutGroup::row(gamma_correction)] } -pub(crate) fn format_number_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn format_number_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::text_nodes::format_number::{DecimalPlacesInput, DecimalSeparatorInput, FixedDecimalsInput, StartAt10000Input, ThousandsSeparatorInput, UseThousandsSeparatorInput}; // Read current values before borrowing context mutably for widgets @@ -2814,7 +2814,7 @@ pub(crate) fn format_number_properties(node_id: NodeId, context: &mut NodeProper (decimal_places == 0, decimal_sep, use_thousands, thousands_sep) } Err(err) => { - log::error!("Could not get document node in format_number_properties: {err}"); + log::error!("Could not get document node in format_number_inspector: {err}"); return Vec::new(); } }; @@ -2867,7 +2867,7 @@ pub(crate) fn format_number_properties(node_id: NodeId, context: &mut NodeProper ] } -pub(crate) fn string_capitalization_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn string_capitalization_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::text_nodes::string_capitalization::*; // Read the current values before borrowing context mutably for widgets @@ -2892,7 +2892,7 @@ pub(crate) fn string_capitalization_properties(node_id: NodeId, context: &mut No (is_simple, use_joiner, joiner) } Err(err) => { - log::error!("Could not get document node in string_capitalization_properties: {err}"); + log::error!("Could not get document node in string_capitalization_inspector: {err}"); return Vec::new(); } }; @@ -2902,7 +2902,7 @@ pub(crate) fn string_capitalization_properties(node_id: NodeId, context: &mut No let capitalization = enum_choice::() .for_socket(ParameterWidgetsInfo::new(node_id, CapitalizationInput, true, context)) - .property_row(); + .inspector_row(); // Joiner row: the UseJoiner checkbox is drawn in the assist area, followed by the Joiner text input let mut joiner_widgets = start_widgets(&ParameterWidgetsInfo::new(node_id, JoinerInput, false, context)); @@ -2966,7 +2966,7 @@ pub(crate) fn string_capitalization_properties(node_id: NodeId, context: &mut No vec![capitalization, LayoutGroup::row(joiner_widgets), LayoutGroup::row(joiner_preset_buttons)] } -pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn rectangle_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::vector::generator_nodes::rectangle::*; // Corner Radius @@ -2980,7 +2980,7 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties let document_node = match get_document_node(node_id, context) { Ok(document_node) => document_node, Err(err) => { - log::error!("Could not get document node in rectangle_properties: {err}"); + log::error!("Could not get document node in rectangle_inspector: {err}"); return Vec::new(); } }; @@ -3081,27 +3081,27 @@ pub(crate) fn rectangle_properties(node_id: NodeId, context: &mut NodeProperties ] } -pub(crate) fn node_no_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn node_no_inspector_content(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { let text = if context.network_interface.is_layer(&node_id, context.selection_network_path) { "Layer has no parameters" } else { "Node has no parameters" }; - string_properties(text) + string_inspector(text) } -pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> LayoutGroup { +pub(crate) fn generate_node_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> LayoutGroup { let mut layout = Vec::new(); - if let Some(properties_override) = context + if let Some(inspector_override) = context .network_interface .reference(&node_id, context.selection_network_path) .as_ref() .and_then(|identifier| resolve_document_node_type(identifier)) - .and_then(|definition| definition.properties) - .and_then(|properties| NODE_OVERRIDES.get(properties)) + .and_then(|definition| definition.inspector) + .and_then(|inspector| NODE_OVERRIDES.get(inspector)) { - layout = properties_override(node_id, context); + layout = inspector_override(node_id, context); } else { let number_of_inputs = context.network_interface.number_of_inputs(&node_id, context.selection_network_path); for input_index in 1..number_of_inputs { @@ -3171,7 +3171,7 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper .unwrap_or(concrete!(())), }; - property_from_type(node_id, input_index, &input_type, options, context).unwrap_or_else(|value| value) + inspector_row_from_type(node_id, input_index, &input_type, options, context).unwrap_or_else(|value| value) }); layout.extend(row); @@ -3179,7 +3179,7 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper } if layout.is_empty() { - layout = node_no_properties(node_id, context); + layout = node_no_inspector_content(node_id, context); } let display_name = context @@ -3206,13 +3206,13 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper let visible = context.network_interface.is_visible(&node_id, context.selection_network_path); let pinned = context.network_interface.is_pinned(&node_id, context.selection_network_path); - let expanded = !context.properties_panel_collapsed_sections.contains(&node_id); + let expanded = !context.inspector_collapsed_sections.contains(&node_id); // An expanded section also contains the sections of the chain feeding one of its inputs, wired up into that input let network_path = context.selection_network_path; let mut chain_wire = None; if expanded - && let Some(input_index) = expanded_input_chain(&node_id, context.properties_panel_expanded_input_chains, context.network_interface, network_path) + && let Some(input_index) = expanded_input_chain(&node_id, context.inspector_expanded_input_chains, context.network_interface, network_path) && let Some((chain, stack_layer)) = input_chain(node_id, input_index, context.network_interface, network_path) { let input_type = context.network_interface.input_type(&InputConnector::node_at_index(node_id, input_index), network_path); @@ -3222,9 +3222,9 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper }); for chain_node_id in chain { - let mut chain_section = generate_node_properties(chain_node_id, context); + let mut chain_section = generate_node_inspector(chain_node_id, context); - if let LayoutGroup::Section(section) = &mut chain_section { + if let LayoutGroup::NodeSection(section) = &mut chain_section { section.output_wire = Some(output_section_wire(chain_node_id, context)); } @@ -3240,7 +3240,7 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper let visible = context.network_interface.is_visible(&layer, network_path); let mut reference_section = LayoutGroup::section(name, None, "", visible, false, true, layer.0, Layout(vec![LayoutGroup::row(vec![button])])); - if let LayoutGroup::Section(section) = &mut reference_section { + if let LayoutGroup::NodeSection(section) = &mut reference_section { section.node_reference = true; section.output_wire = Some(output_section_wire(layer, context)); } @@ -3250,14 +3250,14 @@ pub(crate) fn generate_node_properties(node_id: NodeId, context: &mut NodeProper } let mut section = LayoutGroup::section(name, icon, description, visible, pinned, expanded, node_id.0, Layout(layout)); - if let LayoutGroup::Section(widget_section) = &mut section { - widget_section.chain_wire = chain_wire; + if let LayoutGroup::NodeSection(node_section) = &mut section { + node_section.chain_wire = chain_wire; } section } /// The wire drawn up from a node's section in a chain to the section above, which its output feeds. -fn output_section_wire(node_id: NodeId, context: &NodePropertiesContext) -> SectionWire { +fn output_section_wire(node_id: NodeId, context: &NodeInspectorContext) -> SectionWire { let output_type = context.network_interface.output_type(&OutputConnector::node(node_id, 0), context.selection_network_path); SectionWire { @@ -3268,7 +3268,7 @@ fn output_section_wire(node_id: NodeId, context: &NodePropertiesContext) -> Sect /// The layer that a chain node ultimately feeds, if any. Returns `None` in a nested network since the layer metadata structure /// is only loaded for the root document network, so a `LayerNodeIdentifier` can't be constructed there. -fn root_layer_for_chain_node(node_id: NodeId, context: &mut NodePropertiesContext) -> Option { +fn root_layer_for_chain_node(node_id: NodeId, context: &mut NodeInspectorContext) -> Option { if !context.selection_network_path.is_empty() { return None; } @@ -3278,14 +3278,14 @@ fn root_layer_for_chain_node(node_id: NodeId, context: &mut NodePropertiesContex /// Resolve the viewport-space orientation of a Fill node's gradient by walking downstream to its owning layer /// and reusing the same helper the Gradient tool uses, so canvas tilt and layer transforms behave identically. -fn gradient_orientation_in_fill_node(node_id: NodeId, gradient_transform: DAffine2, context: &mut NodePropertiesContext) -> Option { +fn gradient_orientation_in_fill_node(node_id: NodeId, gradient_transform: DAffine2, context: &mut NodeInspectorContext) -> Option { let layer = root_layer_for_chain_node(node_id, context)?; let transform = graph_modification_utils::gradient_to_viewport_transform(layer, context.network_interface); Some(graph_modification_utils::gradient_orientation_rightward(transform * gradient_transform)) } /// Fill Node Widgets LayoutGroup -pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub(crate) fn fill_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::vector::fill::*; #[derive(Debug, Clone)] @@ -3531,13 +3531,13 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte widgets } -pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub fn stroke_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::vector::stroke::*; let document_node = match get_document_node(node_id, context) { Ok(document_node) => document_node, Err(err) => { - log::error!("Could not get document node in stroke_properties: {err}"); + log::error!("Could not get document node in stroke_inspector: {err}"); return Vec::new(); } }; @@ -3557,9 +3557,9 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) - crate::messages::layout::utility_types::widgets::button_widgets::ColorInput::default(), ); let weight = number_widget(ParameterWidgetsInfo::new(node_id, WeightInput, true, context), NumberInput::default().unit(" px").min(0.)); - let align = enum_choice::().for_socket(ParameterWidgetsInfo::new(node_id, AlignInput, true, context)).property_row(); - let cap = enum_choice::().for_socket(ParameterWidgetsInfo::new(node_id, CapInput, true, context)).property_row(); - let join = enum_choice::().for_socket(ParameterWidgetsInfo::new(node_id, JoinInput, true, context)).property_row(); + let align = enum_choice::().for_socket(ParameterWidgetsInfo::new(node_id, AlignInput, true, context)).inspector_row(); + let cap = enum_choice::().for_socket(ParameterWidgetsInfo::new(node_id, CapInput, true, context)).inspector_row(); + let join = enum_choice::().for_socket(ParameterWidgetsInfo::new(node_id, JoinInput, true, context)).inspector_row(); let miter_limit = number_widget( ParameterWidgetsInfo::new(node_id, MiterLimitInput, true, context), @@ -3582,18 +3582,18 @@ pub fn stroke_properties(node_id: NodeId, context: &mut NodePropertiesContext) - ] } -pub fn offset_path_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec { +pub fn offset_path_inspector(node_id: NodeId, context: &mut NodeInspectorContext) -> Vec { use graphene_std::vector::offset_path::*; let number_input = NumberInput::default().unit(" px"); let distance = number_widget(ParameterWidgetsInfo::new(node_id, DistanceInput, true, context), number_input); - let join = enum_choice::().for_socket(ParameterWidgetsInfo::new(node_id, JoinInput, true, context)).property_row(); + let join = enum_choice::().for_socket(ParameterWidgetsInfo::new(node_id, JoinInput, true, context)).inspector_row(); let document_node = match get_document_node(node_id, context) { Ok(document_node) => document_node, Err(err) => { - log::error!("Could not get document node in offset_path_properties: {err}"); + log::error!("Could not get document node in offset_path_inspector: {err}"); return Vec::new(); } }; @@ -3629,7 +3629,7 @@ pub struct ParameterWidgetsInfo<'a> { impl<'a> ParameterWidgetsInfo<'a> { /// Reference the parameter by its symbol, e.g. `ParameterWidgetsInfo::new(node_id, brightness_contrast::BrightnessInput, true, context)`, or by an erased [`ParameterRef`] chosen at runtime. - pub fn new(node_id: NodeId, parameter: impl Into, blank_assist: bool, context: &'a mut NodePropertiesContext) -> ParameterWidgetsInfo<'a> { + pub fn new(node_id: NodeId, parameter: impl Into, blank_assist: bool, context: &'a mut NodeInspectorContext) -> ParameterWidgetsInfo<'a> { Self::at_index(node_id, parameter.into().input_index, blank_assist, context) } @@ -3649,14 +3649,14 @@ impl<'a> ParameterWidgetsInfo<'a> { } /// Reference the parameter by a runtime input index, for callers that receive the index dynamically (e.g. widget overrides). - pub fn at_index(node_id: NodeId, index: usize, blank_assist: bool, context: &'a mut NodePropertiesContext) -> ParameterWidgetsInfo<'a> { + pub fn at_index(node_id: NodeId, index: usize, blank_assist: bool, context: &'a mut NodeInspectorContext) -> ParameterWidgetsInfo<'a> { let (name, description) = context.network_interface.displayed_input_name_and_description(&node_id, index, context.selection_network_path); let input_type = context .network_interface .input_type_not_invalid(&InputConnector::node_at_index(node_id, index), context.selection_network_path) .displayed_type(); let document_node = context.network_interface.document_node(&node_id, context.selection_network_path); - let chain_expanded = expanded_input_chain(&node_id, context.properties_panel_expanded_input_chains, context.network_interface, context.selection_network_path) == Some(index); + let chain_expanded = expanded_input_chain(&node_id, context.inspector_expanded_input_chains, context.network_interface, context.selection_network_path) == Some(index); ParameterWidgetsInfo { document_id: context.document_id, @@ -3819,9 +3819,9 @@ pub mod choice { } } - pub fn property_row(self) -> LayoutGroup { + pub fn inspector_row(self) -> LayoutGroup { if self.parameter_info.document_node.is_none() { - log::error!("Could not get document node when building property row for node {:?}", self.parameter_info.node_id); + log::error!("Could not get document node when building Inspector row for node {:?}", self.parameter_info.node_id); return LayoutGroup::row(Vec::new()); } diff --git a/editor/src/messages/portfolio/document/properties_panel/mod.rs b/editor/src/messages/portfolio/document/properties_panel/mod.rs deleted file mode 100644 index cc8c2916747..00000000000 --- a/editor/src/messages/portfolio/document/properties_panel/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod properties_panel_message; -pub mod properties_panel_message_handler; - -#[doc(inline)] -pub use properties_panel_message::{PropertiesPanelMessage, PropertiesPanelMessageDiscriminant}; -#[doc(inline)] -pub use properties_panel_message_handler::PropertiesPanelMessageHandler; diff --git a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs b/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs deleted file mode 100644 index 33b28ca655f..00000000000 --- a/editor/src/messages/portfolio/document/properties_panel/properties_panel_message_handler.rs +++ /dev/null @@ -1,77 +0,0 @@ -use graphene_std::uuid::NodeId; - -use crate::messages::layout::utility_types::widget_prelude::*; -use crate::messages::portfolio::document::node_graph::document_node_definitions::NodePropertiesContext; -use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface; -use crate::messages::prelude::*; -use crate::node_graph_executor::NodeGraphExecutor; - -#[derive(ExtractField)] -pub struct PropertiesPanelMessageContext<'a> { - pub executor: &'a mut NodeGraphExecutor, - pub document_id: DocumentId, - pub network_interface: &'a mut NodeNetworkInterface, - pub resources: &'a ResourceMessageHandler, - pub selection_network_path: &'a [NodeId], - pub fonts: &'a FontsMessageHandler, - pub properties_panel_open: bool, - pub properties_panel_collapsed_sections: &'a [NodeId], - pub properties_panel_expanded_input_chains: &'a [(NodeId, Option)], -} - -#[derive(Debug, Clone, Default, ExtractField)] -pub struct PropertiesPanelMessageHandler {} - -#[message_handler_data] -impl MessageHandler> for PropertiesPanelMessageHandler { - fn process_message(&mut self, message: PropertiesPanelMessage, responses: &mut VecDeque, context: PropertiesPanelMessageContext) { - let PropertiesPanelMessageContext { - executor, - document_id, - network_interface, - resources, - selection_network_path, - fonts, - properties_panel_open, - properties_panel_collapsed_sections, - properties_panel_expanded_input_chains, - } = context; - - match message { - PropertiesPanelMessage::Clear => { - responses.add(LayoutMessage::SendLayout { - layout: Layout::default(), - layout_target: LayoutTarget::PropertiesPanel, - }); - } - PropertiesPanelMessage::Refresh => { - if !properties_panel_open { - responses.add(PropertiesPanelMessage::Clear); - return; - } - - let mut node_properties_context = NodePropertiesContext { - responses, - executor, - document_id, - network_interface, - resources, - selection_network_path, - fonts, - properties_panel_collapsed_sections, - properties_panel_expanded_input_chains, - }; - let layout = Layout(NodeGraphMessageHandler::collate_properties(&mut node_properties_context)); - - node_properties_context.responses.add(LayoutMessage::SendLayout { - layout, - layout_target: LayoutTarget::PropertiesPanel, - }); - } - } - } - - fn actions(&self) -> ActionList { - actions!(PropertiesMessageDiscriminant;) - } -} diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface/frontend.rs b/editor/src/messages/portfolio/document/utility_types/network_interface/frontend.rs index f2bafa370a4..87dd727169c 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface/frontend.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface/frontend.rs @@ -164,7 +164,7 @@ impl NodeNetworkInterface { }) } - /// Returns the input name to display in the properties panel. If the name is empty then the type is used. + /// Returns the input name to display in the Inspector. If the name is empty then the type is used. pub fn displayed_input_name_and_description(&self, node_id: &NodeId, input_index: usize, network_path: &[NodeId]) -> (String, String) { let Some(input_metadata) = self.persistent_input_metadata(node_id, input_index, network_path) else { log::warn!("input metadata not found in displayed_input_name_and_description"); diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface/mutations.rs b/editor/src/messages/portfolio/document/utility_types/network_interface/mutations.rs index ead37519c0b..0b9a91d2c04 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface/mutations.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface/mutations.rs @@ -1064,7 +1064,7 @@ impl NodeNetworkInterface { self.transaction_modified(); } - /// Reorders a pinned node within its network's Properties panel display order so it ends up at `insert_index` among the + /// Reorders a pinned node within its network's Inspector display order so it ends up at `insert_index` among the /// pinned nodes (0 being the topmost). Rebuilds the order from the list as currently shown, which also drops stale entries. pub fn reorder_pinned_node(&mut self, node_id: NodeId, insert_index: usize, network_path: &[NodeId]) { let shown = self.ordered_pinned_nodes(network_path); diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface/queries.rs b/editor/src/messages/portfolio/document/utility_types/network_interface/queries.rs index 2c337e4313e..faf77677c68 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface/queries.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface/queries.rs @@ -556,7 +556,7 @@ impl NodeNetworkInterface { .unwrap_or_else(|| "Custom Node".to_string()) } - /// The uneditable name in the Properties panel which represents the function name of the node implementation. + /// The uneditable name in the Inspector which represents the function name of the node implementation. pub fn implementation_name(&self, node_id: &NodeId, network_path: &[NodeId]) -> String { self.query(network_path, "implementation_name", |view| Ok(view.implementation_name(node_id))) .unwrap_or_else(|| "Custom Node".to_string()) diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface/store/cursor.rs b/editor/src/messages/portfolio/document/utility_types/network_interface/store/cursor.rs index 28170545744..64578010800 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface/store/cursor.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface/store/cursor.rs @@ -274,7 +274,7 @@ impl NodeMut<'_> { changed } - /// The identifier of the widget override the properties panel uses for this input, or `None` for the + /// The identifier of the widget override the Inspector uses for this input, or `None` for the /// widget generated from its type. pub(crate) fn set_widget_override(&mut self, input_index: usize, widget_override: Option) -> bool { let Some(input_metadata) = self.metadata.input_metadata.get_mut(input_index) else { return false }; @@ -447,7 +447,7 @@ impl NetworkMut<'_> { changed } - /// The display order of pinned nodes in the Properties panel. + /// The display order of pinned nodes in the Inspector. pub(crate) fn set_pinned_order(&mut self, pinned_node_order: Vec) -> bool { let changed = self.metadata.pinned_node_order != pinned_node_order; self.metadata.pinned_node_order = pinned_node_order; diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface/template.rs b/editor/src/messages/portfolio/document/utility_types/network_interface/template.rs index 57fe1d2e1c4..c3186378487 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface/template.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface/template.rs @@ -27,12 +27,12 @@ pub struct NodeTemplate { pub context_features: ContextDependencies, /// A name chosen by the user for this instance of the node. Empty indicates no given name, in which case the implementation name is displayed in italics. pub display_name: String, - /// Metadata to override the properties panel widgets for each input. Kept the same length as `inputs`. + /// Metadata to override the Inspector widgets for each input. Kept the same length as `inputs`. pub input_metadata: Vec, pub output_names: Vec, /// Represents the lock icon for locking/unlocking the node in the graph UI. pub locked: bool, - /// Indicates that the node will be shown in the Properties panel when it would otherwise be empty. + /// Indicates that the node will be shown in the Inspector when it would otherwise be empty. pub pinned: bool, /// Whether the node is displayed as a left-to-right node or bottom-to-top layer, along with its position. pub node_type_metadata: NodeTypePersistentMetadata, @@ -95,7 +95,7 @@ pub struct NodeNetworkTemplate { /// /// [`DocumentNodeDefinition`]: crate::messages::portfolio::document::node_graph::document_node_definitions::DocumentNodeDefinition pub reference: Option, - /// The display order of pinned nodes in the Properties panel. + /// The display order of pinned nodes in the Inspector. pub pinned_node_order: Vec, pub previewing: Previewing, pub navigation_metadata: NavigationMetadata, diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface/types.rs b/editor/src/messages/portfolio/document/utility_types/network_interface/types.rs index 0199d41ec45..e6786c80bc6 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface/types.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface/types.rs @@ -446,7 +446,7 @@ pub struct NodeNetworkPersistentMetadata { /// Node metadata must exist for every document node in the network #[serde(serialize_with = "graphene_std::vector::serialize_hashmap", deserialize_with = "graphene_std::vector::deserialize_hashmap")] pub node_metadata: HashMap, - /// The display order of pinned nodes in the Properties panel (shown when nothing is selected in this network), keyed by node ID. + /// The display order of pinned nodes in the Inspector (shown when nothing is selected in this network), keyed by node ID. #[serde(default)] pub pinned_node_order: Vec, /// Cached metadata for each node, which is calculated when adding a node to node_metadata @@ -630,7 +630,7 @@ pub enum WidgetOverride { Custom(String), } -// TODO: Custom deserialization/serialization to ensure number of properties row matches number of node inputs +// TODO: Custom deserialization/serialization to ensure number of input metadata rows matches number of node inputs #[derive(Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)] pub struct InputPersistentMetadata { /// A general datastore than can store key value pairs of any types for any input @@ -661,40 +661,40 @@ impl InputPersistentMetadata { WidgetOverride::Hidden => { self.widget_override = Some("hidden".to_string()); } - WidgetOverride::String(string_properties) => { - self.input_data.insert("string_properties".to_string(), Value::String(string_properties)); + WidgetOverride::String(string_inspector) => { + self.input_data.insert("string_inspector".to_string(), Value::String(string_inspector)); self.widget_override = Some("string".to_string()); } - WidgetOverride::Number(mut number_properties) => { - if let Some(unit) = number_properties.unit.take() { + WidgetOverride::Number(mut number_inspector) => { + if let Some(unit) = number_inspector.unit.take() { self.input_data.insert("unit".to_string(), json!(unit)); } - if let Some(min) = number_properties.min.take() { + if let Some(min) = number_inspector.min.take() { self.input_data.insert("min".to_string(), json!(min)); } - if let Some(max) = number_properties.max.take() { + if let Some(max) = number_inspector.max.take() { self.input_data.insert("max".to_string(), json!(max)); } - if let Some(step) = number_properties.step.take() { + if let Some(step) = number_inspector.step.take() { self.input_data.insert("step".to_string(), json!(step)); } - if let Some(range_min) = number_properties.range_min.take() { + if let Some(range_min) = number_inspector.range_min.take() { self.input_data.insert("range_min".to_string(), json!(range_min)); } - if let Some(range_max) = number_properties.range_max.take() { + if let Some(range_max) = number_inspector.range_max.take() { self.input_data.insert("range_max".to_string(), json!(range_max)); } - self.input_data.insert("mode".to_string(), json!(number_properties.mode)); - self.input_data.insert("is_integer".to_string(), Value::Bool(number_properties.is_integer)); - self.input_data.insert("blank_assist".to_string(), Value::Bool(number_properties.blank_assist)); + self.input_data.insert("mode".to_string(), json!(number_inspector.mode)); + self.input_data.insert("is_integer".to_string(), Value::Bool(number_inspector.is_integer)); + self.input_data.insert("blank_assist".to_string(), Value::Bool(number_inspector.blank_assist)); self.widget_override = Some("number".to_string()); } - WidgetOverride::Vec2(vec2_properties) => { - self.input_data.insert("x".to_string(), json!(vec2_properties.x)); - self.input_data.insert("y".to_string(), json!(vec2_properties.y)); - self.input_data.insert("unit".to_string(), json!(vec2_properties.unit)); - self.input_data.insert("is_integer".to_string(), Value::Bool(vec2_properties.is_integer)); - if let Some(min) = vec2_properties.min { + WidgetOverride::Vec2(vec2_inspector) => { + self.input_data.insert("x".to_string(), json!(vec2_inspector.x)); + self.input_data.insert("y".to_string(), json!(vec2_inspector.y)); + self.input_data.insert("unit".to_string(), json!(vec2_inspector.unit)); + self.input_data.insert("is_integer".to_string(), Value::Bool(vec2_inspector.is_integer)); + if let Some(min) = vec2_inspector.min { self.input_data.insert("min".to_string(), json!(min)); } self.widget_override = Some("vec2".to_string()); @@ -724,14 +724,14 @@ pub struct DocumentNodePersistentMetadata { /// A name chosen by the user for this instance of the node. Empty indicates no given name, in which case the implementation name is displayed to the user in italics. #[serde(default)] pub display_name: String, - /// Stores metadata to override the properties in the properties panel for each input. These can either be generated automatically based on the type, or with a custom function. + /// Stores metadata to override the widgets in the Inspector for each input. These can either be generated automatically based on the type, or with a custom function. /// Must match the length of node inputs pub input_metadata: Vec, pub output_names: Vec, /// Represents the lock icon for locking/unlocking the node in the graph UI. When locked, a node cannot be moved in the graph UI. #[serde(default)] pub locked: bool, - /// Indicates that the node will be shown in the Properties panel when it would otherwise be empty, letting a user easily edit its properties by just deselecting everything. + /// Indicates that the node will be shown in the Inspector when it would otherwise be empty, letting a user easily edit its inputs by just deselecting everything. #[serde(default)] pub pinned: bool, /// Metadata that is specific to either nodes or layers, which are chosen states for displaying as a left-to-right node or bottom-to-top layer. diff --git a/editor/src/messages/portfolio/document/utility_types/network_interface/view.rs b/editor/src/messages/portfolio/document/utility_types/network_interface/view.rs index e51cf867005..c1570533bf1 100644 --- a/editor/src/messages/portfolio/document/utility_types/network_interface/view.rs +++ b/editor/src/messages/portfolio/document/utility_types/network_interface/view.rs @@ -131,7 +131,7 @@ impl<'a, 'p> NetworkView<'a, 'p> { .is_some_and(|reference| reference == DefinitionIdentifier::Network("Merge".into())) } - /// The uneditable name in the Properties panel which represents the function name of the node implementation. + /// The uneditable name in the Inspector which represents the function name of the node implementation. pub fn implementation_name(&self, node_id: &NodeId) -> String { self.reference(node_id) .ok() diff --git a/editor/src/messages/portfolio/document_migration.rs b/editor/src/messages/portfolio/document_migration.rs index fc6b6186050..30c1ebbb442 100644 --- a/editor/src/messages/portfolio/document_migration.rs +++ b/editor/src/messages/portfolio/document_migration.rs @@ -1230,7 +1230,7 @@ pub fn document_migration_upgrades(document: &mut DocumentMessageHandler, reset_ } // Pre-2024 documents stored Transform with 6 inputs and used radians for Rotation and `tan(radians)` for Skew. Detect that legacy - // shape (no input at index 6) and convert the units to degrees so the values match what the new Properties panel widgets expect. + // shape (no input at index 6) and convert the units to degrees so the values match what the new Inspector widgets expect. if *old_inputs_count == 6 { match old_inputs.get(2) { Some(NodeInput::Value { tagged_value, exposed }) => { @@ -1852,7 +1852,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], // Only nodes that have not been modified and still refer to a definition can be updated let reference = document.network_interface.reference(node_id, network_path)?; - // Show the Artboard's Content input in the Properties panel, which the definition once hid + // Show the Artboard's Content input in the Inspector, which the definition once hid if reference == DefinitionIdentifier::Network("Artboard".into()) && document .network_interface @@ -1863,9 +1863,23 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], document.network_interface.set_input_override(node_id, 1, None, network_path); } + // Legacy `noise_properties_*` widget overrides + for input_index in 0..node.inputs.len() { + let renamed_override = document + .network_interface + .persistent_input_metadata(node_id, input_index, network_path) + .and_then(|metadata| metadata.widget_override.as_deref()) + .and_then(|widget_override| widget_override.strip_prefix("noise_properties_")) + .map(|suffix| format!("noise_inspector_{suffix}")); + + if let Some(renamed_override) = renamed_override { + document.network_interface.set_input_override(node_id, input_index, Some(renamed_override), network_path); + } + } + let mut inputs_count = node.inputs.len(); - // The expression nodes gained an output-type input, a type witness the Properties panel edits. A node from before it + // The expression nodes gained an output-type input, a type witness the Inspector edits. A node from before it // takes the definition's default choice, Number, which is the output type every such node had. let expression_node_identifiers = [graphene_std::math_nodes::math_fx::IDENTIFIER, graphene_std::math_nodes::math_f::IDENTIFIER]; if expression_node_identifiers.iter().any(|identifier| reference == DefinitionIdentifier::ProtoNode(identifier.clone())) && inputs_count == 2 { diff --git a/editor/src/messages/portfolio/fonts/fonts_message_handler.rs b/editor/src/messages/portfolio/fonts/fonts_message_handler.rs index 95084020c12..69d91ef740f 100644 --- a/editor/src/messages/portfolio/fonts/fonts_message_handler.rs +++ b/editor/src/messages/portfolio/fonts/fonts_message_handler.rs @@ -74,7 +74,7 @@ impl MessageHandler> for FontsMessageHandl self.font_catalog = Arc::new(catalog); responses.add(PortfolioMessage::ResolveResources); responses.add(ToolMessage::RefreshToolOptions); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); } FontsMessage::ResourceResolved { font, hash } => { let font = self.normalize(font); diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 0abce83993f..4d28160dd7f 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -98,7 +98,7 @@ impl MessageHandler> for Portfolio resource_storage, data_panel_open: self.workspace.panel_layout.is_panel_visible(PanelType::Data) && !self.workspace.panel_layout.focus_document, layers_panel_open: self.workspace.panel_layout.is_panel_visible(PanelType::Layers) && !self.workspace.panel_layout.focus_document, - properties_panel_open: self.workspace.panel_layout.is_panel_visible(PanelType::Properties) && !self.workspace.panel_layout.focus_document, + inspector_open: self.workspace.panel_layout.is_panel_visible(PanelType::Inspector) && !self.workspace.panel_layout.focus_document, }; document.process_message(message, responses, document_inputs); refresh_transaction_edited_nodes(document, true, responses); @@ -195,7 +195,7 @@ impl MessageHandler> for Portfolio resource_storage, data_panel_open: self.workspace.panel_layout.is_panel_visible(PanelType::Data) && !self.workspace.panel_layout.focus_document, layers_panel_open: self.workspace.panel_layout.is_panel_visible(PanelType::Layers) && !self.workspace.panel_layout.focus_document, - properties_panel_open: self.workspace.panel_layout.is_panel_visible(PanelType::Properties) && !self.workspace.panel_layout.focus_document, + inspector_open: self.workspace.panel_layout.is_panel_visible(PanelType::Inspector) && !self.workspace.panel_layout.focus_document, }; document.process_message(message, responses, document_inputs); refresh_transaction_edited_nodes(document, self.active_document_id == Some(document_id), responses); @@ -250,7 +250,7 @@ impl MessageHandler> for Portfolio responses.add(ToolMessage::DeactivateTools); // Clear relevant UI layouts if there are no documents - responses.add(PropertiesPanelMessage::Clear); + responses.add(InspectorMessage::Clear); responses.add(DocumentMessage::ClearLayersPanel); responses.add(DataPanelMessage::ClearLayout); HintData::clear_layout(responses); @@ -274,13 +274,13 @@ impl MessageHandler> for Portfolio // Is this the last document? if self.document_ids.len() == 1 && self.document_ids[0] == document_id { // Clear UI layouts that assume the existence of a document - responses.add(PropertiesPanelMessage::Clear); + responses.add(InspectorMessage::Clear); responses.add(DocumentMessage::ClearLayersPanel); responses.add(DataPanelMessage::ClearLayout); HintData::clear_layout(responses); } - // Actually delete the document (delay to delete document is required to let the document and properties panel messages above get processed) + // Actually delete the document (delay to delete document is required to let the document and Inspector messages above get processed) responses.add(PortfolioMessage::DeleteDocument { document_id }); responses.add(remove_stored_document(self.document_store.clone(), document_id)); @@ -849,7 +849,7 @@ impl MessageHandler> for Portfolio document.is_loaded = true; responses.add(PortfolioMessage::ResolveDocumentResources { document_id }); responses.add(PortfolioMessage::UpdateDocumentWidgets); - responses.add(PropertiesPanelMessage::Clear); + responses.add(InspectorMessage::Clear); } } PortfolioMessage::RenameDocument { new_name } => { diff --git a/editor/src/messages/portfolio/utility_types.rs b/editor/src/messages/portfolio/utility_types.rs index eaa1aedd73e..4205e182cf7 100644 --- a/editor/src/messages/portfolio/utility_types.rs +++ b/editor/src/messages/portfolio/utility_types.rs @@ -9,7 +9,8 @@ pub enum PanelType { Welcome, Document, Layers, - Properties, + #[serde(alias = "Properties")] + Inspector, Data, } @@ -19,7 +20,7 @@ impl From for PanelType { "Welcome" => PanelType::Welcome, "Document" => PanelType::Document, "Layers" => PanelType::Layers, - "Properties" => PanelType::Properties, + "Inspector" | "Properties" => PanelType::Inspector, "Data" => PanelType::Data, _ => panic!("Unknown panel type: {value}"), } @@ -28,7 +29,7 @@ impl From for PanelType { impl PanelType { pub fn non_document_panels() -> &'static [PanelType] { - &[PanelType::Layers, PanelType::Properties, PanelType::Data] + &[PanelType::Layers, PanelType::Inspector, PanelType::Data] } } @@ -298,7 +299,7 @@ impl WorkspacePanelLayout { /// Place a panel at its default structural position in the layout tree. /// - Data: below the document in the left column (root child 0) - /// - Properties: top of the right column (root child 1) + /// - Inspector: top of the right column (root child 1) /// - Layers: bottom of the right column (root child 1) fn restore_panel_to_default_position(&mut self, panel_type: PanelType) { let new_id = self.next_id(); @@ -315,9 +316,9 @@ impl WorkspacePanelLayout { // Determine which root child column to insert into and at which position let (root_child_index, insert_at_end) = match panel_type { - PanelType::Data => (0, true), // Left column, after document - PanelType::Properties => (1, false), // Right column, at top - PanelType::Layers => (1, true), // Right column, at bottom + PanelType::Data => (0, true), // Left column, after document + PanelType::Inspector => (1, false), // Right column, at top + PanelType::Layers => (1, true), // Right column, at bottom _ => (1, true), }; @@ -375,7 +376,7 @@ impl Default for WorkspacePanelLayout { // Default layout (sizes are recalculated by `recalculate_default_sizes` before being sent to the frontend): // Row [ // Column [Document] - // Column [Properties, Layers] + // Column [Inspector, Layers] // ] Self { root: PanelLayoutSubdivision::Split { @@ -402,7 +403,7 @@ impl Default for WorkspacePanelLayout { subdivision: PanelLayoutSubdivision::PanelGroup { id: PanelGroupId(1), state: PanelGroupState { - tabs: vec![PanelType::Properties], + tabs: vec![PanelType::Inspector], active_tab_index: 0, }, }, diff --git a/editor/src/messages/portfolio/workspace/workspace_message.rs b/editor/src/messages/portfolio/workspace/workspace_message.rs index 05ec603c394..21e8a3f9b76 100644 --- a/editor/src/messages/portfolio/workspace/workspace_message.rs +++ b/editor/src/messages/portfolio/workspace/workspace_message.rs @@ -31,7 +31,7 @@ pub enum WorkspaceMessage { }, ToggleFocusDocument, ToggleDataPanelOpen, - TogglePropertiesPanelOpen, + ToggleInspectorOpen, ToggleLayersPanelOpen, UpdatePanelsLayout, ResetWorkspaceLayout, diff --git a/editor/src/messages/portfolio/workspace/workspace_message_handler.rs b/editor/src/messages/portfolio/workspace/workspace_message_handler.rs index 10772f892ca..51acd8c44eb 100644 --- a/editor/src/messages/portfolio/workspace/workspace_message_handler.rs +++ b/editor/src/messages/portfolio/workspace/workspace_message_handler.rs @@ -251,12 +251,12 @@ impl MessageHandler for WorkspaceMess responses.add(MenuBarMessage::SendLayout); responses.add(WorkspaceMessage::UpdatePanelsLayout); } - WorkspaceMessage::TogglePropertiesPanelOpen => { + WorkspaceMessage::ToggleInspectorOpen => { if self.panel_layout.focus_document { return; } - let panel_type = PanelType::Properties; + let panel_type = PanelType::Inspector; self.toggle_dockable_panel(panel_type, has_active_document, has_no_documents, responses); } WorkspaceMessage::ToggleLayersPanelOpen => { @@ -334,7 +334,7 @@ impl MessageHandler for WorkspaceMess // Extend with actions that are disabled when focusing the document if !self.panel_layout.focus_document { common.extend(actions!(WorkspaceMessageDiscriminant; - TogglePropertiesPanelOpen, + ToggleInspectorOpen, ToggleLayersPanelOpen, ToggleDataPanelOpen, )); @@ -387,7 +387,7 @@ impl WorkspaceMessageHandler { /// This resets the backend's diffing state so it won't try to send updates to a frontend component that has been unmounted. fn destroy_panel_layouts(panel_type: PanelType, responses: &mut VecDeque) { let targets: &[LayoutTarget] = match panel_type { - PanelType::Properties => &[LayoutTarget::PropertiesPanel], + PanelType::Inspector => &[LayoutTarget::Inspector], PanelType::Layers => &[LayoutTarget::LayersPanelControlLeftBar, LayoutTarget::LayersPanelBottomLeftBar, LayoutTarget::LayersPanelBottomRightBar], PanelType::Data => &[LayoutTarget::DataPanel], PanelType::Document | PanelType::Welcome => return, @@ -403,8 +403,8 @@ impl WorkspaceMessageHandler { responses.add(NodeGraphMessage::RunDocumentGraph); match panel_type { - PanelType::Properties => { - responses.add(PropertiesPanelMessage::Refresh); + PanelType::Inspector => { + responses.add(InspectorMessage::Refresh); } PanelType::Layers => { if has_active_document { @@ -440,15 +440,15 @@ mod tests { }; let group_of = |handler: &WorkspaceMessageHandler, panel_type| handler.panel_layout.find_panel(panel_type).expect("the default layout has this panel"); - // The Layers panel joins the Properties panel's group as its active tab + // The Layers panel joins the Inspector's group as its active tab let join = WorkspaceMessage::MovePanelTab { source_group: group_of(&handler, PanelType::Layers), - target_group: group_of(&handler, PanelType::Properties), + target_group: group_of(&handler, PanelType::Inspector), insert_index: 1, }; handler.process_message(join, &mut VecDeque::new(), context()); - // Splitting it back out beside the document leaves the Properties panel as the active tab of the group it left + // Splitting it back out beside the document leaves the Inspector as the active tab of the group it left let split = WorkspaceMessage::SplitPanelGroup { target_group: group_of(&handler, PanelType::Document), direction: DockingSplitDirection::Right, @@ -458,6 +458,6 @@ mod tests { let mut responses = VecDeque::new(); handler.process_message(split, &mut responses, context()); - assert!(responses.contains(&PropertiesPanelMessage::Refresh.into())); + assert!(responses.contains(&InspectorMessage::Refresh.into())); } } diff --git a/editor/src/messages/prelude.rs b/editor/src/messages/prelude.rs index e47e66e7284..a4f555dc20e 100644 --- a/editor/src/messages/prelude.rs +++ b/editor/src/messages/prelude.rs @@ -25,10 +25,10 @@ pub use crate::messages::menu_bar::{MenuBarMessage, MenuBarMessageDiscriminant, pub use crate::messages::network::{NetworkMessage, NetworkMessageContext, NetworkMessageDiscriminant, NetworkMessageHandler}; pub use crate::messages::portfolio::document::data_panel::{DataPanelMessage, DataPanelMessageDiscriminant}; pub use crate::messages::portfolio::document::graph_operation::{GraphOperationMessage, GraphOperationMessageContext, GraphOperationMessageDiscriminant, GraphOperationMessageHandler}; +pub use crate::messages::portfolio::document::inspector::{InspectorMessage, InspectorMessageDiscriminant, InspectorMessageHandler}; pub use crate::messages::portfolio::document::navigation::{NavigationMessage, NavigationMessageContext, NavigationMessageDiscriminant, NavigationMessageHandler}; pub use crate::messages::portfolio::document::node_graph::{NodeGraphMessage, NodeGraphMessageDiscriminant, NodeGraphMessageHandler}; pub use crate::messages::portfolio::document::overlays::{OverlaysMessage, OverlaysMessageContext, OverlaysMessageDiscriminant, OverlaysMessageHandler}; -pub use crate::messages::portfolio::document::properties_panel::{PropertiesPanelMessage, PropertiesPanelMessageDiscriminant, PropertiesPanelMessageHandler}; pub use crate::messages::portfolio::document::resource::{ResourceMessage, ResourceMessageContext, ResourceMessageDiscriminant, ResourceMessageHandler}; pub use crate::messages::portfolio::document::{DocumentMessage, DocumentMessageContext, DocumentMessageDiscriminant, DocumentMessageHandler}; pub use crate::messages::portfolio::failed_documents::{FailedDocumentsMessage, FailedDocumentsMessageContext, FailedDocumentsMessageDiscriminant, FailedDocumentsMessageHandler}; diff --git a/editor/src/messages/tool/tool_messages/artboard_tool.rs b/editor/src/messages/tool/tool_messages/artboard_tool.rs index a7481d3cc89..d7275c7e2fd 100644 --- a/editor/src/messages/tool/tool_messages/artboard_tool.rs +++ b/editor/src/messages/tool/tool_messages/artboard_tool.rs @@ -171,7 +171,7 @@ impl ArtboardToolData { } else { self.selected_artboard = None; - responses.add(PropertiesPanelMessage::Clear); + responses.add(InspectorMessage::Clear); false } diff --git a/editor/src/messages/tool/tool_messages/gradient_tool.rs b/editor/src/messages/tool/tool_messages/gradient_tool.rs index c983099931f..e9d5e42287e 100644 --- a/editor/src/messages/tool/tool_messages/gradient_tool.rs +++ b/editor/src/messages/tool/tool_messages/gradient_tool.rs @@ -144,7 +144,7 @@ impl<'a> MessageHandler> for Grad { selected_gradient.gradient.set_color(stop_index, color); selected_gradient.render_gradient(responses); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); } } ToolMessage::Gradient(GradientToolMessage::UpdateRamp { ramp }) => { @@ -1183,7 +1183,7 @@ impl Fsm for GradientToolFsmState { GradientDragTarget::Midpoint(index) => { selected_gradient.gradient.reset_midpoint(index); selected_gradient.render_gradient(responses); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); } GradientDragTarget::Start | GradientDragTarget::End | GradientDragTarget::Stop(_) => { // Find the stop index from the drag target @@ -1277,7 +1277,7 @@ impl Fsm for GradientToolFsmState { selected_gradient.render_gradient(responses); responses.add(DocumentMessage::CommitTransaction); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); return ready_default; } @@ -1294,7 +1294,7 @@ impl Fsm for GradientToolFsmState { }); } responses.add(DocumentMessage::CommitTransaction); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); return ready_default; } @@ -1314,7 +1314,7 @@ impl Fsm for GradientToolFsmState { // Render the new gradient selected_gradient.render_gradient(responses); responses.add(DocumentMessage::CommitTransaction); - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); tool_data.selected_gradient = None; ready_default @@ -1929,7 +1929,7 @@ fn apply_gradient_update( { update((&mut selected_gradient.gradient, &mut selected_gradient.appearance)); } - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); data.has_selected_gradient = has_gradient_on_selected_layers(context.document); responses.add(ToolMessage::RefreshToolOptions); } @@ -1997,7 +1997,7 @@ fn apply_stops_update(data: &mut GradientToolData, context: &mut ToolActionMessa data.default_gradient_stops = Some(new_gradient); } - responses.add(PropertiesPanelMessage::Refresh); + responses.add(InspectorMessage::Refresh); // Refresh the tool options so the swatch's `swatch_samples` update live as the user edits stops in the picker. responses.add(ToolMessage::RefreshToolOptions); } @@ -2818,7 +2818,7 @@ mod test_gradient { let (gradient, _) = get_gradient_from_chain(&mut editor).await; assert_eq!(gradient.gradient_spread, GradientSpread::Pad); - // Stamp the spread into the value node's ramp, the way the Properties panel's color picker writes it + // Stamp the spread into the value node's ramp, the way the Inspector's color picker writes it let gradient_value_id = { let network_interface = &editor.active_document().network_interface; get_upstream_gradient_value_node_id(layer, network_interface).expect("the chain should have a gradient value node") @@ -2866,7 +2866,7 @@ mod test_gradient { }) .await; - // The Properties panel reads the value node's own ramp, so the spread has to be stored there + // The Inspector reads the value node's own ramp, so the spread has to be stored there let network_interface = &editor.active_document().network_interface; assert_eq!( get_chain_source_gradient_settings(layer, network_interface).map(|settings| settings.spread), diff --git a/frontend/src/components/Editor.svelte b/frontend/src/components/Editor.svelte index bd8b1c9af42..484edc6e7e6 100644 --- a/frontend/src/components/Editor.svelte +++ b/frontend/src/components/Editor.svelte @@ -313,7 +313,7 @@ .menu-list, .menu-list-button .entry, .layer-tree .expand-arrow, - .widget-section .header { + .node-section .header { &:focus-visible { outline: 1px dashed var(--color-e-nearwhite); outline-offset: -1px; diff --git a/frontend/src/components/README.md b/frontend/src/components/README.md index 6669aaba17e..5962a2871c8 100644 --- a/frontend/src/components/README.md +++ b/frontend/src/components/README.md @@ -12,7 +12,7 @@ Useful containers that control the flow of content held within. ## Panels: `panels/` -The dockable tabbed regions like the Document, Properties, Layers, Data, and Welcome panels. +The dockable tabbed regions like the Document, Inspector, Layers, Data, and Welcome panels. ## Views: `views/` diff --git a/frontend/src/components/panels/Properties.svelte b/frontend/src/components/panels/Inspector.svelte similarity index 91% rename from frontend/src/components/panels/Properties.svelte rename to frontend/src/components/panels/Inspector.svelte index 43f6339c119..15bd9b6c9d6 100644 --- a/frontend/src/components/panels/Properties.svelte +++ b/frontend/src/components/panels/Inspector.svelte @@ -2,14 +2,14 @@ import { getContext, onMount, onDestroy } from "svelte"; import LayoutCol from "/src/components/layout/LayoutCol.svelte"; import WidgetLayout from "/src/components/widgets/WidgetLayout.svelte"; - import { propertiesPanelLayout } from "/src/stores/portfolio"; + import { inspectorLayout } from "/src/stores/portfolio"; import type { EditorWrapper } from "/wrapper/pkg/graphite_wasm_wrapper"; const editor = getContext("editor"); let sectionsCol: LayoutCol | undefined; - // Interactive dragging to reorder Properties panel node sections (a selected layer's chain nodes, or pinned nodes) + // Interactive dragging to reorder Inspector node sections (a selected layer's chain nodes, or pinned nodes) type DragState = { nodeId: bigint; startX: number; startY: number; active: boolean }; let dragState: DragState | undefined = undefined; let dragging = false; @@ -45,7 +45,7 @@ function reorderableSections(): Element[] { const container = sectionsCol?.div(); if (!container) return []; - return Array.from(container.querySelectorAll("[data-properties-reorderable-section]")); + return Array.from(container.querySelectorAll("[data-inspector-reorderable-section]")); } function sectionPointerDown(e: PointerEvent) { @@ -56,13 +56,13 @@ if (!target) return; // The drag handle is the section header - const handle = target.closest("[data-properties-reorder-handle]"); + const handle = target.closest("[data-inspector-reorder-handle]"); if (!handle) return; // Don't begin a drag when pressing one of the header's own buttons (pin/delete/visibility); only the header itself grabs if (target.closest("[data-icon-button]")) return; - const section = target.closest("[data-properties-reorderable-section]"); + const section = target.closest("[data-inspector-reorderable-section]"); const nodeIdAttribute = section?.getAttribute("data-node-id"); if (!section || !nodeIdAttribute) return; @@ -135,7 +135,7 @@ // Skip drops that don't actually move the node (into its own slot, unless copying it), or where the dragged section vanished from the DOM mid-drag (fromIndex of -1) if (insertIndex !== undefined && fromIndex !== undefined && fromIndex !== -1) { const intoOwnSlot = insertIndex === fromIndex || insertIndex === fromIndex + 1; - if (duplicate || !intoOwnSlot) editor.reorderPropertiesSection(dragState.nodeId, insertIndex, duplicate); + if (duplicate || !intoOwnSlot) editor.reorderInspectorSection(dragState.nodeId, insertIndex, duplicate); } } @@ -164,9 +164,9 @@ } - + - + {#if dragging && insertMarkerTop !== undefined}
{/if} @@ -174,7 +174,7 @@