Files
Graphite/node-graph/graph-craft/src/document/value.rs
0HyperCube f9d772070b Add some additional image effect nodes (#869)
* Move the Subpath type to graphene-std

* Add the transform subpath node

* Delete selected nodes

* Inserting node list on right click

* Add several bitmap manipulator nodes

* Convert add node to use f64

* Add posterize node

* Rename names randomly

* Fix naming

* Exposure node

* Fix typo

* Adjust exposure node range

* Comment out vector nodes

* Adjust exposure range again

* Posterise as ints

* Rename input

* Use >= in the to hsl function
2022-12-03 14:29:45 -08:00

110 lines
3.1 KiB
Rust

use dyn_any::StaticType;
use dyn_any::{DynAny, Upcast};
use dyn_clone::DynClone;
use glam::DVec2;
use std::sync::Arc;
/// A type that is known, allowing serialization (serde::Deserialize is not object safe)
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TaggedValue {
None,
String(String),
U32(u32),
F32(f32),
F64(f64),
Bool(bool),
DVec2(DVec2),
Image(graphene_std::raster::Image),
Color(graphene_core::raster::color::Color),
Subpath(graphene_std::vector::subpath::Subpath),
RcSubpath(Arc<graphene_std::vector::subpath::Subpath>),
}
impl TaggedValue {
pub fn to_value(self) -> Value {
match self {
TaggedValue::None => Box::new(()),
TaggedValue::String(x) => Box::new(x),
TaggedValue::U32(x) => Box::new(x),
TaggedValue::F32(x) => Box::new(x),
TaggedValue::F64(x) => Box::new(x),
TaggedValue::Bool(x) => Box::new(x),
TaggedValue::DVec2(x) => Box::new(x),
TaggedValue::Image(x) => Box::new(x),
TaggedValue::Color(x) => Box::new(x),
TaggedValue::Subpath(x) => Box::new(x),
TaggedValue::RcSubpath(x) => Box::new(x),
}
}
}
pub type Value = Box<dyn ValueTrait>;
pub trait ValueTrait: DynAny<'static> + Upcast<dyn DynAny<'static>> + std::fmt::Debug + DynClone {}
pub trait IntoValue: Sized + ValueTrait + 'static {
fn into_any(self) -> Value {
Box::new(self)
}
}
impl<T: 'static + StaticType + Upcast<dyn DynAny<'static>> + std::fmt::Debug + PartialEq + Clone> ValueTrait for T {}
impl<T: 'static + ValueTrait> IntoValue for T {}
#[repr(C)]
pub(crate) struct Vtable {
pub(crate) destructor: unsafe fn(*mut ()),
pub(crate) size: usize,
pub(crate) align: usize,
}
#[repr(C)]
pub(crate) struct TraitObject {
pub(crate) self_ptr: *mut u8,
pub(crate) vtable: &'static Vtable,
}
impl PartialEq for Box<dyn ValueTrait> {
#[cfg_attr(miri, ignore)]
fn eq(&self, other: &Self) -> bool {
if self.type_id() != other.type_id() {
return false;
}
let self_trait_object = unsafe { std::mem::transmute::<&dyn ValueTrait, TraitObject>(self.as_ref()) };
let other_trait_object = unsafe { std::mem::transmute::<&dyn ValueTrait, TraitObject>(other.as_ref()) };
let size = self_trait_object.vtable.size;
let self_mem = unsafe { std::slice::from_raw_parts(self_trait_object.self_ptr, size) };
let other_mem = unsafe { std::slice::from_raw_parts(other_trait_object.self_ptr, size) };
self_mem == other_mem
}
}
impl Clone for Value {
fn clone(&self) -> Self {
let self_trait_object = unsafe { std::mem::transmute::<&dyn ValueTrait, TraitObject>(self.as_ref()) };
let size = self_trait_object.vtable.size;
let self_mem = unsafe { std::slice::from_raw_parts(self_trait_object.self_ptr, size) }.to_owned();
let ptr = Vec::leak(self_mem);
unsafe {
std::mem::transmute(TraitObject {
self_ptr: ptr as *mut [u8] as *mut u8,
vtable: self_trait_object.vtable,
})
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_any_src() {
assert!(2_u32.into_any() == 2_u32.into_any());
assert!(2_u32.into_any() != 3_u32.into_any());
assert!(2_u32.into_any() != 3_i32.into_any());
}
}