mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-30 17:58:13 +08:00
Reintroduce input for the node trait
# Conflicts: # node-graph/gcore/src/raster.rs
This commit is contained in:
+12
-16
@@ -8,23 +8,23 @@ use alloc::boxed::Box;
|
|||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
pub mod generic;
|
//pub mod generic;
|
||||||
pub mod ops;
|
//pub mod ops;
|
||||||
//pub mod structural;
|
//pub mod structural;
|
||||||
pub mod raster;
|
pub mod raster;
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
pub trait Node<'n> {
|
pub trait Node<'n, T> {
|
||||||
type Output; // TODO: replace with generic associated type
|
type Output; // TODO: replace with generic associated type
|
||||||
|
|
||||||
fn eval(&'n self) -> Self::Output;
|
fn eval(&'n self, input: T) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'n, N: Node<'n>> Node<'n> for &'n N {
|
impl<'n, N: Node<'n, T>, T> Node<'n, T> for &'n N {
|
||||||
type Output = N::Output;
|
type Output = N::Output;
|
||||||
|
|
||||||
fn eval(&'n self) -> Self::Output {
|
fn eval(&'n self, input: T) -> Self::Output {
|
||||||
Node::eval(*self)
|
Node::eval(*self, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,29 +34,25 @@ pub trait NodeInput {
|
|||||||
fn new(input: Self::Nodes) -> Self;
|
fn new(input: Self::Nodes) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait FQN {
|
|
||||||
fn fqn(&self) -> &'static str;
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Input<I> {
|
trait Input<I> {
|
||||||
unsafe fn input(&self, input: I);
|
unsafe fn input(&self, input: I);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait AsyncNode<'n> {
|
pub trait AsyncNode<'n, T> {
|
||||||
type Output; // TODO: replace with generic associated type
|
type Output; // TODO: replace with generic associated type
|
||||||
|
|
||||||
async fn eval_async(&'n self) -> Self::Output;
|
async fn eval_async(&'n self, input: T) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<'n, N: Node<'n> + Sync> AsyncNode<'n> for N {
|
impl<'n, N: Node<'n, T> + Sync, T: Send + 'n> AsyncNode<'n, T> for N {
|
||||||
type Output = N::Output;
|
type Output = N::Output;
|
||||||
|
|
||||||
async fn eval_async(&'n self) -> Self::Output {
|
async fn eval_async(&'n self, input: T) -> Self::Output {
|
||||||
Node::eval(self)
|
Node::eval(self, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,40 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::Node;
|
use crate::{value::ValueNode, Node};
|
||||||
|
|
||||||
use self::color::Color;
|
use self::color::Color;
|
||||||
|
|
||||||
pub mod color;
|
pub mod color;
|
||||||
|
|
||||||
pub struct GrayscaleNode<'n, N: Node<'n, Output = Color>>(pub N, PhantomData<&'n ()>);
|
pub struct GrayscaleNode;
|
||||||
|
|
||||||
impl<'n, N: Node<'n, Output = Color>> Node<'n> for GrayscaleNode<'n, N> {
|
impl<'n> Node<'n, Color> for GrayscaleNode {
|
||||||
type Output = Color;
|
type Output = Color;
|
||||||
fn eval(&'n self) -> Color {
|
fn eval(&'n self, color: Color) -> Color {
|
||||||
let color = self.0.eval();
|
|
||||||
let avg = (color.r() + color.g() + color.b()) / 3.0;
|
let avg = (color.r() + color.g() + color.b()) / 3.0;
|
||||||
Color::from_rgbaf32(avg, avg, avg, color.a()).expect("Grayscale node created an invalid color")
|
Color::from_rgbaf32(avg, avg, avg, color.a()).expect("Grayscale node created an invalid color")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ForEachNode<'n, I: Iterator<Item = S>, MN: Node<'n, S>, S>(pub MN, PhantomData<&'n (I, S)>);
|
||||||
|
|
||||||
|
impl<'n, I: Iterator<Item = S>, MN: Node<'n, S, Output = ()>, S> Node<'n, I> for ForEachNode<'n, I, MN, S> {
|
||||||
|
type Output = ();
|
||||||
|
fn eval(&'n self, input: I) -> Self::Output {
|
||||||
|
input.for_each(|x| self.0.eval(x))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MutWrapper<'n, N: Node<'n, T, Output = T>, T: Clone>(pub N, PhantomData<&'n T>);
|
||||||
|
|
||||||
|
impl<'n, T: Clone, N: Node<'n, T, Output = T>> Node<'n, &'n mut T> for MutWrapper<'n, N, T> {
|
||||||
|
type Output = ();
|
||||||
|
fn eval(&'n self, value: &'n mut T) {
|
||||||
|
*value = self.0.eval(value.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() {
|
||||||
|
let map = ForEachNode(MutWrapper(GrayscaleNode, PhantomData), PhantomData);
|
||||||
|
map.eval(&mut [Color::from_rgbaf32(1.0, 0.0, 0.0, 1.0).unwrap()].iter_mut());
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
/// The other components (RGB) are stored as `f32` that range from `0.0` up to `f32::MAX`,
|
/// The other components (RGB) are stored as `f32` that range from `0.0` up to `f32::MAX`,
|
||||||
/// the values encode the brightness of each channel proportional to the light intensity in cd/m² (nits) in HDR, and `0.0` (black) to `1.0` (white) in SDR color.
|
/// the values encode the brightness of each channel proportional to the light intensity in cd/m² (nits) in HDR, and `0.0` (black) to `1.0` (white) in SDR color.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default)] //, Serialize, Deserialize)]
|
||||||
pub struct Color {
|
pub struct Color {
|
||||||
red: f32,
|
red: f32,
|
||||||
green: f32,
|
green: f32,
|
||||||
|
|||||||
@@ -5,32 +5,39 @@ use core::sync::atomic::AtomicBool;
|
|||||||
use crate::Node;
|
use crate::Node;
|
||||||
|
|
||||||
pub struct IntNode<const N: u32>;
|
pub struct IntNode<const N: u32>;
|
||||||
impl<'n, const N: u32> Node<'n> for IntNode<N> {
|
impl<'n, const N: u32> Node<'n, ()> for IntNode<N> {
|
||||||
type Output = u32;
|
type Output = u32;
|
||||||
fn eval(&self) -> u32 {
|
fn eval(&self, _: ()) -> u32 {
|
||||||
N
|
N
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ValueNode<T>(pub T);
|
pub struct ValueNode<T>(pub T);
|
||||||
impl<'n, T: 'n> Node<'n> for ValueNode<T> {
|
impl<'n, T: 'n> Node<'n, ()> for ValueNode<T> {
|
||||||
type Output = &'n T;
|
type Output = &'n T;
|
||||||
fn eval(&'n self) -> Self::Output {
|
fn eval(&'n self, _: ()) -> Self::Output {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ValueNode<T> {
|
impl<T> ValueNode<T> {
|
||||||
pub const fn new(value: T) -> ValueNode<T> {
|
pub const fn new(value: T) -> ValueNode<T> {
|
||||||
ValueNode(value)
|
ValueNode(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> From<T> for ValueNode<T> {
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
ValueNode::new(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct DefaultNode<T>(PhantomData<T>);
|
pub struct DefaultNode<T>(PhantomData<T>);
|
||||||
impl<'n, T: Default + 'n> Node<'n> for DefaultNode<T> {
|
impl<'n, T: Default + 'n> Node<'n, ()> for DefaultNode<T> {
|
||||||
type Output = T;
|
type Output = T;
|
||||||
fn eval(&self) -> T {
|
fn eval(&self, _: ()) -> T {
|
||||||
T::default()
|
T::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,15 +45,15 @@ impl<'n, T: Default + 'n> Node<'n> for DefaultNode<T> {
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
/// Return the unit value
|
/// Return the unit value
|
||||||
pub struct UnitNode;
|
pub struct UnitNode;
|
||||||
impl<'n> Node<'n> for UnitNode {
|
impl<'n> Node<'n, ()> for UnitNode {
|
||||||
type Output = ();
|
type Output = ();
|
||||||
fn eval(&'n self) -> Self::Output {}
|
fn eval(&'n self, _: ()) -> Self::Output {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InputNode<T>(MaybeUninit<T>, AtomicBool);
|
pub struct InputNode<T>(MaybeUninit<T>, AtomicBool);
|
||||||
impl<'n, T: 'n> Node<'n> for InputNode<T> {
|
impl<'n, T: 'n> Node<'n, ()> for InputNode<T> {
|
||||||
type Output = &'n T;
|
type Output = &'n T;
|
||||||
fn eval(&'n self) -> Self::Output {
|
fn eval(&'n self, _: ()) -> Self::Output {
|
||||||
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
|
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
|
||||||
unsafe { self.0.assume_init_ref() }
|
unsafe { self.0.assume_init_ref() }
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
pub mod value;
|
pub mod value;
|
||||||
pub use graphene_core::{generic, ops /*, structural*/};
|
pub use graphene_core::{generic, ops /*, structural*/};
|
||||||
|
|
||||||
#[cfg(feature = "memoization")]
|
//#[cfg(feature = "memoization")]
|
||||||
pub mod memo;
|
//pub mod memo;
|
||||||
|
|
||||||
|
//pub mod raster;
|
||||||
|
|
||||||
pub use graphene_core::*;
|
pub use graphene_core::*;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
use core::marker::PhantomData;
|
||||||
|
use graphene_core::{value::RefNode, value::ValueNode, Node};
|
||||||
|
|
||||||
|
pub struct MapNode<'n, IN: Node<'n, Output = I>, I: Iterator<Item = &'n S>, MAP: Fn(&dyn RefNode<Output = S>) -> MN, MN: Node<'n, Output = O> + 'n, S, O: 'n>(pub IN, pub MAP, PhantomData<&'n (I, S)>);
|
||||||
|
|
||||||
|
impl<'n, IN: Node<'n, Output = I>, I: Iterator<Item = &'n S>, MAP: Fn(&dyn RefNode<Output = S>) -> MN, MN: Node<'n, Output = O>, S, O: 'static + Clone> Node<'n> for MapNode<'n, IN, I, MAP, MN, S, O> {
|
||||||
|
type Output = Vec<O>;
|
||||||
|
fn eval(&'n self) -> Self::Output {
|
||||||
|
self.0
|
||||||
|
.eval()
|
||||||
|
.map(|x| {
|
||||||
|
let map_node = self.1(x as &dyn RefNode<Output = S>);
|
||||||
|
let result = map_node.eval();
|
||||||
|
result.clone()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user