mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
General purpose value node
This commit is contained in:
@@ -13,28 +13,28 @@ impl<'i, const N: u32, I> Node<'i, I> for IntNode<N> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy)]
|
||||
pub struct ValueNode<T>(pub T);
|
||||
// #[derive(Default, Debug, Clone, Copy)]
|
||||
// pub struct ValueNode<T>(pub T);
|
||||
|
||||
impl<'i, T: 'i, I> Node<'i, I> for ValueNode<T> {
|
||||
type Output = &'i T;
|
||||
#[inline(always)]
|
||||
fn eval(&'i self, _input: I) -> Self::Output {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
// impl<'i, T: 'i, I> Node<'i, I> for ValueNode<T> {
|
||||
// type Output = &'i T;
|
||||
// #[inline(always)]
|
||||
// fn eval(&'i self, _input: I) -> Self::Output {
|
||||
// &self.0
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<T> ValueNode<T> {
|
||||
pub const fn new(value: T) -> ValueNode<T> {
|
||||
ValueNode(value)
|
||||
}
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
// impl<T> From<T> for ValueNode<T> {
|
||||
// fn from(value: T) -> Self {
|
||||
// ValueNode::new(value)
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy)]
|
||||
pub struct AsRefNode<T: AsRef<U>, U>(pub T, PhantomData<U>);
|
||||
|
||||
@@ -9,11 +9,13 @@ use graphene_brush::brush_cache::BrushCache;
|
||||
use graphene_brush::brush_stroke::BrushStroke;
|
||||
use graphene_core::raster::Image;
|
||||
use graphene_core::raster_types::CPU;
|
||||
use graphene_core::registry::{ChoiceTypeStatic, ChoiceWidgetHint, VariantMetadata};
|
||||
use graphene_core::transform::ReferencePoint;
|
||||
use graphene_core::uuid::NodeId;
|
||||
use graphene_core::vector::style::Fill;
|
||||
use graphene_core::{Color, MemoHash, Node, Type};
|
||||
use graphene_core::{AsU32, Color, MemoHash, Node, Type};
|
||||
use graphene_svg_renderer::RenderMetadata;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Display;
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
@@ -37,6 +39,65 @@ macro_rules! tagged_value {
|
||||
EditorApi(Arc<WasmEditorApi>)
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(u32)]
|
||||
pub enum TaggedValueChoice {
|
||||
None,
|
||||
$($identifier,)*
|
||||
}
|
||||
|
||||
impl TaggedValueChoice {
|
||||
pub fn to_tagged_value(&self) -> TaggedValue {
|
||||
match self {
|
||||
TaggedValueChoice::None => TaggedValue::None,
|
||||
$(TaggedValueChoice::$identifier => TaggedValue::$identifier(Default::default()),)*
|
||||
}
|
||||
}
|
||||
pub fn from_tagged_value(value: &TaggedValue) -> Option<Self> {
|
||||
match value {
|
||||
TaggedValue::None => Some(TaggedValueChoice::None),
|
||||
$( TaggedValue::$identifier(_) => Some(TaggedValueChoice::$identifier), )*
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ChoiceTypeStatic for TaggedValueChoice {
|
||||
const WIDGET_HINT: ChoiceWidgetHint = ChoiceWidgetHint::Dropdown; // or your preferred hint
|
||||
|
||||
const DESCRIPTION: Option<&'static str> = Some("Select a value");
|
||||
|
||||
fn list() -> &'static [&'static [(Self, VariantMetadata)]] {
|
||||
|
||||
const COUNT: usize = 0 $( + one!($identifier) )*;
|
||||
// Define static array of (choice, metadata) tuples
|
||||
static VALUES: [(TaggedValueChoice, VariantMetadata); 1 + COUNT] = [
|
||||
|
||||
(TaggedValueChoice::None, VariantMetadata {
|
||||
name: Cow::Borrowed(stringify!(None)),
|
||||
label: Cow::Borrowed(stringify!(None)),
|
||||
docstring: None,
|
||||
icon: None,
|
||||
}),
|
||||
$(
|
||||
(TaggedValueChoice::$identifier, VariantMetadata {
|
||||
name: Cow::Borrowed(stringify!($identifier)),
|
||||
label: Cow::Borrowed(stringify!($identifier)),
|
||||
docstring: None,
|
||||
icon: None,
|
||||
}),
|
||||
)*
|
||||
];
|
||||
|
||||
// Static reference to the slice of VALUES
|
||||
static LIST: [&'static [(TaggedValueChoice, VariantMetadata)]; 1] = [
|
||||
&VALUES,
|
||||
];
|
||||
|
||||
&LIST
|
||||
}
|
||||
}
|
||||
|
||||
// We must manually implement hashing because some values are floats and so do not reproducibly hash (see FakeHash below)
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
impl Hash for TaggedValue {
|
||||
@@ -156,6 +217,12 @@ macro_rules! tagged_value {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! one {
|
||||
($anything:tt) => {
|
||||
1
|
||||
};
|
||||
}
|
||||
|
||||
tagged_value! {
|
||||
// ===============
|
||||
// PRIMITIVE TYPES
|
||||
@@ -388,6 +455,12 @@ impl Display for TaggedValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsU32 for TaggedValueChoice {
|
||||
fn as_u32(&self) -> u32 {
|
||||
*self as u32
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UpcastNode {
|
||||
value: MemoHash<TaggedValue>,
|
||||
}
|
||||
|
||||
@@ -46,3 +46,21 @@ pub fn input_node<O: StaticType>(n: SharedNodeContainer) -> DowncastBothNode<(),
|
||||
pub fn downcast_node<I: StaticType, O: StaticType>(n: SharedNodeContainer) -> DowncastBothNode<I, O> {
|
||||
DowncastBothNode::new(n)
|
||||
}
|
||||
|
||||
// Same idea as the identity node, but with a hidden primary input in order to have an auto generated properties widget for the value
|
||||
pub struct Value {
|
||||
value: SharedNodeContainer,
|
||||
}
|
||||
|
||||
impl<'i> Node<'i, Any<'i>> for Value {
|
||||
type Output = DynFuture<'i, Any<'i>>;
|
||||
fn eval(&'i self, input: Any<'i>) -> Self::Output {
|
||||
Box::pin(async move { self.value.eval(input).await })
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub const fn new(value: SharedNodeContainer) -> Self {
|
||||
Value { value }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ use graphene_std::Context;
|
||||
use graphene_std::GraphicElement;
|
||||
#[cfg(feature = "gpu")]
|
||||
use graphene_std::any::DowncastBothNode;
|
||||
use graphene_std::any::{ComposeTypeErased, DynAnyNode, IntoTypeErasedNode};
|
||||
use graphene_std::any::{ComposeTypeErased, DynAnyNode, IntoTypeErasedNode, Value};
|
||||
use graphene_std::application_io::{ImageTexture, SurfaceFrame};
|
||||
#[cfg(feature = "gpu")]
|
||||
use graphene_std::wasm_application_io::{WasmEditorApi, WasmSurfaceHandle};
|
||||
@@ -114,6 +114,16 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||
vec![Type::Fn(Box::new(generic!(T)), Box::new(generic!(V))), Type::Fn(Box::new(generic!(V)), Box::new(generic!(U)))],
|
||||
),
|
||||
),
|
||||
(
|
||||
ProtoNodeIdentifier::new("graphene_core::any::ValueNode"),
|
||||
|args| {
|
||||
Box::pin(async move {
|
||||
let node = Value::new(args[0].clone());
|
||||
node.into_type_erased()
|
||||
})
|
||||
},
|
||||
NodeIOTypes::new(generic!(T), generic!(U), vec![Type::Fn(Box::new(concrete!(Context)), Box::new(generic!(U)))]),
|
||||
),
|
||||
#[cfg(feature = "gpu")]
|
||||
async_node!(graphene_core::memo::MemoNode<_, _>, input: Context, fn_params: [Context => WgpuSurface]),
|
||||
#[cfg(feature = "gpu")]
|
||||
|
||||
Reference in New Issue
Block a user