mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-20 11:28:30 +08:00
Deprecate LetNodes in favor of new scope API (#1814)
* WIP * Start deprecating let nodes * Replace WasmEditorApi network imports with new Scope input * Add missing unwrap * Add #[serde(default)] to scope_injections * Restructure WasmEditorApi definition to be available as a TaggedValue * Fix text node * Use stable toolchain in nix shell again * Code review * FIx text node and remove all remaining warnings * Require executor input to be 'static --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
co-authored by
Keavon Chambers
parent
a17ed68008
commit
3657b37574
+59
-46
@@ -410,65 +410,78 @@ mod test {
|
||||
assert_eq!(layers_after_copy[5], shape_id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[test]
|
||||
/// This test will fail when you make changes to the underlying serialization format for a document.
|
||||
async fn check_if_demo_art_opens() {
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
fn check_if_demo_art_opens() {
|
||||
futures::executor::block_on(async {
|
||||
use crate::messages::layout::utility_types::widget_prelude::*;
|
||||
|
||||
let print_problem_to_terminal_on_failure = |value: &String| {
|
||||
println!();
|
||||
println!("-------------------------------------------------");
|
||||
println!("Failed test due to receiving a DisplayDialogError while loading a Graphite demo file.");
|
||||
println!();
|
||||
println!("DisplayDialogError details:");
|
||||
println!();
|
||||
println!("Description: {value}");
|
||||
println!("-------------------------------------------------");
|
||||
println!();
|
||||
let print_problem_to_terminal_on_failure = |value: &String| {
|
||||
println!();
|
||||
println!("-------------------------------------------------");
|
||||
println!("Failed test due to receiving a DisplayDialogError while loading a Graphite demo file.");
|
||||
println!();
|
||||
println!("DisplayDialogError details:");
|
||||
println!();
|
||||
println!("Description: {value}");
|
||||
println!("-------------------------------------------------");
|
||||
println!();
|
||||
|
||||
panic!()
|
||||
};
|
||||
panic!()
|
||||
};
|
||||
|
||||
init_logger();
|
||||
let mut editor = Editor::create();
|
||||
init_logger();
|
||||
let mut editor = Editor::create();
|
||||
|
||||
for (document_name, _, file_name) in crate::messages::dialog::simple_dialogs::ARTWORK {
|
||||
let document_serialized_content = std::fs::read_to_string(format!("../demo-artwork/{file_name}")).unwrap();
|
||||
// UNCOMMENT THIS FOR RUNNING UNDER MIRI
|
||||
//
|
||||
// let files = [
|
||||
// include_str!("../../demo-artwork/isometric-fountain.graphite"),
|
||||
// include_str!("../../demo-artwork/just-a-potted-cactus.graphite"),
|
||||
// include_str!("../../demo-artwork/procedural-string-lights.graphite"),
|
||||
// include_str!("../../demo-artwork/red-dress.graphite"),
|
||||
// include_str!("../../demo-artwork/valley-of-spires.graphite"),
|
||||
// ];
|
||||
// for (id, document_serialized_content) in files.iter().enumerate() {
|
||||
// let document_name = format!("document {id}");
|
||||
|
||||
assert_eq!(
|
||||
document_serialized_content.lines().count(),
|
||||
1,
|
||||
"Demo artwork '{document_name}' has more than 1 line (remember to open and re-save it in Graphite)",
|
||||
);
|
||||
for (document_name, _, file_name) in crate::messages::dialog::simple_dialogs::ARTWORK {
|
||||
let document_serialized_content = std::fs::read_to_string(format!("../demo-artwork/{file_name}")).unwrap();
|
||||
|
||||
let responses = editor.handle_message(PortfolioMessage::OpenDocumentFile {
|
||||
document_name: document_name.into(),
|
||||
document_serialized_content,
|
||||
});
|
||||
println!("Responses:\n{responses:#?}");
|
||||
assert_eq!(
|
||||
document_serialized_content.lines().count(),
|
||||
1,
|
||||
"Demo artwork '{document_name}' has more than 1 line (remember to open and re-save it in Graphite)",
|
||||
);
|
||||
|
||||
// Check if the graph renders
|
||||
let portfolio = &mut editor.dispatcher.message_handlers.portfolio_message_handler;
|
||||
portfolio
|
||||
.executor
|
||||
.submit_node_graph_evaluation(portfolio.documents.get_mut(&portfolio.active_document_id.unwrap()).unwrap(), glam::UVec2::ONE)
|
||||
.expect("submit_node_graph_evaluation failed");
|
||||
crate::node_graph_executor::run_node_graph().await;
|
||||
let mut messages = VecDeque::new();
|
||||
editor.poll_node_graph_evaluation(&mut messages).expect("Graph should render");
|
||||
let responses = editor.handle_message(PortfolioMessage::OpenDocumentFile {
|
||||
document_name: document_name.into(),
|
||||
document_serialized_content: document_serialized_content.into(),
|
||||
});
|
||||
|
||||
for response in responses {
|
||||
// Check for the existence of the file format incompatibility warning dialog after opening the test file
|
||||
if let FrontendMessage::UpdateDialogColumn1 { layout_target: _, diff } = response {
|
||||
if let DiffUpdate::SubLayout(sub_layout) = &diff[0].new_value {
|
||||
if let LayoutGroup::Row { widgets } = &sub_layout[0] {
|
||||
if let Widget::TextLabel(TextLabel { value, .. }) = &widgets[0].widget {
|
||||
print_problem_to_terminal_on_failure(value);
|
||||
// Check if the graph renders
|
||||
let portfolio = &mut editor.dispatcher.message_handlers.portfolio_message_handler;
|
||||
portfolio
|
||||
.executor
|
||||
.submit_node_graph_evaluation(portfolio.documents.get_mut(&portfolio.active_document_id.unwrap()).unwrap(), glam::UVec2::ONE)
|
||||
.expect("submit_node_graph_evaluation failed");
|
||||
crate::node_graph_executor::run_node_graph().await;
|
||||
let mut messages = VecDeque::new();
|
||||
editor.poll_node_graph_evaluation(&mut messages).expect("Graph should render");
|
||||
|
||||
for response in responses {
|
||||
// Check for the existence of the file format incompatibility warning dialog after opening the test file
|
||||
if let FrontendMessage::UpdateDialogColumn1 { layout_target: _, diff } = response {
|
||||
if let DiffUpdate::SubLayout(sub_layout) = &diff[0].new_value {
|
||||
if let LayoutGroup::Row { widgets } = &sub_layout[0] {
|
||||
if let Widget::TextLabel(TextLabel { value, .. }) = &widgets[0].widget {
|
||||
print_problem_to_terminal_on_failure(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ impl LayoutHolder for ExportDialogMessageHandler {
|
||||
NumberInput::new(Some(self.scale_factor))
|
||||
.unit("")
|
||||
.min(0.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.disabled(self.file_type == FileType::Svg)
|
||||
.on_update(|number_input: &NumberInput| ExportDialogMessage::ScaleFactor(number_input.value.unwrap()).into())
|
||||
.min_width(200)
|
||||
|
||||
+2
-2
@@ -95,7 +95,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler {
|
||||
.label("W")
|
||||
.unit(" px")
|
||||
.min(0.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.is_integer(true)
|
||||
.disabled(self.infinite)
|
||||
.min_width(100)
|
||||
@@ -106,7 +106,7 @@ impl LayoutHolder for NewDocumentDialogMessageHandler {
|
||||
.label("H")
|
||||
.unit(" px")
|
||||
.min(0.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.is_integer(true)
|
||||
.disabled(self.infinite)
|
||||
.min_width(100)
|
||||
|
||||
@@ -63,7 +63,7 @@ impl PreferencesDialogMessageHandler {
|
||||
NumberInput::new(Some(preferences.imaginate_refresh_frequency))
|
||||
.unit(" seconds")
|
||||
.min(0.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.min_width(200)
|
||||
.on_update(|number_input: &NumberInput| PreferencesMessage::ImaginateRefreshFrequency { seconds: number_input.value.unwrap() }.into())
|
||||
.widget_holder(),
|
||||
|
||||
@@ -306,7 +306,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
|
||||
let insert_index = parent
|
||||
.children(self.metadata())
|
||||
.enumerate()
|
||||
.find_map(|(index, item)| self.selected_nodes.selected_layers(self.metadata()).any(|x| x == item).then_some(index as usize))
|
||||
.find_map(|(index, item)| self.selected_nodes.selected_layers(self.metadata()).any(|x| x == item).then_some(index))
|
||||
.unwrap_or(0);
|
||||
|
||||
// Store a history step before doing anything
|
||||
|
||||
@@ -321,7 +321,7 @@ impl<'a> ModifyInputsContext<'a> {
|
||||
pub fn insert_text(&mut self, text: String, font: Font, size: f64, layer: NodeId) {
|
||||
let text = resolve_document_node_type("Text").expect("Text node does not exist").to_document_node(
|
||||
[
|
||||
NodeInput::network(graph_craft::concrete!(graphene_std::wasm_application_io::WasmEditorApi), 0),
|
||||
NodeInput::scope("editor-api"),
|
||||
NodeInput::value(TaggedValue::String(text), false),
|
||||
NodeInput::value(TaggedValue::Font(font), false),
|
||||
NodeInput::value(TaggedValue::F64(size), false),
|
||||
|
||||
@@ -20,6 +20,7 @@ use graphene_core::text::Font;
|
||||
use graphene_core::transform::Footprint;
|
||||
use graphene_core::vector::VectorData;
|
||||
use graphene_core::*;
|
||||
use graphene_std::application_io::RenderConfig;
|
||||
use graphene_std::wasm_application_io::WasmEditorApi;
|
||||
#[cfg(feature = "gpu")]
|
||||
use {gpu_executor::*, graphene_core::application_io::SurfaceHandle, wgpu_executor::WgpuExecutor};
|
||||
@@ -320,23 +321,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
properties: node_properties::artboard_properties,
|
||||
..Default::default()
|
||||
},
|
||||
// TODO: Does this need an internal Cull node to be added to its implementation?
|
||||
DocumentNodeDefinition {
|
||||
name: "Input Frame",
|
||||
category: "Ignore",
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::ExtractImageFrame"),
|
||||
inputs: vec![DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
}],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "Image Frame",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
}],
|
||||
properties: node_properties::node_no_properties,
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
name: "Load Image",
|
||||
category: "Structural",
|
||||
@@ -345,7 +329,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Load Resource".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 0), NodeInput::network(concrete!(String), 1)],
|
||||
inputs: vec![NodeInput::scope("editor-api"), NodeInput::network(concrete!(String), 1)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::LoadResourceNode<_>")),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -373,7 +357,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
DocumentInputType {
|
||||
name: "api",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
default: NodeInput::scope("editor-api"),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "path",
|
||||
@@ -396,7 +380,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Create Canvas".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 0)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::CreateSurfaceNode")),
|
||||
skip_deduplication: true,
|
||||
..Default::default()
|
||||
@@ -415,11 +399,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
}],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "Canvas",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -440,7 +419,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
},
|
||||
DocumentNode {
|
||||
name: "Create Canvas".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 1)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::CreateSurfaceNode")),
|
||||
skip_deduplication: true,
|
||||
..Default::default()
|
||||
@@ -465,18 +444,11 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
default: NodeInput::value(TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
],
|
||||
inputs: vec![DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
default: NodeInput::value(TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
}],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "Canvas",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -491,7 +463,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Create Canvas".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 2)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::CreateSurfaceNode")),
|
||||
skip_deduplication: true,
|
||||
..Default::default()
|
||||
@@ -534,11 +506,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
false,
|
||||
),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
],
|
||||
properties: node_properties::rasterize_properties,
|
||||
outputs: vec![DocumentOutputType {
|
||||
@@ -547,136 +514,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
}],
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
// This essentially builds the concept of a closure where we store variables (`let` bindings) so they can be accessed within this scope.
|
||||
name: "Begin Scope",
|
||||
category: "Ignore",
|
||||
implementation: DocumentNodeImplementation::Network(NodeNetwork {
|
||||
exports: vec![NodeInput::node(NodeId(1), 0), NodeInput::node(NodeId(2), 0)],
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "SetNode".to_string(),
|
||||
manual_composition: Some(concrete!(WasmEditorApi)),
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::SomeNode")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "LetNode".to_string(),
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::memo::LetNode<_>")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "RefNode".to_string(),
|
||||
manual_composition: Some(concrete!(())),
|
||||
inputs: vec![NodeInput::lambda(NodeId(1), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::memo::RefNode<_, _>")),
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(id, node)| (NodeId(id as u64), node))
|
||||
.collect(),
|
||||
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
}],
|
||||
outputs: vec![
|
||||
DocumentOutputType {
|
||||
name: "Scope",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
},
|
||||
DocumentOutputType {
|
||||
name: "Binding",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
},
|
||||
],
|
||||
properties: |_document_node, _node_id, _context| node_properties::string_properties("Binds the input in a local scope as a variable"),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
name: "End Scope",
|
||||
category: "Ignore",
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::memo::EndLetNode<_, _>"),
|
||||
inputs: vec![
|
||||
DocumentInputType {
|
||||
name: "Scope",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::None, true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "Data",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
default: NodeInput::value(TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
},
|
||||
],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "Frame",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
}],
|
||||
properties: |_document_node, _node_id, _context| node_properties::string_properties("Consumes the scope opened by the Begin Scope node and evaluates the contained node network"),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
name: "Output",
|
||||
category: "Ignore",
|
||||
implementation: DocumentNodeImplementation::Network(NodeNetwork {
|
||||
exports: vec![NodeInput::node(NodeId(3), 0)],
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Create Canvas".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 1)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::CreateSurfaceNode")),
|
||||
skip_deduplication: true,
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "Cache".to_string(),
|
||||
manual_composition: Some(concrete!(())),
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "Conversion".to_string(),
|
||||
inputs: vec![NodeInput::network(graphene_core::Type::Fn(Box::new(concrete!(Footprint)), Box::new(generic!(T))), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<_, GraphicGroup>")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "RenderNode".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 1), NodeInput::node(NodeId(2), 0), NodeInput::node(NodeId(1), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::RenderNode<_, _>")),
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(id, node)| (NodeId(id as u64), node))
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
DocumentInputType {
|
||||
name: "Output",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
default: NodeInput::value(TaggedValue::GraphicGroup(GraphicGroup::default()), true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
],
|
||||
outputs: vec![],
|
||||
properties: node_properties::output_properties,
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
name: "Image Frame",
|
||||
category: "General",
|
||||
@@ -1150,7 +987,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Extract Executor".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 1)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<_, &WgpuExecutor>")),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1174,18 +1011,11 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::F64(0.), true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
],
|
||||
inputs: vec![DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::F64(0.), true),
|
||||
}],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "Uniform",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -1201,7 +1031,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Extract Executor".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 1)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<_, &WgpuExecutor>")),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1225,18 +1055,11 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::None, true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
],
|
||||
inputs: vec![DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::None, true),
|
||||
}],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "Storage",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -1252,7 +1075,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Extract Executor".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 2)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<_, &WgpuExecutor>")),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1282,11 +1105,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::None, true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -1309,7 +1127,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Extract Executor".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 1)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<_, &WgpuExecutor>")),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1344,11 +1162,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(gpu_executor::PipelineLayout<WgpuExecutor>), 0),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 1),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -1410,7 +1223,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Extract Executor".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 1)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<_, &WgpuExecutor>")),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1434,18 +1247,11 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::None, true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
],
|
||||
inputs: vec![DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::None, true),
|
||||
}],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "PipelineResult",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -1461,7 +1267,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Extract Executor".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 1)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<_, &WgpuExecutor>")),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1485,18 +1291,11 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::None, true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
],
|
||||
inputs: vec![DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::None, true),
|
||||
}],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "Buffer",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -1512,7 +1311,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Create Gpu Surface".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 0)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("gpu_executor::CreateGpuSurfaceNode")),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1530,11 +1329,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
}],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "GpuSurface",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -1550,7 +1344,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Extract Executor".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 2)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<_, &WgpuExecutor>")),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1582,11 +1376,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::None, true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "EditorApi",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "RenderedTexture",
|
||||
@@ -1603,7 +1392,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Extract Executor".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 1)],
|
||||
inputs: vec![NodeInput::scope("editor-api")],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<_, &WgpuExecutor>")),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -1627,18 +1416,11 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
],
|
||||
inputs: vec![DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
}],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "Texture",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
@@ -1657,11 +1439,6 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::value(TaggedValue::DocumentNode(DocumentNode::default()), true),
|
||||
},
|
||||
DocumentInputType {
|
||||
name: "In",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
},
|
||||
],
|
||||
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
|
||||
..Default::default()
|
||||
@@ -2414,7 +2191,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
category: "Vector",
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::text::TextGeneratorNode<_, _, _>"),
|
||||
inputs: vec![
|
||||
DocumentInputType::none(),
|
||||
DocumentInputType::new("Editor API", FrontendGraphDataType::General, NodeInput::scope("editor-api")),
|
||||
DocumentInputType::value("Text", TaggedValue::String("Lorem ipsum".to_string()), false),
|
||||
DocumentInputType::value(
|
||||
"Font",
|
||||
@@ -2424,7 +2201,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
||||
DocumentInputType::value("Size", TaggedValue::F64(24.), false),
|
||||
],
|
||||
outputs: vec![DocumentOutputType::new("Vector", FrontendGraphDataType::VectorData)],
|
||||
properties: node_properties::node_section_font,
|
||||
properties: node_properties::text_properties,
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
@@ -2895,7 +2672,7 @@ pub static IMAGINATE_NODE: Lazy<DocumentNodeDefinition> = Lazy::new(|| DocumentN
|
||||
name: "Imaginate".into(),
|
||||
inputs: vec![
|
||||
NodeInput::node(NodeId(0), 0),
|
||||
NodeInput::network(concrete!(WasmEditorApi), 1),
|
||||
NodeInput::scope("editor-api"),
|
||||
NodeInput::network(concrete!(ImaginateController), 2),
|
||||
NodeInput::network(concrete!(f64), 3),
|
||||
NodeInput::network(concrete!(Option<DVec2>), 4),
|
||||
@@ -2925,7 +2702,7 @@ pub static IMAGINATE_NODE: Lazy<DocumentNodeDefinition> = Lazy::new(|| DocumentN
|
||||
DocumentInputType {
|
||||
name: "Editor Api",
|
||||
data_type: FrontendGraphDataType::General,
|
||||
default: NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
default: NodeInput::scope("editor-api"),
|
||||
},
|
||||
DocumentInputType::value("Controller", TaggedValue::ImaginateController(Default::default()), false),
|
||||
DocumentInputType::value("Seed", TaggedValue::U64(0), false), // Remember to keep index used in `ImaginateRandom` updated with this entry's index
|
||||
@@ -2992,18 +2769,9 @@ impl DocumentNodeDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork {
|
||||
pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc<WasmEditorApi>) -> NodeNetwork {
|
||||
network.generate_node_paths(&[]);
|
||||
|
||||
let mut begin_scope = resolve_document_node_type("Begin Scope")
|
||||
.expect("Begin Scope node type not found")
|
||||
.to_document_node(vec![NodeInput::network(concrete!(WasmEditorApi), 0)], DocumentNodeMetadata::position((-12, -3)));
|
||||
if let DocumentNodeImplementation::Network(g) = &mut begin_scope.implementation {
|
||||
if let Some(node) = g.nodes.get_mut(&NodeId(0)) {
|
||||
node.world_state_hash = hash;
|
||||
}
|
||||
}
|
||||
|
||||
let inner_network = DocumentNode {
|
||||
name: "Scope".to_string(),
|
||||
implementation: DocumentNodeImplementation::Network(network),
|
||||
@@ -3014,13 +2782,13 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork
|
||||
|
||||
let render_node = graph_craft::document::DocumentNode {
|
||||
name: "Output".into(),
|
||||
inputs: vec![NodeInput::node(NodeId(1), 0), NodeInput::node(NodeId(0), 1)],
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(2), 0)],
|
||||
implementation: graph_craft::document::DocumentNodeImplementation::Network(NodeNetwork {
|
||||
exports: vec![NodeInput::node(NodeId(2), 0)],
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Create Canvas".to_string(),
|
||||
inputs: vec![NodeInput::network(concrete!(WasmEditorApi), 1)],
|
||||
inputs: vec![NodeInput::network(concrete!(&WasmEditorApi), 1)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::CreateSurfaceNode")),
|
||||
skip_deduplication: true,
|
||||
..Default::default()
|
||||
@@ -3032,10 +2800,11 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
|
||||
..Default::default()
|
||||
},
|
||||
// TODO: Add conversion step
|
||||
DocumentNode {
|
||||
name: "RenderNode".to_string(),
|
||||
manual_composition: Some(concrete!(RenderConfig)),
|
||||
inputs: vec![
|
||||
NodeInput::network(concrete!(WasmEditorApi), 1),
|
||||
NodeInput::network(graphene_core::Type::Fn(Box::new(concrete!(Footprint)), Box::new(generic!(T))), 0),
|
||||
NodeInput::node(NodeId(1), 0),
|
||||
],
|
||||
@@ -3055,17 +2824,20 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork
|
||||
|
||||
// wrap the inner network in a scope
|
||||
let nodes = vec![
|
||||
begin_scope,
|
||||
inner_network,
|
||||
render_node,
|
||||
resolve_document_node_type("End Scope")
|
||||
.expect("End Scope node type not found")
|
||||
.to_document_node(vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(2), 0)], DocumentNodeMetadata::position((2, -3))),
|
||||
DocumentNode {
|
||||
name: "Editor Api".into(),
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::ops::IdentityNode"),
|
||||
inputs: vec![NodeInput::value(TaggedValue::EditorApi(editor_api), false)],
|
||||
..Default::default()
|
||||
},
|
||||
];
|
||||
|
||||
NodeNetwork {
|
||||
exports: vec![NodeInput::node(NodeId(3), 0)],
|
||||
exports: vec![NodeInput::node(NodeId(1), 0)],
|
||||
nodes: nodes.into_iter().enumerate().map(|(id, node)| (NodeId(id as u64), node)).collect(),
|
||||
scope_injections: [("editor-api".to_string(), (NodeId(2), concrete!(&WasmEditorApi)))].into_iter().collect(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
@@ -3097,7 +2869,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork
|
||||
// let mut network = NodeNetwork { ..Default::default() };
|
||||
// network.push_node_to_document_network(text_generator.to_document_node(
|
||||
// [
|
||||
// NodeInput::network(concrete!(WasmEditorApi), 0),
|
||||
// NodeInput::scope("editor-api"),
|
||||
// NodeInput::value(TaggedValue::String(text), false),
|
||||
// NodeInput::value(TaggedValue::Font(font), false),
|
||||
// NodeInput::value(TaggedValue::F64(size), false),
|
||||
|
||||
@@ -295,8 +295,8 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
||||
NumberInput::new(Some(dvec2.x))
|
||||
.label(x)
|
||||
.unit(unit)
|
||||
.min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64)))
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.min(min.unwrap_or(-((1_u64 << f64::MANTISSA_DIGITS) as f64)))
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(input.value.unwrap(), dvec2.y)), node_id, index))
|
||||
.on_commit(commit_value)
|
||||
.widget_holder(),
|
||||
@@ -304,8 +304,8 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
||||
NumberInput::new(Some(dvec2.y))
|
||||
.label(y)
|
||||
.unit(unit)
|
||||
.min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64)))
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.min(min.unwrap_or(-((1_u64 << f64::MANTISSA_DIGITS) as f64)))
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(update_value(move |input: &NumberInput| TaggedValue::DVec2(DVec2::new(dvec2.x, input.value.unwrap())), node_id, index))
|
||||
.on_commit(commit_value)
|
||||
.widget_holder(),
|
||||
@@ -323,8 +323,8 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
||||
.int()
|
||||
.label(x)
|
||||
.unit(unit)
|
||||
.min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64)))
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.min(min.unwrap_or(-((1_u64 << f64::MANTISSA_DIGITS) as f64)))
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(update_value(update_x, node_id, index))
|
||||
.on_commit(commit_value)
|
||||
.widget_holder(),
|
||||
@@ -333,8 +333,8 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
||||
.int()
|
||||
.label(y)
|
||||
.unit(unit)
|
||||
.min(min.unwrap_or(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64)))
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.min(min.unwrap_or(-((1_u64 << f64::MANTISSA_DIGITS) as f64)))
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(update_value(update_y, node_id, index))
|
||||
.on_commit(commit_value)
|
||||
.widget_holder(),
|
||||
@@ -353,7 +353,7 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
||||
.label(x)
|
||||
.unit(unit)
|
||||
.min(min.unwrap_or(0.))
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(update_value(update_x, node_id, index))
|
||||
.on_commit(commit_value)
|
||||
.widget_holder(),
|
||||
@@ -363,7 +363,7 @@ fn vec2_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, name
|
||||
.label(y)
|
||||
.unit(unit)
|
||||
.min(min.unwrap_or(0.))
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(update_value(update_y, node_id, index))
|
||||
.on_commit(commit_value)
|
||||
.widget_holder(),
|
||||
@@ -1769,7 +1769,7 @@ pub fn rasterize_properties(document_node: &DocumentNode, node_id: NodeId, _cont
|
||||
footprint_widget(document_node, node_id, 1)
|
||||
}
|
||||
|
||||
pub fn node_section_font(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
pub fn text_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let text = text_area_widget(document_node, node_id, 1, "Text", true);
|
||||
let (font, style) = font_inputs(document_node, node_id, 2, "Font", true);
|
||||
let size = number_widget(document_node, node_id, 3, "Size", NumberInput::default().unit(" px").min(1.), true);
|
||||
|
||||
@@ -177,13 +177,13 @@ impl DocumentMetadata {
|
||||
|
||||
// Should refer to output node
|
||||
|
||||
let mut awaiting_horizontal_flow = vec![(NodeId(std::u64::MAX), LayerNodeIdentifier::ROOT_PARENT)];
|
||||
let mut awaiting_horizontal_flow = vec![(NodeId(u64::MAX), LayerNodeIdentifier::ROOT_PARENT)];
|
||||
let mut awaiting_primary_flow = vec![];
|
||||
|
||||
while let Some((horizontal_root_node_id, mut parent_layer_node)) = awaiting_horizontal_flow.pop() {
|
||||
let horizontal_flow_iter = graph.upstream_flow_back_from_nodes(vec![horizontal_root_node_id], FlowType::HorizontalFlow);
|
||||
// Skip the horizontal_root_node_id node
|
||||
for (current_node, current_node_id) in horizontal_flow_iter.skip(if horizontal_root_node_id == NodeId(std::u64::MAX) { 0 } else { 1 }) {
|
||||
for (current_node, current_node_id) in horizontal_flow_iter.skip(if horizontal_root_node_id == NodeId(u64::MAX) { 0 } else { 1 }) {
|
||||
if !current_node.visible {
|
||||
self.hidden.insert(current_node_id);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
||||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
||||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(1.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
||||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| LineToolMessage::UpdateOptions(LineOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
||||
@@ -98,8 +98,8 @@ impl LayoutHolder for PathTool {
|
||||
.label("X")
|
||||
.min_width(120)
|
||||
.disabled(x.is_none())
|
||||
.min(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64))
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.min(-((1_u64 << f64::MANTISSA_DIGITS) as f64))
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(move |number_input: &NumberInput| {
|
||||
if let Some(new_x) = number_input.value.or(x) {
|
||||
PathToolMessage::SelectedPointXChanged { new_x }.into()
|
||||
@@ -114,8 +114,8 @@ impl LayoutHolder for PathTool {
|
||||
.label("Y")
|
||||
.min_width(120)
|
||||
.disabled(y.is_none())
|
||||
.min(-((1_u64 << std::f64::MANTISSA_DIGITS) as f64))
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.min(-((1_u64 << f64::MANTISSA_DIGITS) as f64))
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(move |number_input: &NumberInput| {
|
||||
if let Some(new_y) = number_input.value.or(y) {
|
||||
PathToolMessage::SelectedPointYChanged { new_y }.into()
|
||||
|
||||
@@ -96,7 +96,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
||||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
||||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| PolygonToolMessage::UpdateOptions(PolygonOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
||||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| RectangleToolMessage::UpdateOptions(RectangleOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder {
|
||||
.unit(" px")
|
||||
.label("Weight")
|
||||
.min(0.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| SplineToolMessage::UpdateOptions(SplineOptionsUpdate::LineWeight(number_input.value.unwrap())).into())
|
||||
.widget_holder()
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ fn create_text_widgets(tool: &TextTool) -> Vec<WidgetHolder> {
|
||||
.label("Size")
|
||||
.int()
|
||||
.min(1.)
|
||||
.max((1_u64 << std::f64::MANTISSA_DIGITS) as f64)
|
||||
.max((1_u64 << f64::MANTISSA_DIGITS) as f64)
|
||||
.on_update(|number_input: &NumberInput| TextToolMessage::UpdateOptions(TextOptionsUpdate::FontSize(number_input.value.unwrap() as u32)).into())
|
||||
.widget_holder();
|
||||
vec![
|
||||
|
||||
@@ -39,14 +39,11 @@ pub struct NodeRuntime {
|
||||
executor: DynamicExecutor,
|
||||
receiver: Receiver<NodeRuntimeMessage>,
|
||||
sender: InternalNodeGraphUpdateSender,
|
||||
|
||||
/// Font data (for rendering text) made available to the graph through the [`WasmEditorApi`].
|
||||
font_cache: FontCache,
|
||||
/// Imaginate preferences made available to the graph through the [`WasmEditorApi`].
|
||||
imaginate_preferences: ImaginatePreferences,
|
||||
recompile_graph: bool,
|
||||
|
||||
editor_api: Arc<WasmEditorApi>,
|
||||
|
||||
/// Gives access to APIs like a rendering surface (native window handle or HTML5 canvas) and WGPU (which becomes WebGPU on web).
|
||||
wasm_application_io: Option<WasmApplicationIo>,
|
||||
graph_hash: Option<u64>,
|
||||
node_graph_errors: GraphErrors,
|
||||
resolved_types: ResolvedDocumentNodeTypes,
|
||||
@@ -89,7 +86,7 @@ pub struct ExecutionRequest {
|
||||
pub struct ExecutionResponse {
|
||||
execution_id: u64,
|
||||
result: Result<TaggedValue, String>,
|
||||
responses: VecDeque<Message>,
|
||||
responses: VecDeque<FrontendMessage>,
|
||||
new_click_targets: HashMap<LayerNodeIdentifier, Vec<ClickTarget>>,
|
||||
new_vector_modify: HashMap<NodeId, VectorData>,
|
||||
new_upstream_transforms: HashMap<NodeId, (Footprint, DAffine2)>,
|
||||
@@ -103,6 +100,7 @@ pub enum NodeGraphUpdate {
|
||||
NodeGraphUpdateMessage(NodeGraphUpdateMessage),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct InternalNodeGraphUpdateSender(Sender<NodeGraphUpdate>);
|
||||
|
||||
impl InternalNodeGraphUpdateSender {
|
||||
@@ -126,12 +124,19 @@ impl NodeRuntime {
|
||||
Self {
|
||||
executor: DynamicExecutor::default(),
|
||||
receiver,
|
||||
sender: InternalNodeGraphUpdateSender(sender),
|
||||
sender: InternalNodeGraphUpdateSender(sender.clone()),
|
||||
imaginate_preferences: ImaginatePreferences::default(),
|
||||
recompile_graph: true,
|
||||
|
||||
font_cache: FontCache::default(),
|
||||
imaginate_preferences: Default::default(),
|
||||
editor_api: WasmEditorApi {
|
||||
font_cache: FontCache::default(),
|
||||
imaginate_preferences: Box::new(ImaginatePreferences::default()),
|
||||
node_graph_message_sender: Box::new(InternalNodeGraphUpdateSender(sender)),
|
||||
|
||||
application_io: None,
|
||||
}
|
||||
.into(),
|
||||
|
||||
wasm_application_io: None,
|
||||
graph_hash: None,
|
||||
node_graph_errors: Vec::new(),
|
||||
resolved_types: ResolvedDocumentNodeTypes::default(),
|
||||
@@ -153,8 +158,26 @@ impl NodeRuntime {
|
||||
requests.reverse();
|
||||
for request in requests {
|
||||
match request {
|
||||
NodeRuntimeMessage::FontCacheUpdate(font_cache) => self.font_cache = font_cache,
|
||||
NodeRuntimeMessage::ImaginatePreferencesUpdate(preferences) => self.imaginate_preferences = preferences,
|
||||
NodeRuntimeMessage::FontCacheUpdate(font_cache) => {
|
||||
self.editor_api = WasmEditorApi {
|
||||
font_cache,
|
||||
application_io: self.editor_api.application_io.clone(),
|
||||
node_graph_message_sender: Box::new(self.sender.clone()),
|
||||
imaginate_preferences: Box::new(self.imaginate_preferences.clone()),
|
||||
}
|
||||
.into();
|
||||
self.recompile_graph = true;
|
||||
}
|
||||
NodeRuntimeMessage::ImaginatePreferencesUpdate(preferences) => {
|
||||
self.editor_api = WasmEditorApi {
|
||||
font_cache: self.editor_api.font_cache.clone(),
|
||||
application_io: self.editor_api.application_io.clone(),
|
||||
node_graph_message_sender: Box::new(self.sender.clone()),
|
||||
imaginate_preferences: Box::new(preferences),
|
||||
}
|
||||
.into();
|
||||
self.recompile_graph = true;
|
||||
}
|
||||
NodeRuntimeMessage::ExecutionRequest(ExecutionRequest {
|
||||
execution_id, graph, render_config, ..
|
||||
}) => {
|
||||
@@ -182,23 +205,21 @@ impl NodeRuntime {
|
||||
}
|
||||
|
||||
async fn execute_network(&mut self, graph: NodeNetwork, render_config: RenderConfig) -> Result<TaggedValue, String> {
|
||||
if self.wasm_application_io.is_none() {
|
||||
self.wasm_application_io = Some(WasmApplicationIo::new().await);
|
||||
if self.editor_api.application_io.is_none() {
|
||||
self.editor_api = WasmEditorApi {
|
||||
application_io: Some(WasmApplicationIo::new().await.into()),
|
||||
font_cache: self.editor_api.font_cache.clone(),
|
||||
node_graph_message_sender: Box::new(self.sender.clone()),
|
||||
imaginate_preferences: Box::new(ImaginatePreferences::default()),
|
||||
}
|
||||
.into();
|
||||
}
|
||||
|
||||
let editor_api = WasmEditorApi {
|
||||
font_cache: &self.font_cache,
|
||||
imaginate_preferences: &self.imaginate_preferences,
|
||||
application_io: self.wasm_application_io.as_ref().unwrap(),
|
||||
node_graph_message_sender: &self.sender,
|
||||
render_config,
|
||||
image_frame: None,
|
||||
};
|
||||
|
||||
let editor_api = &self.editor_api;
|
||||
// Required to ensure that the appropriate proto nodes are reinserted when the Editor API changes.
|
||||
let mut graph_input_hash = DefaultHasher::new();
|
||||
editor_api.font_cache.hash(&mut graph_input_hash);
|
||||
let font_hash_code = graph_input_hash.finish();
|
||||
let _font_hash_code = graph_input_hash.finish();
|
||||
graph.hash(&mut graph_input_hash);
|
||||
let hash_code = graph_input_hash.finish();
|
||||
|
||||
@@ -206,8 +227,8 @@ impl NodeRuntime {
|
||||
self.graph_hash = None;
|
||||
}
|
||||
|
||||
if self.graph_hash.is_none() {
|
||||
let scoped_network = wrap_network_in_scope(graph, font_hash_code);
|
||||
if self.graph_hash.is_none() || self.recompile_graph {
|
||||
let scoped_network = wrap_network_in_scope(graph, self.editor_api.clone());
|
||||
|
||||
self.monitor_nodes = scoped_network
|
||||
.recursive_nodes()
|
||||
@@ -235,7 +256,7 @@ impl NodeRuntime {
|
||||
use graph_craft::graphene_compiler::Executor;
|
||||
|
||||
let result = match self.executor.input_type() {
|
||||
Some(t) if t == concrete!(WasmEditorApi) => (&self.executor).execute(editor_api).await.map_err(|e| e.to_string()),
|
||||
Some(t) if t == concrete!(RenderConfig) => (&self.executor).execute(render_config).await.map_err(|e| e.to_string()),
|
||||
Some(t) if t == concrete!(()) => (&self.executor).execute(()).await.map_err(|e| e.to_string()),
|
||||
Some(t) => Err(format!("Invalid input type {t:?}")),
|
||||
_ => Err(format!("No input type:\n{:?}", self.node_graph_errors)),
|
||||
@@ -259,7 +280,7 @@ impl NodeRuntime {
|
||||
}
|
||||
|
||||
/// Updates state data
|
||||
pub fn process_monitor_nodes(&mut self, responses: &mut VecDeque<Message>) {
|
||||
pub fn process_monitor_nodes(&mut self, responses: &mut VecDeque<FrontendMessage>) {
|
||||
// TODO: Consider optimizing this since it's currently O(m*n^2), with a sort it could be made O(m * n*log(n))
|
||||
self.thumbnail_renders.retain(|id, _| self.monitor_nodes.iter().any(|monitor_node_path| monitor_node_path.contains(id)));
|
||||
|
||||
@@ -325,7 +346,7 @@ impl NodeRuntime {
|
||||
let old_thumbnail_svg = self.thumbnail_renders.entry(parent_network_node_id).or_default();
|
||||
|
||||
if old_thumbnail_svg != &new_thumbnail_svg {
|
||||
responses.add(FrontendMessage::UpdateNodeThumbnail {
|
||||
responses.push_back(FrontendMessage::UpdateNodeThumbnail {
|
||||
id: parent_network_node_id,
|
||||
value: new_thumbnail_svg.to_svg_string(),
|
||||
});
|
||||
@@ -576,7 +597,7 @@ impl NodeGraphExecutor {
|
||||
transform,
|
||||
} = execution_response;
|
||||
|
||||
responses.extend(existing_responses);
|
||||
responses.extend(existing_responses.into_iter().map(Into::into));
|
||||
responses.add(NodeGraphMessage::UpdateTypes { resolved_types, node_graph_errors });
|
||||
responses.add(NodeGraphMessage::SendGraph);
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
|
||||
Reference in New Issue
Block a user