From f06d9512071fcf62dfbc64cc92f4cd9386fb8277 Mon Sep 17 00:00:00 2001 From: LunaticWyrm467 Date: Sun, 10 Nov 2024 13:05:35 +0100 Subject: [PATCH] Implemented more type support + `glam` support! --- Cargo.lock | 58 +- README.md | 5 +- node_tree_core/Cargo.toml | 10 +- node_tree_core/src/services/node_registry.rs | 2 +- node_tree_core/src/structs/cloneable_types.rs | 8 +- node_tree_core/src/structs/node_scene.rs | 75 +- .../src/traits/glam_serializables.rs | 830 ++++++++++++++++++ node_tree_core/src/traits/mod.rs | 3 + node_tree_core/src/traits/registered.rs | 2 +- node_tree_core/src/traits/serializable.rs | 265 ++++-- node_tree_core/tests/glam_integration.rs | 30 + 11 files changed, 1142 insertions(+), 146 deletions(-) create mode 100644 node_tree_core/src/traits/glam_serializables.rs create mode 100644 node_tree_core/tests/glam_integration.rs diff --git a/Cargo.lock b/Cargo.lock index e00b437..aaa4367 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,6 +103,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "glam" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677" + [[package]] name = "hashbrown" version = "0.14.5" @@ -187,14 +193,14 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "node_tree" -version = "0.9.0" +version = "0.9.1" dependencies = [ "chrono", "ctor", "dashmap", + "glam", "node_tree_derive", - "serde", - "toml", + "toml_edit", ] [[package]] @@ -267,35 +273,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "serde" -version = "1.0.214" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.214" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - [[package]] name = "smallvec" version = "1.13.2" @@ -324,26 +301,11 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "toml" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - [[package]] name = "toml_datetime" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] [[package]] name = "toml_edit" @@ -352,8 +314,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", - "serde", - "serde_spanned", "toml_datetime", "winnow", ] diff --git a/README.md b/README.md index daae624..7828728 100644 --- a/README.md +++ b/README.md @@ -259,7 +259,10 @@ pub struct SpecializedNode { } ``` -## Features +## Supported Features +- `glam` - Enables support with glam's types when it comes with saving and loading. + +## Highlights - 🏗️ An easy abstraction framework for different processes to communicate and interact with each other in a scalable manner. Inspired by Godot! - ⏯️ The ability to `pause()` and `unpause()` the `NodeTree`, and fine tune individual `Node` behaviours for when a tree is paused/unpaused. - 📡 Various methods to communicate with other nodes, such as `owner()`, `parent()`, `get_child()`, `children()`, and `get_node()`, as well as methods to automate the process such as signals. diff --git a/node_tree_core/Cargo.toml b/node_tree_core/Cargo.toml index 92aa4e2..fb57e4d 100644 --- a/node_tree_core/Cargo.toml +++ b/node_tree_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "node_tree" -version = "0.9.0" +version = "0.9.1" edition = "2021" rust-version = "1.78" @@ -22,6 +22,10 @@ license = "MIT OR Apache-2.0" node_tree_derive = { path = "../node_tree_derive", version = "0.7.0" } chrono = "0.4.38" dashmap = "6.1.0" -serde = { version = "1.0.214", features = ["derive"] } ctor = "0.2.8" -toml = "0.8.19" +toml_edit = "0.22.22" +glam = { version = "0.29.2", optional = true } + +[features] +default = [] +glam = ["dep:glam"] diff --git a/node_tree_core/src/services/node_registry.rs b/node_tree_core/src/services/node_registry.rs index 9d528a9..afaad64 100644 --- a/node_tree_core/src/services/node_registry.rs +++ b/node_tree_core/src/services/node_registry.rs @@ -30,7 +30,7 @@ use std::collections::HashMap; use dashmap::DashMap; -pub use toml::Value; +pub use toml_edit::Value; use crate::traits::node::Node; use crate::traits::serializable::Serializable; diff --git a/node_tree_core/src/structs/cloneable_types.rs b/node_tree_core/src/structs/cloneable_types.rs index 2f7f7c9..6c2885c 100644 --- a/node_tree_core/src/structs/cloneable_types.rs +++ b/node_tree_core/src/structs/cloneable_types.rs @@ -28,10 +28,16 @@ use std::ops::{ Deref, DerefMut }; +use toml_edit as toml; + use crate::traits::serializable::Serializable; /// `Doc` (Default on Clone), simply returns the default type when cloned. +/// +/// # Note +/// This automatically implements `Serializable`, and will always yield the default value when +/// serialized. #[derive(Debug, Default)] pub struct Doc(T); @@ -69,7 +75,7 @@ impl DerefMut for Doc { impl Serializable for Doc { fn to_value(&self) -> toml::Value { - toml::Value::Array(Vec::new()) + toml::Value::Array(toml::Array::new()) } fn from_value(_value: toml::Value) -> Option where Self: Sized { diff --git a/node_tree_core/src/structs/node_scene.rs b/node_tree_core/src/structs/node_scene.rs index cf243a0..6032efd 100644 --- a/node_tree_core/src/structs/node_scene.rs +++ b/node_tree_core/src/structs/node_scene.rs @@ -30,8 +30,7 @@ use std::path::PathBuf; use std::collections::HashMap; use std::hash::{ self, Hash, Hasher }; -use serde::{ Serialize, Deserialize }; -use toml::Table; +use toml_edit as toml; use crate::structs::rid::RID; use crate::traits::{ node::Node, instanceable::Instanceable }; @@ -44,18 +43,6 @@ use crate::services::node_registry::{ self, FieldMap, SFieldMap }; */ -/// Used to represent a node's data. -/// -/// # Note -/// The `ID` is stored as the key to this data, not in the data itself. -#[derive(Serialize, Deserialize)] -struct NodeData { - type_name: String, - parent: Option, - is_owner: bool, - fields: Table -} - /// A recursive structure that allows for the storage, saving, and loading of a dormant scene of nodes. /// The root node is what every node in the scene will have its owner set to. #[derive(Debug)] @@ -102,26 +89,34 @@ impl NodeScene { drop(file); // Attempt to parse the file as a table. - let document: String = String::from_utf8(buffer).map_err(|err| format!("{err}"))?; - let document: Table = toml::from_str(&document).map_err(|err| format!("{err}"))?; + let document: String = String::from_utf8(buffer).map_err(|err| format!("{err}"))?; + let document: toml::DocumentMut = document.parse().map_err(|err| format!("{err}"))?; // Go through each node and deserialize it: let mut node_scene: Option = None; let mut traversal: HashMap> = HashMap::new(); // Cache used for quick traversal. - for (key, node_data) in document { - + for (key, node_data) in document.iter() { + + // Deserialize the node's metadata. + let node_data: &toml::Table = node_data.as_table().ok_or(format!("Failed to parse {}'s data", key))?; + let metadata: &toml::InlineTable = node_data.get("metadata").map(|nd| nd.as_inline_table()).flatten().ok_or(format!("Failed to parse {}'s metadata", key))?; + let type_name: String = metadata.get("type_name").map(|tn| tn.as_str().map(|s| s.to_string())).flatten().ok_or(format!("Failed to parse {}'s type name", key))?; + let is_owner: bool = metadata.get("is_owner").map(|tn| tn.as_bool()).flatten().ok_or(format!("Failed to parse {}'s ownership status", key))?; + let parent: Option = metadata.get("parent").map(|p| p.as_integer().map(|rid| rid as RID)).flatten(); + // Deserialize the node data back into its respective type. - let NodeData { - type_name, - is_owner, - parent, - fields - } = toml::from_str(&toml::to_string(&node_data).unwrap()).unwrap(); - - let node_fields: SFieldMap = fields.into_iter().map(|(key, value)| (key.into(), value)).collect(); - let node: Box = node_registry::deserialize(&type_name, node_fields)?; - let local_rid: RID = key.split_once('_') + let node_fields: Option = node_data.into_iter() + .filter(|(field, _)| *field != "metadata") + .map(|(field, value)| { + match value { + toml::Item::Value(value) => Some((field.into(), value.to_owned())), + _ => None + } + }).collect(); + + let node: Box = node_registry::deserialize(&type_name, node_fields.ok_or("Could not parse node fields".to_string())?)?; + let local_rid: RID = key.split_once('_') .ok_or("Failed to parse Node key".to_string())? .1.parse() .map_err(|err| format!("{err}"))?; @@ -188,7 +183,7 @@ impl NodeScene { pub fn save(&self, path: &Path, name: &str) -> Result<(), String> { // Constuct a buffer for the toml format. - let mut document: Table = Table::new(); + let mut document: toml::DocumentMut = toml::DocumentMut::new(); // Go through each node and serialize it: self.update_internal(0); @@ -197,22 +192,22 @@ impl NodeScene { let parent: Option<&dyn Node> = parent.map(|x| unsafe { &*x }); // Format the metadata. - let mut node_data: NodeData = NodeData { - type_name: node.name_as_type(), - is_owner, - parent: parent.map(|p| p.rid()), - fields: Table::new() - }; + let node_key: String = format!("Node_{}", node.rid()); + + document[&node_key] = toml::Item::Table(toml::Table::new()); + document[&node_key]["metadata"] = toml::InlineTable::new().into(); + document[&node_key]["metadata"]["type_name"] = node.name_as_type().into(); + document[&node_key]["metadata"]["is_owner"] = is_owner.into(); + + if let Some(parent_rid) = parent.map(|p| p.rid()) { + document[&node_key]["metadata"]["parent"] = (parent_rid as i64).into(); + } // Save the fields. let node_fields: FieldMap = node.save_from_owned(); for (field_name, value) in node_fields { - node_data.fields.insert(field_name.to_string(), value.to_value()); + document[&node_key][&field_name.to_string()] = toml::Item::Value(value.to_value()); } - - // Serialize this as a table and insert it into a document. - let node_table: Table = toml::from_str(&toml::to_string(&node_data).unwrap()).unwrap(); - document.insert(format!("Node_{}", node.rid()), node_table.into()); }); // Write the saved scene data to disk. diff --git a/node_tree_core/src/traits/glam_serializables.rs b/node_tree_core/src/traits/glam_serializables.rs new file mode 100644 index 0000000..3a907f8 --- /dev/null +++ b/node_tree_core/src/traits/glam_serializables.rs @@ -0,0 +1,830 @@ +use glam::{ + bool as g_bool, + u8 as g_u8, u16 as g_u16, u32 as g_u32, u64 as g_u64, + i8 as g_i8, i16 as g_i16, i32 as g_i32, i64 as g_i64, + f32 as g_f32, f64 as g_f64 +}; +use toml_edit as toml; + +use super::serializable::Serializable; + + +impl Serializable for g_bool::BVec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x, self.y])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_bool::bvec2(x.as_bool()?, y.as_bool()?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_bool::BVec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x, self.y, self.z])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_bool::bvec3(x.as_bool()?, y.as_bool()?, z.as_bool()?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_bool::BVec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x, self.y, self.z, self.w])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_bool::bvec4(x.as_bool()?, y.as_bool()?, z.as_bool()?, w.as_bool()?)); + } + None + }, + _ => None + } + } +} + +impl Serializable for g_u8::U8Vec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_u8::u8vec2(x.as_integer()? as u8, y.as_integer()? as u8)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_u8::U8Vec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_u8::u8vec3(x.as_integer()? as u8, y.as_integer()? as u8, z.as_integer()? as u8)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_u8::U8Vec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_u8::u8vec4(x.as_integer()? as u8, y.as_integer()? as u8, z.as_integer()? as u8, w.as_integer()? as u8)); + } + None + }, + _ => None + } + } +} + +impl Serializable for g_u16::U16Vec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_u16::u16vec2(x.as_integer()? as u16, y.as_integer()? as u16)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_u16::U16Vec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_u16::u16vec3(x.as_integer()? as u16, y.as_integer()? as u16, z.as_integer()? as u16)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_u16::U16Vec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_u16::u16vec4(x.as_integer()? as u16, y.as_integer()? as u16, z.as_integer()? as u16, w.as_integer()? as u16)); + } + None + }, + _ => None + } + } +} + +impl Serializable for g_u32::UVec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_u32::uvec2(x.as_integer()? as u32, y.as_integer()? as u32)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_u32::UVec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_u32::uvec3(x.as_integer()? as u32, y.as_integer()? as u32, z.as_integer()? as u32)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_u32::UVec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_u32::uvec4(x.as_integer()? as u32, y.as_integer()? as u32, z.as_integer()? as u32, w.as_integer()? as u32)); + } + None + }, + _ => None + } + } +} + +impl Serializable for g_u64::U64Vec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_u64::u64vec2(x.as_integer()? as u64, y.as_integer()? as u64)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_u64::U64Vec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_u64::u64vec3(x.as_integer()? as u64, y.as_integer()? as u64, z.as_integer()? as u64)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_u64::U64Vec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_u64::u64vec4(x.as_integer()? as u64, y.as_integer()? as u64, z.as_integer()? as u64, w.as_integer()? as u64)); + } + None + }, + _ => None + } + } +} + +impl Serializable for g_i8::I8Vec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_i8::i8vec2(x.as_integer()? as i8, y.as_integer()? as i8)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_i8::I8Vec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_i8::i8vec3(x.as_integer()? as i8, y.as_integer()? as i8, z.as_integer()? as i8)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_i8::I8Vec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_i8::i8vec4(x.as_integer()? as i8, y.as_integer()? as i8, z.as_integer()? as i8, w.as_integer()? as i8)); + } + None + }, + _ => None + } + } +} + +impl Serializable for g_i16::I16Vec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_i16::i16vec2(x.as_integer()? as i16, y.as_integer()? as i16)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_i16::I16Vec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_i16::i16vec3(x.as_integer()? as i16, y.as_integer()? as i16, z.as_integer()? as i16)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_i16::I16Vec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_i16::i16vec4(x.as_integer()? as i16, y.as_integer()? as i16, z.as_integer()? as i16, w.as_integer()? as i16)); + } + None + }, + _ => None + } + } +} + +impl Serializable for g_i32::IVec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_i32::ivec2(x.as_integer()? as i32, y.as_integer()? as i32)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_i32::IVec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_i32::ivec3(x.as_integer()? as i32, y.as_integer()? as i32, z.as_integer()? as i32)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_i32::IVec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as i64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_i32::ivec4(x.as_integer()? as i32, y.as_integer()? as i32, z.as_integer()? as i32, w.as_integer()? as i32)); + } + None + }, + _ => None + } + } +} + +impl Serializable for g_i64::I64Vec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array())) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_i64::i64vec2(x.as_integer()?, y.as_integer()?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_i64::I64Vec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array())) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_i64::i64vec3(x.as_integer()?, y.as_integer()?, z.as_integer()?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_i64::I64Vec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array())) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_i64::i64vec4(x.as_integer()?, y.as_integer()?, z.as_integer()?, w.as_integer()?)); + } + None + }, + _ => None + } + } +} + +impl Serializable for g_f32::Vec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as f64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_f32::vec2(x.as_float()? as f32, y.as_float()? as f32)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f32::Vec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as f64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_f32::vec3(x.as_float()? as f32, y.as_float()? as f32, z.as_float()? as f32)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f32::Vec3A { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as f64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_f32::vec3a(x.as_float()? as f32, y.as_float()? as f32, z.as_float()? as f32)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f32::Vec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array().map(|x| x as f64))) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_f32::vec4(x.as_float()? as f32, y.as_float()? as f32, z.as_float()? as f32, w.as_float()? as f32)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f32::Mat2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x_axis.to_value(), self.y_axis.to_value()])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x_axis, y_axis] = arr.into_iter().collect::>().as_slice() { + return Some(g_f32::mat2(g_f32::Vec2::from_value(x_axis.clone())?, g_f32::Vec2::from_value(y_axis.clone())?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f32::Mat3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x_axis.to_value(), self.y_axis.to_value(), self.z_axis.to_value()])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x_axis, y_axis, z_axis] = arr.into_iter().collect::>().as_slice() { + return Some(g_f32::mat3(g_f32::Vec3::from_value(x_axis.clone())?, g_f32::Vec3::from_value(y_axis.clone())?, g_f32::Vec3::from_value(z_axis.clone())?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f32::Mat3A { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x_axis.to_value(), self.y_axis.to_value(), self.z_axis.to_value()])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x_axis, y_axis, z_axis] = arr.into_iter().collect::>().as_slice() { + return Some(g_f32::mat3a(g_f32::Vec3A::from_value(x_axis.clone())?, g_f32::Vec3A::from_value(y_axis.clone())?, g_f32::Vec3A::from_value(z_axis.clone())?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f32::Mat4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x_axis.to_value(), self.y_axis.to_value(), self.z_axis.to_value(), self.w_axis.to_value()])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x_axis, y_axis, z_axis, w_axis] = arr.into_iter().collect::>().as_slice() { + return Some(g_f32::mat4( + g_f32::Vec4::from_value(x_axis.clone())?, g_f32::Vec4::from_value(y_axis.clone())?, + g_f32::Vec4::from_value(z_axis.clone())?, g_f32::Vec4::from_value(w_axis.clone())? + )); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f32::Quat { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x as f64, self.y as f64, self.z as f64, self.w as f64])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_f32::quat(x.as_float()? as f32, y.as_float()? as f32, z.as_float()? as f32, w.as_float()? as f32)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f32::Affine2 { + fn to_value(&self) -> toml_edit::Value { + let mut table: toml::InlineTable = toml::InlineTable::new(); + table.insert("matrix2", self.matrix2.to_value()); + table.insert("translation", self.translation.to_value()); + + table.into() + } + + fn from_value(mut value: toml::Value) -> Option where Self: Sized { + let table: &mut toml::InlineTable = value.as_inline_table_mut()?; + + Some(g_f32::Affine2::from_mat2_translation( + g_f32::Mat2::from_value(table.remove("matrix2")?)?, + g_f32::Vec2::from_value(table.remove("translation")?)? + )) + } +} +impl Serializable for g_f32::Affine3A { + fn to_value(&self) -> toml_edit::Value { + let mut table: toml::InlineTable = toml::InlineTable::new(); + table.insert("matrix3", self.matrix3.to_value()); + table.insert("translation", self.translation.to_value()); + + table.into() + } + + fn from_value(mut value: toml::Value) -> Option where Self: Sized { + let table: &mut toml::InlineTable = value.as_inline_table_mut()?; + + Some(g_f32::Affine3A::from_mat3_translation( + g_f32::Mat3A::from_value(table.remove("matrix3")?)?.into(), + g_f32::Vec3A::from_value(table.remove("translation")?)?.into() + )) + } +} + +impl Serializable for g_f64::DVec2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array())) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y] = arr.into_iter().collect::>().as_slice() { + return Some(g_f64::dvec2(x.as_float()?, y.as_float()?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f64::DVec3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array())) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z] = arr.into_iter().collect::>().as_slice() { + return Some(g_f64::dvec3(x.as_float()?, y.as_float()?, z.as_float()?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f64::DVec4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(self.to_array())) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_f64::dvec4(x.as_float()?, y.as_float()?, z.as_float()?, w.as_float()?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f64::DMat2 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x_axis.to_value(), self.y_axis.to_value()])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x_axis, y_axis] = arr.into_iter().collect::>().as_slice() { + return Some(g_f64::dmat2(g_f64::DVec2::from_value(x_axis.clone())?, g_f64::DVec2::from_value(y_axis.clone())?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f64::DMat3 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x_axis.to_value(), self.y_axis.to_value(), self.z_axis.to_value()])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x_axis, y_axis, z_axis] = arr.into_iter().collect::>().as_slice() { + return Some(g_f64::dmat3(g_f64::DVec3::from_value(x_axis.clone())?, g_f64::DVec3::from_value(y_axis.clone())?, g_f64::DVec3::from_value(z_axis.clone())?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f64::DMat4 { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x_axis.to_value(), self.y_axis.to_value(), self.z_axis.to_value(), self.w_axis.to_value()])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x_axis, y_axis, z_axis, w_axis] = arr.into_iter().collect::>().as_slice() { + return Some(g_f64::dmat4( + g_f64::DVec4::from_value(x_axis.clone())?, g_f64::DVec4::from_value(y_axis.clone())?, + g_f64::DVec4::from_value(z_axis.clone())?, g_f64::DVec4::from_value(w_axis.clone())? + )); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f64::DQuat { + fn to_value(&self) -> toml::Value { + toml::Value::Array(toml::Array::from_iter(vec![self.x, self.y, self.z, self.w])) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => { + if let [x, y, z, w] = arr.into_iter().collect::>().as_slice() { + return Some(g_f64::dquat(x.as_float()?, y.as_float()?, z.as_float()?, w.as_float()?)); + } + None + }, + _ => None + } + } +} +impl Serializable for g_f64::DAffine2 { + fn to_value(&self) -> toml_edit::Value { + let mut table: toml::InlineTable = toml::InlineTable::new(); + table.insert("matrix2", self.matrix2.to_value()); + table.insert("translation", self.translation.to_value()); + + table.into() + } + + fn from_value(mut value: toml::Value) -> Option where Self: Sized { + let table: &mut toml::InlineTable = value.as_inline_table_mut()?; + + Some(g_f64::DAffine2::from_mat2_translation( + g_f64::DMat2::from_value(table.remove("matrix2")?)?, + g_f64::DVec2::from_value(table.remove("translation")?)? + )) + } +} +impl Serializable for g_f64::DAffine3 { + fn to_value(&self) -> toml_edit::Value { + let mut table: toml::InlineTable = toml::InlineTable::new(); + table.insert("matrix3", self.matrix3.to_value()); + table.insert("translation", self.translation.to_value()); + + table.into() + } + + fn from_value(mut value: toml::Value) -> Option where Self: Sized { + let table: &mut toml::InlineTable = value.as_inline_table_mut()?; + + Some(g_f64::DAffine3::from_mat3_translation( + g_f64::DMat3::from_value(table.remove("matrix3")?)?, + g_f64::DVec3::from_value(table.remove("translation")?)? + )) + } +} diff --git a/node_tree_core/src/traits/mod.rs b/node_tree_core/src/traits/mod.rs index a600dc7..a4ae182 100644 --- a/node_tree_core/src/traits/mod.rs +++ b/node_tree_core/src/traits/mod.rs @@ -4,3 +4,6 @@ pub mod node_tree; pub mod instanceable; pub mod registered; pub mod serializable; + +#[cfg(feature = "glam")] +pub mod glam_serializables; diff --git a/node_tree_core/src/traits/registered.rs b/node_tree_core/src/traits/registered.rs index cac6db6..4e2039e 100644 --- a/node_tree_core/src/traits/registered.rs +++ b/node_tree_core/src/traits/registered.rs @@ -37,6 +37,6 @@ pub trait Registered { /// Loads a `Node` from a set of owned data in a `toml` compatible format. fn load_from_owned(owned_state: SFieldMap) -> Result where Self: Sized; /* Required for V-Table Initialization */ - /// Saves a `Node`'s owned state to a `FieldMap`, which is compatible with `Serde`. + /// Saves a `Node`'s owned state to a `FieldMap`, which is compatible with `toml_edit`. fn save_from_owned(&self) -> FieldMap; } diff --git a/node_tree_core/src/traits/serializable.rs b/node_tree_core/src/traits/serializable.rs index 66c6600..35b1863 100644 --- a/node_tree_core/src/traits/serializable.rs +++ b/node_tree_core/src/traits/serializable.rs @@ -25,12 +25,18 @@ //! use std::{ - collections::HashMap, + collections::{ BTreeMap, BTreeSet, HashMap, HashSet }, + mem, ops::Deref, - mem + path, + str::FromStr, + time, + net, + hash, + cmp }; -use toml::value::Datetime; +use toml_edit as toml; use crate::structs::node_path::NodePath; @@ -48,7 +54,7 @@ pub trait Serializable { impl Serializable for () { fn to_value(&self) -> toml::Value { - toml::Value::Array(Vec::new()) + toml::Value::Array(toml::Array::new()) } fn from_value(_value: toml::Value) -> Option where Self: Sized { @@ -63,7 +69,7 @@ impl Serializable for bool { fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Boolean(b) => Some(b), + toml::Value::Boolean(b) => Some(b.into_value()), _ => None } } @@ -76,7 +82,7 @@ impl Serializable for u8 { fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Integer(i) => Some(i as u8), + toml::Value::Integer(i) => Some(i.into_value() as u8), _ => None } } @@ -88,7 +94,7 @@ impl Serializable for u16 { fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Integer(i) => Some(i as u16), + toml::Value::Integer(i) => Some(i.into_value() as u16), _ => None } } @@ -100,7 +106,7 @@ impl Serializable for u32 { fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Integer(i) => Some(i as u32), + toml::Value::Integer(i) => Some(i.into_value() as u32), _ => None } } @@ -112,7 +118,7 @@ impl Serializable for u64 { fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Integer(i) => Some(i as u64), + toml::Value::Integer(i) => Some(i.into_value() as u64), _ => None } } @@ -124,7 +130,7 @@ impl Serializable for i8 { fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Integer(i) => Some(i as i8), + toml::Value::Integer(i) => Some(i.into_value() as i8), _ => None } } @@ -136,7 +142,7 @@ impl Serializable for i16 { fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Integer(i) => Some(i as i16), + toml::Value::Integer(i) => Some(i.into_value() as i16), _ => None } } @@ -148,23 +154,47 @@ impl Serializable for i32 { fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Integer(i) => Some(i as i32), + toml::Value::Integer(i) => Some(i.into_value() as i32), _ => None } } } impl Serializable for i64 { fn to_value(&self) -> toml::Value { - (*self as i64).into() + (*self).into() } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Integer(i) => Some(i as i64), + toml::Value::Integer(i) => Some(i.into_value()), _ => None } } } +impl Serializable for f32 { + fn to_value(&self) -> toml::Value { + (*self as f64).into() + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Float(i) => Some(i.into_value() as f32), + _ => None + } + } +} +impl Serializable for f64 { + fn to_value(&self) -> toml::Value { + (*self).into() + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Float(i) => Some(i.into_value()), + _ => None + } + } +} impl Serializable for char { fn to_value(&self) -> toml::Value { @@ -174,6 +204,7 @@ impl Serializable for char { fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::String(c) => { + let c: String = c.into_value(); if c.len() != 1 { None } else { @@ -191,7 +222,7 @@ impl Serializable for String { fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::String(s) => Some(s), + toml::Value::String(s) => Some(s.into_value()), _ => None } } @@ -205,23 +236,92 @@ impl Serializable for NodePath { String::from_value(value).map(|str| NodePath::from_str(&str)) } } +impl Serializable for path::PathBuf { + fn to_value(&self) -> toml::Value { + self.to_str().expect("Invalid unicode").to_owned().to_value() + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + path::PathBuf::from_str(&String::from_value(value)?).ok() + } +} + +impl Serializable for net::Ipv4Addr { + fn to_value(&self) -> toml::Value { + self.to_string().to_value() + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + net::Ipv4Addr::from_str(&String::from_value(value)?).ok() + } +} +impl Serializable for net::Ipv6Addr { + fn to_value(&self) -> toml::Value { + self.to_string().to_value() + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + net::Ipv6Addr::from_str(&String::from_value(value)?).ok() + } +} +impl Serializable for net::IpAddr { + fn to_value(&self) -> toml::Value { + self.to_string().to_value() + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + net::IpAddr::from_str(&String::from_value(value)?).ok() + } +} -impl Serializable for Datetime { +impl Serializable for time::Duration { + fn to_value(&self) -> toml::Value { + self.as_secs_f64().to_value() + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + Some(time::Duration::from_secs_f64(value.as_float()?)) + } +} +impl Serializable for toml::Datetime { fn to_value(&self) -> toml::Value { - toml::Value::Datetime(self.to_owned()) + toml::Value::Datetime(toml::Formatted::new(self.to_owned())) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Datetime(dt) => Some(dt), + toml::Value::Datetime(dt) => Some(dt.into_value()), _ => None } } } +impl Serializable for Option { + fn to_value(&self) -> toml::Value { + let map: toml::InlineTable = match self { + Some(value) => toml::InlineTable::from_iter(vec![("value".to_string(), value.to_value())]), + None => toml::InlineTable::new() + }; + + map.into() + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::InlineTable(mut table) => match table.remove("value") { + Some(value) => Some(Some(T::from_value(value)?)), + None => Some(None) + }, + _ => None + } + + } +} + impl Serializable for Vec { fn to_value(&self) -> toml::Value { - self.iter().map(|v| (v.to_owned()).to_value()).collect::>().into() + let arr: toml::Array = toml::Array::from_iter(self.iter().map(|v| (v.to_owned()).to_value())); + arr.into() } fn from_value(value: toml::Value) -> Option where Self: Sized { @@ -232,14 +332,27 @@ impl Serializable for Vec { } } +impl Serializable for HashSet { + fn to_value(&self) -> toml::Value { + let arr: toml::Array = toml::Array::from_iter(self.iter().map(|x| x.to_value())); + toml::Value::Array(arr) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => arr.into_iter().map(|x| T::from_value(x)).collect::>>(), + _ => None + } + } +} impl Serializable for HashMap { fn to_value(&self) -> toml::Value { - self.iter().map(|(k, v)| (k.to_string(), (v.to_owned()).to_value())).collect::().into() + self.iter().map(|(k, v)| (k.to_string(), (v.to_owned()).to_value())).collect::().into() } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Table(table) => { + toml::Value::InlineTable(table) => { table.into_iter().map(|(key, value)| { if key.len() != 1 { None @@ -255,17 +368,16 @@ impl Serializable for HashMap { } } } - impl Serializable for HashMap { fn to_value(&self) -> toml::Value { - self.iter().map(|(k, v)| (k.to_owned(), (v.to_owned()).to_value())).collect::().into() + self.iter().map(|(k, v)| (k.to_owned(), (v.to_owned()).to_value())).collect::().into() } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { - toml::Value::Table(table) => { + toml::Value::InlineTable(table) => { table.into_iter() - .map(|(key, value)| V::from_value(value).map(|value| (key, value))) + .map(|(key, value)| V::from_value(value).map(|value| (key.to_string(), value))) .collect::>>() }, _ => None @@ -273,6 +385,59 @@ impl Serializable for HashMap { } } +impl Serializable for BTreeSet { + fn to_value(&self) -> toml::Value { + let arr: toml::Array = toml::Array::from_iter(self.iter().map(|x| x.to_value())); + toml::Value::Array(arr) + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::Array(arr) => arr.into_iter().map(|x| T::from_value(x)).collect::>>(), + _ => None + } + } +} +impl Serializable for BTreeMap { + fn to_value(&self) -> toml::Value { + self.iter().map(|(k, v)| (k.to_string(), (v.to_owned()).to_value())).collect::().into() + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::InlineTable(table) => { + table.into_iter().map(|(key, value)| { + if key.len() != 1 { + None + } else { + match V::from_value(value) { + Some(value) => Some((key.chars().collect::>()[0], value)), + None => None + } + } + }).collect::>>() + }, + _ => None + } + } +} +impl Serializable for BTreeMap { + fn to_value(&self) -> toml::Value { + self.iter().map(|(k, v)| (k.to_owned(), (v.to_owned()).to_value())).collect::().into() + } + + fn from_value(value: toml::Value) -> Option where Self: Sized { + match value { + toml::Value::InlineTable(table) => { + table.into_iter() + .map(|(key, value)| V::from_value(value).map(|value| (key.to_string(), value))) + .collect::>>() + }, + _ => None + } + } +} + impl Serializable for Box { fn to_value(&self) -> toml::Value { self.deref().to_value() @@ -338,13 +503,13 @@ impl Serializable for [T; N] { impl Serializable for (A,) { fn to_value(&self) -> toml::Value { - toml::Value::Array(vec![self.0.to_value()]) + toml::Value::Array(toml::Array::from_iter(vec![self.0.to_value()])) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::Array(arr) => { - if let [a] = arr.as_slice() { + if let [a] = arr.into_iter().collect::>().as_slice() { return Some((A::from_value(a.to_owned())?,)) } None @@ -355,13 +520,13 @@ impl Serializable for (A,) { } impl Serializable for (A, B) { fn to_value(&self) -> toml::Value { - toml::Value::Array(vec![self.0.to_value(), self.1.to_value()]) + toml::Value::Array(toml::Array::from_iter(vec![self.0.to_value(), self.1.to_value()])) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::Array(arr) => { - if let [a, b] = arr.as_slice() { + if let [a, b] = arr.into_iter().collect::>().as_slice() { return Some((A::from_value(a.to_owned())?, B::from_value(b.to_owned())?)) } None @@ -372,13 +537,13 @@ impl Serializable for (A, B) { } impl Serializable for (A, B, C) { fn to_value(&self) -> toml::Value { - toml::Value::Array(vec![self.0.to_value(), self.1.to_value(), self.2.to_value()]) + toml::Value::Array(toml::Array::from_iter(vec![self.0.to_value(), self.1.to_value(), self.2.to_value()])) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::Array(arr) => { - if let [a, b, c] = arr.as_slice() { + if let [a, b, c] = arr.into_iter().collect::>().as_slice() { return Some((A::from_value(a.to_owned())?, B::from_value(b.to_owned())?, C::from_value(c.to_owned())?)) } None @@ -389,13 +554,13 @@ impl Serializable for (A, B, } impl Serializable for (A, B, C, D) { fn to_value(&self) -> toml::Value { - toml::Value::Array(vec![self.0.to_value(), self.1.to_value(), self.2.to_value(), self.3.to_value()]) + toml::Value::Array(toml::Array::from_iter(vec![self.0.to_value(), self.1.to_value(), self.2.to_value(), self.3.to_value()])) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::Array(arr) => { - if let [a, b, c, d] = arr.as_slice() { + if let [a, b, c, d] = arr.into_iter().collect::>().as_slice() { return Some((A::from_value(a.to_owned())?, B::from_value(b.to_owned())?, C::from_value(c.to_owned())?, D::from_value(d.to_owned())?)) } None @@ -406,13 +571,13 @@ impl Serial } impl Serializable for (A, B, C, D, E) { fn to_value(&self) -> toml::Value { - toml::Value::Array(vec![self.0.to_value(), self.1.to_value(), self.2.to_value(), self.3.to_value(), self.4.to_value()]) + toml::Value::Array(toml::Array::from_iter(vec![self.0.to_value(), self.1.to_value(), self.2.to_value(), self.3.to_value(), self.4.to_value()])) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::Array(arr) => { - if let [a, b, c, d, e] = arr.as_slice() { + if let [a, b, c, d, e] = arr.into_iter().collect::>().as_slice() { return Some((A::from_value(a.to_owned())?, B::from_value(b.to_owned())?, C::from_value(c.to_owned())?, D::from_value(d.to_owned())?, E::from_value(e.to_owned())?)) } None @@ -424,16 +589,16 @@ impl Serializable for (A, B, C, D, E, F) { fn to_value(&self) -> toml::Value { - toml::Value::Array(vec![ + toml::Value::Array(toml::Array::from_iter(vec![ self.0.to_value(), self.1.to_value(), self.2.to_value(), self.3.to_value(), self.4.to_value(), self.5.to_value() - ]) + ])) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::Array(arr) => { - if let [a, b, c, d, e, f] = arr.as_slice() { + if let [a, b, c, d, e, f] = arr.into_iter().collect::>().as_slice() { return Some(( A::from_value(a.to_owned())?, B::from_value(b.to_owned())?, C::from_value(c.to_owned())?, D::from_value(d.to_owned())?, E::from_value(e.to_owned())?, F::from_value(f.to_owned())? @@ -448,16 +613,16 @@ impl Serializable for (A, B, C, D, E, F, G) { fn to_value(&self) -> toml::Value { - toml::Value::Array(vec![ + toml::Value::Array(toml::Array::from_iter(vec![ self.0.to_value(), self.1.to_value(), self.2.to_value(), self.3.to_value(), self.4.to_value(), self.5.to_value(), self.6.to_value() - ]) + ])) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::Array(arr) => { - if let [a, b, c, d, e, f, g] = arr.as_slice() { + if let [a, b, c, d, e, f, g] = arr.into_iter().collect::>().as_slice() { return Some(( A::from_value(a.to_owned())?, B::from_value(b.to_owned())?, C::from_value(c.to_owned())?, D::from_value(d.to_owned())?, E::from_value(e.to_owned())?, F::from_value(f.to_owned())?, G::from_value(g.to_owned())? @@ -472,16 +637,16 @@ impl Serializable for (A, B, C, D, E, F, G, H) { fn to_value(&self) -> toml::Value { - toml::Value::Array(vec![ + toml::Value::Array(toml::Array::from_iter(vec![ self.0.to_value(), self.1.to_value(), self.2.to_value(), self.3.to_value(), self.4.to_value(), self.5.to_value(), self.6.to_value(), self.7.to_value() - ]) + ])) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::Array(arr) => { - if let [a, b, c, d, e, f, g, h] = arr.as_slice() { + if let [a, b, c, d, e, f, g, h] = arr.into_iter().collect::>().as_slice() { return Some(( A::from_value(a.to_owned())?, B::from_value(b.to_owned())?, C::from_value(c.to_owned())?, D::from_value(d.to_owned())?, E::from_value(e.to_owned())?, F::from_value(f.to_owned())?, G::from_value(g.to_owned())?, H::from_value(h.to_owned())? @@ -496,16 +661,16 @@ impl Serializable for (A, B, C, D, E, F, G, H, I) { fn to_value(&self) -> toml::Value { - toml::Value::Array(vec![ + toml::Value::Array(toml::Array::from_iter(vec![ self.0.to_value(), self.1.to_value(), self.2.to_value(), self.3.to_value(), self.4.to_value(), self.5.to_value(), self.6.to_value(), self.7.to_value(), self.8.to_value() - ]) + ])) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::Array(arr) => { - if let [a, b, c, d, e, f, g, h, i] = arr.as_slice() { + if let [a, b, c, d, e, f, g, h, i] = arr.into_iter().collect::>().as_slice() { return Some(( A::from_value(a.to_owned())?, B::from_value(b.to_owned())?, C::from_value(c.to_owned())?, D::from_value(d.to_owned())?, E::from_value(e.to_owned())?, F::from_value(f.to_owned())?, G::from_value(g.to_owned())?, H::from_value(h.to_owned())?, I::from_value(i.to_owned())? @@ -520,16 +685,16 @@ impl Serializable for (A, B, C, D, E, F, G, H, I, J) { fn to_value(&self) -> toml::Value { - toml::Value::Array(vec![ + toml::Value::Array(toml::Array::from_iter(vec![ self.0.to_value(), self.1.to_value(), self.2.to_value(), self.3.to_value(), self.4.to_value(), self.5.to_value(), self.6.to_value(), self.7.to_value(), self.8.to_value(), self.9.to_value() - ]) + ])) } fn from_value(value: toml::Value) -> Option where Self: Sized { match value { toml::Value::Array(arr) => { - if let [a, b, c, d, e, f, g, h, i, j] = arr.as_slice() { + if let [a, b, c, d, e, f, g, h, i, j] = arr.into_iter().collect::>().as_slice() { return Some(( A::from_value(a.to_owned())?, B::from_value(b.to_owned())?, C::from_value(c.to_owned())?, D::from_value(d.to_owned())?, E::from_value(e.to_owned())?, F::from_value(f.to_owned())?, G::from_value(g.to_owned())?, H::from_value(h.to_owned())?, I::from_value(i.to_owned())?, J::from_value(j.to_owned())? diff --git a/node_tree_core/tests/glam_integration.rs b/node_tree_core/tests/glam_integration.rs new file mode 100644 index 0000000..35ab768 --- /dev/null +++ b/node_tree_core/tests/glam_integration.rs @@ -0,0 +1,30 @@ +#![cfg(feature = "glam")] + +use std::path::Path; +use std::fs; + +use node_tree::prelude::*; +use glam::*; + + +class! { + dec Node3D; + + let direction: Vec3 = Vec3::ZERO; + let transform: DAffine3 = DAffine3::IDENTITY; +} + + +#[test] +fn test_glam() { + + // Create a scene and save it. + let scene: NodeScene = scene! { + Node3D + }; + scene.save(Path::new(""), "glam_integration").unwrap(); + + // Load the scene. + let scene_loaded: NodeScene = NodeScene::load(Path::new("glam_integration.scn")).unwrap(); + fs::remove_file(Path::new("glam_integration.scn")).unwrap(); +}