Store Input for Monitor Nodes (#1454)
* Add input storage to monitor_node * Return input via serialize function
This commit is contained in:
parent
58660f5548
commit
81519601ae
|
|
@ -125,6 +125,17 @@ impl Default for DocumentNodeBlueprint {
|
||||||
// TODO: make document nodes not require a `'static` lifetime to avoid having to split the construction into const and non-const parts.
|
// TODO: make document nodes not require a `'static` lifetime to avoid having to split the construction into const and non-const parts.
|
||||||
static DOCUMENT_NODE_TYPES: once_cell::sync::Lazy<Vec<DocumentNodeBlueprint>> = once_cell::sync::Lazy::new(static_nodes);
|
static DOCUMENT_NODE_TYPES: once_cell::sync::Lazy<Vec<DocumentNodeBlueprint>> = once_cell::sync::Lazy::new(static_nodes);
|
||||||
|
|
||||||
|
fn monitor_node() -> DocumentNode {
|
||||||
|
DocumentNode {
|
||||||
|
name: "Monitor".to_string(),
|
||||||
|
inputs: Vec::new(),
|
||||||
|
implementation: DocumentNodeImplementation::proto("graphene_core::memo::MonitorNode<_, _, _>"),
|
||||||
|
manual_composition: Some(concrete!(Footprint)),
|
||||||
|
skip_deduplication: true,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Dynamic node library
|
// TODO: Dynamic node library
|
||||||
/// Defines the "signature" or "header file"-like metadata for the document nodes, but not the implementation (which is defined in the node registry).
|
/// Defines the "signature" or "header file"-like metadata for the document nodes, but not the implementation (which is defined in the node registry).
|
||||||
/// The document node is the instance while these are the "class" (or "blueprint").
|
/// The document node is the instance while these are the "class" (or "blueprint").
|
||||||
|
|
@ -203,11 +214,8 @@ fn static_nodes() -> Vec<DocumentNodeBlueprint> {
|
||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
name: "Monitor".to_string(),
|
|
||||||
inputs: vec![NodeInput::node(0, 0)],
|
inputs: vec![NodeInput::node(0, 0)],
|
||||||
implementation: DocumentNodeImplementation::proto("graphene_core::memo::MonitorNode<_>"),
|
..monitor_node()
|
||||||
skip_deduplication: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
@ -2122,11 +2130,8 @@ fn static_nodes() -> Vec<DocumentNodeBlueprint> {
|
||||||
outputs: vec![NodeOutput::new(1, 0)],
|
outputs: vec![NodeOutput::new(1, 0)],
|
||||||
nodes: [
|
nodes: [
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
name: "Monitor".to_string(),
|
|
||||||
inputs: vec![NodeInput::Network(concrete!(VectorData))],
|
inputs: vec![NodeInput::Network(concrete!(VectorData))],
|
||||||
implementation: DocumentNodeImplementation::proto("graphene_core::memo::MonitorNode<_>"),
|
..monitor_node()
|
||||||
skip_deduplication: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
name: "Transform".to_string(),
|
name: "Transform".to_string(),
|
||||||
|
|
@ -2329,11 +2334,8 @@ pub static IMAGINATE_NODE: Lazy<DocumentNodeBlueprint> = Lazy::new(|| DocumentNo
|
||||||
(
|
(
|
||||||
0,
|
0,
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
name: "Frame Monitor".into(),
|
|
||||||
inputs: vec![NodeInput::Network(concrete!(ImageFrame<Color>))],
|
inputs: vec![NodeInput::Network(concrete!(ImageFrame<Color>))],
|
||||||
implementation: DocumentNodeImplementation::proto("graphene_core::memo::MonitorNode<_>"),
|
..monitor_node()
|
||||||
skip_deduplication: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,7 @@ impl NodeRuntime {
|
||||||
|
|
||||||
let monitor_nodes = scoped_network
|
let monitor_nodes = scoped_network
|
||||||
.recursive_nodes()
|
.recursive_nodes()
|
||||||
.filter(|(_, node)| node.implementation == DocumentNodeImplementation::proto("graphene_core::memo::MonitorNode<_>"))
|
.filter(|(_, node)| node.implementation == DocumentNodeImplementation::proto("graphene_core::memo::MonitorNode<_, _, _>"))
|
||||||
.map(|(_, node)| node.path.clone().unwrap_or_default())
|
.map(|(_, node)| node.path.clone().unwrap_or_default())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
@ -259,10 +259,12 @@ impl NodeRuntime {
|
||||||
warn!("Failed to introspect monitor node for thumbnail");
|
warn!("Failed to introspect monitor node for thumbnail");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let Some(graphic_element_data) = value.downcast_ref::<graphene_core::GraphicElementData>() else {
|
|
||||||
|
let Some(io_data) = value.downcast_ref::<graphene_core::memo::IORecord<Footprint, graphene_core::GraphicElementData>>() else {
|
||||||
warn!("Failed to downcast thumbnail to graphic element data");
|
warn!("Failed to downcast thumbnail to graphic element data");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
let graphic_element_data = &io_data.output;
|
||||||
use graphene_core::renderer::*;
|
use graphene_core::renderer::*;
|
||||||
let bounds = graphic_element_data.bounding_box(DAffine2::IDENTITY);
|
let bounds = graphic_element_data.bounding_box(DAffine2::IDENTITY);
|
||||||
let render_params = RenderParams::new(ViewMode::Normal, ImageRenderMode::BlobUrl, bounds, true);
|
let render_params = RenderParams::new(ViewMode::Normal, ImageRenderMode::BlobUrl, bounds, true);
|
||||||
|
|
|
||||||
|
|
@ -45,32 +45,48 @@ impl<T, CachedNode> MemoNode<T, CachedNode> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct IORecord<I, O> {
|
||||||
|
pub input: I,
|
||||||
|
pub output: O,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
/// Caches the output of the last graph evaluation for introspection
|
/// Caches the output of the last graph evaluation for introspection
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct MonitorNode<T> {
|
pub struct MonitorNode<I, T, N> {
|
||||||
output: Cell<Option<Arc<T>>>,
|
io: Cell<Option<Arc<IORecord<I, T>>>>,
|
||||||
|
node: N,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<'i, T: 'static + Clone> Node<'i, T> for MonitorNode<T> {
|
impl<'i, 'a: 'i, T, I, N> Node<'i, I> for MonitorNode<I, T, N>
|
||||||
type Output = T;
|
where
|
||||||
fn eval(&'i self, input: T) -> Self::Output {
|
I: Clone + 'static,
|
||||||
self.output.set(Some(Arc::new(input.clone())));
|
<N as Node<'i, I>>::Output: Future<Output = T>,
|
||||||
input
|
T: Clone + 'static,
|
||||||
|
N: Node<'i, I>,
|
||||||
|
{
|
||||||
|
type Output = Pin<Box<dyn Future<Output = T> + 'i>>;
|
||||||
|
fn eval(&'i self, input: I) -> Self::Output {
|
||||||
|
Box::pin(async move {
|
||||||
|
let output = self.node.eval(input.clone()).await;
|
||||||
|
self.io.set(Some(Arc::new(IORecord { input, output: output.clone() })));
|
||||||
|
output
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize(&self) -> Option<Arc<dyn core::any::Any>> {
|
fn serialize(&self) -> Option<Arc<dyn core::any::Any>> {
|
||||||
let out = self.output.take();
|
let io = self.io.take();
|
||||||
self.output.set(out.clone());
|
self.io.set(io.clone());
|
||||||
(out).as_ref().map(|output| output.clone() as Arc<dyn core::any::Any>)
|
(io).as_ref().map(|output| output.clone() as Arc<dyn core::any::Any>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<T> MonitorNode<T> {
|
impl<I, T, N> MonitorNode<I, T, N> {
|
||||||
pub const fn new() -> MonitorNode<T> {
|
pub const fn new(node: N) -> MonitorNode<I, T, N> {
|
||||||
MonitorNode { output: Cell::new(None) }
|
MonitorNode { io: Cell::new(None), node }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ pub mod node_registry;
|
||||||
mod tests {
|
mod tests {
|
||||||
use graph_craft::document::value::TaggedValue;
|
use graph_craft::document::value::TaggedValue;
|
||||||
use graphene_core::*;
|
use graphene_core::*;
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
use futures::executor::block_on;
|
use futures::executor::block_on;
|
||||||
|
|
||||||
|
|
@ -95,7 +94,7 @@ mod tests {
|
||||||
0,
|
0,
|
||||||
DocumentNode {
|
DocumentNode {
|
||||||
name: "id".into(),
|
name: "id".into(),
|
||||||
inputs: vec![NodeInput::ShortCircut(concrete!(u32))],
|
inputs: vec![NodeInput::Network(concrete!(u32))],
|
||||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")),
|
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -327,9 +327,9 @@ fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstruct
|
||||||
),
|
),
|
||||||
)],
|
)],
|
||||||
register_node!(graphene_std::raster::EmptyImageNode<_, _>, input: DAffine2, params: [Color]),
|
register_node!(graphene_std::raster::EmptyImageNode<_, _>, input: DAffine2, params: [Color]),
|
||||||
register_node!(graphene_core::memo::MonitorNode<_>, input: ImageFrame<Color>, params: []),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Footprint, output: ImageFrame<Color>, fn_params: [Footprint => ImageFrame<Color>]),
|
||||||
register_node!(graphene_core::memo::MonitorNode<_>, input: VectorData, params: []),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Footprint, output: VectorData, fn_params: [Footprint => VectorData]),
|
||||||
register_node!(graphene_core::memo::MonitorNode<_>, input: graphene_core::GraphicElementData, params: []),
|
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Footprint, output: graphene_core::GraphicElementData, fn_params: [Footprint => graphene_core::GraphicElementData]),
|
||||||
async_node!(graphene_std::wasm_application_io::LoadResourceNode<_>, input: WasmEditorApi, output: Arc<[u8]>, params: [String]),
|
async_node!(graphene_std::wasm_application_io::LoadResourceNode<_>, input: WasmEditorApi, output: Arc<[u8]>, params: [String]),
|
||||||
register_node!(graphene_std::wasm_application_io::DecodeImageNode, input: Arc<[u8]>, params: []),
|
register_node!(graphene_std::wasm_application_io::DecodeImageNode, input: Arc<[u8]>, params: []),
|
||||||
async_node!(graphene_std::wasm_application_io::CreateSurfaceNode, input: WasmEditorApi, output: Arc<SurfaceHandle<<graphene_std::wasm_application_io::WasmApplicationIo as graphene_core::application_io::ApplicationIo>::Surface>>, params: []),
|
async_node!(graphene_std::wasm_application_io::CreateSurfaceNode, input: WasmEditorApi, output: Arc<SurfaceHandle<<graphene_std::wasm_application_io::WasmApplicationIo as graphene_core::application_io::ApplicationIo>::Surface>>, params: []),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue