mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-03 21:08:18 +00:00
Reintroduce input for the node trait
# Conflicts: # node-graph/gcore/src/raster.rs
This commit is contained in:
parent
b46bcc16ba
commit
ef08c27e9c
6 changed files with 79 additions and 34 deletions
|
@ -8,23 +8,23 @@ use alloc::boxed::Box;
|
|||
#[cfg(feature = "async")]
|
||||
use async_trait::async_trait;
|
||||
|
||||
pub mod generic;
|
||||
pub mod ops;
|
||||
//pub mod generic;
|
||||
//pub mod ops;
|
||||
//pub mod structural;
|
||||
pub mod raster;
|
||||
pub mod value;
|
||||
|
||||
pub trait Node<'n> {
|
||||
pub trait Node<'n, T> {
|
||||
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;
|
||||
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
Node::eval(*self)
|
||||
fn eval(&'n self, input: T) -> Self::Output {
|
||||
Node::eval(*self, input)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,29 +34,25 @@ pub trait NodeInput {
|
|||
fn new(input: Self::Nodes) -> Self;
|
||||
}
|
||||
|
||||
trait FQN {
|
||||
fn fqn(&self) -> &'static str;
|
||||
}
|
||||
|
||||
trait Input<I> {
|
||||
unsafe fn input(&self, input: I);
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_trait]
|
||||
pub trait AsyncNode<'n> {
|
||||
pub trait AsyncNode<'n, T> {
|
||||
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")]
|
||||
#[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;
|
||||
|
||||
async fn eval_async(&'n self) -> Self::Output {
|
||||
Node::eval(self)
|
||||
async fn eval_async(&'n self, input: T) -> Self::Output {
|
||||
Node::eval(self, input)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,40 @@
|
|||
use core::marker::PhantomData;
|
||||
|
||||
use crate::Node;
|
||||
use crate::{value::ValueNode, Node};
|
||||
|
||||
use self::color::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;
|
||||
fn eval(&'n self) -> Color {
|
||||
let color = self.0.eval();
|
||||
fn eval(&'n self, color: Color) -> Color {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
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 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)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default)] //, Serialize, Deserialize)]
|
||||
pub struct Color {
|
||||
red: f32,
|
||||
green: f32,
|
||||
|
|
|
@ -5,32 +5,39 @@ use core::sync::atomic::AtomicBool;
|
|||
use crate::Node;
|
||||
|
||||
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;
|
||||
fn eval(&self) -> u32 {
|
||||
fn eval(&self, _: ()) -> u32 {
|
||||
N
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
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;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
fn eval(&'n self, _: ()) -> Self::Output {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ValueNode<T> {
|
||||
pub const fn new(value: T) -> ValueNode<T> {
|
||||
ValueNode(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for ValueNode<T> {
|
||||
fn from(value: T) -> Self {
|
||||
ValueNode::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
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;
|
||||
fn eval(&self) -> T {
|
||||
fn eval(&self, _: ()) -> T {
|
||||
T::default()
|
||||
}
|
||||
}
|
||||
|
@ -38,15 +45,15 @@ impl<'n, T: Default + 'n> Node<'n> for DefaultNode<T> {
|
|||
#[repr(C)]
|
||||
/// Return the unit value
|
||||
pub struct UnitNode;
|
||||
impl<'n> Node<'n> for UnitNode {
|
||||
impl<'n> Node<'n, ()> for UnitNode {
|
||||
type Output = ();
|
||||
fn eval(&'n self) -> Self::Output {}
|
||||
fn eval(&'n self, _: ()) -> Self::Output {}
|
||||
}
|
||||
|
||||
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;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
fn eval(&'n self, _: ()) -> Self::Output {
|
||||
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
|
||||
unsafe { self.0.assume_init_ref() }
|
||||
} else {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
pub mod value;
|
||||
pub use graphene_core::{generic, ops /*, structural*/};
|
||||
|
||||
#[cfg(feature = "memoization")]
|
||||
pub mod memo;
|
||||
//#[cfg(feature = "memoization")]
|
||||
//pub mod memo;
|
||||
|
||||
//pub mod raster;
|
||||
|
||||
pub use graphene_core::*;
|
||||
|
||||
|
|
18
node-graph/gstd/src/raster.rs
Normal file
18
node-graph/gstd/src/raster.rs
Normal file
|
@ -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()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue