fyrox_graph/constructor.rs
1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use fxhash::FxHashMap;
22use fyrox_core::pool::Handle;
23use fyrox_core::{
24 parking_lot::{Mutex, MutexGuard},
25 reflect::prelude::*,
26 SafeLock, TypeUuidProvider, Uuid,
27};
28use std::sync::Arc;
29
30pub trait ConstructorProvider<T, Ctx>: TypeUuidProvider + Default + Reflect {
31 fn constructor() -> GraphNodeConstructor<T, Ctx>;
32}
33
34pub enum VariantResult<Node> {
35 Owned(Node),
36 Handle(Handle<Node>),
37}
38
39impl<Node> From<Node> for VariantResult<Node> {
40 fn from(node: Node) -> Self {
41 VariantResult::Owned(node)
42 }
43}
44
45impl<Node> From<Handle<Node>> for VariantResult<Node> {
46 fn from(value: Handle<Node>) -> Self {
47 VariantResult::Handle(value)
48 }
49}
50
51/// Shared closure that creates a node of some type.
52pub type Constructor<Node> = Arc<dyn Fn() -> Node + Send + Sync>;
53
54pub type VariantConstructor<Node, Ctx> = Arc<dyn Fn(&mut Ctx) -> VariantResult<Node> + Send + Sync>;
55
56/// Constructor variant.
57pub struct Variant<Node, Ctx> {
58 /// Name of the variant.
59 pub name: String,
60 /// Boxed type constructor.
61 pub constructor: VariantConstructor<Node, Ctx>,
62}
63
64/// Node constructor creates scene nodes in various states.
65pub struct GraphNodeConstructor<Node, Ctx> {
66 /// A boxed type constructor that returns a node in default state. This constructor is used at
67 /// deserialization stage.
68 pub default: Constructor<Node>,
69
70 /// A set of node constructors that returns specific variants of the same node type. Could be
71 /// used to pre-define specific variations of nodes, for example a `Mesh` node could have
72 /// different surfaces (sphere, cube, cone, etc.). It is used by the editor, this collection must
73 /// have at least one item to be shown in the editor.
74 pub variants: Vec<Variant<Node, Ctx>>,
75
76 /// Name of the group the type belongs to.
77 pub group: &'static str,
78
79 /// A name of the assembly this node constructor is from.
80 pub assembly_name: &'static str,
81}
82
83impl<Node, Ctx> GraphNodeConstructor<Node, Ctx> {
84 /// Creates a new node constructor with default values for the given scene node type. This method
85 /// automatically creates default constructor, but leaves potential variants empty (nothing will
86 /// be shown in the editor, use [`Self::with_variant`] to add potential variant of the constructor).
87 pub fn new<Inner>() -> Self
88 where
89 Node: From<Inner>,
90 Inner: ConstructorProvider<Node, Ctx>,
91 {
92 Self {
93 default: Arc::new(|| Node::from(Inner::default())),
94 variants: vec![],
95 group: "",
96 assembly_name: Inner::type_assembly_name(),
97 }
98 }
99
100 /// Sets a desired group for the constructor.
101 pub fn with_group(mut self, group: &'static str) -> Self {
102 self.group = group;
103 self
104 }
105
106 /// Adds a new constructor variant.
107 pub fn with_variant<F>(mut self, name: impl AsRef<str>, variant: F) -> Self
108 where
109 F: Fn(&mut Ctx) -> VariantResult<Node> + Send + Sync + 'static,
110 {
111 self.variants.push(Variant {
112 name: name.as_ref().to_string(),
113 constructor: Arc::new(variant),
114 });
115 self
116 }
117}
118
119/// A special container that is able to create nodes by their type UUID.
120pub struct GraphNodeConstructorContainer<Node, Ctx> {
121 map: Mutex<FxHashMap<Uuid, GraphNodeConstructor<Node, Ctx>>>,
122}
123
124impl<Node, Ctx> Default for GraphNodeConstructorContainer<Node, Ctx> {
125 fn default() -> Self {
126 Self {
127 map: Default::default(),
128 }
129 }
130}
131
132impl<Node, Ctx> GraphNodeConstructorContainer<Node, Ctx> {
133 /// Adds new type constructor for a given type and return previous constructor for the type
134 /// (if any).
135 pub fn add<Inner>(&self)
136 where
137 Inner: ConstructorProvider<Node, Ctx>,
138 {
139 let previous = self
140 .map
141 .safe_lock()
142 .insert(Inner::type_uuid(), Inner::constructor());
143 assert!(previous.is_none());
144 }
145
146 /// Adds custom type constructor.
147 pub fn add_custom(&self, type_uuid: Uuid, constructor: GraphNodeConstructor<Node, Ctx>) {
148 self.map.safe_lock().insert(type_uuid, constructor);
149 }
150
151 /// Unregisters type constructor.
152 pub fn remove(&self, type_uuid: Uuid) {
153 self.map.safe_lock().remove(&type_uuid);
154 }
155
156 /// Makes an attempt to create a node using provided type UUID. It may fail if there is no
157 /// node constructor for specified type UUID.
158 pub fn try_create(&self, type_uuid: &Uuid) -> Option<Node> {
159 self.map
160 .safe_lock()
161 .get_mut(type_uuid)
162 .map(|c| (c.default)())
163 }
164
165 /// Returns total amount of constructors.
166 pub fn len(&self) -> usize {
167 self.map.safe_lock().len()
168 }
169
170 /// Returns true if the container is empty.
171 pub fn is_empty(&self) -> bool {
172 self.len() == 0
173 }
174
175 /// Returns the inner map of the node constructors.
176 pub fn map(&self) -> MutexGuard<'_, FxHashMap<Uuid, GraphNodeConstructor<Node, Ctx>>> {
177 self.map.safe_lock()
178 }
179}