ferroui_base/rendering/composition/animations/
property_set_snapshot.rs1use crate::rendering::composition::expressions::{
2 ExpressionObjectKey, ExpressionVariant, IExpressionObject, IExpressionParameterCollection,
3};
4use crate::rendering::composition::server::{IAnimatedServerObject, ServerCompositor, ServerObjectId};
5use std::cell::OnceCell;
6use std::collections::HashMap;
7use std::rc::{Rc, Weak};
8
9pub struct PropertySetSnapshot {
16 dic: HashMap<String, PropertySetSnapshotValue>,
17}
18
19pub enum PropertySetSnapshotObject {
21 PropertySet(Rc<PropertySetSnapshot>),
23 Server(ServerObjectId, OnceCell<SnapshotServerObject>),
26}
27
28pub struct SnapshotServerObject(Weak<dyn IAnimatedServerObject>);
39
40impl SnapshotServerObject {
41 pub fn upgrade(&self) -> Option<Rc<dyn IAnimatedServerObject>> {
43 self.0.upgrade()
44 }
45
46 fn is_alive(&self) -> bool {
47 self.0.strong_count() > 0
48 }
49}
50
51impl IExpressionObject for SnapshotServerObject {
52 fn get_property(&self, name: &str) -> ExpressionVariant {
53 match self.0.upgrade() {
54 Some(object) => object.server_object().get_property(name),
55 None => ExpressionVariant::default(),
56 }
57 }
58
59 fn key(&self) -> ExpressionObjectKey {
60 ExpressionObjectKey(Weak::as_ptr(&self.0) as *const () as usize)
61 }
62}
63
64#[derive(Default)]
66pub struct PropertySetSnapshotValue {
67 pub variant: ExpressionVariant,
68 pub object: Option<PropertySetSnapshotObject>,
69}
70
71impl PropertySetSnapshotValue {
72 pub fn from_object(o: PropertySetSnapshotObject) -> Self {
74 Self { object: Some(o), variant: ExpressionVariant::default() }
75 }
76}
77
78impl From<ExpressionVariant> for PropertySetSnapshotValue {
79 fn from(v: ExpressionVariant) -> Self {
80 Self { variant: v, object: None }
81 }
82}
83
84impl PropertySetSnapshot {
85 pub fn new(dic: HashMap<String, PropertySetSnapshotValue>) -> Self {
86 Self { dic }
87 }
88
89 pub fn get_parameter(&self, name: &str) -> ExpressionVariant {
90 self.dic.get(name).map(|v| v.variant).unwrap_or_default()
91 }
92
93 pub fn get_object_parameter(&self, name: &str) -> Option<&dyn IExpressionObject> {
94 match self.dic.get(name)?.object.as_ref()? {
95 PropertySetSnapshotObject::PropertySet(snapshot) => Some(&**snapshot as &dyn IExpressionObject),
96 PropertySetSnapshotObject::Server(_, resolved) => {
97 resolved.get().filter(|o| o.is_alive()).map(|o| o as &dyn IExpressionObject)
98 }
99 }
100 }
101
102 pub fn get_server_object_parameter(&self, name: &str) -> Option<Rc<dyn IAnimatedServerObject>> {
105 match self.dic.get(name)?.object.as_ref()? {
106 PropertySetSnapshotObject::PropertySet(_) => None,
107 PropertySetSnapshotObject::Server(_, resolved) => resolved.get().and_then(SnapshotServerObject::upgrade),
108 }
109 }
110
111 pub fn get_property(&self, name: &str) -> ExpressionVariant {
112 self.get_parameter(name)
113 }
114
115 pub fn resolve(&self, compositor: &ServerCompositor) {
125 for value in self.dic.values() {
126 match &value.object {
127 Some(PropertySetSnapshotObject::PropertySet(snapshot)) => snapshot.resolve(compositor),
128 Some(PropertySetSnapshotObject::Server(id, resolved)) => {
129 if resolved.get().is_some() {
130 continue;
131 }
132 if let Some(object) = compositor.get_animated_object(*id) {
133 let _ = resolved.set(SnapshotServerObject(Rc::downgrade(&object)));
134 }
135 }
136 None => {}
137 }
138 }
139 }
140}
141
142impl IExpressionParameterCollection for PropertySetSnapshot {
143 fn get_parameter(&self, name: &str) -> ExpressionVariant {
144 PropertySetSnapshot::get_parameter(self, name)
145 }
146
147 fn get_object_parameter(&self, name: &str) -> Option<&dyn IExpressionObject> {
148 PropertySetSnapshot::get_object_parameter(self, name)
149 }
150}
151
152impl IExpressionObject for PropertySetSnapshot {
153 fn get_property(&self, name: &str) -> ExpressionVariant {
154 PropertySetSnapshot::get_property(self, name)
155 }
156}
157
158#[derive(Default)]
162pub struct PropertySetSnapshotSource {
163 dic: HashMap<String, PropertySetSnapshotSourceValue>,
164}
165
166pub enum PropertySetSnapshotSourceValue {
168 Variant(ExpressionVariant),
169 PropertySet(PropertySetSnapshotSource),
171 Server(ServerObjectId),
173}
174
175impl PropertySetSnapshotSource {
176 pub fn new(dic: HashMap<String, PropertySetSnapshotSourceValue>) -> Self {
177 Self { dic }
178 }
179
180 pub fn build(self) -> PropertySetSnapshot {
182 let dic = self
183 .dic
184 .into_iter()
185 .map(|(key, value)| {
186 let value = match value {
187 PropertySetSnapshotSourceValue::Variant(variant) => variant.into(),
188 PropertySetSnapshotSourceValue::PropertySet(source) => PropertySetSnapshotValue::from_object(
189 PropertySetSnapshotObject::PropertySet(Rc::new(source.build())),
190 ),
191 PropertySetSnapshotSourceValue::Server(server) => PropertySetSnapshotValue::from_object(
192 PropertySetSnapshotObject::Server(server, OnceCell::new()),
193 ),
194 };
195 (key, value)
196 })
197 .collect();
198 PropertySetSnapshot::new(dic)
199 }
200}