From f5ef1a94fe51c6e74edb229adb02614adb1f9975 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Mon, 10 Nov 2025 00:06:10 -0800 Subject: [PATCH] Update the website with an evolved roadmap and new product screenshots/videos --- demo-artwork/marbled-mandelbrot.graphite | 2 +- website/content/_index.md | 28 +- website/content/features.md | 352 +++++++++++------- website/content/learn/_index.md | 4 +- website/content/learn/interface/_index.md | 8 +- .../guide/graphene/networks-and-nodes.md | 2 +- .../guide/student-projects/_index.md | 6 - website/sass/component/carousel.scss | 10 +- website/static/js/carousel.js | 162 +++++++- website/templates/base.html | 2 +- 10 files changed, 410 insertions(+), 166 deletions(-) diff --git a/demo-artwork/marbled-mandelbrot.graphite b/demo-artwork/marbled-mandelbrot.graphite index 676c2c96..52765a62 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":[[4388711862172196665,{"inputs":[],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphene_raster_nodes::std_nodes::MandelbrotNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"FOOTPRINT","inject":""}}],[3606681156406984991,{"inputs":[{"Node":{"node_id":6323350524796370485,"output_index":0}},{"Value":{"tagged_value":{"GradientStops":[[0.3237704918032787,{"red":1.0,"green":0.0,"blue":1.0,"alpha":0.1}],[0.5655737704918032,{"red":0.8901961,"green":0.8117647,"blue":0.39215687,"alpha":1.0}],[0.8155737704918032,{"red":0.0,"green":1.0,"blue":1.0,"alpha":0.5}]]},"exposed":false}},{"Value":{"tagged_value":{"Bool":true},"exposed":false}}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_raster_nodes::gradient_map::GradientMapNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[6029481207635803402,{"inputs":[{"Node":{"node_id":4388711862172196665,"output_index":0}},{"Value":{"tagged_value":{"DVec2":[0.0,0.0]},"exposed":false}},{"Value":{"tagged_value":{"F64":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":{"Generic":"T"},"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","alias":null}},"import_index":1}},{"Import":{"import_type":{"Concrete":{"name":"f64","alias":null}},"import_index":2}},{"Import":{"import_type":{"Concrete":{"name":"glam::f64::dvec2::DVec2","alias":null}},"import_index":3}},{"Import":{"import_type":{"Concrete":{"name":"glam::f64::dvec2::DVec2","alias":null}},"import_index":4}}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::transform_nodes::TransformNode"}},"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":{"Graphic":{"element":[],"transform":[],"alpha_blending":[],"source_node_id":[]}},"exposed":true}},{"Node":{"node_id":3606681156406984991,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":4,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::ToGraphicNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[4,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Node":{"node_id":3,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::ExtendNode"}},"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>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Node":{"node_id":1,"output_index":0}},{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::SourceNodeIdNode"}},"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>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::WrapGraphicNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[80924370013313595,{"inputs":[{"Node":{"node_id":6029481207635803402,"output_index":0}},{"Value":{"tagged_value":{"GradientStops":[[0.0,{"red":0.19607843,"green":0.0,"blue":0.21176471,"alpha":1.0}],[0.12704918032786883,{"red":0.0627451,"green":0.19215687,"blue":0.39607844,"alpha":1.0}],[0.5,{"red":0.8901961,"green":0.8117647,"blue":0.39215687,"alpha":1.0}],[1.0,{"red":0.58431375,"green":0.92941177,"blue":0.92941177,"alpha":0.01}]]},"exposed":false}},{"Value":{"tagged_value":{"Bool":false},"exposed":false}}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_raster_nodes::gradient_map::GradientMapNode"}},"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":{"U32":0},"exposed":false}},{"Value":{"tagged_value":{"F64":35.0},"exposed":false}},{"Value":{"tagged_value":{"NoiseType":"OpenSimplex2"},"exposed":false}},{"Value":{"tagged_value":{"DomainWarpType":"OpenSimplex2"},"exposed":false}},{"Value":{"tagged_value":{"F64":100.0},"exposed":false}},{"Value":{"tagged_value":{"FractalType":"PingPong"},"exposed":false}},{"Value":{"tagged_value":{"U32":3},"exposed":false}},{"Value":{"tagged_value":{"F64":2.0},"exposed":false}},{"Value":{"tagged_value":{"F64":0.5},"exposed":false}},{"Value":{"tagged_value":{"F64":0.0},"exposed":false}},{"Value":{"tagged_value":{"F64":2.0},"exposed":false}},{"Value":{"tagged_value":{"CellularDistanceFunction":"Hybrid"},"exposed":false}},{"Value":{"tagged_value":{"CellularReturnType":"CellValue"},"exposed":false}},{"Value":{"tagged_value":{"F64":1.0},"exposed":false}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphene_raster_nodes::std_nodes::NoisePatternNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","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":4,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::ToGraphicNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[4,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Node":{"node_id":3,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::ExtendNode"}},"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>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Node":{"node_id":1,"output_index":0}},{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::SourceNodeIdNode"}},"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>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::WrapGraphicNode"}},"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":{"Artboard":{"element":[],"transform":[],"alpha_blending":[],"source_node_id":[]}},"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":{"element":[{"red":0.0,"green":0.0,"blue":0.0,"alpha":1.0}],"transform":[[1.0,0.0,0.0,1.0,0.0,0.0]],"alpha_blending":[{"blend_mode":"Normal","opacity":1.0,"fill":1.0,"clip":false}],"source_node_id":[null]}},"exposed":false}},{"Value":{"tagged_value":{"Bool":true},"exposed":false}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":3,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Concrete":{"name":"graph_craft::document::value::TaggedValue","alias":null}},"import_index":1}},{"Value":{"tagged_value":{"String":"Artboard"},"exposed":false}},{"Import":{"import_type":{"Concrete":{"name":"graph_craft::document::value::TaggedValue","alias":null}},"import_index":2}},{"Import":{"import_type":{"Concrete":{"name":"graph_craft::document::value::TaggedValue","alias":null}},"import_index":3}},{"Import":{"import_type":{"Concrete":{"name":"graph_craft::document::value::TaggedValue","alias":null}},"import_index":4}},{"Import":{"import_type":{"Concrete":{"name":"graph_craft::document::value::TaggedValue","alias":null}},"import_index":5}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphene_core::artboard::CreateArtboardNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[3,{"inputs":[{"Import":{"import_type":{"Fn":[{"Concrete":{"name":"core::option::Option>","alias":null}},{"Concrete":{"name":"graphene_core::table::Table","alias":null}}]},"import_index":0}},{"Node":{"node_id":2,"output_index":0}},{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::ExtendNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Node":{"node_id":1,"output_index":0}}],"call_argument":{"Generic":"T"},"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}},{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::SourceNodeIdNode"}},"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":{"node_metadata":[[4388711862172196665,{"persistent_metadata":{"reference":"Mandelbrot","display_name":"Mandelbrot","input_metadata":[],"output_names":["Raster"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":null}}],[6323350524796370485,{"persistent_metadata":{"reference":"Noise Pattern","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}}],[12241147352993594415,{"persistent_metadata":{"reference":"Artboard","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","y":"Y","x":"X"},"widget_override":"vec2","input_name":"Location","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"is_integer":true,"y":"H","x":"W","unit":" px"},"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":{"node_metadata":[[0,{"persistent_metadata":{"reference":null,"display_name":"Create Artboard","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":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-3]}}},"network_metadata":null}}],[3,{"persistent_metadata":{"reference":null,"display_name":"Extend","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":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,-4]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"reference":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":[-7,-3]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"reference":null,"display_name":"Source Node ID","input_metadata":[{"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":[-14,-3]}}},"network_metadata":null}}]],"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_top_right":[0.0,0.0]},"selection_undo_history":[],"selection_redo_history":[]}}}}],[6029481207635803402,{"persistent_metadata":{"reference":null,"display_name":"Transform","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"y":"Y","unit":" px","is_integer":false,"x":"X"},"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":{"y":"H","x":"W","is_integer":false,"unit":"x"},"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":{"node_metadata":[[1,{"persistent_metadata":{"reference":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}}],[0,{"persistent_metadata":{"reference":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}}]],"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_top_right":[0.0,0.0]},"selection_undo_history":[],"selection_redo_history":[]}}}}],[7624113397561636853,{"persistent_metadata":{"reference":"Merge","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":{"node_metadata":[[3,{"persistent_metadata":{"reference":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":[-7,-1]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"reference":null,"display_name":"Wrap Graphic","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":[-21,-1]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"reference":null,"display_name":"Source Node ID","input_metadata":[{"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":[-14,-1]}}},"network_metadata":null}}],[4,{"persistent_metadata":{"reference":null,"display_name":"Extend","input_metadata":[{"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":[0,-3]}}},"network_metadata":null}}],[0,{"persistent_metadata":{"reference":null,"display_name":"To Graphic","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":[-21,-3]}}},"network_metadata":null}}]],"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_top_right":[0.0,0.0]},"selection_undo_history":[],"selection_redo_history":[]}}}}],[3606681156406984991,{"persistent_metadata":{"reference":"Gradient Map","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}}],[6565638614909771142,{"persistent_metadata":{"reference":"Merge","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":{"node_metadata":[[4,{"persistent_metadata":{"reference":null,"display_name":"Extend","input_metadata":[{"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":[0,-3]}}},"network_metadata":null}}],[3,{"persistent_metadata":{"reference":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":[-7,-1]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"reference":null,"display_name":"Wrap Graphic","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":[-21,-1]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"reference":null,"display_name":"Source Node ID","input_metadata":[{"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":[-14,-1]}}},"network_metadata":null}}],[0,{"persistent_metadata":{"reference":null,"display_name":"To Graphic","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":[-21,-3]}}},"network_metadata":null}}]],"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_top_right":[0.0,0.0]},"selection_undo_history":[],"selection_redo_history":[]}}}}],[80924370013313595,{"persistent_metadata":{"reference":"Gradient Map","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}}]],"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,1336.0,394.0],"node_graph_top_right":[1468.796875,0.0]},"selection_undo_history":[[12241147352993594415]],"selection_redo_history":[]}}},"collapsed":[],"commit_hash":"f6ffa45a8180183d70a67d3e41249934a8fcacc9","document_ptz":{"pan":[-339.3903349049215,-502.62390663267854],"tilt":0.0,"zoom":4.0,"flip":false},"document_mode":"DesignMode","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,"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,"grid_color":{"red":0.6038274,"green":0.6038274,"blue":0.6038274,"alpha":1.0},"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":[[4388711862172196665,{"inputs":[],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphene_raster_nodes::std_nodes::MandelbrotNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"FOOTPRINT","inject":""}}],[3606681156406984991,{"inputs":[{"Node":{"node_id":6323350524796370485,"output_index":0}},{"Value":{"tagged_value":{"GradientStops":[[0.0,{"red":0.0,"green":0.0,"blue":0.0,"alpha":1.0}],[0.3237704918032787,{"red":0.23828125,"green":0.0,"blue":0.08377075,"alpha":1.0}],[0.5655737704918032,{"red":0.92578125,"green":0.8676921,"blue":0.5569153,"alpha":1.0}],[0.8155737704918032,{"red":0.17333984,"green":0.625,"blue":0.625,"alpha":1.0}],[1.0,{"red":0.106292725,"green":0.3359375,"blue":0.3359375,"alpha":1.0}]]},"exposed":false}},{"Value":{"tagged_value":{"Bool":true},"exposed":false}}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_raster_nodes::gradient_map::GradientMapNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[6029481207635803402,{"inputs":[{"Node":{"node_id":4388711862172196665,"output_index":0}},{"Value":{"tagged_value":{"DVec2":[0.0,0.0]},"exposed":false}},{"Value":{"tagged_value":{"F64":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":{"Generic":"T"},"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","alias":null}},"import_index":1}},{"Import":{"import_type":{"Concrete":{"name":"f64","alias":null}},"import_index":2}},{"Import":{"import_type":{"Concrete":{"name":"glam::f64::dvec2::DVec2","alias":null}},"import_index":3}},{"Import":{"import_type":{"Concrete":{"name":"glam::f64::dvec2::DVec2","alias":null}},"import_index":4}}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::transform_nodes::TransformNode"}},"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":{"Graphic":{"element":[],"transform":[],"alpha_blending":[],"source_node_id":[]}},"exposed":true}},{"Node":{"node_id":3606681156406984991,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":4,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::ToGraphicNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[4,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Node":{"node_id":3,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::ExtendNode"}},"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>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Node":{"node_id":1,"output_index":0}},{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::SourceNodeIdNode"}},"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>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::WrapGraphicNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}]],"scope_injections":[]}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[80924370013313595,{"inputs":[{"Node":{"node_id":6029481207635803402,"output_index":0}},{"Value":{"tagged_value":{"GradientStops":[[0.0,{"red":0.28211805,"green":0.0,"blue":0.3046875,"alpha":1.0}],[0.12704918032786883,{"red":0.13647461,"green":0.3989315,"blue":0.8125,"alpha":1.0}],[0.5,{"red":1.0,"green":0.9409449,"blue":0.625,"alpha":1.0}],[1.0,{"red":0.58431375,"green":0.92941177,"blue":0.92941177,"alpha":0.01}]]},"exposed":false}},{"Value":{"tagged_value":{"Bool":false},"exposed":false}}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_raster_nodes::gradient_map::GradientMapNode"}},"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":{"U32":0},"exposed":false}},{"Value":{"tagged_value":{"F64":35.0},"exposed":false}},{"Value":{"tagged_value":{"NoiseType":"OpenSimplex2"},"exposed":false}},{"Value":{"tagged_value":{"DomainWarpType":"OpenSimplex2"},"exposed":false}},{"Value":{"tagged_value":{"F64":100.0},"exposed":false}},{"Value":{"tagged_value":{"FractalType":"PingPong"},"exposed":false}},{"Value":{"tagged_value":{"U32":3},"exposed":false}},{"Value":{"tagged_value":{"F64":2.0},"exposed":false}},{"Value":{"tagged_value":{"F64":0.5},"exposed":false}},{"Value":{"tagged_value":{"F64":0.0},"exposed":false}},{"Value":{"tagged_value":{"F64":2.0},"exposed":false}},{"Value":{"tagged_value":{"CellularDistanceFunction":"Hybrid"},"exposed":false}},{"Value":{"tagged_value":{"CellularReturnType":"CellValue"},"exposed":false}},{"Value":{"tagged_value":{"F64":1.0},"exposed":false}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphene_raster_nodes::std_nodes::NoisePatternNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","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":4,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Generic":"T"},"import_index":0}}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::ToGraphicNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[4,{"inputs":[{"Node":{"node_id":0,"output_index":0}},{"Node":{"node_id":3,"output_index":0}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::ExtendNode"}},"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>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::memo::MonitorNode"}},"visible":true,"skip_deduplication":true,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Node":{"node_id":1,"output_index":0}},{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::SourceNodeIdNode"}},"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>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::WrapGraphicNode"}},"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":{"Artboard":{"element":[],"transform":[],"alpha_blending":[],"source_node_id":[]}},"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":{"element":[{"red":0.0,"green":0.0,"blue":0.0,"alpha":1.0}],"transform":[[1.0,0.0,0.0,1.0,0.0,0.0]],"alpha_blending":[{"blend_mode":"Normal","opacity":1.0,"fill":1.0,"clip":false}],"source_node_id":[null]}},"exposed":false}},{"Value":{"tagged_value":{"Bool":true},"exposed":false}}],"call_argument":{"Generic":"T"},"implementation":{"Network":{"exports":[{"Node":{"node_id":3,"output_index":0}}],"nodes":[[0,{"inputs":[{"Import":{"import_type":{"Concrete":{"name":"graph_craft::document::value::TaggedValue","alias":null}},"import_index":1}},{"Value":{"tagged_value":{"String":"Artboard"},"exposed":false}},{"Import":{"import_type":{"Concrete":{"name":"graph_craft::document::value::TaggedValue","alias":null}},"import_index":2}},{"Import":{"import_type":{"Concrete":{"name":"graph_craft::document::value::TaggedValue","alias":null}},"import_index":3}},{"Import":{"import_type":{"Concrete":{"name":"graph_craft::document::value::TaggedValue","alias":null}},"import_index":4}},{"Import":{"import_type":{"Concrete":{"name":"graph_craft::document::value::TaggedValue","alias":null}},"import_index":5}}],"call_argument":{"Generic":"T"},"implementation":{"ProtoNode":{"name":"graphene_core::artboard::CreateArtboardNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[3,{"inputs":[{"Import":{"import_type":{"Fn":[{"Concrete":{"name":"core::option::Option>","alias":null}},{"Concrete":{"name":"graphene_core::table::Table","alias":null}}]},"import_index":0}},{"Node":{"node_id":2,"output_index":0}},{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::ExtendNode"}},"visible":true,"skip_deduplication":false,"context_features":{"extract":"","inject":""}}],[2,{"inputs":[{"Node":{"node_id":1,"output_index":0}}],"call_argument":{"Generic":"T"},"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}},{"Reflection":"DocumentNodePath"}],"call_argument":{"Concrete":{"name":"core::option::Option>","alias":null}},"implementation":{"ProtoNode":{"name":"graphene_core::graphic::SourceNodeIdNode"}},"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":{"node_metadata":[[4388711862172196665,{"persistent_metadata":{"reference":"Mandelbrot","display_name":"Mandelbrot","input_metadata":[],"output_names":["Raster"],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":"Chain"}},"network_metadata":null}}],[6029481207635803402,{"persistent_metadata":{"reference":null,"display_name":"Transform","input_metadata":[{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"Value","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"x":"X","is_integer":false,"y":"Y","unit":" px"},"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":{"unit":"x","y":"H","is_integer":false,"x":"W"},"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":{"node_metadata":[[1,{"persistent_metadata":{"reference":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}}],[0,{"persistent_metadata":{"reference":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}}]],"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_top_right":[0.0,0.0]},"selection_undo_history":[],"selection_redo_history":[]}}}}],[3606681156406984991,{"persistent_metadata":{"reference":"Gradient Map","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}}],[12241147352993594415,{"persistent_metadata":{"reference":"Artboard","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","y":"Y","x":"X"},"widget_override":"vec2","input_name":"Location","input_description":"TODO"}},{"persistent_metadata":{"input_data":{"unit":" px","x":"W","y":"H","is_integer":true},"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":{"node_metadata":[[3,{"persistent_metadata":{"reference":null,"display_name":"Extend","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":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[0,-4]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"reference":null,"display_name":"Source Node ID","input_metadata":[{"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":[-14,-3]}}},"network_metadata":null}}],[0,{"persistent_metadata":{"reference":null,"display_name":"Create Artboard","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":""}},{"persistent_metadata":{"input_data":{},"widget_override":null,"input_name":"","input_description":""}}],"output_names":[],"locked":false,"pinned":false,"node_type_metadata":{"Node":{"position":{"Absolute":[-21,-3]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"reference":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":[-7,-3]}}},"network_metadata":null}}]],"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_top_right":[0.0,0.0]},"selection_undo_history":[],"selection_redo_history":[]}}}}],[80924370013313595,{"persistent_metadata":{"reference":"Gradient Map","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}}],[6565638614909771142,{"persistent_metadata":{"reference":"Merge","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":{"node_metadata":[[0,{"persistent_metadata":{"reference":null,"display_name":"To Graphic","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":[-21,-3]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"reference":null,"display_name":"Wrap Graphic","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":[-21,-1]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"reference":null,"display_name":"Source Node ID","input_metadata":[{"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":[-14,-1]}}},"network_metadata":null}}],[4,{"persistent_metadata":{"reference":null,"display_name":"Extend","input_metadata":[{"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":[0,-3]}}},"network_metadata":null}}],[3,{"persistent_metadata":{"reference":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":[-7,-1]}}},"network_metadata":null}}]],"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_top_right":[0.0,0.0]},"selection_undo_history":[],"selection_redo_history":[]}}}}],[7624113397561636853,{"persistent_metadata":{"reference":"Merge","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":{"node_metadata":[[3,{"persistent_metadata":{"reference":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":[-7,-1]}}},"network_metadata":null}}],[1,{"persistent_metadata":{"reference":null,"display_name":"Wrap Graphic","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":[-21,-1]}}},"network_metadata":null}}],[2,{"persistent_metadata":{"reference":null,"display_name":"Source Node ID","input_metadata":[{"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":[-14,-1]}}},"network_metadata":null}}],[0,{"persistent_metadata":{"reference":null,"display_name":"To Graphic","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":[-21,-3]}}},"network_metadata":null}}],[4,{"persistent_metadata":{"reference":null,"display_name":"Extend","input_metadata":[{"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":[0,-3]}}},"network_metadata":null}}]],"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_top_right":[0.0,0.0]},"selection_undo_history":[],"selection_redo_history":[]}}}}],[6323350524796370485,{"persistent_metadata":{"reference":"Noise Pattern","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}}]],"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,1336.0,394.0],"node_graph_top_right":[1468.796875,0.0]},"selection_undo_history":[[6565638614909771142],[7624113397561636853],[6565638614909771142],[7624113397561636853],[6565638614909771142],[6565638614909771142]],"selection_redo_history":[]}}},"collapsed":[],"commit_hash":"f6ffa45a8180183d70a67d3e41249934a8fcacc9","document_ptz":{"pan":[-339.3903349049215,-502.62390663267854],"tilt":0.0,"zoom":4.0,"flip":false},"document_mode":"DesignMode","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,"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,"grid_color":{"red":0.6038274,"green":0.6038274,"blue":0.6038274,"alpha":1.0},"dot_display":false}},"graph_view_overlay_open":false,"graph_fade_artwork_percentage":80.0} \ No newline at end of file diff --git a/website/content/_index.md b/website/content/_index.md index b0af5f7e..cff512bb 100644 --- a/website/content/_index.md +++ b/website/content/_index.md @@ -25,7 +25,7 @@ meta_description = "Open source free software. A vector graphics creativity suit

Your procedural toolbox for 2D content creation

-

Graphite is a free, open source vector and raster graphics editor, available now in alpha. Get creative with a fully nondestructive editing workflow that combines layer-based compositing with node-based generative design.

+

Graphite is a free, open source vector graphics editor and animation engine, available now in alpha. Get creative with a fully nondestructive editing workflow that combines layer-based compositing with node-based generative design.

@@ -85,15 +85,15 @@ meta_description = "Open source free software. A vector graphics creativity suit + +
+ +
+ +## Roadmap spotlight: keyframe animation + +Coming early 2026, Graphite will expand its animation toolset beyond parametrically-driven motion to include traditional keyframe animation. The Timeline panel pictured below will let animators drive parameters using keyframes and curves through a traditional dopesheet interface. + +Node parameters can be set to a constant value in the Properties panel, exposed to the graph for procedural animation, or exposed to a channel in the upcoming Timeline panel for hand-authored keyframing. + +The panel will enable users to scrub through time with the playhead and choose between timing with discrete frames or continuous seconds. A dedicated curves editing mode (not pictured) will enable fine-tuning parameters with a labeled Y-axis, while the dopesheet allows individual channels to be expanded to view and edit the shape and smoothness of curves inline. + +Work-in-progress design mockup: + + + +
+ +
+ +
+ +
+ +## Roadmap spotlight: raster image editing + +The vision since Graphite's inception has been to open up the traditional raster image editing workflow to the greater degree of flexibility found in node-based compositors, without one approach compromising the ergonomics of the other. + +As with Graphite's current vector toolset, raster editing will interpret the user's interactive edits as modifications to the construction of layers in the underlying node graph rather than destructive alterations to layer pixel data (as in other image editors). By containing only a description of the user's editing operations without the data, documents will remain ultra tiny when source assets are linked externally. + +Brushes, selection tools, masks, filters, effects, adjustment layers, and other tools used to manipulate raster layers will all be presented in a familiar form when Graphite's raster toolset nears maturity by the end of beta. + +Work-in-progress design mockup: + + + + + +
+ +
diff --git a/website/content/learn/_index.md b/website/content/learn/_index.md index 5a191906..52771ba7 100644 --- a/website/content/learn/_index.md +++ b/website/content/learn/_index.md @@ -9,9 +9,7 @@ js = ["/js/youtube-embed.js"] css = ["/component/youtube-embed.css"] +++ -Welcome to the Graphite user manual. Keep reading to to learn how the software can help bring your 2D creative ideas to life. - -You may choose to read this sequentially and learn from the structured introduction and sample projects. Or you may jump to chapters of interest that also serve as quick reference. +Welcome to the Graphite user manual. Keep reading to learn how the software can help bring your 2D creative ideas to life. ## More chapters on the way diff --git a/website/content/learn/interface/_index.md b/website/content/learn/interface/_index.md index 0148aae3..2fce2aed 100644 --- a/website/content/learn/interface/_index.md +++ b/website/content/learn/interface/_index.md @@ -23,12 +23,6 @@ On the left, the [**menu bar**](./menu-bar) provides quick access to many editor -### Document title - -In the center, the **document title** displays the name of the active document. That name is given a `*` suffix if the file has unsaved changes. For example, *Painting.graphite** would be unsaved but *Painting.graphite* would have no changes following its last save. - -

The document title

- ### Window buttons On the right, the **window buttons** provide platform-specific controls for the application. @@ -37,7 +31,7 @@ On the right, the **window buttons** provide platform-specific controls for the | | | |-|-| -| **Web** |

A button to enter fullscreen mode is displayed.

The label "*Go fullscreen to access all hotkeys*" indicates that some shortcut keys like CtrlN (macOS: N) are reserved by the web browser and can only be used in fullscreen mode. (An alternative to going fullscreen: include Alt in the shortcut combinations for browser-reserved hotkeys.)

Fullscreen button

| +| **Web** |

A button to enter fullscreen mode is displayed.

Some shortcut keys like CtrlN (macOS: N) are reserved by the web browser and can only be used in fullscreen mode. (Alternative to going fullscreen: include Alt in the shortcut combinations for browser-reserved hotkeys.)

Fullscreen button

| diff --git a/website/content/volunteer/guide/graphene/networks-and-nodes.md b/website/content/volunteer/guide/graphene/networks-and-nodes.md index d3cf1624..aeb12cb9 100644 --- a/website/content/volunteer/guide/graphene/networks-and-nodes.md +++ b/website/content/volunteer/guide/graphene/networks-and-nodes.md @@ -13,7 +13,7 @@ Any (sub)graph can import/export data from/to the outside world. For example, a In the Graphite editor UI, here is an example graph of artwork that imports no data but exports its content to the canvas: -Node graph UI mockup +Node graph UI mockup The graph shown above represents the full artwork, meaning it's the root-level graph in its document. But there is nothing special about that graph compared to any subgraph. To avoid the confusion of calling it a graph or subgraph which comes with implications about user-facing concepts in the context of a document, we will use the less-ambiguous term **network** in the context of Graphene's internal concepts and codebase. diff --git a/website/content/volunteer/guide/student-projects/_index.md b/website/content/volunteer/guide/student-projects/_index.md index 7cac22d5..7ddce48c 100644 --- a/website/content/volunteer/guide/student-projects/_index.md +++ b/website/content/volunteer/guide/student-projects/_index.md @@ -95,12 +95,6 @@ Based on the experience and insight brought to the table by the student, the nat -### Native development - -#### Graphite desktop app engineering - -*This is a newly added project pending a full written overview. Come ask on Discord for details.* - ### Rendering and graphics Several of these require a good understanding of computer graphics rendering techniques and algorithms. Experience in game development and writing your own rendering engines is a plus. diff --git a/website/sass/component/carousel.scss b/website/sass/component/carousel.scss index 78f18cba..8f042c80 100644 --- a/website/sass/component/carousel.scss +++ b/website/sass/component/carousel.scss @@ -8,7 +8,7 @@ touch-action: pan-y pinch-zoom; cursor: grab; - img { + :is(img, video) { position: relative; display: inline-block; user-select: none; @@ -33,7 +33,7 @@ } } - &:not(.dragging, .jostling) .carousel-slide img { + &:not(.dragging, .jostling) .carousel-slide :is(img, video) { transition: transform 500ms; } @@ -141,11 +141,11 @@ } } - &.window-size-1 .carousel-slide img { + &.window-size-1 .carousel-slide :is(img, video) { width: 100%; } - &.window-size-2 .carousel-slide img { + &.window-size-2 .carousel-slide :is(img, video) { width: calc((100% / 2) - 10px); padding: 0 10px; @@ -158,7 +158,7 @@ } } - &.window-size-3 .carousel-slide img { + &.window-size-3 .carousel-slide :is(img, video) { width: calc((100% / 3) - 10px * (4 / 3)); padding: 0 10px; diff --git a/website/static/js/carousel.js b/website/static/js/carousel.js index cb7263ff..2b2c7b2e 100644 --- a/website/static/js/carousel.js +++ b/website/static/js/carousel.js @@ -17,7 +17,8 @@ window.addEventListener("pointermove", dragMove); * dragLastClientX: number | undefined, * velocityDeltaWindow: Array<{ time: number, delta: number }>, * jostleNoLongerNeeded: boolean, - * requestAnimationFrameActive: boolean + * requestAnimationFrameActive: boolean, + * videoSyncInterval: ReturnType | undefined, * }} Carousel */ @@ -34,8 +35,8 @@ function initializeCarousel() { if (!(insertInsideElement instanceof HTMLElement)) return; slideImages.forEach((image) => { const clonedImage = image.cloneNode(true); - if (!(clonedImage instanceof HTMLImageElement)) return; - clonedImage.alt = ""; + if (!(clonedImage instanceof HTMLImageElement) && !(clonedImage instanceof HTMLVideoElement)) return; + if (clonedImage instanceof HTMLImageElement) clonedImage.alt = ""; insertInsideElement.insertAdjacentElement("beforeend", clonedImage); }); }); @@ -61,6 +62,7 @@ function initializeCarousel() { velocityDeltaWindow, jostleNoLongerNeeded, requestAnimationFrameActive: false, + videoSyncInterval: undefined, }; carousels.push(carousel); @@ -166,6 +168,160 @@ function slideTo(carousel, index, smooth) { slideImages[clamp(offsetIndex + 2, 0, slideImages.length - 1)].removeAttribute("loading"); setCurrentTransform(carousel, index * -100, "%", smooth); + + // Manage video preloading and playback + manageVideoPlayback(carousel, index); +} + +/** + * Get all video elements for a given slide index (main + torn edge copies) + * @param {Carousel} carousel + * @param {number} index + */ +function getVideosForSlide(carousel, index) { + // Account for the first image being the faded-out last image + const offsetIndex = index + 1; + const slideImages = Array.from(carousel.carouselContainer.querySelectorAll("[data-carousel-slide] [data-carousel-image]")); + const tornLeftImages = Array.from(carousel.carouselContainer.querySelectorAll("[data-carousel-slide-torn-left] [data-carousel-image]")); + const tornRightImages = Array.from(carousel.carouselContainer.querySelectorAll("[data-carousel-slide-torn-right] [data-carousel-image]")); + + const mainElement = slideImages[offsetIndex]; + const tornLeftElement = tornLeftImages[offsetIndex]; + const tornRightElement = tornRightImages[offsetIndex]; + + return { + main: mainElement instanceof HTMLVideoElement ? mainElement : null, + tornLeft: tornLeftElement instanceof HTMLVideoElement ? tornLeftElement : null, + tornRight: tornRightElement instanceof HTMLVideoElement ? tornRightElement : null, + }; +} + +/** + * Check if the carousel is currently in transition (dragging or animating) + * @param {Carousel} carousel + */ +function isCarouselInTransition(carousel) { + // Check if user is dragging + if (carousel.dragLastClientX !== undefined) return true; + + // Check if carousel has the "dragging" class (set during drag) + if (carousel.carouselContainer.classList.contains("dragging")) return true; + + // Check if any slide has a transition in progress by looking at the computed style + const firstImage = carousel.images[1]; + if (firstImage instanceof HTMLElement) { + const style = window.getComputedStyle(firstImage); + // If transform is transitioning, we're in motion + if (style.transitionProperty.includes("transform") && style.transitionDuration !== "0s") { + return true; + } + } + + return false; +} + +/** + * Preload and manage playback of videos on current and adjacent slides + * @param {Carousel} carousel + * @param {number} currentIndex + */ +function manageVideoPlayback(carousel, currentIndex) { + const totalSlides = carousel.dots.length; + + // Clear any existing sync interval + if (carousel.videoSyncInterval !== undefined) { + clearTimeout(carousel.videoSyncInterval); + carousel.videoSyncInterval = undefined; + } + + // Stop all videos that aren't on current or adjacent slides + for (let i = 0; i < totalSlides; i++) { + if (Math.abs(i - currentIndex) > 1) { + const videos = getVideosForSlide(carousel, i); + [videos.main, videos.tornLeft, videos.tornRight].forEach((video) => { + if (video) { + video.pause(); + video.currentTime = 0; + } + }); + } + } + + // Preload and potentially play videos on current and adjacent slides + const indicesToPreload = [currentIndex - 1, currentIndex, currentIndex + 1].filter((index) => index >= 0 && index < totalSlides); + + indicesToPreload.forEach((index) => { + const videos = getVideosForSlide(carousel, index); + + // Exit early if not a video slide + if (!videos.main) return; + + // Preload the video + if (videos.main.readyState < 3) videos.main.load(); + + // If this is the current slide, play the main video when ready + if (index === currentIndex) { + const playWhenReady = () => { + if (videos.main && videos.main.readyState >= 3) { + // Start the main video + videos.main.currentTime = 0; + videos.main.play().catch(() => {}); + } else if (videos.main) { + // Video not ready yet, check again + videos.main.addEventListener("canplaythrough", playWhenReady, { once: true }); + } + }; + + playWhenReady(); + + // Monitor for transitions and sync torn videos when in motion + updateVideoSyncForTransitions(carousel, videos); + } + }); +} + +/** + * Set up monitoring to play/pause torn edge videos based on transition state + * @param {Carousel} carousel + * @param {{ main: HTMLVideoElement | null, tornLeft: HTMLVideoElement | null, tornRight: HTMLVideoElement | null }} videos + */ +function updateVideoSyncForTransitions(carousel, videos) { + if (!videos.main) return; + + const syncTornVideos = () => { + const inTransition = isCarouselInTransition(carousel); + + // During transition: sync and play all copies + if (inTransition && videos.main) { + const mainTime = videos.main.currentTime; + [videos.tornLeft, videos.tornRight].forEach((video) => { + if (!video) return; + + if (video.paused) { + video.currentTime = mainTime; + video.play().catch(() => { + // Ignore autoplay errors + }); + } else { + // Keep synced + const drift = Math.abs(video.currentTime - mainTime); + if (drift > 0.1) { + video.currentTime = mainTime; + } + } + }); + } + // Not in transition: pause torn edge videos to save performance + else { + if (videos.tornLeft && !videos.tornLeft.paused) videos.tornLeft.pause(); + if (videos.tornRight && !videos.tornRight.paused) videos.tornRight.pause(); + } + + // Continue checking while in transition, or check again soon in case transition starts + carousel.videoSyncInterval = setTimeout(syncTornVideos, 100); + }; + + syncTornVideos(); } /** diff --git a/website/templates/base.html b/website/templates/base.html index 72436164..b7798fbe 100644 --- a/website/templates/base.html +++ b/website/templates/base.html @@ -140,7 +140,7 @@ Press Contact - Copyright © {{ now() | date(format = "%Y") }} Graphite Labs, LLC (an open source organization) + Copyright © {{ now() | date(format = "%Y") }} Graphite Labs, LLC (an open source community organization)