1use crate::{
24 core::{pool::Handle, reflect::prelude::*, visitor::prelude::*},
25 machine::{Parameter, ParameterContainer, State},
26 Animation, AnimationContainer, EntityId,
27};
28use fyrox_core::uuid::{uuid, Uuid};
29use fyrox_core::{NameProvider, TypeUuidProvider};
30use std::any::{type_name, Any, TypeId};
31use strum_macros::{AsRefStr, EnumString, VariantNames};
32
33macro_rules! define_two_args_node {
34 ($(#[$meta:meta])* $name:ident) => {
35 $(#[$meta])*
36 #[derive(Debug, Clone, PartialEq)]
37 pub struct $name <T:EntityId> {
38 pub lhs: Box<LogicNode<T>>,
40 pub rhs: Box<LogicNode<T>>,
42 }
43
44 impl<T:EntityId> Default for $name<T> {
45 fn default() -> Self {
46 Self {
47 lhs: Box::new(LogicNode::Parameter(Default::default())),
48 rhs: Box::new(LogicNode::Parameter(Default::default())),
49 }
50 }
51 }
52
53 impl<T:EntityId> Visit for $name<T> {
54 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
55 let mut guard = visitor.enter_region(name)?;
56
57 self.lhs.visit("Lhs", &mut guard)?;
58 self.rhs.visit("Rhs", &mut guard)?;
59
60 Ok(())
61 }
62 }
63
64 impl<T:EntityId> Reflect for $name<T> {
65 fn source_path() -> &'static str {
66 file!()
67 }
68
69 fn type_name(&self) -> &'static str {
70 type_name::<Self>()
71 }
72
73 fn doc(&self) -> &'static str {
74 ""
75 }
76
77 fn assembly_name(&self) -> &'static str {
78 env!("CARGO_PKG_NAME")
79 }
80
81 fn type_assembly_name() -> &'static str {
82 env!("CARGO_PKG_NAME")
83 }
84
85 fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
86 func(&[
87 FieldInfo {
88 owner_type_id: TypeId::of::<Self>(),
89 name: "Lhs",
90 display_name: "Lhs",
91 description: "",
92 tag: "",
93 type_name: type_name::<Self>(),
94 value: &*self.lhs,
95 reflect_value: &*self.lhs,
96 read_only: false,
97 immutable_collection: false,
98 min_value: None,
99 max_value: None,
100 step: None,
101 precision: None,
102 doc: "",
103 },
104 FieldInfo {
105 owner_type_id: TypeId::of::<Self>(),
106 name: "Rhs",
107 display_name: "Rhs",
108 description: "",
109 tag: "",
110 type_name: type_name::<Self>(),
111 value: &*self.rhs,
112 reflect_value: &*self.rhs,
113 read_only: false,
114 immutable_collection: false,
115 min_value: None,
116 max_value: None,
117 step: None,
118 precision: None,doc: "",
119 },
120 ])
121 }
122
123 fn into_any(self: Box<Self>) -> Box<dyn Any> {
124 self
125 }
126
127 fn as_any(&self, func: &mut dyn FnMut(&dyn ::core::any::Any)) {
128 func(self)
129 }
130
131 fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn ::core::any::Any)) {
132 func(self)
133 }
134
135 fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect)) {
136 func(self)
137 }
138
139 fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect)) {
140 func(self)
141 }
142
143 fn set(
144 &mut self,
145 value: Box<dyn Reflect>,
146 ) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
147 let this = std::mem::replace(self, value.take()?);
148 Ok(Box::new(this))
149 }
150
151 fn fields(&self, func: &mut dyn FnMut(&[&dyn Reflect])) {
152 func(&[&self.lhs, &self.rhs])
153 }
154
155 fn fields_mut(&mut self, func: &mut dyn FnMut(&mut [&mut dyn Reflect])) {
156 func(&mut [&mut self.lhs, &mut self.rhs])
157 }
158
159 fn field(&self, name: &str, func: &mut dyn FnMut(Option<&dyn Reflect>)) {
160 func(match name {
161 "Lhs" => Some(&self.lhs),
162 "Rhs" => Some(&self.rhs),
163 _ => None,
164 })
165 }
166
167 fn field_mut(
168 &mut self,
169 name: &str,
170 func: &mut dyn FnMut(Option<&mut dyn Reflect>),
171 ) {
172 func(match name {
173 "Lhs" => Some(&mut self.lhs),
174 "Rhs" => Some(&mut self.rhs),
175 _ => None,
176 })
177 }
178 }
179 };
180}
181
182define_two_args_node!(
183 AndNode
185);
186define_two_args_node!(
187 OrNode
189);
190define_two_args_node!(
191 XorNode
193);
194
195#[derive(Debug, Clone, PartialEq)]
197pub struct NotNode<T: EntityId> {
198 pub lhs: Box<LogicNode<T>>,
200}
201
202impl<T: EntityId> Default for NotNode<T> {
203 fn default() -> Self {
204 Self {
205 lhs: Box::new(LogicNode::Parameter(Default::default())),
206 }
207 }
208}
209
210impl<T: EntityId> Visit for NotNode<T> {
211 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
212 let mut guard = visitor.enter_region(name)?;
213
214 self.lhs.visit("Lhs", &mut guard)?;
215
216 Ok(())
217 }
218}
219
220impl<T: EntityId> Reflect for NotNode<T> {
221 fn source_path() -> &'static str {
222 file!()
223 }
224
225 fn type_name(&self) -> &'static str {
226 type_name::<Self>()
227 }
228
229 fn doc(&self) -> &'static str {
230 ""
231 }
232
233 fn assembly_name(&self) -> &'static str {
234 env!("CARGO_PKG_NAME")
235 }
236
237 fn type_assembly_name() -> &'static str {
238 env!("CARGO_PKG_NAME")
239 }
240
241 fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
242 func(&[FieldInfo {
243 owner_type_id: TypeId::of::<Self>(),
244 name: "Lhs",
245 display_name: "Lhs",
246 description: "",
247 tag: "",
248 type_name: type_name::<Self>(),
249 value: &*self.lhs,
250 reflect_value: &*self.lhs,
251 read_only: false,
252 immutable_collection: false,
253 min_value: None,
254 max_value: None,
255 step: None,
256 precision: None,
257 doc: "",
258 }])
259 }
260
261 fn into_any(self: Box<Self>) -> Box<dyn Any> {
262 self
263 }
264
265 fn as_any(&self, func: &mut dyn FnMut(&dyn ::core::any::Any)) {
266 func(self)
267 }
268
269 fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn ::core::any::Any)) {
270 func(self)
271 }
272
273 fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect)) {
274 func(self)
275 }
276
277 fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect)) {
278 func(self)
279 }
280
281 fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
282 let this = std::mem::replace(self, value.take()?);
283 Ok(Box::new(this))
284 }
285
286 fn fields(&self, func: &mut dyn FnMut(&[&dyn Reflect])) {
287 func(&[&self.lhs])
288 }
289
290 fn fields_mut(&mut self, func: &mut dyn FnMut(&mut [&mut dyn Reflect])) {
291 func(&mut [&mut self.lhs])
292 }
293
294 fn field(&self, name: &str, func: &mut dyn FnMut(Option<&dyn Reflect>)) {
295 func(match name {
296 "Lhs" => Some(&self.lhs),
297 _ => None,
298 })
299 }
300
301 fn field_mut(&mut self, name: &str, func: &mut dyn FnMut(Option<&mut dyn Reflect>)) {
302 func(match name {
303 "Lhs" => Some(&mut self.lhs),
304 _ => None,
305 })
306 }
307}
308
309#[derive(Debug, Visit, Clone, Reflect, PartialEq, AsRefStr, EnumString, VariantNames)]
336pub enum LogicNode<T: EntityId> {
337 Parameter(String),
339 And(AndNode<T>),
341 Or(OrNode<T>),
343 Xor(XorNode<T>),
345 Not(NotNode<T>),
347 IsAnimationEnded(Handle<Animation<T>>),
349}
350
351impl<T: EntityId> TypeUuidProvider for LogicNode<T> {
352 fn type_uuid() -> Uuid {
353 uuid!("98a5b767-5560-4ed7-ad40-1625a8868e39")
354 }
355}
356
357impl<T: EntityId> Default for LogicNode<T> {
358 fn default() -> Self {
359 Self::Parameter(Default::default())
360 }
361}
362
363impl<T: EntityId> LogicNode<T> {
364 pub fn calculate_value(
366 &self,
367 parameters: &ParameterContainer,
368 animations: &AnimationContainer<T>,
369 ) -> bool {
370 match self {
371 LogicNode::Parameter(rule_name) => parameters.get(rule_name).is_some_and(|p| {
372 if let Parameter::Rule(rule_value) = p {
373 *rule_value
374 } else {
375 false
376 }
377 }),
378 LogicNode::And(and) => {
379 let lhs_value = and.lhs.calculate_value(parameters, animations);
380 let rhs_value = and.rhs.calculate_value(parameters, animations);
381 lhs_value & rhs_value
382 }
383 LogicNode::Or(or) => {
384 let lhs_value = or.lhs.calculate_value(parameters, animations);
385 let rhs_value = or.rhs.calculate_value(parameters, animations);
386 lhs_value | rhs_value
387 }
388 LogicNode::Xor(or) => {
389 let lhs_value = or.lhs.calculate_value(parameters, animations);
390 let rhs_value = or.rhs.calculate_value(parameters, animations);
391 lhs_value ^ rhs_value
392 }
393 LogicNode::Not(node) => !node.lhs.calculate_value(parameters, animations),
394 LogicNode::IsAnimationEnded(animation) => animations
395 .try_get(*animation)
396 .map_or(true, |a| a.has_ended()),
397 }
398 }
399}
400
401#[derive(Default, Debug, Clone, Reflect, PartialEq)]
403pub struct Transition<T: EntityId> {
404 #[reflect(description = "The name of the transition, it is used for debug output.")]
406 pub(crate) name: String,
407
408 #[reflect(description = "Total amount of time (in seconds) to transition \
410 from source to destination state")]
411 pub(crate) transition_time: f32,
412
413 pub(crate) elapsed_time: f32,
414
415 #[reflect(read_only)]
416 pub(crate) source: Handle<State<T>>,
417
418 #[reflect(read_only)]
419 pub(crate) dest: Handle<State<T>>,
420
421 #[reflect(
422 description = "Computational graph that can use any amount of Rule parameters to calculate transition value."
423 )]
424 pub(crate) condition: LogicNode<T>,
425
426 pub(crate) blend_factor: f32,
428}
429
430impl<T: EntityId> Visit for Transition<T> {
431 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
432 let mut guard = visitor.enter_region(name)?;
433
434 self.name.visit("Name", &mut guard)?;
435 self.transition_time.visit("TransitionTime", &mut guard)?;
436 self.source.visit("Source", &mut guard)?;
437 self.dest.visit("Dest", &mut guard)?;
438 self.blend_factor.visit("BlendFactor", &mut guard)?;
439
440 if guard.is_reading() {
441 if self.condition.visit("Condition", &mut guard).is_err() {
442 let mut invert_rule = false;
444 let mut rule: String = Default::default();
445
446 invert_rule.visit("InvertRule", &mut guard)?;
447 rule.visit("Rule", &mut guard)?;
448
449 if invert_rule {
450 self.condition = LogicNode::Not(NotNode {
451 lhs: Box::new(LogicNode::Parameter(rule)),
452 });
453 } else {
454 self.condition = LogicNode::Parameter(rule);
455 }
456 }
457 } else {
458 self.condition.visit("Condition", &mut guard)?;
459 }
460
461 Ok(())
462 }
463}
464
465impl<T: EntityId> NameProvider for Transition<T> {
466 fn name(&self) -> &str {
467 &self.name
468 }
469}
470
471impl<T: EntityId> Transition<T> {
472 pub fn new(
475 name: &str,
476 src: Handle<State<T>>,
477 dest: Handle<State<T>>,
478 time: f32,
479 rule: &str,
480 ) -> Transition<T> {
481 Self {
482 name: name.to_owned(),
483 transition_time: time,
484 elapsed_time: 0.0,
485 source: src,
486 dest,
487 blend_factor: 0.0,
488 condition: LogicNode::Parameter(rule.to_owned()),
489 }
490 }
491
492 #[inline]
494 pub fn name(&self) -> &str {
495 self.name.as_str()
496 }
497
498 #[inline]
500 pub fn transition_time(&self) -> f32 {
501 self.transition_time
502 }
503
504 #[inline]
506 pub fn source(&self) -> Handle<State<T>> {
507 self.source
508 }
509
510 #[inline]
512 pub fn dest(&self) -> Handle<State<T>> {
513 self.dest
514 }
515
516 pub fn set_condition(&mut self, condition: LogicNode<T>) {
518 self.condition = condition;
519 }
520
521 pub fn condition(&self) -> &LogicNode<T> {
523 &self.condition
524 }
525
526 #[inline]
528 pub fn is_done(&self) -> bool {
529 (self.transition_time - self.elapsed_time).abs() <= f32::EPSILON
530 }
531
532 #[inline]
534 pub fn blend_factor(&self) -> f32 {
535 self.blend_factor
536 }
537
538 pub(super) fn reset(&mut self) {
539 self.elapsed_time = 0.0;
540 self.blend_factor = 0.0;
541 }
542
543 pub(super) fn update(&mut self, dt: f32) {
544 self.elapsed_time += dt;
545 if self.elapsed_time > self.transition_time {
546 self.elapsed_time = self.transition_time;
547 }
548 self.blend_factor = self.elapsed_time / self.transition_time;
549 }
550}