mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 23:08:05 +08:00
merge onto master
This commit is contained in:
@@ -234,6 +234,7 @@ impl CloneVarArgs for Arc<OwnedContextImpl> {
|
||||
}
|
||||
}
|
||||
|
||||
// Lifetime isnt necessary?
|
||||
pub type Context<'a> = Option<Arc<OwnedContextImpl>>;
|
||||
type DynRef<'a> = &'a (dyn Any + Send + Sync);
|
||||
type DynBox = Box<dyn Any + Send + Sync>;
|
||||
|
||||
@@ -37,6 +37,7 @@ pub use context::*;
|
||||
pub use ctor;
|
||||
pub use dyn_any::{StaticTypeSized, WasmNotSend, WasmNotSync};
|
||||
pub use graphic_element::{Artboard, ArtboardGroupTable, GraphicElement, GraphicGroupTable};
|
||||
pub use memo::IntrospectMode;
|
||||
pub use memo::MemoHash;
|
||||
pub use num_traits;
|
||||
pub use raster::Color;
|
||||
@@ -58,11 +59,18 @@ pub trait Node<'i, Input> {
|
||||
fn node_name(&self) -> &'static str {
|
||||
std::any::type_name::<Self>()
|
||||
}
|
||||
/// Serialize the node which is used for the `introspect` function which can retrieve values from monitor nodes.
|
||||
fn serialize(&self) -> Option<std::sync::Arc<dyn std::any::Any + Send + Sync>> {
|
||||
log::warn!("Node::serialize not implemented for {}", std::any::type_name::<Self>());
|
||||
|
||||
/// Get the call argument or output data for the monitor node on the next evaluation after set_introspect_input
|
||||
/// Also returns a boolean of whether the node was evaluated
|
||||
fn introspect(&self, _introspect_mode: IntrospectMode) -> Option<Box<dyn std::any::Any + Send + Sync>> {
|
||||
log::warn!("Node::introspect not implemented for {}", std::any::type_name::<Self>());
|
||||
None
|
||||
}
|
||||
|
||||
// The introspect mode is set before the graph evaluation, and tells the monitor node what data to store
|
||||
fn set_introspect(&self, _introspect_mode: IntrospectMode) {
|
||||
log::warn!("Node::set_introspect not implemented for {}", std::any::type_name::<Self>());
|
||||
}
|
||||
}
|
||||
|
||||
mod types;
|
||||
|
||||
@@ -107,47 +107,73 @@ pub mod impure_memo {
|
||||
pub const IDENTIFIER: crate::ProtoNodeIdentifier = crate::ProtoNodeIdentifier::new("graphene_core::memo::ImpureMemoNode");
|
||||
}
|
||||
|
||||
/// Stores both what a node was called with and what it returned.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IORecord<I, O> {
|
||||
pub input: I,
|
||||
pub output: O,
|
||||
#[derive(Copy, Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub enum IntrospectMode {
|
||||
Input,
|
||||
Data,
|
||||
}
|
||||
|
||||
/// Caches the output of the last graph evaluation for introspection
|
||||
#[derive(Default)]
|
||||
pub struct MonitorNode<I, T, N> {
|
||||
pub struct MonitorNode<I, O, N> {
|
||||
#[allow(clippy::type_complexity)]
|
||||
io: Arc<Mutex<Option<Arc<IORecord<I, T>>>>>,
|
||||
input: Arc<Mutex<Option<Box<I>>>>,
|
||||
output: Arc<Mutex<Option<Box<O>>>>,
|
||||
// Gets set to true by the editor when before evaluating the network, then reset when the monitor node is evaluated
|
||||
introspect_input: Arc<Mutex<bool>>,
|
||||
introspect_output: Arc<Mutex<bool>>,
|
||||
node: N,
|
||||
}
|
||||
|
||||
impl<'i, T, I, N> Node<'i, I> for MonitorNode<I, T, N>
|
||||
impl<'i, I, O, N> Node<'i, I> for MonitorNode<I, O, N>
|
||||
where
|
||||
I: Clone + 'static + Send + Sync,
|
||||
T: Clone + 'static + Send + Sync,
|
||||
for<'a> N: Node<'a, I, Output: Future<Output = T> + WasmNotSend> + 'i,
|
||||
O: Clone + 'static + Send + Sync,
|
||||
for<'a> N: Node<'a, I, Output: Future<Output = O> + WasmNotSend> + Send + Sync + 'i,
|
||||
{
|
||||
type Output = DynFuture<'i, T>;
|
||||
type Output = DynFuture<'i, O>;
|
||||
fn eval(&'i self, input: I) -> Self::Output {
|
||||
let io = self.io.clone();
|
||||
let output_fut = self.node.eval(input.clone());
|
||||
Box::pin(async move {
|
||||
let output = output_fut.await;
|
||||
*io.lock().unwrap() = Some(Arc::new(IORecord { input, output: output.clone() }));
|
||||
let output = self.node.eval(input.clone()).await;
|
||||
let mut introspect_input = self.introspect_input.lock().unwrap();
|
||||
if *introspect_input {
|
||||
*self.input.lock().unwrap() = Some(Box::new(input));
|
||||
*introspect_input = false;
|
||||
}
|
||||
let mut introspect_output = self.introspect_output.lock().unwrap();
|
||||
if *introspect_output {
|
||||
*self.output.lock().unwrap() = Some(Box::new(output.clone()));
|
||||
*introspect_output = false;
|
||||
}
|
||||
output
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize(&self) -> Option<Arc<dyn std::any::Any + Send + Sync>> {
|
||||
let io = self.io.lock().unwrap();
|
||||
(io).as_ref().map(|output| output.clone() as Arc<dyn std::any::Any + Send + Sync>)
|
||||
// After introspecting, the input/output get set to None because the Arc is moved to the editor where it can be directly accessed.
|
||||
fn introspect(&self, introspect_mode: IntrospectMode) -> Option<Box<dyn std::any::Any + Send + Sync>> {
|
||||
match introspect_mode {
|
||||
IntrospectMode::Input => self.input.lock().unwrap().take().map(|input| input as Box<dyn std::any::Any + Send + Sync>),
|
||||
IntrospectMode::Data => self.output.lock().unwrap().take().map(|output| output as Box<dyn std::any::Any + Send + Sync>),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_introspect(&self, introspect_mode: IntrospectMode) {
|
||||
match introspect_mode {
|
||||
IntrospectMode::Input => *self.introspect_input.lock().unwrap() = true,
|
||||
IntrospectMode::Data => *self.introspect_output.lock().unwrap() = true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T, N> MonitorNode<I, T, N> {
|
||||
pub fn new(node: N) -> MonitorNode<I, T, N> {
|
||||
MonitorNode { io: Arc::new(Mutex::new(None)), node }
|
||||
impl<I, O, N> MonitorNode<I, O, N> {
|
||||
pub fn new(node: N) -> MonitorNode<I, O, N> {
|
||||
MonitorNode {
|
||||
input: Arc::new(Mutex::new(None)),
|
||||
output: Arc::new(Mutex::new(None)),
|
||||
introspect_input: Arc::new(Mutex::new(false)),
|
||||
introspect_output: Arc::new(Mutex::new(false)),
|
||||
node,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,6 @@ where
|
||||
fn reset(&self) {
|
||||
self.0.reset();
|
||||
}
|
||||
|
||||
fn serialize(&self) -> Option<std::sync::Arc<dyn std::any::Any + Send + Sync>> {
|
||||
self.0.serialize()
|
||||
}
|
||||
}
|
||||
impl<'i, N: for<'a> Node<'a, I>, I: 'i> TypeNode<N, I, <N as Node<'i, I>>::Output> {
|
||||
pub fn new(node: N) -> Self {
|
||||
|
||||
@@ -132,6 +132,7 @@ pub type TypeErasedPinned<'n> = Pin<Box<TypeErasedNode<'n>>>;
|
||||
pub type SharedNodeContainer = std::sync::Arc<NodeContainer>;
|
||||
|
||||
pub type NodeConstructor = fn(Vec<SharedNodeContainer>) -> DynFuture<'static, TypeErasedBox<'static>>;
|
||||
pub type MonitorConstructor = fn(SharedNodeContainer) -> TypeErasedBox<'static>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct NodeContainer {
|
||||
@@ -208,11 +209,10 @@ where
|
||||
#[inline]
|
||||
fn eval(&'input self, input: I) -> Self::Output {
|
||||
{
|
||||
let node_name = self.node.node_name();
|
||||
let input = Box::new(input);
|
||||
let future = self.node.eval(input);
|
||||
Box::pin(async move {
|
||||
let out = dyn_any::downcast(future.await).unwrap_or_else(|e| panic!("DowncastBothNode Input {e} in: \n{node_name}"));
|
||||
let out = dyn_any::downcast(future.await).unwrap_or_else(|e| panic!("DowncastBothNode Input {e} in: \n{:?}", self.node.node_name()));
|
||||
*out
|
||||
})
|
||||
}
|
||||
@@ -220,11 +220,8 @@ where
|
||||
fn reset(&self) {
|
||||
self.node.reset();
|
||||
}
|
||||
|
||||
fn serialize(&self) -> Option<std::sync::Arc<dyn std::any::Any + Send + Sync>> {
|
||||
self.node.serialize()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, O> DowncastBothNode<I, O> {
|
||||
pub const fn new(node: SharedNodeContainer) -> Self {
|
||||
Self {
|
||||
@@ -234,6 +231,11 @@ impl<I, O> DowncastBothNode<I, O> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn downcast_node<I: StaticType, O: StaticType>(n: SharedNodeContainer) -> DowncastBothNode<I, O> {
|
||||
DowncastBothNode::new(n)
|
||||
}
|
||||
|
||||
pub struct FutureWrapperNode<Node> {
|
||||
node: Node,
|
||||
}
|
||||
@@ -252,11 +254,6 @@ where
|
||||
fn reset(&self) {
|
||||
self.node.reset();
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn serialize(&self) -> Option<std::sync::Arc<dyn std::any::Any + Send + Sync>> {
|
||||
self.node.serialize()
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> FutureWrapperNode<N> {
|
||||
@@ -294,10 +291,6 @@ where
|
||||
fn reset(&self) {
|
||||
self.node.reset();
|
||||
}
|
||||
|
||||
fn serialize(&self) -> Option<std::sync::Arc<dyn std::any::Any + Send + Sync>> {
|
||||
self.node.serialize()
|
||||
}
|
||||
}
|
||||
impl<'input, I, O, N> DynAnyNode<I, O, N>
|
||||
where
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::Node;
|
||||
use crate::registry::Node;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// This is how we can generically define composition of two nodes.
|
||||
|
||||
@@ -84,3 +84,12 @@ impl std::fmt::Display for NodeId {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
// Stable Node Id of a protonode, generated during compilation based on the input values
|
||||
pub type SNI = NodeId;
|
||||
|
||||
// An input of a compiled protonode, used to reference thumbnails, which are stored on a per input basis
|
||||
pub type CompiledProtonodeInput = (NodeId, usize);
|
||||
|
||||
// Path to the protonode in the document network
|
||||
pub type ProtonodePath = Box<[NodeId]>;
|
||||
|
||||
Reference in New Issue
Block a user