ferroui_base/rendering/composition/generated/
composition_visual_surface.rs1use bitflags::bitflags;
8use crate::Vector;
9use crate::rendering::composition::ICompositionObject;
10use crate::rendering::composition::ICompositionObjectHost;
11use crate::rendering::composition::animations::AnimationInstanceFactory;
12use crate::rendering::composition::animations::ICompositionAnimation;
13use crate::rendering::composition::expressions::ExpressionVariant;
14use crate::rendering::composition::server::AsServerRenderResource;
15use crate::rendering::composition::server::CompositionProperty;
16use crate::rendering::composition::server::CompositionPropertyOf;
17use crate::rendering::composition::server::IServerAnimatedPropertyHost;
18use crate::rendering::composition::server::IServerObject;
19use crate::rendering::composition::server::ServerPropertyValue;
20use crate::rendering::composition::server::ServerValueChange;
21use crate::rendering::composition::server::props_of;
22use crate::rendering::composition::server::read_server_object;
23use crate::rendering::composition::transport::BatchStreamReader;
24use crate::rendering::composition::transport::BatchStreamWriter;
25use crate::rendering::composition::transport::BatchValue;
26use crate::rendering::composition::transport::BatchValueReader;
27use std::any::Any;
28use std::any::TypeId;
29use std::cell::Cell;
30use std::cell::RefCell;
31use std::rc::Rc;
32use std::sync::OnceLock;
33use std::time::Duration;
34
35bitflags! {
36 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
38 pub struct CompositionVisualSurfaceChangedFields: u8 {
39 const SOURCE_VISUAL = 1;
40 const SOURCE_OFFSET = 2;
41 const SOURCE_OFFSET_ANIMATED = 4;
42 const SOURCE_SIZE = 8;
43 const SOURCE_SIZE_ANIMATED = 16;
44 }
45}
46
47impl BatchValue for CompositionVisualSurfaceChangedFields {
48 #[inline]
49 fn write_to(&self, out: &mut Vec<u8>) {
50 self.bits().write_to(out);
51 }
52
53 #[inline]
54 fn read_from(input: &mut BatchValueReader<'_>) -> Self {
55 CompositionVisualSurfaceChangedFields::from_bits_retain(u8::read_from(input))
56 }
57}
58
59pub trait CompositionVisualSurfaceHooks: ICompositionObjectHost {
62 fn initialize_defaults_extra(&self) {}
63
64 fn validate_source_visual_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
65 fn on_source_visual_changed(&self) {}
66 fn on_source_visual_changing(&self) {}
67
68 fn validate_source_offset_change(&self, _old_value: Vector, _new_value: Vector) {}
69 fn on_source_offset_changed(&self) {}
70 fn on_source_offset_changing(&self) {}
71
72 fn validate_source_size_change(&self, _old_value: Vector, _new_value: Vector) {}
73 fn on_source_size_changed(&self) {}
74 fn on_source_size_changing(&self) {}
75}
76
77pub struct CompositionVisualSurfaceProps {
79 changed_fields_of_composition_visual_surface: Cell<CompositionVisualSurfaceChangedFields>,
80 source_visual: RefCell<Option<Rc<dyn ICompositionObject>>>,
81 source_offset: Cell<Vector>,
82 source_size: Cell<Vector>,
83}
84
85impl Default for CompositionVisualSurfaceProps {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91impl CompositionVisualSurfaceProps {
92 pub fn new() -> Self {
96 Self {
97 changed_fields_of_composition_visual_surface: Cell::new(CompositionVisualSurfaceChangedFields::empty()),
98 source_visual: RefCell::new(None),
99 source_offset: Cell::new(Default::default()),
100 source_size: Cell::new(Default::default()),
101 }
102 }
103
104 pub fn initialize_defaults(&self, host: &dyn CompositionVisualSurfaceHooks) {
107 self.initialize_own_defaults(host);
108 }
109
110 pub fn initialize_own_defaults(&self, host: &dyn CompositionVisualSurfaceHooks) {
112 CompositionVisualSurfaceHooks::initialize_defaults_extra(host);
113 }
114
115 pub fn source_visual(&self) -> Option<Rc<dyn ICompositionObject>> {
117 self.source_visual.borrow().clone()
118 }
119
120 pub fn set_source_visual(&self, host: &dyn CompositionVisualSurfaceHooks, value: Option<Rc<dyn ICompositionObject>>) {
122 let mut changed = false;
123 let old_value = self.source_visual.borrow().clone();
124 if old_value.differs(&value) {
125 CompositionVisualSurfaceHooks::validate_source_visual_change(host, &old_value, &value);
126 CompositionVisualSurfaceHooks::on_source_visual_changing(host);
127 changed = true;
128 *self.source_visual.borrow_mut() = value.clone();
130 self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_VISUAL);
132 host.register_for_serialization();
133 }
134 *self.source_visual.borrow_mut() = value;
135 if changed {
136 CompositionVisualSurfaceHooks::on_source_visual_changed(host);
137 }
138 }
139
140 pub fn source_offset(&self) -> Vector {
142 self.source_offset.get()
143 }
144
145 pub fn set_source_offset(&self, host: &dyn CompositionVisualSurfaceHooks, value: Vector) {
147 let mut changed = false;
148 let old_value = self.source_offset.get();
149 if old_value.differs(&value) {
150 CompositionVisualSurfaceHooks::validate_source_offset_change(host, old_value, value);
151 CompositionVisualSurfaceHooks::on_source_offset_changing(host);
152 changed = true;
153 self.source_offset.set(value);
155 self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_OFFSET);
157 host.register_for_serialization();
158 host.pending_animations().remove(ServerCompositionVisualSurfaceProps::id_of_source_offset_property().base());
160 self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() & !CompositionVisualSurfaceChangedFields::SOURCE_OFFSET_ANIMATED);
161 if let Some(animation) = host.implicit_animation("SourceOffset") {
163 if let Some(a) = animation.as_composition_animation() {
165 self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_OFFSET_ANIMATED);
166 host.pending_animations().set(
167 ServerCompositionVisualSurfaceProps::id_of_source_offset_property().base(),
168 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
169 );
170 }
171 host.start_animation_group(&animation, "SourceOffset", ExpressionVariant::create(value));
173 }
174 }
175 self.source_offset.set(value);
176 if changed {
177 CompositionVisualSurfaceHooks::on_source_offset_changed(host);
178 }
179 }
180
181 pub fn source_size(&self) -> Vector {
183 self.source_size.get()
184 }
185
186 pub fn set_source_size(&self, host: &dyn CompositionVisualSurfaceHooks, value: Vector) {
188 let mut changed = false;
189 let old_value = self.source_size.get();
190 if old_value.differs(&value) {
191 CompositionVisualSurfaceHooks::validate_source_size_change(host, old_value, value);
192 CompositionVisualSurfaceHooks::on_source_size_changing(host);
193 changed = true;
194 self.source_size.set(value);
196 self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_SIZE);
198 host.register_for_serialization();
199 host.pending_animations().remove(ServerCompositionVisualSurfaceProps::id_of_source_size_property().base());
201 self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() & !CompositionVisualSurfaceChangedFields::SOURCE_SIZE_ANIMATED);
202 if let Some(animation) = host.implicit_animation("SourceSize") {
204 if let Some(a) = animation.as_composition_animation() {
206 self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_SIZE_ANIMATED);
207 host.pending_animations().set(
208 ServerCompositionVisualSurfaceProps::id_of_source_size_property().base(),
209 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
210 );
211 }
212 host.start_animation_group(&animation, "SourceSize", ExpressionVariant::create(value));
214 }
215 }
216 self.source_size.set(value);
217 if changed {
218 CompositionVisualSurfaceHooks::on_source_size_changed(host);
219 }
220 }
221
222 pub fn start_animation(
226 &self,
227 host: &dyn CompositionVisualSurfaceHooks,
228 property_name: &str,
229 animation: &dyn ICompositionAnimation,
230 final_value: Option<ExpressionVariant>,
231 ) -> bool {
232 if property_name == "SourceOffset" {
233 let server = animation.create_instance(host.server(), final_value);
234 host.pending_animations().set(ServerCompositionVisualSurfaceProps::id_of_source_offset_property().base(), server);
235 self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_OFFSET_ANIMATED);
236 host.register_for_serialization();
237 return true;
238 }
239 if property_name == "SourceSize" {
240 let server = animation.create_instance(host.server(), final_value);
241 host.pending_animations().set(ServerCompositionVisualSurfaceProps::id_of_source_size_property().base(), server);
242 self.changed_fields_of_composition_visual_surface.set(self.changed_fields_of_composition_visual_surface.get() | CompositionVisualSurfaceChangedFields::SOURCE_SIZE_ANIMATED);
243 host.register_for_serialization();
244 return true;
245 }
246 false
247 }
248
249 pub fn serialize_changes_core(&self, host: &dyn CompositionVisualSurfaceHooks, writer: &mut BatchStreamWriter<'_>) {
252 let changed = self.changed_fields_of_composition_visual_surface.get();
253 writer.write(changed);
254 if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_VISUAL) {
255 writer.write_server_object(self.source_visual.borrow().clone().map(|o| o.server()));
256 }
257 if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_OFFSET_ANIMATED) {
258 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualSurfaceProps::id_of_source_offset_property().base()));
259 } else if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_OFFSET) {
260 writer.write(self.source_offset.get());
261 }
262 if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_SIZE_ANIMATED) {
263 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualSurfaceProps::id_of_source_size_property().base()));
264 } else if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_SIZE) {
265 writer.write(self.source_size.get());
266 }
267 self.changed_fields_of_composition_visual_surface.set(CompositionVisualSurfaceChangedFields::empty());
268 }
269}
270
271pub trait ServerCompositionVisualSurfaceHooks: IServerAnimatedPropertyHost {
274 fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
275 fn on_fields_deserialized(&self, _changed: CompositionVisualSurfaceChangedFields) {}
276
277 fn on_source_visual_changed(&self) {}
278 fn on_source_visual_changing(&self) {}
279}
280
281pub struct ServerCompositionVisualSurfaceProps {
283 source_visual: RefCell<Option<Rc<dyn IServerObject>>>,
284 source_offset: Cell<Vector>,
285 source_size: Cell<Vector>,
286}
287
288impl Default for ServerCompositionVisualSurfaceProps {
289 fn default() -> Self {
290 Self::new()
291 }
292}
293
294impl ServerCompositionVisualSurfaceProps {
295 pub fn new() -> Self {
298 Self {
299 source_visual: RefCell::new(None),
300 source_offset: Cell::new(Default::default()),
301 source_size: Cell::new(Default::default()),
302 }
303 }
304
305 pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
308 if type_id == TypeId::of::<Self>() {
309 return Some(self);
310 }
311 None
312 }
313
314 pub fn id_of_source_visual_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
316 static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
317 PROPERTY.get_or_init(|| {
318 CompositionProperty::register::<ServerCompositionVisualSurfaceProps, Option<Rc<dyn IServerObject>>>(
319 "SourceVisual",
320 "ServerCompositionVisualSurface",
321 |obj| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_visual.borrow().clone(),
322 |obj, v| *props_of::<ServerCompositionVisualSurfaceProps>(obj).source_visual.borrow_mut() = v,
323 None,
324 None,
325 )
326 })
327 }
328
329 pub fn source_visual(&self) -> Option<Rc<dyn IServerObject>> {
331 self.source_visual.borrow().clone()
332 }
333
334 pub fn set_source_visual(&self, host: &dyn ServerCompositionVisualSurfaceHooks, value: Option<Rc<dyn IServerObject>>) {
335 let old_value = self.source_visual.borrow().clone();
336 let mut changed = false;
337 if old_value.differs(&value) {
338 ServerCompositionVisualSurfaceHooks::on_source_visual_changing(host);
339 changed = true;
340 }
341 host.set_value(
342 Self::id_of_source_visual_property().base(),
343 ServerValueChange {
344 equal: old_value.default_equals(&value),
345 old_resource: old_value.as_server_render_resource(),
346 new_resource: value.as_server_render_resource(),
347 assign: &mut || *self.source_visual.borrow_mut() = value.clone(),
348 },
349 );
350 if changed {
351 ServerCompositionVisualSurfaceHooks::on_source_visual_changed(host);
352 }
353 }
354
355 pub fn id_of_source_offset_property() -> &'static CompositionPropertyOf<Vector> {
357 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
358 PROPERTY.get_or_init(|| {
359 CompositionProperty::register::<ServerCompositionVisualSurfaceProps, Vector>(
360 "SourceOffset",
361 "ServerCompositionVisualSurface",
362 |obj| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_offset.get(),
363 |obj, v| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_offset.set(v),
364 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualSurfaceProps>(obj).source_offset.get())),
365 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_offset.set(v.cast_or_default::<Vector>())),
366 )
367 })
368 }
369
370 pub fn source_offset(&self) -> Vector {
372 self.source_offset.get()
373 }
374
375 pub fn set_source_offset(&self, host: &dyn ServerCompositionVisualSurfaceHooks, value: Vector) {
376 self.source_offset.set(value);
377 host.remove_animation_for_property(Self::id_of_source_offset_property().base());
378 }
379
380 pub fn id_of_source_size_property() -> &'static CompositionPropertyOf<Vector> {
382 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
383 PROPERTY.get_or_init(|| {
384 CompositionProperty::register::<ServerCompositionVisualSurfaceProps, Vector>(
385 "SourceSize",
386 "ServerCompositionVisualSurface",
387 |obj| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_size.get(),
388 |obj, v| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_size.set(v),
389 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualSurfaceProps>(obj).source_size.get())),
390 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualSurfaceProps>(obj).source_size.set(v.cast_or_default::<Vector>())),
391 )
392 })
393 }
394
395 pub fn source_size(&self) -> Vector {
397 self.source_size.get()
398 }
399
400 pub fn set_source_size(&self, host: &dyn ServerCompositionVisualSurfaceHooks, value: Vector) {
401 self.source_size.set(value);
402 host.remove_animation_for_property(Self::id_of_source_size_property().base());
403 }
404
405 pub fn deserialize_changes_core(
408 &self,
409 host: &dyn ServerCompositionVisualSurfaceHooks,
410 reader: &mut BatchStreamReader<'_>,
411 committed_at: Duration,
412 ) {
413 let compositor = host.server_compositor();
414 ServerCompositionVisualSurfaceHooks::deserialize_changes_extra(host, reader);
415 let changed = reader.read::<CompositionVisualSurfaceChangedFields>();
416 if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_VISUAL) {
417 let value = read_server_object(reader, compositor.as_ref());
418 self.set_source_visual(host, value);
419 }
420 if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_OFFSET_ANIMATED) {
421 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
422 panic!("a batch starts an animation of `SourceOffset` without an animation instance");
423 };
424 host.set_animated_value(
425 Self::id_of_source_offset_property().base(),
426 ExpressionVariant::create(self.source_offset.get()),
427 committed_at,
428 animation,
429 );
430 } else if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_OFFSET) {
431 let value = reader.read::<Vector>();
432 self.set_source_offset(host, value);
433 }
434 if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_SIZE_ANIMATED) {
435 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
436 panic!("a batch starts an animation of `SourceSize` without an animation instance");
437 };
438 host.set_animated_value(
439 Self::id_of_source_size_property().base(),
440 ExpressionVariant::create(self.source_size.get()),
441 committed_at,
442 animation,
443 );
444 } else if changed.contains(CompositionVisualSurfaceChangedFields::SOURCE_SIZE) {
445 let value = reader.read::<Vector>();
446 self.set_source_size(host, value);
447 }
448 ServerCompositionVisualSurfaceHooks::on_fields_deserialized(host, changed);
449 }
450
451 pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
454 if name == "SourceOffset" {
455 return Some(Self::id_of_source_offset_property().base());
456 }
457 if name == "SourceSize" {
458 return Some(Self::id_of_source_size_property().base());
459 }
460 None
461 }
462}