Skip to main content

ferroui_base/rendering/composition/generated/
composition_visual.rs

1// @generated by scripts/generate_composition.py — do not edit
2
3//! `CompositionVisual`.
4//!
5//! Properties added by the FerroUI overlay (scripts/composition-schema-winui.xml): `CompositionClip`, `RotationAxis`, `RelativeOffsetAdjustment`, `RelativeSizeAdjustment`, `IsHitTestVisible`, `IsPixelSnappingEnabled`, `BorderMode`, `BackfaceVisibility`, `CompositeMode`, `ParentForTransform`.
6//!
7//! Schema attributes: abstract.
8
9use bitflags::bitflags;
10use crate::Matrix;
11use crate::Vector;
12use crate::Vector3D;
13use crate::media::IBrush;
14use crate::media::IImmutableEffect;
15use crate::media::RenderOptions;
16use crate::media::TextOptions;
17use crate::numerics::Quaternion;
18use crate::platform::IGeometryImpl;
19use crate::rendering::composition::CompositionBackfaceVisibility;
20use crate::rendering::composition::CompositionBorderMode;
21use crate::rendering::composition::CompositionCompositeMode;
22use crate::rendering::composition::ICompositionObject;
23use crate::rendering::composition::ICompositionObjectHost;
24use crate::rendering::composition::animations::AnimationInstanceFactory;
25use crate::rendering::composition::animations::ICompositionAnimation;
26use crate::rendering::composition::expressions::ExpressionVariant;
27use crate::rendering::composition::server::AsServerRenderResource;
28use crate::rendering::composition::server::CompositionProperty;
29use crate::rendering::composition::server::CompositionPropertyOf;
30use crate::rendering::composition::server::IServerAnimatedPropertyHost;
31use crate::rendering::composition::server::IServerObject;
32use crate::rendering::composition::server::ServerPropertyValue;
33use crate::rendering::composition::server::ServerResourceRef;
34use crate::rendering::composition::server::ServerValueChange;
35use crate::rendering::composition::server::props_of;
36use crate::rendering::composition::server::read_resource;
37use crate::rendering::composition::server::read_server_object;
38use crate::rendering::composition::transport::BatchResource;
39use crate::rendering::composition::transport::BatchStreamReader;
40use crate::rendering::composition::transport::BatchStreamWriter;
41use crate::rendering::composition::transport::BatchValue;
42use crate::rendering::composition::transport::BatchValueReader;
43use std::any::Any;
44use std::any::TypeId;
45use std::cell::Cell;
46use std::cell::RefCell;
47use std::rc::Rc;
48use std::sync::Arc;
49use std::sync::OnceLock;
50use std::time::Duration;
51
52bitflags! {
53    /// The fields of `CompositionVisual` that changed since its last serialization.
54    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
55    pub struct CompositionVisualChangedFields: u64 {
56        const ROOT = 1;
57        const PARENT = 2;
58        const VISIBLE = 4;
59        const VISIBLE_ANIMATED = 8;
60        const OPACITY = 16;
61        const OPACITY_ANIMATED = 32;
62        const CLIP = 64;
63        const CLIP_TO_BOUNDS = 128;
64        const CLIP_TO_BOUNDS_ANIMATED = 256;
65        const OFFSET = 512;
66        const OFFSET_ANIMATED = 1024;
67        const TRANSLATION = 2048;
68        const TRANSLATION_ANIMATED = 4096;
69        const SIZE = 8192;
70        const SIZE_ANIMATED = 16384;
71        const ANCHOR_POINT = 32768;
72        const ANCHOR_POINT_ANIMATED = 65536;
73        const CENTER_POINT = 131072;
74        const CENTER_POINT_ANIMATED = 262144;
75        const ROTATION_ANGLE = 524288;
76        const ROTATION_ANGLE_ANIMATED = 1048576;
77        const ORIENTATION = 2097152;
78        const ORIENTATION_ANIMATED = 4194304;
79        const SCALE = 8388608;
80        const SCALE_ANIMATED = 16777216;
81        const TRANSFORM_MATRIX = 33554432;
82        const TRANSFORM_MATRIX_ANIMATED = 67108864;
83        const ADORNED_VISUAL = 134217728;
84        const ADORNER_IS_CLIPPED = 268435456;
85        const OPACITY_MASK_BRUSH = 536870912;
86        const EFFECT = 1073741824;
87        const RENDER_OPTIONS = 2147483648;
88        const TEXT_OPTIONS = 4294967296;
89        const CACHE_MODE = 8589934592;
90        const COMPOSITION_CLIP = 17179869184;
91        const ROTATION_AXIS = 34359738368;
92        const ROTATION_AXIS_ANIMATED = 68719476736;
93        const RELATIVE_OFFSET_ADJUSTMENT = 137438953472;
94        const RELATIVE_OFFSET_ADJUSTMENT_ANIMATED = 274877906944;
95        const RELATIVE_SIZE_ADJUSTMENT = 549755813888;
96        const RELATIVE_SIZE_ADJUSTMENT_ANIMATED = 1099511627776;
97        const IS_HIT_TEST_VISIBLE = 2199023255552;
98        const IS_PIXEL_SNAPPING_ENABLED = 4398046511104;
99        const BORDER_MODE = 8796093022208;
100        const BACKFACE_VISIBILITY = 17592186044416;
101        const COMPOSITE_MODE = 35184372088832;
102        const PARENT_FOR_TRANSFORM = 70368744177664;
103    }
104}
105
106impl BatchValue for CompositionVisualChangedFields {
107    #[inline]
108    fn write_to(&self, out: &mut Vec<u8>) {
109        self.bits().write_to(out);
110    }
111
112    #[inline]
113    fn read_from(input: &mut BatchValueReader<'_>) -> Self {
114        CompositionVisualChangedFields::from_bits_retain(u64::read_from(input))
115    }
116}
117
118/// The partial methods of `CompositionVisual`: implemented by the class that embeds
119/// [`CompositionVisualProps`]. Every hook defaults to doing nothing.
120pub trait CompositionVisualHooks: ICompositionObjectHost {
121    fn initialize_defaults_extra(&self) {}
122
123    fn validate_root_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
124    fn on_root_changed(&self) {}
125    fn on_root_changing(&self) {}
126
127    fn validate_parent_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
128    fn on_parent_changed(&self) {}
129    fn on_parent_changing(&self) {}
130
131    fn validate_visible_change(&self, _old_value: bool, _new_value: bool) {}
132    fn on_visible_changed(&self) {}
133    fn on_visible_changing(&self) {}
134
135    fn validate_opacity_change(&self, _old_value: f32, _new_value: f32) {}
136    fn on_opacity_changed(&self) {}
137    fn on_opacity_changing(&self) {}
138
139    fn validate_clip_change(&self, _old_value: &Option<Arc<dyn IGeometryImpl>>, _new_value: &Option<Arc<dyn IGeometryImpl>>) {}
140    fn on_clip_changed(&self) {}
141    fn on_clip_changing(&self) {}
142
143    fn validate_clip_to_bounds_change(&self, _old_value: bool, _new_value: bool) {}
144    fn on_clip_to_bounds_changed(&self) {}
145    fn on_clip_to_bounds_changing(&self) {}
146
147    fn validate_offset_change(&self, _old_value: Vector3D, _new_value: Vector3D) {}
148    fn on_offset_changed(&self) {}
149    fn on_offset_changing(&self) {}
150
151    fn validate_translation_change(&self, _old_value: Vector3D, _new_value: Vector3D) {}
152    fn on_translation_changed(&self) {}
153    fn on_translation_changing(&self) {}
154
155    fn validate_size_change(&self, _old_value: Vector, _new_value: Vector) {}
156    fn on_size_changed(&self) {}
157    fn on_size_changing(&self) {}
158
159    fn validate_anchor_point_change(&self, _old_value: Vector, _new_value: Vector) {}
160    fn on_anchor_point_changed(&self) {}
161    fn on_anchor_point_changing(&self) {}
162
163    fn validate_center_point_change(&self, _old_value: Vector3D, _new_value: Vector3D) {}
164    fn on_center_point_changed(&self) {}
165    fn on_center_point_changing(&self) {}
166
167    fn validate_rotation_angle_change(&self, _old_value: f32, _new_value: f32) {}
168    fn on_rotation_angle_changed(&self) {}
169    fn on_rotation_angle_changing(&self) {}
170
171    fn validate_orientation_change(&self, _old_value: Quaternion, _new_value: Quaternion) {}
172    fn on_orientation_changed(&self) {}
173    fn on_orientation_changing(&self) {}
174
175    fn validate_scale_change(&self, _old_value: Vector3D, _new_value: Vector3D) {}
176    fn on_scale_changed(&self) {}
177    fn on_scale_changing(&self) {}
178
179    fn validate_transform_matrix_change(&self, _old_value: Matrix, _new_value: Matrix) {}
180    fn on_transform_matrix_changed(&self) {}
181    fn on_transform_matrix_changing(&self) {}
182
183    fn validate_adorned_visual_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
184    fn on_adorned_visual_changed(&self) {}
185    fn on_adorned_visual_changing(&self) {}
186
187    fn validate_adorner_is_clipped_change(&self, _old_value: bool, _new_value: bool) {}
188    fn on_adorner_is_clipped_changed(&self) {}
189    fn on_adorner_is_clipped_changing(&self) {}
190
191    fn validate_opacity_mask_brush_change(&self, _old_value: &Option<BatchResource<dyn IBrush>>, _new_value: &Option<BatchResource<dyn IBrush>>) {}
192    fn on_opacity_mask_brush_changed(&self) {}
193    fn on_opacity_mask_brush_changing(&self) {}
194
195    fn validate_effect_change(&self, _old_value: &Option<Arc<dyn IImmutableEffect>>, _new_value: &Option<Arc<dyn IImmutableEffect>>) {}
196    fn on_effect_changed(&self) {}
197    fn on_effect_changing(&self) {}
198
199    fn validate_render_options_change(&self, _old_value: RenderOptions, _new_value: RenderOptions) {}
200    fn on_render_options_changed(&self) {}
201    fn on_render_options_changing(&self) {}
202
203    fn validate_text_options_change(&self, _old_value: TextOptions, _new_value: TextOptions) {}
204    fn on_text_options_changed(&self) {}
205    fn on_text_options_changing(&self) {}
206
207    fn validate_cache_mode_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
208    fn on_cache_mode_changed(&self) {}
209    fn on_cache_mode_changing(&self) {}
210
211    fn validate_composition_clip_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
212    fn on_composition_clip_changed(&self) {}
213    fn on_composition_clip_changing(&self) {}
214
215    fn validate_rotation_axis_change(&self, _old_value: Vector3D, _new_value: Vector3D) {}
216    fn on_rotation_axis_changed(&self) {}
217    fn on_rotation_axis_changing(&self) {}
218
219    fn validate_relative_offset_adjustment_change(&self, _old_value: Vector3D, _new_value: Vector3D) {}
220    fn on_relative_offset_adjustment_changed(&self) {}
221    fn on_relative_offset_adjustment_changing(&self) {}
222
223    fn validate_relative_size_adjustment_change(&self, _old_value: Vector, _new_value: Vector) {}
224    fn on_relative_size_adjustment_changed(&self) {}
225    fn on_relative_size_adjustment_changing(&self) {}
226
227    fn validate_is_hit_test_visible_change(&self, _old_value: bool, _new_value: bool) {}
228    fn on_is_hit_test_visible_changed(&self) {}
229    fn on_is_hit_test_visible_changing(&self) {}
230
231    fn validate_is_pixel_snapping_enabled_change(&self, _old_value: bool, _new_value: bool) {}
232    fn on_is_pixel_snapping_enabled_changed(&self) {}
233    fn on_is_pixel_snapping_enabled_changing(&self) {}
234
235    fn validate_border_mode_change(&self, _old_value: CompositionBorderMode, _new_value: CompositionBorderMode) {}
236    fn on_border_mode_changed(&self) {}
237    fn on_border_mode_changing(&self) {}
238
239    fn validate_backface_visibility_change(&self, _old_value: CompositionBackfaceVisibility, _new_value: CompositionBackfaceVisibility) {}
240    fn on_backface_visibility_changed(&self) {}
241    fn on_backface_visibility_changing(&self) {}
242
243    fn validate_composite_mode_change(&self, _old_value: CompositionCompositeMode, _new_value: CompositionCompositeMode) {}
244    fn on_composite_mode_changed(&self) {}
245    fn on_composite_mode_changing(&self) {}
246
247    fn validate_parent_for_transform_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
248    fn on_parent_for_transform_changed(&self) {}
249    fn on_parent_for_transform_changing(&self) {}
250}
251
252/// The UI-thread properties of `CompositionVisual`.
253pub struct CompositionVisualProps {
254    changed_fields_of_composition_visual: Cell<CompositionVisualChangedFields>,
255    root: RefCell<Option<Rc<dyn ICompositionObject>>>,
256    parent: RefCell<Option<Rc<dyn ICompositionObject>>>,
257    visible: Cell<bool>,
258    opacity: Cell<f32>,
259    clip: RefCell<Option<Arc<dyn IGeometryImpl>>>,
260    clip_to_bounds: Cell<bool>,
261    offset: Cell<Vector3D>,
262    translation: Cell<Vector3D>,
263    size: Cell<Vector>,
264    anchor_point: Cell<Vector>,
265    center_point: Cell<Vector3D>,
266    rotation_angle: Cell<f32>,
267    orientation: Cell<Quaternion>,
268    scale: Cell<Vector3D>,
269    transform_matrix: Cell<Matrix>,
270    adorned_visual: RefCell<Option<Rc<dyn ICompositionObject>>>,
271    adorner_is_clipped: Cell<bool>,
272    opacity_mask_brush: RefCell<Option<BatchResource<dyn IBrush>>>,
273    effect: RefCell<Option<Arc<dyn IImmutableEffect>>>,
274    render_options: Cell<RenderOptions>,
275    text_options: Cell<TextOptions>,
276    cache_mode: RefCell<Option<Rc<dyn ICompositionObject>>>,
277    composition_clip: RefCell<Option<Rc<dyn ICompositionObject>>>,
278    rotation_axis: Cell<Vector3D>,
279    relative_offset_adjustment: Cell<Vector3D>,
280    relative_size_adjustment: Cell<Vector>,
281    is_hit_test_visible: Cell<bool>,
282    is_pixel_snapping_enabled: Cell<bool>,
283    border_mode: Cell<CompositionBorderMode>,
284    backface_visibility: Cell<CompositionBackfaceVisibility>,
285    composite_mode: Cell<CompositionCompositeMode>,
286    parent_for_transform: RefCell<Option<Rc<dyn ICompositionObject>>>,
287}
288
289impl Default for CompositionVisualProps {
290    fn default() -> Self {
291        Self::new()
292    }
293}
294
295impl CompositionVisualProps {
296    /// Creates the properties with every field at the default of its type.
297    /// The defaults of the schema are applied by
298    /// [`initialize_defaults`](Self::initialize_defaults).
299    pub fn new() -> Self {
300        Self {
301            changed_fields_of_composition_visual: Cell::new(CompositionVisualChangedFields::empty()),
302            root: RefCell::new(None),
303            parent: RefCell::new(None),
304            visible: Cell::new(Default::default()),
305            opacity: Cell::new(Default::default()),
306            clip: RefCell::new(None),
307            clip_to_bounds: Cell::new(Default::default()),
308            offset: Cell::new(Default::default()),
309            translation: Cell::new(Default::default()),
310            size: Cell::new(Default::default()),
311            anchor_point: Cell::new(Default::default()),
312            center_point: Cell::new(Default::default()),
313            rotation_angle: Cell::new(Default::default()),
314            orientation: Cell::new(Default::default()),
315            scale: Cell::new(Default::default()),
316            transform_matrix: Cell::new(Default::default()),
317            adorned_visual: RefCell::new(None),
318            adorner_is_clipped: Cell::new(Default::default()),
319            opacity_mask_brush: RefCell::new(None),
320            effect: RefCell::new(None),
321            render_options: Cell::new(Default::default()),
322            text_options: Cell::new(Default::default()),
323            cache_mode: RefCell::new(None),
324            composition_clip: RefCell::new(None),
325            rotation_axis: Cell::new(Default::default()),
326            relative_offset_adjustment: Cell::new(Default::default()),
327            relative_size_adjustment: Cell::new(Default::default()),
328            is_hit_test_visible: Cell::new(Default::default()),
329            is_pixel_snapping_enabled: Cell::new(Default::default()),
330            border_mode: Cell::new(Default::default()),
331            backface_visibility: Cell::new(Default::default()),
332            composite_mode: Cell::new(Default::default()),
333            parent_for_transform: RefCell::new(None),
334        }
335    }
336
337    /// The `InitializeDefaults` calls of the constructor chain: the base
338    /// classes first, then this class.
339    pub fn initialize_defaults(&self, host: &dyn CompositionVisualHooks) {
340        self.initialize_own_defaults(host);
341    }
342
343    /// `InitializeDefaults` of this class alone.
344    pub fn initialize_own_defaults(&self, host: &dyn CompositionVisualHooks) {
345        CompositionVisualHooks::initialize_defaults_extra(host);
346        self.set_visible(host, true);
347        self.set_opacity(host, 1.0);
348        self.set_clip_to_bounds(host, true);
349        self.set_orientation(host, Quaternion::IDENTITY);
350        self.set_scale(host, Vector3D::new(1.0, 1.0, 1.0));
351        self.set_transform_matrix(host, Matrix::IDENTITY);
352        self.set_rotation_axis(host, Vector3D::new(0.0, 0.0, 1.0));
353        self.set_is_hit_test_visible(host, true);
354    }
355
356    /// `Root` (internal).
357    pub fn root(&self) -> Option<Rc<dyn ICompositionObject>> {
358        self.root.borrow().clone()
359    }
360
361    /// Sets `Root` (internal).
362    pub fn set_root(&self, host: &dyn CompositionVisualHooks, value: Option<Rc<dyn ICompositionObject>>) {
363        let mut changed = false;
364        let old_value = self.root.borrow().clone();
365        if old_value.differs(&value) {
366            CompositionVisualHooks::validate_root_change(host, &old_value, &value);
367            CompositionVisualHooks::on_root_changing(host);
368            changed = true;
369            // Update the backing value
370            *self.root.borrow_mut() = value.clone();
371            // Register object for serialization in the next batch
372            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROOT);
373            host.register_for_serialization();
374        }
375        *self.root.borrow_mut() = value;
376        if changed {
377            CompositionVisualHooks::on_root_changed(host);
378        }
379    }
380
381    /// `Parent` (internal).
382    pub fn parent(&self) -> Option<Rc<dyn ICompositionObject>> {
383        self.parent.borrow().clone()
384    }
385
386    /// Sets `Parent` (internal).
387    pub fn set_parent(&self, host: &dyn CompositionVisualHooks, value: Option<Rc<dyn ICompositionObject>>) {
388        let mut changed = false;
389        let old_value = self.parent.borrow().clone();
390        if old_value.differs(&value) {
391            CompositionVisualHooks::validate_parent_change(host, &old_value, &value);
392            CompositionVisualHooks::on_parent_changing(host);
393            changed = true;
394            // Update the backing value
395            *self.parent.borrow_mut() = value.clone();
396            // Register object for serialization in the next batch
397            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::PARENT);
398            host.register_for_serialization();
399        }
400        *self.parent.borrow_mut() = value;
401        if changed {
402            CompositionVisualHooks::on_parent_changed(host);
403        }
404    }
405
406    /// `Visible` (animated, default `true`).
407    pub fn visible(&self) -> bool {
408        self.visible.get()
409    }
410
411    /// Sets `Visible` (animated, default `true`).
412    pub fn set_visible(&self, host: &dyn CompositionVisualHooks, value: bool) {
413        let mut changed = false;
414        let old_value = self.visible.get();
415        if old_value.differs(&value) {
416            CompositionVisualHooks::validate_visible_change(host, old_value, value);
417            CompositionVisualHooks::on_visible_changing(host);
418            changed = true;
419            // Update the backing value
420            self.visible.set(value);
421            // Register object for serialization in the next batch
422            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::VISIBLE);
423            host.register_for_serialization();
424            // Reset previous animation if any
425            host.pending_animations().remove(ServerCompositionVisualProps::id_of_visible_property().base());
426            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::VISIBLE_ANIMATED);
427            // Check for implicit animations
428            if let Some(animation) = host.implicit_animation("Visible") {
429                // Animation affects only current property
430                if let Some(a) = animation.as_composition_animation() {
431                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::VISIBLE_ANIMATED);
432                    host.pending_animations().set(
433                        ServerCompositionVisualProps::id_of_visible_property().base(),
434                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
435                    );
436                }
437                // Animation is triggered by the current field, but does not necessary affects it
438                host.start_animation_group(&animation, "Visible", ExpressionVariant::create(value));
439            }
440        }
441        self.visible.set(value);
442        if changed {
443            CompositionVisualHooks::on_visible_changed(host);
444        }
445    }
446
447    /// `Opacity` (animated, default `1.0`).
448    pub fn opacity(&self) -> f32 {
449        self.opacity.get()
450    }
451
452    /// Sets `Opacity` (animated, default `1.0`).
453    pub fn set_opacity(&self, host: &dyn CompositionVisualHooks, value: f32) {
454        let mut changed = false;
455        let old_value = self.opacity.get();
456        if old_value.differs(&value) {
457            CompositionVisualHooks::validate_opacity_change(host, old_value, value);
458            CompositionVisualHooks::on_opacity_changing(host);
459            changed = true;
460            // Update the backing value
461            self.opacity.set(value);
462            // Register object for serialization in the next batch
463            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OPACITY);
464            host.register_for_serialization();
465            // Reset previous animation if any
466            host.pending_animations().remove(ServerCompositionVisualProps::id_of_opacity_property().base());
467            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::OPACITY_ANIMATED);
468            // Check for implicit animations
469            if let Some(animation) = host.implicit_animation("Opacity") {
470                // Animation affects only current property
471                if let Some(a) = animation.as_composition_animation() {
472                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OPACITY_ANIMATED);
473                    host.pending_animations().set(
474                        ServerCompositionVisualProps::id_of_opacity_property().base(),
475                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
476                    );
477                }
478                // Animation is triggered by the current field, but does not necessary affects it
479                host.start_animation_group(&animation, "Opacity", ExpressionVariant::create(value));
480            }
481        }
482        self.opacity.set(value);
483        if changed {
484            CompositionVisualHooks::on_opacity_changed(host);
485        }
486    }
487
488    /// `Clip` (internal).
489    pub fn clip(&self) -> Option<Arc<dyn IGeometryImpl>> {
490        self.clip.borrow().clone()
491    }
492
493    /// Sets `Clip` (internal).
494    pub fn set_clip(&self, host: &dyn CompositionVisualHooks, value: Option<Arc<dyn IGeometryImpl>>) {
495        let mut changed = false;
496        let old_value = self.clip.borrow().clone();
497        if old_value.differs(&value) {
498            CompositionVisualHooks::validate_clip_change(host, &old_value, &value);
499            CompositionVisualHooks::on_clip_changing(host);
500            changed = true;
501            // Update the backing value
502            *self.clip.borrow_mut() = value.clone();
503            // Register object for serialization in the next batch
504            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CLIP);
505            host.register_for_serialization();
506        }
507        *self.clip.borrow_mut() = value;
508        if changed {
509            CompositionVisualHooks::on_clip_changed(host);
510        }
511    }
512
513    /// `ClipToBounds` (animated, default `true`).
514    pub fn clip_to_bounds(&self) -> bool {
515        self.clip_to_bounds.get()
516    }
517
518    /// Sets `ClipToBounds` (animated, default `true`).
519    pub fn set_clip_to_bounds(&self, host: &dyn CompositionVisualHooks, value: bool) {
520        let mut changed = false;
521        let old_value = self.clip_to_bounds.get();
522        if old_value.differs(&value) {
523            CompositionVisualHooks::validate_clip_to_bounds_change(host, old_value, value);
524            CompositionVisualHooks::on_clip_to_bounds_changing(host);
525            changed = true;
526            // Update the backing value
527            self.clip_to_bounds.set(value);
528            // Register object for serialization in the next batch
529            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CLIP_TO_BOUNDS);
530            host.register_for_serialization();
531            // Reset previous animation if any
532            host.pending_animations().remove(ServerCompositionVisualProps::id_of_clip_to_bounds_property().base());
533            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::CLIP_TO_BOUNDS_ANIMATED);
534            // Check for implicit animations
535            if let Some(animation) = host.implicit_animation("ClipToBounds") {
536                // Animation affects only current property
537                if let Some(a) = animation.as_composition_animation() {
538                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CLIP_TO_BOUNDS_ANIMATED);
539                    host.pending_animations().set(
540                        ServerCompositionVisualProps::id_of_clip_to_bounds_property().base(),
541                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
542                    );
543                }
544                // Animation is triggered by the current field, but does not necessary affects it
545                host.start_animation_group(&animation, "ClipToBounds", ExpressionVariant::create(value));
546            }
547        }
548        self.clip_to_bounds.set(value);
549        if changed {
550            CompositionVisualHooks::on_clip_to_bounds_changed(host);
551        }
552    }
553
554    /// `Offset` (animated).
555    pub fn offset(&self) -> Vector3D {
556        self.offset.get()
557    }
558
559    /// Sets `Offset` (animated).
560    pub fn set_offset(&self, host: &dyn CompositionVisualHooks, value: Vector3D) {
561        let mut changed = false;
562        let old_value = self.offset.get();
563        if old_value.differs(&value) {
564            CompositionVisualHooks::validate_offset_change(host, old_value, value);
565            CompositionVisualHooks::on_offset_changing(host);
566            changed = true;
567            // Update the backing value
568            self.offset.set(value);
569            // Register object for serialization in the next batch
570            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OFFSET);
571            host.register_for_serialization();
572            // Reset previous animation if any
573            host.pending_animations().remove(ServerCompositionVisualProps::id_of_offset_property().base());
574            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::OFFSET_ANIMATED);
575            // Check for implicit animations
576            if let Some(animation) = host.implicit_animation("Offset") {
577                // Animation affects only current property
578                if let Some(a) = animation.as_composition_animation() {
579                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OFFSET_ANIMATED);
580                    host.pending_animations().set(
581                        ServerCompositionVisualProps::id_of_offset_property().base(),
582                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
583                    );
584                }
585                // Animation is triggered by the current field, but does not necessary affects it
586                host.start_animation_group(&animation, "Offset", ExpressionVariant::create(value));
587            }
588        }
589        self.offset.set(value);
590        if changed {
591            CompositionVisualHooks::on_offset_changed(host);
592        }
593    }
594
595    /// `Translation` (animated).
596    pub fn translation(&self) -> Vector3D {
597        self.translation.get()
598    }
599
600    /// Sets `Translation` (animated).
601    pub fn set_translation(&self, host: &dyn CompositionVisualHooks, value: Vector3D) {
602        let mut changed = false;
603        let old_value = self.translation.get();
604        if old_value.differs(&value) {
605            CompositionVisualHooks::validate_translation_change(host, old_value, value);
606            CompositionVisualHooks::on_translation_changing(host);
607            changed = true;
608            // Update the backing value
609            self.translation.set(value);
610            // Register object for serialization in the next batch
611            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSLATION);
612            host.register_for_serialization();
613            // Reset previous animation if any
614            host.pending_animations().remove(ServerCompositionVisualProps::id_of_translation_property().base());
615            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::TRANSLATION_ANIMATED);
616            // Check for implicit animations
617            if let Some(animation) = host.implicit_animation("Translation") {
618                // Animation affects only current property
619                if let Some(a) = animation.as_composition_animation() {
620                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSLATION_ANIMATED);
621                    host.pending_animations().set(
622                        ServerCompositionVisualProps::id_of_translation_property().base(),
623                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
624                    );
625                }
626                // Animation is triggered by the current field, but does not necessary affects it
627                host.start_animation_group(&animation, "Translation", ExpressionVariant::create(value));
628            }
629        }
630        self.translation.set(value);
631        if changed {
632            CompositionVisualHooks::on_translation_changed(host);
633        }
634    }
635
636    /// `Size` (animated).
637    pub fn size(&self) -> Vector {
638        self.size.get()
639    }
640
641    /// Sets `Size` (animated).
642    pub fn set_size(&self, host: &dyn CompositionVisualHooks, value: Vector) {
643        let mut changed = false;
644        let old_value = self.size.get();
645        if old_value.differs(&value) {
646            CompositionVisualHooks::validate_size_change(host, old_value, value);
647            CompositionVisualHooks::on_size_changing(host);
648            changed = true;
649            // Update the backing value
650            self.size.set(value);
651            // Register object for serialization in the next batch
652            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SIZE);
653            host.register_for_serialization();
654            // Reset previous animation if any
655            host.pending_animations().remove(ServerCompositionVisualProps::id_of_size_property().base());
656            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::SIZE_ANIMATED);
657            // Check for implicit animations
658            if let Some(animation) = host.implicit_animation("Size") {
659                // Animation affects only current property
660                if let Some(a) = animation.as_composition_animation() {
661                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SIZE_ANIMATED);
662                    host.pending_animations().set(
663                        ServerCompositionVisualProps::id_of_size_property().base(),
664                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
665                    );
666                }
667                // Animation is triggered by the current field, but does not necessary affects it
668                host.start_animation_group(&animation, "Size", ExpressionVariant::create(value));
669            }
670        }
671        self.size.set(value);
672        if changed {
673            CompositionVisualHooks::on_size_changed(host);
674        }
675    }
676
677    /// `AnchorPoint` (animated).
678    pub fn anchor_point(&self) -> Vector {
679        self.anchor_point.get()
680    }
681
682    /// Sets `AnchorPoint` (animated).
683    pub fn set_anchor_point(&self, host: &dyn CompositionVisualHooks, value: Vector) {
684        let mut changed = false;
685        let old_value = self.anchor_point.get();
686        if old_value.differs(&value) {
687            CompositionVisualHooks::validate_anchor_point_change(host, old_value, value);
688            CompositionVisualHooks::on_anchor_point_changing(host);
689            changed = true;
690            // Update the backing value
691            self.anchor_point.set(value);
692            // Register object for serialization in the next batch
693            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ANCHOR_POINT);
694            host.register_for_serialization();
695            // Reset previous animation if any
696            host.pending_animations().remove(ServerCompositionVisualProps::id_of_anchor_point_property().base());
697            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::ANCHOR_POINT_ANIMATED);
698            // Check for implicit animations
699            if let Some(animation) = host.implicit_animation("AnchorPoint") {
700                // Animation affects only current property
701                if let Some(a) = animation.as_composition_animation() {
702                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ANCHOR_POINT_ANIMATED);
703                    host.pending_animations().set(
704                        ServerCompositionVisualProps::id_of_anchor_point_property().base(),
705                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
706                    );
707                }
708                // Animation is triggered by the current field, but does not necessary affects it
709                host.start_animation_group(&animation, "AnchorPoint", ExpressionVariant::create(value));
710            }
711        }
712        self.anchor_point.set(value);
713        if changed {
714            CompositionVisualHooks::on_anchor_point_changed(host);
715        }
716    }
717
718    /// `CenterPoint` (animated).
719    pub fn center_point(&self) -> Vector3D {
720        self.center_point.get()
721    }
722
723    /// Sets `CenterPoint` (animated).
724    pub fn set_center_point(&self, host: &dyn CompositionVisualHooks, value: Vector3D) {
725        let mut changed = false;
726        let old_value = self.center_point.get();
727        if old_value.differs(&value) {
728            CompositionVisualHooks::validate_center_point_change(host, old_value, value);
729            CompositionVisualHooks::on_center_point_changing(host);
730            changed = true;
731            // Update the backing value
732            self.center_point.set(value);
733            // Register object for serialization in the next batch
734            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CENTER_POINT);
735            host.register_for_serialization();
736            // Reset previous animation if any
737            host.pending_animations().remove(ServerCompositionVisualProps::id_of_center_point_property().base());
738            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::CENTER_POINT_ANIMATED);
739            // Check for implicit animations
740            if let Some(animation) = host.implicit_animation("CenterPoint") {
741                // Animation affects only current property
742                if let Some(a) = animation.as_composition_animation() {
743                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CENTER_POINT_ANIMATED);
744                    host.pending_animations().set(
745                        ServerCompositionVisualProps::id_of_center_point_property().base(),
746                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
747                    );
748                }
749                // Animation is triggered by the current field, but does not necessary affects it
750                host.start_animation_group(&animation, "CenterPoint", ExpressionVariant::create(value));
751            }
752        }
753        self.center_point.set(value);
754        if changed {
755            CompositionVisualHooks::on_center_point_changed(host);
756        }
757    }
758
759    /// `RotationAngle` (animated).
760    pub fn rotation_angle(&self) -> f32 {
761        self.rotation_angle.get()
762    }
763
764    /// Sets `RotationAngle` (animated).
765    pub fn set_rotation_angle(&self, host: &dyn CompositionVisualHooks, value: f32) {
766        let mut changed = false;
767        let old_value = self.rotation_angle.get();
768        if old_value.differs(&value) {
769            CompositionVisualHooks::validate_rotation_angle_change(host, old_value, value);
770            CompositionVisualHooks::on_rotation_angle_changing(host);
771            changed = true;
772            // Update the backing value
773            self.rotation_angle.set(value);
774            // Register object for serialization in the next batch
775            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROTATION_ANGLE);
776            host.register_for_serialization();
777            // Reset previous animation if any
778            host.pending_animations().remove(ServerCompositionVisualProps::id_of_rotation_angle_property().base());
779            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::ROTATION_ANGLE_ANIMATED);
780            // Check for implicit animations
781            if let Some(animation) = host.implicit_animation("RotationAngle") {
782                // Animation affects only current property
783                if let Some(a) = animation.as_composition_animation() {
784                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROTATION_ANGLE_ANIMATED);
785                    host.pending_animations().set(
786                        ServerCompositionVisualProps::id_of_rotation_angle_property().base(),
787                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
788                    );
789                }
790                // Animation is triggered by the current field, but does not necessary affects it
791                host.start_animation_group(&animation, "RotationAngle", ExpressionVariant::create(value));
792            }
793        }
794        self.rotation_angle.set(value);
795        if changed {
796            CompositionVisualHooks::on_rotation_angle_changed(host);
797        }
798    }
799
800    /// `Orientation` (animated, default `Quaternion::IDENTITY`).
801    pub fn orientation(&self) -> Quaternion {
802        self.orientation.get()
803    }
804
805    /// Sets `Orientation` (animated, default `Quaternion::IDENTITY`).
806    pub fn set_orientation(&self, host: &dyn CompositionVisualHooks, value: Quaternion) {
807        let mut changed = false;
808        let old_value = self.orientation.get();
809        if old_value.differs(&value) {
810            CompositionVisualHooks::validate_orientation_change(host, old_value, value);
811            CompositionVisualHooks::on_orientation_changing(host);
812            changed = true;
813            // Update the backing value
814            self.orientation.set(value);
815            // Register object for serialization in the next batch
816            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ORIENTATION);
817            host.register_for_serialization();
818            // Reset previous animation if any
819            host.pending_animations().remove(ServerCompositionVisualProps::id_of_orientation_property().base());
820            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::ORIENTATION_ANIMATED);
821            // Check for implicit animations
822            if let Some(animation) = host.implicit_animation("Orientation") {
823                // Animation affects only current property
824                if let Some(a) = animation.as_composition_animation() {
825                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ORIENTATION_ANIMATED);
826                    host.pending_animations().set(
827                        ServerCompositionVisualProps::id_of_orientation_property().base(),
828                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
829                    );
830                }
831                // Animation is triggered by the current field, but does not necessary affects it
832                host.start_animation_group(&animation, "Orientation", ExpressionVariant::create(value));
833            }
834        }
835        self.orientation.set(value);
836        if changed {
837            CompositionVisualHooks::on_orientation_changed(host);
838        }
839    }
840
841    /// `Scale` (animated, default `Vector3D::new(1.0, 1.0, 1.0)`).
842    pub fn scale(&self) -> Vector3D {
843        self.scale.get()
844    }
845
846    /// Sets `Scale` (animated, default `Vector3D::new(1.0, 1.0, 1.0)`).
847    pub fn set_scale(&self, host: &dyn CompositionVisualHooks, value: Vector3D) {
848        let mut changed = false;
849        let old_value = self.scale.get();
850        if old_value.differs(&value) {
851            CompositionVisualHooks::validate_scale_change(host, old_value, value);
852            CompositionVisualHooks::on_scale_changing(host);
853            changed = true;
854            // Update the backing value
855            self.scale.set(value);
856            // Register object for serialization in the next batch
857            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SCALE);
858            host.register_for_serialization();
859            // Reset previous animation if any
860            host.pending_animations().remove(ServerCompositionVisualProps::id_of_scale_property().base());
861            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::SCALE_ANIMATED);
862            // Check for implicit animations
863            if let Some(animation) = host.implicit_animation("Scale") {
864                // Animation affects only current property
865                if let Some(a) = animation.as_composition_animation() {
866                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SCALE_ANIMATED);
867                    host.pending_animations().set(
868                        ServerCompositionVisualProps::id_of_scale_property().base(),
869                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
870                    );
871                }
872                // Animation is triggered by the current field, but does not necessary affects it
873                host.start_animation_group(&animation, "Scale", ExpressionVariant::create(value));
874            }
875        }
876        self.scale.set(value);
877        if changed {
878            CompositionVisualHooks::on_scale_changed(host);
879        }
880    }
881
882    /// `TransformMatrix` (internal, animated, default `Matrix::IDENTITY`).
883    pub fn transform_matrix(&self) -> Matrix {
884        self.transform_matrix.get()
885    }
886
887    /// Sets `TransformMatrix` (internal, animated, default `Matrix::IDENTITY`).
888    pub fn set_transform_matrix(&self, host: &dyn CompositionVisualHooks, value: Matrix) {
889        let mut changed = false;
890        let old_value = self.transform_matrix.get();
891        if old_value.differs(&value) {
892            CompositionVisualHooks::validate_transform_matrix_change(host, old_value, value);
893            CompositionVisualHooks::on_transform_matrix_changing(host);
894            changed = true;
895            // Update the backing value
896            self.transform_matrix.set(value);
897            // Register object for serialization in the next batch
898            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSFORM_MATRIX);
899            host.register_for_serialization();
900            // Reset previous animation if any
901            host.pending_animations().remove(ServerCompositionVisualProps::id_of_transform_matrix_property().base());
902            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::TRANSFORM_MATRIX_ANIMATED);
903            // Check for implicit animations
904            if let Some(animation) = host.implicit_animation("TransformMatrix") {
905                // Animation affects only current property
906                if let Some(a) = animation.as_composition_animation() {
907                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSFORM_MATRIX_ANIMATED);
908                    host.pending_animations().set(
909                        ServerCompositionVisualProps::id_of_transform_matrix_property().base(),
910                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
911                    );
912                }
913                // Animation is triggered by the current field, but does not necessary affects it
914                host.start_animation_group(&animation, "TransformMatrix", ExpressionVariant::create(value));
915            }
916        }
917        self.transform_matrix.set(value);
918        if changed {
919            CompositionVisualHooks::on_transform_matrix_changed(host);
920        }
921    }
922
923    /// `AdornedVisual` (internal).
924    pub fn adorned_visual(&self) -> Option<Rc<dyn ICompositionObject>> {
925        self.adorned_visual.borrow().clone()
926    }
927
928    /// Sets `AdornedVisual` (internal).
929    pub fn set_adorned_visual(&self, host: &dyn CompositionVisualHooks, value: Option<Rc<dyn ICompositionObject>>) {
930        let mut changed = false;
931        let old_value = self.adorned_visual.borrow().clone();
932        if old_value.differs(&value) {
933            CompositionVisualHooks::validate_adorned_visual_change(host, &old_value, &value);
934            CompositionVisualHooks::on_adorned_visual_changing(host);
935            changed = true;
936            // Update the backing value
937            *self.adorned_visual.borrow_mut() = value.clone();
938            // Register object for serialization in the next batch
939            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ADORNED_VISUAL);
940            host.register_for_serialization();
941        }
942        *self.adorned_visual.borrow_mut() = value;
943        if changed {
944            CompositionVisualHooks::on_adorned_visual_changed(host);
945        }
946    }
947
948    /// `AdornerIsClipped` (internal).
949    pub fn adorner_is_clipped(&self) -> bool {
950        self.adorner_is_clipped.get()
951    }
952
953    /// Sets `AdornerIsClipped` (internal).
954    pub fn set_adorner_is_clipped(&self, host: &dyn CompositionVisualHooks, value: bool) {
955        let mut changed = false;
956        let old_value = self.adorner_is_clipped.get();
957        if old_value.differs(&value) {
958            CompositionVisualHooks::validate_adorner_is_clipped_change(host, old_value, value);
959            CompositionVisualHooks::on_adorner_is_clipped_changing(host);
960            changed = true;
961            // Update the backing value
962            self.adorner_is_clipped.set(value);
963            // Register object for serialization in the next batch
964            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ADORNER_IS_CLIPPED);
965            host.register_for_serialization();
966        }
967        self.adorner_is_clipped.set(value);
968        if changed {
969            CompositionVisualHooks::on_adorner_is_clipped_changed(host);
970        }
971    }
972
973    /// `OpacityMaskBrush` (private to the class).
974    pub fn opacity_mask_brush_transport_field(&self) -> Option<BatchResource<dyn IBrush>> {
975        self.opacity_mask_brush.borrow().clone()
976    }
977
978    /// Sets `OpacityMaskBrush` (private to the class).
979    pub fn set_opacity_mask_brush_transport_field(&self, host: &dyn CompositionVisualHooks, value: Option<BatchResource<dyn IBrush>>) {
980        let mut changed = false;
981        let old_value = self.opacity_mask_brush.borrow().clone();
982        if old_value.differs(&value) {
983            CompositionVisualHooks::validate_opacity_mask_brush_change(host, &old_value, &value);
984            CompositionVisualHooks::on_opacity_mask_brush_changing(host);
985            changed = true;
986            // Update the backing value
987            *self.opacity_mask_brush.borrow_mut() = value.clone();
988            // Register object for serialization in the next batch
989            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OPACITY_MASK_BRUSH);
990            host.register_for_serialization();
991        }
992        *self.opacity_mask_brush.borrow_mut() = value;
993        if changed {
994            CompositionVisualHooks::on_opacity_mask_brush_changed(host);
995        }
996    }
997
998    /// `Effect` (internal).
999    pub fn effect(&self) -> Option<Arc<dyn IImmutableEffect>> {
1000        self.effect.borrow().clone()
1001    }
1002
1003    /// Sets `Effect` (internal).
1004    pub fn set_effect(&self, host: &dyn CompositionVisualHooks, value: Option<Arc<dyn IImmutableEffect>>) {
1005        let mut changed = false;
1006        let old_value = self.effect.borrow().clone();
1007        if old_value.differs(&value) {
1008            CompositionVisualHooks::validate_effect_change(host, &old_value, &value);
1009            CompositionVisualHooks::on_effect_changing(host);
1010            changed = true;
1011            // Update the backing value
1012            *self.effect.borrow_mut() = value.clone();
1013            // Register object for serialization in the next batch
1014            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::EFFECT);
1015            host.register_for_serialization();
1016        }
1017        *self.effect.borrow_mut() = value;
1018        if changed {
1019            CompositionVisualHooks::on_effect_changed(host);
1020        }
1021    }
1022
1023    /// `RenderOptions`.
1024    pub fn render_options(&self) -> RenderOptions {
1025        self.render_options.get()
1026    }
1027
1028    /// Sets `RenderOptions`.
1029    pub fn set_render_options(&self, host: &dyn CompositionVisualHooks, value: RenderOptions) {
1030        let mut changed = false;
1031        let old_value = self.render_options.get();
1032        if old_value.differs(&value) {
1033            CompositionVisualHooks::validate_render_options_change(host, old_value, value);
1034            CompositionVisualHooks::on_render_options_changing(host);
1035            changed = true;
1036            // Update the backing value
1037            self.render_options.set(value);
1038            // Register object for serialization in the next batch
1039            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::RENDER_OPTIONS);
1040            host.register_for_serialization();
1041        }
1042        self.render_options.set(value);
1043        if changed {
1044            CompositionVisualHooks::on_render_options_changed(host);
1045        }
1046    }
1047
1048    /// `TextOptions`.
1049    pub fn text_options(&self) -> TextOptions {
1050        self.text_options.get()
1051    }
1052
1053    /// Sets `TextOptions`.
1054    pub fn set_text_options(&self, host: &dyn CompositionVisualHooks, value: TextOptions) {
1055        let mut changed = false;
1056        let old_value = self.text_options.get();
1057        if old_value.differs(&value) {
1058            CompositionVisualHooks::validate_text_options_change(host, old_value, value);
1059            CompositionVisualHooks::on_text_options_changing(host);
1060            changed = true;
1061            // Update the backing value
1062            self.text_options.set(value);
1063            // Register object for serialization in the next batch
1064            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TEXT_OPTIONS);
1065            host.register_for_serialization();
1066        }
1067        self.text_options.set(value);
1068        if changed {
1069            CompositionVisualHooks::on_text_options_changed(host);
1070        }
1071    }
1072
1073    /// `CacheMode` (internal).
1074    pub fn cache_mode(&self) -> Option<Rc<dyn ICompositionObject>> {
1075        self.cache_mode.borrow().clone()
1076    }
1077
1078    /// Sets `CacheMode` (internal).
1079    pub fn set_cache_mode(&self, host: &dyn CompositionVisualHooks, value: Option<Rc<dyn ICompositionObject>>) {
1080        let mut changed = false;
1081        let old_value = self.cache_mode.borrow().clone();
1082        if old_value.differs(&value) {
1083            CompositionVisualHooks::validate_cache_mode_change(host, &old_value, &value);
1084            CompositionVisualHooks::on_cache_mode_changing(host);
1085            changed = true;
1086            // Update the backing value
1087            *self.cache_mode.borrow_mut() = value.clone();
1088            // Register object for serialization in the next batch
1089            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CACHE_MODE);
1090            host.register_for_serialization();
1091        }
1092        *self.cache_mode.borrow_mut() = value;
1093        if changed {
1094            CompositionVisualHooks::on_cache_mode_changed(host);
1095        }
1096    }
1097
1098    /// `CompositionClip` (FerroUI overlay).
1099    pub fn composition_clip(&self) -> Option<Rc<dyn ICompositionObject>> {
1100        self.composition_clip.borrow().clone()
1101    }
1102
1103    /// Sets `CompositionClip` (FerroUI overlay).
1104    pub fn set_composition_clip(&self, host: &dyn CompositionVisualHooks, value: Option<Rc<dyn ICompositionObject>>) {
1105        let mut changed = false;
1106        let old_value = self.composition_clip.borrow().clone();
1107        if old_value.differs(&value) {
1108            CompositionVisualHooks::validate_composition_clip_change(host, &old_value, &value);
1109            CompositionVisualHooks::on_composition_clip_changing(host);
1110            changed = true;
1111            // Update the backing value
1112            *self.composition_clip.borrow_mut() = value.clone();
1113            // Register object for serialization in the next batch
1114            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::COMPOSITION_CLIP);
1115            host.register_for_serialization();
1116        }
1117        *self.composition_clip.borrow_mut() = value;
1118        if changed {
1119            CompositionVisualHooks::on_composition_clip_changed(host);
1120        }
1121    }
1122
1123    /// `RotationAxis` (animated, default `Vector3D::new(0.0, 0.0, 1.0)`, FerroUI overlay).
1124    pub fn rotation_axis(&self) -> Vector3D {
1125        self.rotation_axis.get()
1126    }
1127
1128    /// Sets `RotationAxis` (animated, default `Vector3D::new(0.0, 0.0, 1.0)`, FerroUI overlay).
1129    pub fn set_rotation_axis(&self, host: &dyn CompositionVisualHooks, value: Vector3D) {
1130        let mut changed = false;
1131        let old_value = self.rotation_axis.get();
1132        if old_value.differs(&value) {
1133            CompositionVisualHooks::validate_rotation_axis_change(host, old_value, value);
1134            CompositionVisualHooks::on_rotation_axis_changing(host);
1135            changed = true;
1136            // Update the backing value
1137            self.rotation_axis.set(value);
1138            // Register object for serialization in the next batch
1139            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROTATION_AXIS);
1140            host.register_for_serialization();
1141            // Reset previous animation if any
1142            host.pending_animations().remove(ServerCompositionVisualProps::id_of_rotation_axis_property().base());
1143            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::ROTATION_AXIS_ANIMATED);
1144            // Check for implicit animations
1145            if let Some(animation) = host.implicit_animation("RotationAxis") {
1146                // Animation affects only current property
1147                if let Some(a) = animation.as_composition_animation() {
1148                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROTATION_AXIS_ANIMATED);
1149                    host.pending_animations().set(
1150                        ServerCompositionVisualProps::id_of_rotation_axis_property().base(),
1151                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
1152                    );
1153                }
1154                // Animation is triggered by the current field, but does not necessary affects it
1155                host.start_animation_group(&animation, "RotationAxis", ExpressionVariant::create(value));
1156            }
1157        }
1158        self.rotation_axis.set(value);
1159        if changed {
1160            CompositionVisualHooks::on_rotation_axis_changed(host);
1161        }
1162    }
1163
1164    /// `RelativeOffsetAdjustment` (animated, FerroUI overlay).
1165    pub fn relative_offset_adjustment(&self) -> Vector3D {
1166        self.relative_offset_adjustment.get()
1167    }
1168
1169    /// Sets `RelativeOffsetAdjustment` (animated, FerroUI overlay).
1170    pub fn set_relative_offset_adjustment(&self, host: &dyn CompositionVisualHooks, value: Vector3D) {
1171        let mut changed = false;
1172        let old_value = self.relative_offset_adjustment.get();
1173        if old_value.differs(&value) {
1174            CompositionVisualHooks::validate_relative_offset_adjustment_change(host, old_value, value);
1175            CompositionVisualHooks::on_relative_offset_adjustment_changing(host);
1176            changed = true;
1177            // Update the backing value
1178            self.relative_offset_adjustment.set(value);
1179            // Register object for serialization in the next batch
1180            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::RELATIVE_OFFSET_ADJUSTMENT);
1181            host.register_for_serialization();
1182            // Reset previous animation if any
1183            host.pending_animations().remove(ServerCompositionVisualProps::id_of_relative_offset_adjustment_property().base());
1184            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::RELATIVE_OFFSET_ADJUSTMENT_ANIMATED);
1185            // Check for implicit animations
1186            if let Some(animation) = host.implicit_animation("RelativeOffsetAdjustment") {
1187                // Animation affects only current property
1188                if let Some(a) = animation.as_composition_animation() {
1189                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::RELATIVE_OFFSET_ADJUSTMENT_ANIMATED);
1190                    host.pending_animations().set(
1191                        ServerCompositionVisualProps::id_of_relative_offset_adjustment_property().base(),
1192                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
1193                    );
1194                }
1195                // Animation is triggered by the current field, but does not necessary affects it
1196                host.start_animation_group(&animation, "RelativeOffsetAdjustment", ExpressionVariant::create(value));
1197            }
1198        }
1199        self.relative_offset_adjustment.set(value);
1200        if changed {
1201            CompositionVisualHooks::on_relative_offset_adjustment_changed(host);
1202        }
1203    }
1204
1205    /// `RelativeSizeAdjustment` (animated, FerroUI overlay).
1206    pub fn relative_size_adjustment(&self) -> Vector {
1207        self.relative_size_adjustment.get()
1208    }
1209
1210    /// Sets `RelativeSizeAdjustment` (animated, FerroUI overlay).
1211    pub fn set_relative_size_adjustment(&self, host: &dyn CompositionVisualHooks, value: Vector) {
1212        let mut changed = false;
1213        let old_value = self.relative_size_adjustment.get();
1214        if old_value.differs(&value) {
1215            CompositionVisualHooks::validate_relative_size_adjustment_change(host, old_value, value);
1216            CompositionVisualHooks::on_relative_size_adjustment_changing(host);
1217            changed = true;
1218            // Update the backing value
1219            self.relative_size_adjustment.set(value);
1220            // Register object for serialization in the next batch
1221            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::RELATIVE_SIZE_ADJUSTMENT);
1222            host.register_for_serialization();
1223            // Reset previous animation if any
1224            host.pending_animations().remove(ServerCompositionVisualProps::id_of_relative_size_adjustment_property().base());
1225            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::RELATIVE_SIZE_ADJUSTMENT_ANIMATED);
1226            // Check for implicit animations
1227            if let Some(animation) = host.implicit_animation("RelativeSizeAdjustment") {
1228                // Animation affects only current property
1229                if let Some(a) = animation.as_composition_animation() {
1230                    self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::RELATIVE_SIZE_ADJUSTMENT_ANIMATED);
1231                    host.pending_animations().set(
1232                        ServerCompositionVisualProps::id_of_relative_size_adjustment_property().base(),
1233                        a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
1234                    );
1235                }
1236                // Animation is triggered by the current field, but does not necessary affects it
1237                host.start_animation_group(&animation, "RelativeSizeAdjustment", ExpressionVariant::create(value));
1238            }
1239        }
1240        self.relative_size_adjustment.set(value);
1241        if changed {
1242            CompositionVisualHooks::on_relative_size_adjustment_changed(host);
1243        }
1244    }
1245
1246    /// `IsHitTestVisible` (default `true`, FerroUI overlay).
1247    pub fn is_hit_test_visible(&self) -> bool {
1248        self.is_hit_test_visible.get()
1249    }
1250
1251    /// Sets `IsHitTestVisible` (default `true`, FerroUI overlay).
1252    pub fn set_is_hit_test_visible(&self, host: &dyn CompositionVisualHooks, value: bool) {
1253        let mut changed = false;
1254        let old_value = self.is_hit_test_visible.get();
1255        if old_value.differs(&value) {
1256            CompositionVisualHooks::validate_is_hit_test_visible_change(host, old_value, value);
1257            CompositionVisualHooks::on_is_hit_test_visible_changing(host);
1258            changed = true;
1259            // Update the backing value
1260            self.is_hit_test_visible.set(value);
1261            // Register object for serialization in the next batch
1262            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::IS_HIT_TEST_VISIBLE);
1263            host.register_for_serialization();
1264        }
1265        self.is_hit_test_visible.set(value);
1266        if changed {
1267            CompositionVisualHooks::on_is_hit_test_visible_changed(host);
1268        }
1269    }
1270
1271    /// `IsPixelSnappingEnabled` (FerroUI overlay).
1272    pub fn is_pixel_snapping_enabled(&self) -> bool {
1273        self.is_pixel_snapping_enabled.get()
1274    }
1275
1276    /// Sets `IsPixelSnappingEnabled` (FerroUI overlay).
1277    pub fn set_is_pixel_snapping_enabled(&self, host: &dyn CompositionVisualHooks, value: bool) {
1278        let mut changed = false;
1279        let old_value = self.is_pixel_snapping_enabled.get();
1280        if old_value.differs(&value) {
1281            CompositionVisualHooks::validate_is_pixel_snapping_enabled_change(host, old_value, value);
1282            CompositionVisualHooks::on_is_pixel_snapping_enabled_changing(host);
1283            changed = true;
1284            // Update the backing value
1285            self.is_pixel_snapping_enabled.set(value);
1286            // Register object for serialization in the next batch
1287            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::IS_PIXEL_SNAPPING_ENABLED);
1288            host.register_for_serialization();
1289        }
1290        self.is_pixel_snapping_enabled.set(value);
1291        if changed {
1292            CompositionVisualHooks::on_is_pixel_snapping_enabled_changed(host);
1293        }
1294    }
1295
1296    /// `BorderMode` (FerroUI overlay).
1297    pub fn border_mode(&self) -> CompositionBorderMode {
1298        self.border_mode.get()
1299    }
1300
1301    /// Sets `BorderMode` (FerroUI overlay).
1302    pub fn set_border_mode(&self, host: &dyn CompositionVisualHooks, value: CompositionBorderMode) {
1303        let mut changed = false;
1304        let old_value = self.border_mode.get();
1305        if old_value.differs(&value) {
1306            CompositionVisualHooks::validate_border_mode_change(host, old_value, value);
1307            CompositionVisualHooks::on_border_mode_changing(host);
1308            changed = true;
1309            // Update the backing value
1310            self.border_mode.set(value);
1311            // Register object for serialization in the next batch
1312            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::BORDER_MODE);
1313            host.register_for_serialization();
1314        }
1315        self.border_mode.set(value);
1316        if changed {
1317            CompositionVisualHooks::on_border_mode_changed(host);
1318        }
1319    }
1320
1321    /// `BackfaceVisibility` (FerroUI overlay).
1322    pub fn backface_visibility(&self) -> CompositionBackfaceVisibility {
1323        self.backface_visibility.get()
1324    }
1325
1326    /// Sets `BackfaceVisibility` (FerroUI overlay).
1327    pub fn set_backface_visibility(&self, host: &dyn CompositionVisualHooks, value: CompositionBackfaceVisibility) {
1328        let mut changed = false;
1329        let old_value = self.backface_visibility.get();
1330        if old_value.differs(&value) {
1331            CompositionVisualHooks::validate_backface_visibility_change(host, old_value, value);
1332            CompositionVisualHooks::on_backface_visibility_changing(host);
1333            changed = true;
1334            // Update the backing value
1335            self.backface_visibility.set(value);
1336            // Register object for serialization in the next batch
1337            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::BACKFACE_VISIBILITY);
1338            host.register_for_serialization();
1339        }
1340        self.backface_visibility.set(value);
1341        if changed {
1342            CompositionVisualHooks::on_backface_visibility_changed(host);
1343        }
1344    }
1345
1346    /// `CompositeMode` (FerroUI overlay).
1347    pub fn composite_mode(&self) -> CompositionCompositeMode {
1348        self.composite_mode.get()
1349    }
1350
1351    /// Sets `CompositeMode` (FerroUI overlay).
1352    pub fn set_composite_mode(&self, host: &dyn CompositionVisualHooks, value: CompositionCompositeMode) {
1353        let mut changed = false;
1354        let old_value = self.composite_mode.get();
1355        if old_value.differs(&value) {
1356            CompositionVisualHooks::validate_composite_mode_change(host, old_value, value);
1357            CompositionVisualHooks::on_composite_mode_changing(host);
1358            changed = true;
1359            // Update the backing value
1360            self.composite_mode.set(value);
1361            // Register object for serialization in the next batch
1362            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::COMPOSITE_MODE);
1363            host.register_for_serialization();
1364        }
1365        self.composite_mode.set(value);
1366        if changed {
1367            CompositionVisualHooks::on_composite_mode_changed(host);
1368        }
1369    }
1370
1371    /// `ParentForTransform` (FerroUI overlay).
1372    pub fn parent_for_transform(&self) -> Option<Rc<dyn ICompositionObject>> {
1373        self.parent_for_transform.borrow().clone()
1374    }
1375
1376    /// Sets `ParentForTransform` (FerroUI overlay).
1377    pub fn set_parent_for_transform(&self, host: &dyn CompositionVisualHooks, value: Option<Rc<dyn ICompositionObject>>) {
1378        let mut changed = false;
1379        let old_value = self.parent_for_transform.borrow().clone();
1380        if old_value.differs(&value) {
1381            CompositionVisualHooks::validate_parent_for_transform_change(host, &old_value, &value);
1382            CompositionVisualHooks::on_parent_for_transform_changing(host);
1383            changed = true;
1384            // Update the backing value
1385            *self.parent_for_transform.borrow_mut() = value.clone();
1386            // Register object for serialization in the next batch
1387            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::PARENT_FOR_TRANSFORM);
1388            host.register_for_serialization();
1389        }
1390        *self.parent_for_transform.borrow_mut() = value;
1391        if changed {
1392            CompositionVisualHooks::on_parent_for_transform_changed(host);
1393        }
1394    }
1395
1396    /// Connects an animation with the named property. Returns `false` when
1397    /// neither this class nor its generated bases have an animated property
1398    /// of that name: the caller continues with its hand-written base.
1399    pub fn start_animation(
1400        &self,
1401        host: &dyn CompositionVisualHooks,
1402        property_name: &str,
1403        animation: &dyn ICompositionAnimation,
1404        final_value: Option<ExpressionVariant>,
1405    ) -> bool {
1406        if property_name == "Visible" {
1407            let server = animation.create_instance(host.server(), final_value);
1408            host.pending_animations().set(ServerCompositionVisualProps::id_of_visible_property().base(), server);
1409            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::VISIBLE_ANIMATED);
1410            host.register_for_serialization();
1411            return true;
1412        }
1413        if property_name == "Opacity" {
1414            let server = animation.create_instance(host.server(), final_value);
1415            host.pending_animations().set(ServerCompositionVisualProps::id_of_opacity_property().base(), server);
1416            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OPACITY_ANIMATED);
1417            host.register_for_serialization();
1418            return true;
1419        }
1420        if property_name == "ClipToBounds" {
1421            let server = animation.create_instance(host.server(), final_value);
1422            host.pending_animations().set(ServerCompositionVisualProps::id_of_clip_to_bounds_property().base(), server);
1423            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CLIP_TO_BOUNDS_ANIMATED);
1424            host.register_for_serialization();
1425            return true;
1426        }
1427        if property_name == "Offset" {
1428            let server = animation.create_instance(host.server(), final_value);
1429            host.pending_animations().set(ServerCompositionVisualProps::id_of_offset_property().base(), server);
1430            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OFFSET_ANIMATED);
1431            host.register_for_serialization();
1432            return true;
1433        }
1434        if property_name == "Translation" {
1435            let server = animation.create_instance(host.server(), final_value);
1436            host.pending_animations().set(ServerCompositionVisualProps::id_of_translation_property().base(), server);
1437            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSLATION_ANIMATED);
1438            host.register_for_serialization();
1439            return true;
1440        }
1441        if property_name == "Size" {
1442            let server = animation.create_instance(host.server(), final_value);
1443            host.pending_animations().set(ServerCompositionVisualProps::id_of_size_property().base(), server);
1444            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SIZE_ANIMATED);
1445            host.register_for_serialization();
1446            return true;
1447        }
1448        if property_name == "AnchorPoint" {
1449            let server = animation.create_instance(host.server(), final_value);
1450            host.pending_animations().set(ServerCompositionVisualProps::id_of_anchor_point_property().base(), server);
1451            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ANCHOR_POINT_ANIMATED);
1452            host.register_for_serialization();
1453            return true;
1454        }
1455        if property_name == "CenterPoint" {
1456            let server = animation.create_instance(host.server(), final_value);
1457            host.pending_animations().set(ServerCompositionVisualProps::id_of_center_point_property().base(), server);
1458            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CENTER_POINT_ANIMATED);
1459            host.register_for_serialization();
1460            return true;
1461        }
1462        if property_name == "RotationAngle" {
1463            let server = animation.create_instance(host.server(), final_value);
1464            host.pending_animations().set(ServerCompositionVisualProps::id_of_rotation_angle_property().base(), server);
1465            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROTATION_ANGLE_ANIMATED);
1466            host.register_for_serialization();
1467            return true;
1468        }
1469        if property_name == "Orientation" {
1470            let server = animation.create_instance(host.server(), final_value);
1471            host.pending_animations().set(ServerCompositionVisualProps::id_of_orientation_property().base(), server);
1472            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ORIENTATION_ANIMATED);
1473            host.register_for_serialization();
1474            return true;
1475        }
1476        if property_name == "Scale" {
1477            let server = animation.create_instance(host.server(), final_value);
1478            host.pending_animations().set(ServerCompositionVisualProps::id_of_scale_property().base(), server);
1479            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SCALE_ANIMATED);
1480            host.register_for_serialization();
1481            return true;
1482        }
1483        if property_name == "TransformMatrix" {
1484            let server = animation.create_instance(host.server(), final_value);
1485            host.pending_animations().set(ServerCompositionVisualProps::id_of_transform_matrix_property().base(), server);
1486            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSFORM_MATRIX_ANIMATED);
1487            host.register_for_serialization();
1488            return true;
1489        }
1490        if property_name == "RotationAxis" {
1491            let server = animation.create_instance(host.server(), final_value);
1492            host.pending_animations().set(ServerCompositionVisualProps::id_of_rotation_axis_property().base(), server);
1493            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROTATION_AXIS_ANIMATED);
1494            host.register_for_serialization();
1495            return true;
1496        }
1497        if property_name == "RelativeOffsetAdjustment" {
1498            let server = animation.create_instance(host.server(), final_value);
1499            host.pending_animations().set(ServerCompositionVisualProps::id_of_relative_offset_adjustment_property().base(), server);
1500            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::RELATIVE_OFFSET_ADJUSTMENT_ANIMATED);
1501            host.register_for_serialization();
1502            return true;
1503        }
1504        if property_name == "RelativeSizeAdjustment" {
1505            let server = animation.create_instance(host.server(), final_value);
1506            host.pending_animations().set(ServerCompositionVisualProps::id_of_relative_size_adjustment_property().base(), server);
1507            self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::RELATIVE_SIZE_ADJUSTMENT_ANIMATED);
1508            host.register_for_serialization();
1509            return true;
1510        }
1511        false
1512    }
1513
1514    /// Writes the changes of the object: the base class first, then the
1515    /// changed-fields mask and the changed members of this class.
1516    pub fn serialize_changes_core(&self, host: &dyn CompositionVisualHooks, writer: &mut BatchStreamWriter<'_>) {
1517        let changed = self.changed_fields_of_composition_visual.get();
1518        writer.write(changed);
1519        if changed.contains(CompositionVisualChangedFields::ROOT) {
1520            writer.write_server_object(self.root.borrow().clone().map(|o| o.server()));
1521        }
1522        if changed.contains(CompositionVisualChangedFields::PARENT) {
1523            writer.write_server_object(self.parent.borrow().clone().map(|o| o.server()));
1524        }
1525        if changed.contains(CompositionVisualChangedFields::VISIBLE_ANIMATED) {
1526            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_visible_property().base()));
1527        } else if changed.contains(CompositionVisualChangedFields::VISIBLE) {
1528            writer.write(self.visible.get());
1529        }
1530        if changed.contains(CompositionVisualChangedFields::OPACITY_ANIMATED) {
1531            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_opacity_property().base()));
1532        } else if changed.contains(CompositionVisualChangedFields::OPACITY) {
1533            writer.write(self.opacity.get());
1534        }
1535        if changed.contains(CompositionVisualChangedFields::CLIP) {
1536            writer.write_value(self.clip.borrow().clone());
1537        }
1538        if changed.contains(CompositionVisualChangedFields::CLIP_TO_BOUNDS_ANIMATED) {
1539            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_clip_to_bounds_property().base()));
1540        } else if changed.contains(CompositionVisualChangedFields::CLIP_TO_BOUNDS) {
1541            writer.write(self.clip_to_bounds.get());
1542        }
1543        if changed.contains(CompositionVisualChangedFields::OFFSET_ANIMATED) {
1544            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_offset_property().base()));
1545        } else if changed.contains(CompositionVisualChangedFields::OFFSET) {
1546            writer.write(self.offset.get());
1547        }
1548        if changed.contains(CompositionVisualChangedFields::TRANSLATION_ANIMATED) {
1549            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_translation_property().base()));
1550        } else if changed.contains(CompositionVisualChangedFields::TRANSLATION) {
1551            writer.write(self.translation.get());
1552        }
1553        if changed.contains(CompositionVisualChangedFields::SIZE_ANIMATED) {
1554            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_size_property().base()));
1555        } else if changed.contains(CompositionVisualChangedFields::SIZE) {
1556            writer.write(self.size.get());
1557        }
1558        if changed.contains(CompositionVisualChangedFields::ANCHOR_POINT_ANIMATED) {
1559            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_anchor_point_property().base()));
1560        } else if changed.contains(CompositionVisualChangedFields::ANCHOR_POINT) {
1561            writer.write(self.anchor_point.get());
1562        }
1563        if changed.contains(CompositionVisualChangedFields::CENTER_POINT_ANIMATED) {
1564            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_center_point_property().base()));
1565        } else if changed.contains(CompositionVisualChangedFields::CENTER_POINT) {
1566            writer.write(self.center_point.get());
1567        }
1568        if changed.contains(CompositionVisualChangedFields::ROTATION_ANGLE_ANIMATED) {
1569            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_rotation_angle_property().base()));
1570        } else if changed.contains(CompositionVisualChangedFields::ROTATION_ANGLE) {
1571            writer.write(self.rotation_angle.get());
1572        }
1573        if changed.contains(CompositionVisualChangedFields::ORIENTATION_ANIMATED) {
1574            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_orientation_property().base()));
1575        } else if changed.contains(CompositionVisualChangedFields::ORIENTATION) {
1576            writer.write(self.orientation.get());
1577        }
1578        if changed.contains(CompositionVisualChangedFields::SCALE_ANIMATED) {
1579            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_scale_property().base()));
1580        } else if changed.contains(CompositionVisualChangedFields::SCALE) {
1581            writer.write(self.scale.get());
1582        }
1583        if changed.contains(CompositionVisualChangedFields::TRANSFORM_MATRIX_ANIMATED) {
1584            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_transform_matrix_property().base()));
1585        } else if changed.contains(CompositionVisualChangedFields::TRANSFORM_MATRIX) {
1586            writer.write(self.transform_matrix.get());
1587        }
1588        if changed.contains(CompositionVisualChangedFields::ADORNED_VISUAL) {
1589            writer.write_server_object(self.adorned_visual.borrow().clone().map(|o| o.server()));
1590        }
1591        if changed.contains(CompositionVisualChangedFields::ADORNER_IS_CLIPPED) {
1592            writer.write(self.adorner_is_clipped.get());
1593        }
1594        if changed.contains(CompositionVisualChangedFields::OPACITY_MASK_BRUSH) {
1595            writer.write_resource(self.opacity_mask_brush.borrow().clone());
1596        }
1597        if changed.contains(CompositionVisualChangedFields::EFFECT) {
1598            writer.write_value(self.effect.borrow().clone());
1599        }
1600        if changed.contains(CompositionVisualChangedFields::RENDER_OPTIONS) {
1601            writer.write(self.render_options.get());
1602        }
1603        if changed.contains(CompositionVisualChangedFields::TEXT_OPTIONS) {
1604            writer.write(self.text_options.get());
1605        }
1606        if changed.contains(CompositionVisualChangedFields::CACHE_MODE) {
1607            writer.write_server_object(self.cache_mode.borrow().clone().map(|o| o.server()));
1608        }
1609        if changed.contains(CompositionVisualChangedFields::COMPOSITION_CLIP) {
1610            writer.write_server_object(self.composition_clip.borrow().clone().map(|o| o.server()));
1611        }
1612        if changed.contains(CompositionVisualChangedFields::ROTATION_AXIS_ANIMATED) {
1613            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_rotation_axis_property().base()));
1614        } else if changed.contains(CompositionVisualChangedFields::ROTATION_AXIS) {
1615            writer.write(self.rotation_axis.get());
1616        }
1617        if changed.contains(CompositionVisualChangedFields::RELATIVE_OFFSET_ADJUSTMENT_ANIMATED) {
1618            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_relative_offset_adjustment_property().base()));
1619        } else if changed.contains(CompositionVisualChangedFields::RELATIVE_OFFSET_ADJUSTMENT) {
1620            writer.write(self.relative_offset_adjustment.get());
1621        }
1622        if changed.contains(CompositionVisualChangedFields::RELATIVE_SIZE_ADJUSTMENT_ANIMATED) {
1623            writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_relative_size_adjustment_property().base()));
1624        } else if changed.contains(CompositionVisualChangedFields::RELATIVE_SIZE_ADJUSTMENT) {
1625            writer.write(self.relative_size_adjustment.get());
1626        }
1627        if changed.contains(CompositionVisualChangedFields::IS_HIT_TEST_VISIBLE) {
1628            writer.write(self.is_hit_test_visible.get());
1629        }
1630        if changed.contains(CompositionVisualChangedFields::IS_PIXEL_SNAPPING_ENABLED) {
1631            writer.write(self.is_pixel_snapping_enabled.get());
1632        }
1633        if changed.contains(CompositionVisualChangedFields::BORDER_MODE) {
1634            writer.write(self.border_mode.get());
1635        }
1636        if changed.contains(CompositionVisualChangedFields::BACKFACE_VISIBILITY) {
1637            writer.write(self.backface_visibility.get());
1638        }
1639        if changed.contains(CompositionVisualChangedFields::COMPOSITE_MODE) {
1640            writer.write(self.composite_mode.get());
1641        }
1642        if changed.contains(CompositionVisualChangedFields::PARENT_FOR_TRANSFORM) {
1643            writer.write_server_object(self.parent_for_transform.borrow().clone().map(|o| o.server()));
1644        }
1645        self.changed_fields_of_composition_visual.set(CompositionVisualChangedFields::empty());
1646    }
1647}
1648
1649/// The partial methods of `ServerCompositionVisual`: implemented by the class that embeds
1650/// [`ServerCompositionVisualProps`]. Every hook defaults to doing nothing.
1651pub trait ServerCompositionVisualHooks: IServerAnimatedPropertyHost {
1652    fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
1653    fn on_fields_deserialized(&self, _changed: CompositionVisualChangedFields) {}
1654
1655    fn on_root_changed(&self) {}
1656    fn on_root_changing(&self) {}
1657
1658    fn on_parent_changed(&self) {}
1659    fn on_parent_changing(&self) {}
1660
1661    fn on_clip_changed(&self) {}
1662    fn on_clip_changing(&self) {}
1663
1664    fn on_adorned_visual_changed(&self) {}
1665    fn on_adorned_visual_changing(&self) {}
1666
1667    fn on_adorner_is_clipped_changed(&self) {}
1668    fn on_adorner_is_clipped_changing(&self) {}
1669
1670    fn on_opacity_mask_brush_changed(&self) {}
1671    fn on_opacity_mask_brush_changing(&self) {}
1672
1673    fn on_effect_changed(&self) {}
1674    fn on_effect_changing(&self) {}
1675
1676    fn on_render_options_changed(&self) {}
1677    fn on_render_options_changing(&self) {}
1678
1679    fn on_text_options_changed(&self) {}
1680    fn on_text_options_changing(&self) {}
1681
1682    fn on_cache_mode_changed(&self) {}
1683    fn on_cache_mode_changing(&self) {}
1684
1685    fn on_composition_clip_changed(&self) {}
1686    fn on_composition_clip_changing(&self) {}
1687
1688    fn on_is_hit_test_visible_changed(&self) {}
1689    fn on_is_hit_test_visible_changing(&self) {}
1690
1691    fn on_is_pixel_snapping_enabled_changed(&self) {}
1692    fn on_is_pixel_snapping_enabled_changing(&self) {}
1693
1694    fn on_border_mode_changed(&self) {}
1695    fn on_border_mode_changing(&self) {}
1696
1697    fn on_backface_visibility_changed(&self) {}
1698    fn on_backface_visibility_changing(&self) {}
1699
1700    fn on_composite_mode_changed(&self) {}
1701    fn on_composite_mode_changing(&self) {}
1702
1703    fn on_parent_for_transform_changed(&self) {}
1704    fn on_parent_for_transform_changing(&self) {}
1705}
1706
1707/// The server-side properties of `ServerCompositionVisual`.
1708pub struct ServerCompositionVisualProps {
1709    root: RefCell<Option<Rc<dyn IServerObject>>>,
1710    parent: RefCell<Option<Rc<dyn IServerObject>>>,
1711    visible: Cell<bool>,
1712    opacity: Cell<f32>,
1713    clip: RefCell<Option<Arc<dyn IGeometryImpl>>>,
1714    clip_to_bounds: Cell<bool>,
1715    offset: Cell<Vector3D>,
1716    translation: Cell<Vector3D>,
1717    size: Cell<Vector>,
1718    anchor_point: Cell<Vector>,
1719    center_point: Cell<Vector3D>,
1720    rotation_angle: Cell<f32>,
1721    orientation: Cell<Quaternion>,
1722    scale: Cell<Vector3D>,
1723    transform_matrix: Cell<Matrix>,
1724    adorned_visual: RefCell<Option<Rc<dyn IServerObject>>>,
1725    adorner_is_clipped: Cell<bool>,
1726    opacity_mask_brush: RefCell<Option<ServerResourceRef<dyn IBrush>>>,
1727    effect: RefCell<Option<Arc<dyn IImmutableEffect>>>,
1728    render_options: Cell<RenderOptions>,
1729    text_options: Cell<TextOptions>,
1730    cache_mode: RefCell<Option<Rc<dyn IServerObject>>>,
1731    composition_clip: RefCell<Option<Rc<dyn IServerObject>>>,
1732    rotation_axis: Cell<Vector3D>,
1733    relative_offset_adjustment: Cell<Vector3D>,
1734    relative_size_adjustment: Cell<Vector>,
1735    is_hit_test_visible: Cell<bool>,
1736    is_pixel_snapping_enabled: Cell<bool>,
1737    border_mode: Cell<CompositionBorderMode>,
1738    backface_visibility: Cell<CompositionBackfaceVisibility>,
1739    composite_mode: Cell<CompositionCompositeMode>,
1740    parent_for_transform: RefCell<Option<Rc<dyn IServerObject>>>,
1741}
1742
1743impl Default for ServerCompositionVisualProps {
1744    fn default() -> Self {
1745        Self::new()
1746    }
1747}
1748
1749impl ServerCompositionVisualProps {
1750    /// Creates the properties with every field at the default of its type; the
1751    /// values of the UI thread arrive with the first batch.
1752    pub fn new() -> Self {
1753        Self {
1754            root: RefCell::new(None),
1755            parent: RefCell::new(None),
1756            visible: Cell::new(Default::default()),
1757            opacity: Cell::new(Default::default()),
1758            clip: RefCell::new(None),
1759            clip_to_bounds: Cell::new(Default::default()),
1760            offset: Cell::new(Default::default()),
1761            translation: Cell::new(Default::default()),
1762            size: Cell::new(Default::default()),
1763            anchor_point: Cell::new(Default::default()),
1764            center_point: Cell::new(Default::default()),
1765            rotation_angle: Cell::new(Default::default()),
1766            orientation: Cell::new(Default::default()),
1767            scale: Cell::new(Default::default()),
1768            transform_matrix: Cell::new(Default::default()),
1769            adorned_visual: RefCell::new(None),
1770            adorner_is_clipped: Cell::new(Default::default()),
1771            opacity_mask_brush: RefCell::new(None),
1772            effect: RefCell::new(None),
1773            render_options: Cell::new(Default::default()),
1774            text_options: Cell::new(Default::default()),
1775            cache_mode: RefCell::new(None),
1776            composition_clip: RefCell::new(None),
1777            rotation_axis: Cell::new(Default::default()),
1778            relative_offset_adjustment: Cell::new(Default::default()),
1779            relative_size_adjustment: Cell::new(Default::default()),
1780            is_hit_test_visible: Cell::new(Default::default()),
1781            is_pixel_snapping_enabled: Cell::new(Default::default()),
1782            border_mode: Cell::new(Default::default()),
1783            backface_visibility: Cell::new(Default::default()),
1784            composite_mode: Cell::new(Default::default()),
1785            parent_for_transform: RefCell::new(None),
1786        }
1787    }
1788
1789    /// This block or the block of a base class, by type: what
1790    /// `IServerObject::get_props` of the embedding class returns.
1791    pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
1792        if type_id == TypeId::of::<Self>() {
1793            return Some(self);
1794        }
1795        None
1796    }
1797
1798    /// The composition property of `Root`.
1799    pub fn id_of_root_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
1800        static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
1801        PROPERTY.get_or_init(|| {
1802            CompositionProperty::register::<ServerCompositionVisualProps, Option<Rc<dyn IServerObject>>>(
1803                "Root",
1804                "ServerCompositionVisual",
1805                |obj| props_of::<ServerCompositionVisualProps>(obj).root.borrow().clone(),
1806                |obj, v| *props_of::<ServerCompositionVisualProps>(obj).root.borrow_mut() = v,
1807                None,
1808                None,
1809            )
1810        })
1811    }
1812
1813    /// `Root`.
1814    pub fn root(&self) -> Option<Rc<dyn IServerObject>> {
1815        self.root.borrow().clone()
1816    }
1817
1818    pub fn set_root(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Rc<dyn IServerObject>>) {
1819        let old_value = self.root.borrow().clone();
1820        let mut changed = false;
1821        if old_value.differs(&value) {
1822            ServerCompositionVisualHooks::on_root_changing(host);
1823            changed = true;
1824        }
1825        host.set_value(
1826            Self::id_of_root_property().base(),
1827            ServerValueChange {
1828                equal: old_value.default_equals(&value),
1829                old_resource: old_value.as_server_render_resource(),
1830                new_resource: value.as_server_render_resource(),
1831                assign: &mut || *self.root.borrow_mut() = value.clone(),
1832            },
1833        );
1834        if changed {
1835            ServerCompositionVisualHooks::on_root_changed(host);
1836        }
1837    }
1838
1839    /// The composition property of `Parent`.
1840    pub fn id_of_parent_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
1841        static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
1842        PROPERTY.get_or_init(|| {
1843            CompositionProperty::register::<ServerCompositionVisualProps, Option<Rc<dyn IServerObject>>>(
1844                "Parent",
1845                "ServerCompositionVisual",
1846                |obj| props_of::<ServerCompositionVisualProps>(obj).parent.borrow().clone(),
1847                |obj, v| *props_of::<ServerCompositionVisualProps>(obj).parent.borrow_mut() = v,
1848                None,
1849                None,
1850            )
1851        })
1852    }
1853
1854    /// `Parent`.
1855    pub fn parent(&self) -> Option<Rc<dyn IServerObject>> {
1856        self.parent.borrow().clone()
1857    }
1858
1859    pub fn set_parent(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Rc<dyn IServerObject>>) {
1860        let old_value = self.parent.borrow().clone();
1861        let mut changed = false;
1862        if old_value.differs(&value) {
1863            ServerCompositionVisualHooks::on_parent_changing(host);
1864            changed = true;
1865        }
1866        host.set_value(
1867            Self::id_of_parent_property().base(),
1868            ServerValueChange {
1869                equal: old_value.default_equals(&value),
1870                old_resource: old_value.as_server_render_resource(),
1871                new_resource: value.as_server_render_resource(),
1872                assign: &mut || *self.parent.borrow_mut() = value.clone(),
1873            },
1874        );
1875        if changed {
1876            ServerCompositionVisualHooks::on_parent_changed(host);
1877        }
1878    }
1879
1880    /// The composition property of `Visible`.
1881    pub fn id_of_visible_property() -> &'static CompositionPropertyOf<bool> {
1882        static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
1883        PROPERTY.get_or_init(|| {
1884            CompositionProperty::register::<ServerCompositionVisualProps, bool>(
1885                "Visible",
1886                "ServerCompositionVisual",
1887                |obj| props_of::<ServerCompositionVisualProps>(obj).visible.get(),
1888                |obj, v| props_of::<ServerCompositionVisualProps>(obj).visible.set(v),
1889                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).visible.get())),
1890                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).visible.set(v.cast_or_default::<bool>())),
1891            )
1892        })
1893    }
1894
1895    /// `Visible` (animated).
1896    pub fn visible(&self) -> bool {
1897        self.visible.get()
1898    }
1899
1900    pub fn set_visible(&self, host: &dyn ServerCompositionVisualHooks, value: bool) {
1901        self.visible.set(value);
1902        host.remove_animation_for_property(Self::id_of_visible_property().base());
1903    }
1904
1905    /// The composition property of `Opacity`.
1906    pub fn id_of_opacity_property() -> &'static CompositionPropertyOf<f32> {
1907        static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
1908        PROPERTY.get_or_init(|| {
1909            CompositionProperty::register::<ServerCompositionVisualProps, f32>(
1910                "Opacity",
1911                "ServerCompositionVisual",
1912                |obj| props_of::<ServerCompositionVisualProps>(obj).opacity.get(),
1913                |obj, v| props_of::<ServerCompositionVisualProps>(obj).opacity.set(v),
1914                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).opacity.get())),
1915                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).opacity.set(v.cast_or_default::<f32>())),
1916            )
1917        })
1918    }
1919
1920    /// `Opacity` (animated).
1921    pub fn opacity(&self) -> f32 {
1922        self.opacity.get()
1923    }
1924
1925    pub fn set_opacity(&self, host: &dyn ServerCompositionVisualHooks, value: f32) {
1926        self.opacity.set(value);
1927        host.remove_animation_for_property(Self::id_of_opacity_property().base());
1928    }
1929
1930    /// The composition property of `Clip`.
1931    pub fn id_of_clip_property() -> &'static CompositionPropertyOf<Option<Arc<dyn IGeometryImpl>>> {
1932        static PROPERTY: OnceLock<CompositionPropertyOf<Option<Arc<dyn IGeometryImpl>>>> = OnceLock::new();
1933        PROPERTY.get_or_init(|| {
1934            CompositionProperty::register::<ServerCompositionVisualProps, Option<Arc<dyn IGeometryImpl>>>(
1935                "Clip",
1936                "ServerCompositionVisual",
1937                |obj| props_of::<ServerCompositionVisualProps>(obj).clip.borrow().clone(),
1938                |obj, v| *props_of::<ServerCompositionVisualProps>(obj).clip.borrow_mut() = v,
1939                None,
1940                None,
1941            )
1942        })
1943    }
1944
1945    /// `Clip`.
1946    pub fn clip(&self) -> Option<Arc<dyn IGeometryImpl>> {
1947        self.clip.borrow().clone()
1948    }
1949
1950    pub fn set_clip(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Arc<dyn IGeometryImpl>>) {
1951        let old_value = self.clip.borrow().clone();
1952        let mut changed = false;
1953        if old_value.differs(&value) {
1954            ServerCompositionVisualHooks::on_clip_changing(host);
1955            changed = true;
1956        }
1957        host.set_value(
1958            Self::id_of_clip_property().base(),
1959            ServerValueChange {
1960                equal: old_value.default_equals(&value),
1961                old_resource: None,
1962                new_resource: None,
1963                assign: &mut || *self.clip.borrow_mut() = value.clone(),
1964            },
1965        );
1966        if changed {
1967            ServerCompositionVisualHooks::on_clip_changed(host);
1968        }
1969    }
1970
1971    /// The composition property of `ClipToBounds`.
1972    pub fn id_of_clip_to_bounds_property() -> &'static CompositionPropertyOf<bool> {
1973        static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
1974        PROPERTY.get_or_init(|| {
1975            CompositionProperty::register::<ServerCompositionVisualProps, bool>(
1976                "ClipToBounds",
1977                "ServerCompositionVisual",
1978                |obj| props_of::<ServerCompositionVisualProps>(obj).clip_to_bounds.get(),
1979                |obj, v| props_of::<ServerCompositionVisualProps>(obj).clip_to_bounds.set(v),
1980                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).clip_to_bounds.get())),
1981                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).clip_to_bounds.set(v.cast_or_default::<bool>())),
1982            )
1983        })
1984    }
1985
1986    /// `ClipToBounds` (animated).
1987    pub fn clip_to_bounds(&self) -> bool {
1988        self.clip_to_bounds.get()
1989    }
1990
1991    pub fn set_clip_to_bounds(&self, host: &dyn ServerCompositionVisualHooks, value: bool) {
1992        self.clip_to_bounds.set(value);
1993        host.remove_animation_for_property(Self::id_of_clip_to_bounds_property().base());
1994    }
1995
1996    /// The composition property of `Offset`.
1997    pub fn id_of_offset_property() -> &'static CompositionPropertyOf<Vector3D> {
1998        static PROPERTY: OnceLock<CompositionPropertyOf<Vector3D>> = OnceLock::new();
1999        PROPERTY.get_or_init(|| {
2000            CompositionProperty::register::<ServerCompositionVisualProps, Vector3D>(
2001                "Offset",
2002                "ServerCompositionVisual",
2003                |obj| props_of::<ServerCompositionVisualProps>(obj).offset.get(),
2004                |obj, v| props_of::<ServerCompositionVisualProps>(obj).offset.set(v),
2005                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).offset.get())),
2006                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).offset.set(v.cast_or_default::<Vector3D>())),
2007            )
2008        })
2009    }
2010
2011    /// `Offset` (animated).
2012    pub fn offset(&self) -> Vector3D {
2013        self.offset.get()
2014    }
2015
2016    pub fn set_offset(&self, host: &dyn ServerCompositionVisualHooks, value: Vector3D) {
2017        self.offset.set(value);
2018        host.remove_animation_for_property(Self::id_of_offset_property().base());
2019    }
2020
2021    /// The composition property of `Translation`.
2022    pub fn id_of_translation_property() -> &'static CompositionPropertyOf<Vector3D> {
2023        static PROPERTY: OnceLock<CompositionPropertyOf<Vector3D>> = OnceLock::new();
2024        PROPERTY.get_or_init(|| {
2025            CompositionProperty::register::<ServerCompositionVisualProps, Vector3D>(
2026                "Translation",
2027                "ServerCompositionVisual",
2028                |obj| props_of::<ServerCompositionVisualProps>(obj).translation.get(),
2029                |obj, v| props_of::<ServerCompositionVisualProps>(obj).translation.set(v),
2030                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).translation.get())),
2031                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).translation.set(v.cast_or_default::<Vector3D>())),
2032            )
2033        })
2034    }
2035
2036    /// `Translation` (animated).
2037    pub fn translation(&self) -> Vector3D {
2038        self.translation.get()
2039    }
2040
2041    pub fn set_translation(&self, host: &dyn ServerCompositionVisualHooks, value: Vector3D) {
2042        self.translation.set(value);
2043        host.remove_animation_for_property(Self::id_of_translation_property().base());
2044    }
2045
2046    /// The composition property of `Size`.
2047    pub fn id_of_size_property() -> &'static CompositionPropertyOf<Vector> {
2048        static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
2049        PROPERTY.get_or_init(|| {
2050            CompositionProperty::register::<ServerCompositionVisualProps, Vector>(
2051                "Size",
2052                "ServerCompositionVisual",
2053                |obj| props_of::<ServerCompositionVisualProps>(obj).size.get(),
2054                |obj, v| props_of::<ServerCompositionVisualProps>(obj).size.set(v),
2055                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).size.get())),
2056                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).size.set(v.cast_or_default::<Vector>())),
2057            )
2058        })
2059    }
2060
2061    /// `Size` (animated).
2062    pub fn size(&self) -> Vector {
2063        self.size.get()
2064    }
2065
2066    pub fn set_size(&self, host: &dyn ServerCompositionVisualHooks, value: Vector) {
2067        self.size.set(value);
2068        host.remove_animation_for_property(Self::id_of_size_property().base());
2069    }
2070
2071    /// The composition property of `AnchorPoint`.
2072    pub fn id_of_anchor_point_property() -> &'static CompositionPropertyOf<Vector> {
2073        static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
2074        PROPERTY.get_or_init(|| {
2075            CompositionProperty::register::<ServerCompositionVisualProps, Vector>(
2076                "AnchorPoint",
2077                "ServerCompositionVisual",
2078                |obj| props_of::<ServerCompositionVisualProps>(obj).anchor_point.get(),
2079                |obj, v| props_of::<ServerCompositionVisualProps>(obj).anchor_point.set(v),
2080                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).anchor_point.get())),
2081                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).anchor_point.set(v.cast_or_default::<Vector>())),
2082            )
2083        })
2084    }
2085
2086    /// `AnchorPoint` (animated).
2087    pub fn anchor_point(&self) -> Vector {
2088        self.anchor_point.get()
2089    }
2090
2091    pub fn set_anchor_point(&self, host: &dyn ServerCompositionVisualHooks, value: Vector) {
2092        self.anchor_point.set(value);
2093        host.remove_animation_for_property(Self::id_of_anchor_point_property().base());
2094    }
2095
2096    /// The composition property of `CenterPoint`.
2097    pub fn id_of_center_point_property() -> &'static CompositionPropertyOf<Vector3D> {
2098        static PROPERTY: OnceLock<CompositionPropertyOf<Vector3D>> = OnceLock::new();
2099        PROPERTY.get_or_init(|| {
2100            CompositionProperty::register::<ServerCompositionVisualProps, Vector3D>(
2101                "CenterPoint",
2102                "ServerCompositionVisual",
2103                |obj| props_of::<ServerCompositionVisualProps>(obj).center_point.get(),
2104                |obj, v| props_of::<ServerCompositionVisualProps>(obj).center_point.set(v),
2105                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).center_point.get())),
2106                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).center_point.set(v.cast_or_default::<Vector3D>())),
2107            )
2108        })
2109    }
2110
2111    /// `CenterPoint` (animated).
2112    pub fn center_point(&self) -> Vector3D {
2113        self.center_point.get()
2114    }
2115
2116    pub fn set_center_point(&self, host: &dyn ServerCompositionVisualHooks, value: Vector3D) {
2117        self.center_point.set(value);
2118        host.remove_animation_for_property(Self::id_of_center_point_property().base());
2119    }
2120
2121    /// The composition property of `RotationAngle`.
2122    pub fn id_of_rotation_angle_property() -> &'static CompositionPropertyOf<f32> {
2123        static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
2124        PROPERTY.get_or_init(|| {
2125            CompositionProperty::register::<ServerCompositionVisualProps, f32>(
2126                "RotationAngle",
2127                "ServerCompositionVisual",
2128                |obj| props_of::<ServerCompositionVisualProps>(obj).rotation_angle.get(),
2129                |obj, v| props_of::<ServerCompositionVisualProps>(obj).rotation_angle.set(v),
2130                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).rotation_angle.get())),
2131                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).rotation_angle.set(v.cast_or_default::<f32>())),
2132            )
2133        })
2134    }
2135
2136    /// `RotationAngle` (animated).
2137    pub fn rotation_angle(&self) -> f32 {
2138        self.rotation_angle.get()
2139    }
2140
2141    pub fn set_rotation_angle(&self, host: &dyn ServerCompositionVisualHooks, value: f32) {
2142        self.rotation_angle.set(value);
2143        host.remove_animation_for_property(Self::id_of_rotation_angle_property().base());
2144    }
2145
2146    /// The composition property of `Orientation`.
2147    pub fn id_of_orientation_property() -> &'static CompositionPropertyOf<Quaternion> {
2148        static PROPERTY: OnceLock<CompositionPropertyOf<Quaternion>> = OnceLock::new();
2149        PROPERTY.get_or_init(|| {
2150            CompositionProperty::register::<ServerCompositionVisualProps, Quaternion>(
2151                "Orientation",
2152                "ServerCompositionVisual",
2153                |obj| props_of::<ServerCompositionVisualProps>(obj).orientation.get(),
2154                |obj, v| props_of::<ServerCompositionVisualProps>(obj).orientation.set(v),
2155                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).orientation.get())),
2156                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).orientation.set(v.cast_or_default::<Quaternion>())),
2157            )
2158        })
2159    }
2160
2161    /// `Orientation` (animated).
2162    pub fn orientation(&self) -> Quaternion {
2163        self.orientation.get()
2164    }
2165
2166    pub fn set_orientation(&self, host: &dyn ServerCompositionVisualHooks, value: Quaternion) {
2167        self.orientation.set(value);
2168        host.remove_animation_for_property(Self::id_of_orientation_property().base());
2169    }
2170
2171    /// The composition property of `Scale`.
2172    pub fn id_of_scale_property() -> &'static CompositionPropertyOf<Vector3D> {
2173        static PROPERTY: OnceLock<CompositionPropertyOf<Vector3D>> = OnceLock::new();
2174        PROPERTY.get_or_init(|| {
2175            CompositionProperty::register::<ServerCompositionVisualProps, Vector3D>(
2176                "Scale",
2177                "ServerCompositionVisual",
2178                |obj| props_of::<ServerCompositionVisualProps>(obj).scale.get(),
2179                |obj, v| props_of::<ServerCompositionVisualProps>(obj).scale.set(v),
2180                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).scale.get())),
2181                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).scale.set(v.cast_or_default::<Vector3D>())),
2182            )
2183        })
2184    }
2185
2186    /// `Scale` (animated).
2187    pub fn scale(&self) -> Vector3D {
2188        self.scale.get()
2189    }
2190
2191    pub fn set_scale(&self, host: &dyn ServerCompositionVisualHooks, value: Vector3D) {
2192        self.scale.set(value);
2193        host.remove_animation_for_property(Self::id_of_scale_property().base());
2194    }
2195
2196    /// The composition property of `TransformMatrix`.
2197    pub fn id_of_transform_matrix_property() -> &'static CompositionPropertyOf<Matrix> {
2198        static PROPERTY: OnceLock<CompositionPropertyOf<Matrix>> = OnceLock::new();
2199        PROPERTY.get_or_init(|| {
2200            CompositionProperty::register::<ServerCompositionVisualProps, Matrix>(
2201                "TransformMatrix",
2202                "ServerCompositionVisual",
2203                |obj| props_of::<ServerCompositionVisualProps>(obj).transform_matrix.get(),
2204                |obj, v| props_of::<ServerCompositionVisualProps>(obj).transform_matrix.set(v),
2205                None,
2206                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).transform_matrix.set(v.cast_or_default::<Matrix>())),
2207            )
2208        })
2209    }
2210
2211    /// `TransformMatrix` (animated).
2212    pub fn transform_matrix(&self) -> Matrix {
2213        self.transform_matrix.get()
2214    }
2215
2216    pub fn set_transform_matrix(&self, host: &dyn ServerCompositionVisualHooks, value: Matrix) {
2217        self.transform_matrix.set(value);
2218        host.remove_animation_for_property(Self::id_of_transform_matrix_property().base());
2219    }
2220
2221    /// The composition property of `AdornedVisual`.
2222    pub fn id_of_adorned_visual_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
2223        static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
2224        PROPERTY.get_or_init(|| {
2225            CompositionProperty::register::<ServerCompositionVisualProps, Option<Rc<dyn IServerObject>>>(
2226                "AdornedVisual",
2227                "ServerCompositionVisual",
2228                |obj| props_of::<ServerCompositionVisualProps>(obj).adorned_visual.borrow().clone(),
2229                |obj, v| *props_of::<ServerCompositionVisualProps>(obj).adorned_visual.borrow_mut() = v,
2230                None,
2231                None,
2232            )
2233        })
2234    }
2235
2236    /// `AdornedVisual`.
2237    pub fn adorned_visual(&self) -> Option<Rc<dyn IServerObject>> {
2238        self.adorned_visual.borrow().clone()
2239    }
2240
2241    pub fn set_adorned_visual(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Rc<dyn IServerObject>>) {
2242        let old_value = self.adorned_visual.borrow().clone();
2243        let mut changed = false;
2244        if old_value.differs(&value) {
2245            ServerCompositionVisualHooks::on_adorned_visual_changing(host);
2246            changed = true;
2247        }
2248        host.set_value(
2249            Self::id_of_adorned_visual_property().base(),
2250            ServerValueChange {
2251                equal: old_value.default_equals(&value),
2252                old_resource: old_value.as_server_render_resource(),
2253                new_resource: value.as_server_render_resource(),
2254                assign: &mut || *self.adorned_visual.borrow_mut() = value.clone(),
2255            },
2256        );
2257        if changed {
2258            ServerCompositionVisualHooks::on_adorned_visual_changed(host);
2259        }
2260    }
2261
2262    /// The composition property of `AdornerIsClipped`.
2263    pub fn id_of_adorner_is_clipped_property() -> &'static CompositionPropertyOf<bool> {
2264        static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
2265        PROPERTY.get_or_init(|| {
2266            CompositionProperty::register::<ServerCompositionVisualProps, bool>(
2267                "AdornerIsClipped",
2268                "ServerCompositionVisual",
2269                |obj| props_of::<ServerCompositionVisualProps>(obj).adorner_is_clipped.get(),
2270                |obj, v| props_of::<ServerCompositionVisualProps>(obj).adorner_is_clipped.set(v),
2271                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).adorner_is_clipped.get())),
2272                None,
2273            )
2274        })
2275    }
2276
2277    /// `AdornerIsClipped`.
2278    pub fn adorner_is_clipped(&self) -> bool {
2279        self.adorner_is_clipped.get()
2280    }
2281
2282    pub fn set_adorner_is_clipped(&self, host: &dyn ServerCompositionVisualHooks, value: bool) {
2283        let old_value = self.adorner_is_clipped.get();
2284        let mut changed = false;
2285        if old_value.differs(&value) {
2286            ServerCompositionVisualHooks::on_adorner_is_clipped_changing(host);
2287            changed = true;
2288        }
2289        host.set_value(
2290            Self::id_of_adorner_is_clipped_property().base(),
2291            ServerValueChange {
2292                equal: old_value.default_equals(&value),
2293                old_resource: None,
2294                new_resource: None,
2295                assign: &mut || self.adorner_is_clipped.set(value),
2296            },
2297        );
2298        if changed {
2299            ServerCompositionVisualHooks::on_adorner_is_clipped_changed(host);
2300        }
2301    }
2302
2303    /// The composition property of `OpacityMaskBrush`.
2304    pub fn id_of_opacity_mask_brush_property() -> &'static CompositionPropertyOf<Option<ServerResourceRef<dyn IBrush>>> {
2305        static PROPERTY: OnceLock<CompositionPropertyOf<Option<ServerResourceRef<dyn IBrush>>>> = OnceLock::new();
2306        PROPERTY.get_or_init(|| {
2307            CompositionProperty::register::<ServerCompositionVisualProps, Option<ServerResourceRef<dyn IBrush>>>(
2308                "OpacityMaskBrush",
2309                "ServerCompositionVisual",
2310                |obj| props_of::<ServerCompositionVisualProps>(obj).opacity_mask_brush.borrow().clone(),
2311                |obj, v| *props_of::<ServerCompositionVisualProps>(obj).opacity_mask_brush.borrow_mut() = v,
2312                None,
2313                None,
2314            )
2315        })
2316    }
2317
2318    /// `OpacityMaskBrush`.
2319    pub fn opacity_mask_brush(&self) -> Option<ServerResourceRef<dyn IBrush>> {
2320        self.opacity_mask_brush.borrow().clone()
2321    }
2322
2323    pub fn set_opacity_mask_brush(&self, host: &dyn ServerCompositionVisualHooks, value: Option<ServerResourceRef<dyn IBrush>>) {
2324        let old_value = self.opacity_mask_brush.borrow().clone();
2325        let mut changed = false;
2326        if old_value.differs(&value) {
2327            ServerCompositionVisualHooks::on_opacity_mask_brush_changing(host);
2328            changed = true;
2329        }
2330        host.set_value(
2331            Self::id_of_opacity_mask_brush_property().base(),
2332            ServerValueChange {
2333                equal: old_value.default_equals(&value),
2334                old_resource: old_value.as_server_render_resource(),
2335                new_resource: value.as_server_render_resource(),
2336                assign: &mut || *self.opacity_mask_brush.borrow_mut() = value.clone(),
2337            },
2338        );
2339        if changed {
2340            ServerCompositionVisualHooks::on_opacity_mask_brush_changed(host);
2341        }
2342    }
2343
2344    /// The composition property of `Effect`.
2345    pub fn id_of_effect_property() -> &'static CompositionPropertyOf<Option<Arc<dyn IImmutableEffect>>> {
2346        static PROPERTY: OnceLock<CompositionPropertyOf<Option<Arc<dyn IImmutableEffect>>>> = OnceLock::new();
2347        PROPERTY.get_or_init(|| {
2348            CompositionProperty::register::<ServerCompositionVisualProps, Option<Arc<dyn IImmutableEffect>>>(
2349                "Effect",
2350                "ServerCompositionVisual",
2351                |obj| props_of::<ServerCompositionVisualProps>(obj).effect.borrow().clone(),
2352                |obj, v| *props_of::<ServerCompositionVisualProps>(obj).effect.borrow_mut() = v,
2353                None,
2354                None,
2355            )
2356        })
2357    }
2358
2359    /// `Effect`.
2360    pub fn effect(&self) -> Option<Arc<dyn IImmutableEffect>> {
2361        self.effect.borrow().clone()
2362    }
2363
2364    pub fn set_effect(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Arc<dyn IImmutableEffect>>) {
2365        let old_value = self.effect.borrow().clone();
2366        let mut changed = false;
2367        if old_value.differs(&value) {
2368            ServerCompositionVisualHooks::on_effect_changing(host);
2369            changed = true;
2370        }
2371        host.set_value(
2372            Self::id_of_effect_property().base(),
2373            ServerValueChange {
2374                equal: old_value.default_equals(&value),
2375                old_resource: None,
2376                new_resource: None,
2377                assign: &mut || *self.effect.borrow_mut() = value.clone(),
2378            },
2379        );
2380        if changed {
2381            ServerCompositionVisualHooks::on_effect_changed(host);
2382        }
2383    }
2384
2385    /// The composition property of `RenderOptions`.
2386    pub fn id_of_render_options_property() -> &'static CompositionPropertyOf<RenderOptions> {
2387        static PROPERTY: OnceLock<CompositionPropertyOf<RenderOptions>> = OnceLock::new();
2388        PROPERTY.get_or_init(|| {
2389            CompositionProperty::register::<ServerCompositionVisualProps, RenderOptions>(
2390                "RenderOptions",
2391                "ServerCompositionVisual",
2392                |obj| props_of::<ServerCompositionVisualProps>(obj).render_options.get(),
2393                |obj, v| props_of::<ServerCompositionVisualProps>(obj).render_options.set(v),
2394                None,
2395                None,
2396            )
2397        })
2398    }
2399
2400    /// `RenderOptions`.
2401    pub fn render_options(&self) -> RenderOptions {
2402        self.render_options.get()
2403    }
2404
2405    pub fn set_render_options(&self, host: &dyn ServerCompositionVisualHooks, value: RenderOptions) {
2406        let old_value = self.render_options.get();
2407        let mut changed = false;
2408        if old_value.differs(&value) {
2409            ServerCompositionVisualHooks::on_render_options_changing(host);
2410            changed = true;
2411        }
2412        host.set_value(
2413            Self::id_of_render_options_property().base(),
2414            ServerValueChange {
2415                equal: old_value.default_equals(&value),
2416                old_resource: None,
2417                new_resource: None,
2418                assign: &mut || self.render_options.set(value),
2419            },
2420        );
2421        if changed {
2422            ServerCompositionVisualHooks::on_render_options_changed(host);
2423        }
2424    }
2425
2426    /// The composition property of `TextOptions`.
2427    pub fn id_of_text_options_property() -> &'static CompositionPropertyOf<TextOptions> {
2428        static PROPERTY: OnceLock<CompositionPropertyOf<TextOptions>> = OnceLock::new();
2429        PROPERTY.get_or_init(|| {
2430            CompositionProperty::register::<ServerCompositionVisualProps, TextOptions>(
2431                "TextOptions",
2432                "ServerCompositionVisual",
2433                |obj| props_of::<ServerCompositionVisualProps>(obj).text_options.get(),
2434                |obj, v| props_of::<ServerCompositionVisualProps>(obj).text_options.set(v),
2435                None,
2436                None,
2437            )
2438        })
2439    }
2440
2441    /// `TextOptions`.
2442    pub fn text_options(&self) -> TextOptions {
2443        self.text_options.get()
2444    }
2445
2446    pub fn set_text_options(&self, host: &dyn ServerCompositionVisualHooks, value: TextOptions) {
2447        let old_value = self.text_options.get();
2448        let mut changed = false;
2449        if old_value.differs(&value) {
2450            ServerCompositionVisualHooks::on_text_options_changing(host);
2451            changed = true;
2452        }
2453        host.set_value(
2454            Self::id_of_text_options_property().base(),
2455            ServerValueChange {
2456                equal: old_value.default_equals(&value),
2457                old_resource: None,
2458                new_resource: None,
2459                assign: &mut || self.text_options.set(value),
2460            },
2461        );
2462        if changed {
2463            ServerCompositionVisualHooks::on_text_options_changed(host);
2464        }
2465    }
2466
2467    /// The composition property of `CacheMode`.
2468    pub fn id_of_cache_mode_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
2469        static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
2470        PROPERTY.get_or_init(|| {
2471            CompositionProperty::register::<ServerCompositionVisualProps, Option<Rc<dyn IServerObject>>>(
2472                "CacheMode",
2473                "ServerCompositionVisual",
2474                |obj| props_of::<ServerCompositionVisualProps>(obj).cache_mode.borrow().clone(),
2475                |obj, v| *props_of::<ServerCompositionVisualProps>(obj).cache_mode.borrow_mut() = v,
2476                None,
2477                None,
2478            )
2479        })
2480    }
2481
2482    /// `CacheMode`.
2483    pub fn cache_mode(&self) -> Option<Rc<dyn IServerObject>> {
2484        self.cache_mode.borrow().clone()
2485    }
2486
2487    pub fn set_cache_mode(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Rc<dyn IServerObject>>) {
2488        let old_value = self.cache_mode.borrow().clone();
2489        let mut changed = false;
2490        if old_value.differs(&value) {
2491            ServerCompositionVisualHooks::on_cache_mode_changing(host);
2492            changed = true;
2493        }
2494        host.set_value(
2495            Self::id_of_cache_mode_property().base(),
2496            ServerValueChange {
2497                equal: old_value.default_equals(&value),
2498                old_resource: old_value.as_server_render_resource(),
2499                new_resource: value.as_server_render_resource(),
2500                assign: &mut || *self.cache_mode.borrow_mut() = value.clone(),
2501            },
2502        );
2503        if changed {
2504            ServerCompositionVisualHooks::on_cache_mode_changed(host);
2505        }
2506    }
2507
2508    /// The composition property of `CompositionClip`.
2509    pub fn id_of_composition_clip_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
2510        static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
2511        PROPERTY.get_or_init(|| {
2512            CompositionProperty::register::<ServerCompositionVisualProps, Option<Rc<dyn IServerObject>>>(
2513                "CompositionClip",
2514                "ServerCompositionVisual",
2515                |obj| props_of::<ServerCompositionVisualProps>(obj).composition_clip.borrow().clone(),
2516                |obj, v| *props_of::<ServerCompositionVisualProps>(obj).composition_clip.borrow_mut() = v,
2517                None,
2518                None,
2519            )
2520        })
2521    }
2522
2523    /// `CompositionClip`.
2524    pub fn composition_clip(&self) -> Option<Rc<dyn IServerObject>> {
2525        self.composition_clip.borrow().clone()
2526    }
2527
2528    pub fn set_composition_clip(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Rc<dyn IServerObject>>) {
2529        let old_value = self.composition_clip.borrow().clone();
2530        let mut changed = false;
2531        if old_value.differs(&value) {
2532            ServerCompositionVisualHooks::on_composition_clip_changing(host);
2533            changed = true;
2534        }
2535        host.set_value(
2536            Self::id_of_composition_clip_property().base(),
2537            ServerValueChange {
2538                equal: old_value.default_equals(&value),
2539                old_resource: old_value.as_server_render_resource(),
2540                new_resource: value.as_server_render_resource(),
2541                assign: &mut || *self.composition_clip.borrow_mut() = value.clone(),
2542            },
2543        );
2544        if changed {
2545            ServerCompositionVisualHooks::on_composition_clip_changed(host);
2546        }
2547    }
2548
2549    /// The composition property of `RotationAxis`.
2550    pub fn id_of_rotation_axis_property() -> &'static CompositionPropertyOf<Vector3D> {
2551        static PROPERTY: OnceLock<CompositionPropertyOf<Vector3D>> = OnceLock::new();
2552        PROPERTY.get_or_init(|| {
2553            CompositionProperty::register::<ServerCompositionVisualProps, Vector3D>(
2554                "RotationAxis",
2555                "ServerCompositionVisual",
2556                |obj| props_of::<ServerCompositionVisualProps>(obj).rotation_axis.get(),
2557                |obj, v| props_of::<ServerCompositionVisualProps>(obj).rotation_axis.set(v),
2558                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).rotation_axis.get())),
2559                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).rotation_axis.set(v.cast_or_default::<Vector3D>())),
2560            )
2561        })
2562    }
2563
2564    /// `RotationAxis` (animated).
2565    pub fn rotation_axis(&self) -> Vector3D {
2566        self.rotation_axis.get()
2567    }
2568
2569    pub fn set_rotation_axis(&self, host: &dyn ServerCompositionVisualHooks, value: Vector3D) {
2570        self.rotation_axis.set(value);
2571        host.remove_animation_for_property(Self::id_of_rotation_axis_property().base());
2572    }
2573
2574    /// The composition property of `RelativeOffsetAdjustment`.
2575    pub fn id_of_relative_offset_adjustment_property() -> &'static CompositionPropertyOf<Vector3D> {
2576        static PROPERTY: OnceLock<CompositionPropertyOf<Vector3D>> = OnceLock::new();
2577        PROPERTY.get_or_init(|| {
2578            CompositionProperty::register::<ServerCompositionVisualProps, Vector3D>(
2579                "RelativeOffsetAdjustment",
2580                "ServerCompositionVisual",
2581                |obj| props_of::<ServerCompositionVisualProps>(obj).relative_offset_adjustment.get(),
2582                |obj, v| props_of::<ServerCompositionVisualProps>(obj).relative_offset_adjustment.set(v),
2583                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).relative_offset_adjustment.get())),
2584                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).relative_offset_adjustment.set(v.cast_or_default::<Vector3D>())),
2585            )
2586        })
2587    }
2588
2589    /// `RelativeOffsetAdjustment` (animated).
2590    pub fn relative_offset_adjustment(&self) -> Vector3D {
2591        self.relative_offset_adjustment.get()
2592    }
2593
2594    pub fn set_relative_offset_adjustment(&self, host: &dyn ServerCompositionVisualHooks, value: Vector3D) {
2595        self.relative_offset_adjustment.set(value);
2596        host.remove_animation_for_property(Self::id_of_relative_offset_adjustment_property().base());
2597    }
2598
2599    /// The composition property of `RelativeSizeAdjustment`.
2600    pub fn id_of_relative_size_adjustment_property() -> &'static CompositionPropertyOf<Vector> {
2601        static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
2602        PROPERTY.get_or_init(|| {
2603            CompositionProperty::register::<ServerCompositionVisualProps, Vector>(
2604                "RelativeSizeAdjustment",
2605                "ServerCompositionVisual",
2606                |obj| props_of::<ServerCompositionVisualProps>(obj).relative_size_adjustment.get(),
2607                |obj, v| props_of::<ServerCompositionVisualProps>(obj).relative_size_adjustment.set(v),
2608                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).relative_size_adjustment.get())),
2609                Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).relative_size_adjustment.set(v.cast_or_default::<Vector>())),
2610            )
2611        })
2612    }
2613
2614    /// `RelativeSizeAdjustment` (animated).
2615    pub fn relative_size_adjustment(&self) -> Vector {
2616        self.relative_size_adjustment.get()
2617    }
2618
2619    pub fn set_relative_size_adjustment(&self, host: &dyn ServerCompositionVisualHooks, value: Vector) {
2620        self.relative_size_adjustment.set(value);
2621        host.remove_animation_for_property(Self::id_of_relative_size_adjustment_property().base());
2622    }
2623
2624    /// The composition property of `IsHitTestVisible`.
2625    pub fn id_of_is_hit_test_visible_property() -> &'static CompositionPropertyOf<bool> {
2626        static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
2627        PROPERTY.get_or_init(|| {
2628            CompositionProperty::register::<ServerCompositionVisualProps, bool>(
2629                "IsHitTestVisible",
2630                "ServerCompositionVisual",
2631                |obj| props_of::<ServerCompositionVisualProps>(obj).is_hit_test_visible.get(),
2632                |obj, v| props_of::<ServerCompositionVisualProps>(obj).is_hit_test_visible.set(v),
2633                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).is_hit_test_visible.get())),
2634                None,
2635            )
2636        })
2637    }
2638
2639    /// `IsHitTestVisible`.
2640    pub fn is_hit_test_visible(&self) -> bool {
2641        self.is_hit_test_visible.get()
2642    }
2643
2644    pub fn set_is_hit_test_visible(&self, host: &dyn ServerCompositionVisualHooks, value: bool) {
2645        let old_value = self.is_hit_test_visible.get();
2646        let mut changed = false;
2647        if old_value.differs(&value) {
2648            ServerCompositionVisualHooks::on_is_hit_test_visible_changing(host);
2649            changed = true;
2650        }
2651        host.set_value(
2652            Self::id_of_is_hit_test_visible_property().base(),
2653            ServerValueChange {
2654                equal: old_value.default_equals(&value),
2655                old_resource: None,
2656                new_resource: None,
2657                assign: &mut || self.is_hit_test_visible.set(value),
2658            },
2659        );
2660        if changed {
2661            ServerCompositionVisualHooks::on_is_hit_test_visible_changed(host);
2662        }
2663    }
2664
2665    /// The composition property of `IsPixelSnappingEnabled`.
2666    pub fn id_of_is_pixel_snapping_enabled_property() -> &'static CompositionPropertyOf<bool> {
2667        static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
2668        PROPERTY.get_or_init(|| {
2669            CompositionProperty::register::<ServerCompositionVisualProps, bool>(
2670                "IsPixelSnappingEnabled",
2671                "ServerCompositionVisual",
2672                |obj| props_of::<ServerCompositionVisualProps>(obj).is_pixel_snapping_enabled.get(),
2673                |obj, v| props_of::<ServerCompositionVisualProps>(obj).is_pixel_snapping_enabled.set(v),
2674                Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).is_pixel_snapping_enabled.get())),
2675                None,
2676            )
2677        })
2678    }
2679
2680    /// `IsPixelSnappingEnabled`.
2681    pub fn is_pixel_snapping_enabled(&self) -> bool {
2682        self.is_pixel_snapping_enabled.get()
2683    }
2684
2685    pub fn set_is_pixel_snapping_enabled(&self, host: &dyn ServerCompositionVisualHooks, value: bool) {
2686        let old_value = self.is_pixel_snapping_enabled.get();
2687        let mut changed = false;
2688        if old_value.differs(&value) {
2689            ServerCompositionVisualHooks::on_is_pixel_snapping_enabled_changing(host);
2690            changed = true;
2691        }
2692        host.set_value(
2693            Self::id_of_is_pixel_snapping_enabled_property().base(),
2694            ServerValueChange {
2695                equal: old_value.default_equals(&value),
2696                old_resource: None,
2697                new_resource: None,
2698                assign: &mut || self.is_pixel_snapping_enabled.set(value),
2699            },
2700        );
2701        if changed {
2702            ServerCompositionVisualHooks::on_is_pixel_snapping_enabled_changed(host);
2703        }
2704    }
2705
2706    /// The composition property of `BorderMode`.
2707    pub fn id_of_border_mode_property() -> &'static CompositionPropertyOf<CompositionBorderMode> {
2708        static PROPERTY: OnceLock<CompositionPropertyOf<CompositionBorderMode>> = OnceLock::new();
2709        PROPERTY.get_or_init(|| {
2710            CompositionProperty::register::<ServerCompositionVisualProps, CompositionBorderMode>(
2711                "BorderMode",
2712                "ServerCompositionVisual",
2713                |obj| props_of::<ServerCompositionVisualProps>(obj).border_mode.get(),
2714                |obj, v| props_of::<ServerCompositionVisualProps>(obj).border_mode.set(v),
2715                None,
2716                None,
2717            )
2718        })
2719    }
2720
2721    /// `BorderMode`.
2722    pub fn border_mode(&self) -> CompositionBorderMode {
2723        self.border_mode.get()
2724    }
2725
2726    pub fn set_border_mode(&self, host: &dyn ServerCompositionVisualHooks, value: CompositionBorderMode) {
2727        let old_value = self.border_mode.get();
2728        let mut changed = false;
2729        if old_value.differs(&value) {
2730            ServerCompositionVisualHooks::on_border_mode_changing(host);
2731            changed = true;
2732        }
2733        host.set_value(
2734            Self::id_of_border_mode_property().base(),
2735            ServerValueChange {
2736                equal: old_value.default_equals(&value),
2737                old_resource: None,
2738                new_resource: None,
2739                assign: &mut || self.border_mode.set(value),
2740            },
2741        );
2742        if changed {
2743            ServerCompositionVisualHooks::on_border_mode_changed(host);
2744        }
2745    }
2746
2747    /// The composition property of `BackfaceVisibility`.
2748    pub fn id_of_backface_visibility_property() -> &'static CompositionPropertyOf<CompositionBackfaceVisibility> {
2749        static PROPERTY: OnceLock<CompositionPropertyOf<CompositionBackfaceVisibility>> = OnceLock::new();
2750        PROPERTY.get_or_init(|| {
2751            CompositionProperty::register::<ServerCompositionVisualProps, CompositionBackfaceVisibility>(
2752                "BackfaceVisibility",
2753                "ServerCompositionVisual",
2754                |obj| props_of::<ServerCompositionVisualProps>(obj).backface_visibility.get(),
2755                |obj, v| props_of::<ServerCompositionVisualProps>(obj).backface_visibility.set(v),
2756                None,
2757                None,
2758            )
2759        })
2760    }
2761
2762    /// `BackfaceVisibility`.
2763    pub fn backface_visibility(&self) -> CompositionBackfaceVisibility {
2764        self.backface_visibility.get()
2765    }
2766
2767    pub fn set_backface_visibility(&self, host: &dyn ServerCompositionVisualHooks, value: CompositionBackfaceVisibility) {
2768        let old_value = self.backface_visibility.get();
2769        let mut changed = false;
2770        if old_value.differs(&value) {
2771            ServerCompositionVisualHooks::on_backface_visibility_changing(host);
2772            changed = true;
2773        }
2774        host.set_value(
2775            Self::id_of_backface_visibility_property().base(),
2776            ServerValueChange {
2777                equal: old_value.default_equals(&value),
2778                old_resource: None,
2779                new_resource: None,
2780                assign: &mut || self.backface_visibility.set(value),
2781            },
2782        );
2783        if changed {
2784            ServerCompositionVisualHooks::on_backface_visibility_changed(host);
2785        }
2786    }
2787
2788    /// The composition property of `CompositeMode`.
2789    pub fn id_of_composite_mode_property() -> &'static CompositionPropertyOf<CompositionCompositeMode> {
2790        static PROPERTY: OnceLock<CompositionPropertyOf<CompositionCompositeMode>> = OnceLock::new();
2791        PROPERTY.get_or_init(|| {
2792            CompositionProperty::register::<ServerCompositionVisualProps, CompositionCompositeMode>(
2793                "CompositeMode",
2794                "ServerCompositionVisual",
2795                |obj| props_of::<ServerCompositionVisualProps>(obj).composite_mode.get(),
2796                |obj, v| props_of::<ServerCompositionVisualProps>(obj).composite_mode.set(v),
2797                None,
2798                None,
2799            )
2800        })
2801    }
2802
2803    /// `CompositeMode`.
2804    pub fn composite_mode(&self) -> CompositionCompositeMode {
2805        self.composite_mode.get()
2806    }
2807
2808    pub fn set_composite_mode(&self, host: &dyn ServerCompositionVisualHooks, value: CompositionCompositeMode) {
2809        let old_value = self.composite_mode.get();
2810        let mut changed = false;
2811        if old_value.differs(&value) {
2812            ServerCompositionVisualHooks::on_composite_mode_changing(host);
2813            changed = true;
2814        }
2815        host.set_value(
2816            Self::id_of_composite_mode_property().base(),
2817            ServerValueChange {
2818                equal: old_value.default_equals(&value),
2819                old_resource: None,
2820                new_resource: None,
2821                assign: &mut || self.composite_mode.set(value),
2822            },
2823        );
2824        if changed {
2825            ServerCompositionVisualHooks::on_composite_mode_changed(host);
2826        }
2827    }
2828
2829    /// The composition property of `ParentForTransform`.
2830    pub fn id_of_parent_for_transform_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
2831        static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
2832        PROPERTY.get_or_init(|| {
2833            CompositionProperty::register::<ServerCompositionVisualProps, Option<Rc<dyn IServerObject>>>(
2834                "ParentForTransform",
2835                "ServerCompositionVisual",
2836                |obj| props_of::<ServerCompositionVisualProps>(obj).parent_for_transform.borrow().clone(),
2837                |obj, v| *props_of::<ServerCompositionVisualProps>(obj).parent_for_transform.borrow_mut() = v,
2838                None,
2839                None,
2840            )
2841        })
2842    }
2843
2844    /// `ParentForTransform`.
2845    pub fn parent_for_transform(&self) -> Option<Rc<dyn IServerObject>> {
2846        self.parent_for_transform.borrow().clone()
2847    }
2848
2849    pub fn set_parent_for_transform(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Rc<dyn IServerObject>>) {
2850        let old_value = self.parent_for_transform.borrow().clone();
2851        let mut changed = false;
2852        if old_value.differs(&value) {
2853            ServerCompositionVisualHooks::on_parent_for_transform_changing(host);
2854            changed = true;
2855        }
2856        host.set_value(
2857            Self::id_of_parent_for_transform_property().base(),
2858            ServerValueChange {
2859                equal: old_value.default_equals(&value),
2860                old_resource: old_value.as_server_render_resource(),
2861                new_resource: value.as_server_render_resource(),
2862                assign: &mut || *self.parent_for_transform.borrow_mut() = value.clone(),
2863            },
2864        );
2865        if changed {
2866            ServerCompositionVisualHooks::on_parent_for_transform_changed(host);
2867        }
2868    }
2869
2870    /// Reads the changes of the object: the base class first, then the
2871    /// changed-fields mask and the changed members of this class.
2872    pub fn deserialize_changes_core(
2873        &self,
2874        host: &dyn ServerCompositionVisualHooks,
2875        reader: &mut BatchStreamReader<'_>,
2876        committed_at: Duration,
2877    ) {
2878        let compositor = host.server_compositor();
2879        ServerCompositionVisualHooks::deserialize_changes_extra(host, reader);
2880        let changed = reader.read::<CompositionVisualChangedFields>();
2881        if changed.contains(CompositionVisualChangedFields::ROOT) {
2882            let value = read_server_object(reader, compositor.as_ref());
2883            self.set_root(host, value);
2884        }
2885        if changed.contains(CompositionVisualChangedFields::PARENT) {
2886            let value = read_server_object(reader, compositor.as_ref());
2887            self.set_parent(host, value);
2888        }
2889        if changed.contains(CompositionVisualChangedFields::VISIBLE_ANIMATED) {
2890            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
2891                panic!("a batch starts an animation of `Visible` without an animation instance");
2892            };
2893            host.set_animated_value(
2894                Self::id_of_visible_property().base(),
2895                ExpressionVariant::create(self.visible.get()),
2896                committed_at,
2897                animation,
2898            );
2899        } else if changed.contains(CompositionVisualChangedFields::VISIBLE) {
2900            let value = reader.read::<bool>();
2901            self.set_visible(host, value);
2902        }
2903        if changed.contains(CompositionVisualChangedFields::OPACITY_ANIMATED) {
2904            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
2905                panic!("a batch starts an animation of `Opacity` without an animation instance");
2906            };
2907            host.set_animated_value(
2908                Self::id_of_opacity_property().base(),
2909                ExpressionVariant::create(self.opacity.get()),
2910                committed_at,
2911                animation,
2912            );
2913        } else if changed.contains(CompositionVisualChangedFields::OPACITY) {
2914            let value = reader.read::<f32>();
2915            self.set_opacity(host, value);
2916        }
2917        if changed.contains(CompositionVisualChangedFields::CLIP) {
2918            let value = reader.read_value::<Arc<dyn IGeometryImpl>>();
2919            self.set_clip(host, value);
2920        }
2921        if changed.contains(CompositionVisualChangedFields::CLIP_TO_BOUNDS_ANIMATED) {
2922            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
2923                panic!("a batch starts an animation of `ClipToBounds` without an animation instance");
2924            };
2925            host.set_animated_value(
2926                Self::id_of_clip_to_bounds_property().base(),
2927                ExpressionVariant::create(self.clip_to_bounds.get()),
2928                committed_at,
2929                animation,
2930            );
2931        } else if changed.contains(CompositionVisualChangedFields::CLIP_TO_BOUNDS) {
2932            let value = reader.read::<bool>();
2933            self.set_clip_to_bounds(host, value);
2934        }
2935        if changed.contains(CompositionVisualChangedFields::OFFSET_ANIMATED) {
2936            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
2937                panic!("a batch starts an animation of `Offset` without an animation instance");
2938            };
2939            host.set_animated_value(
2940                Self::id_of_offset_property().base(),
2941                ExpressionVariant::create(self.offset.get()),
2942                committed_at,
2943                animation,
2944            );
2945        } else if changed.contains(CompositionVisualChangedFields::OFFSET) {
2946            let value = reader.read::<Vector3D>();
2947            self.set_offset(host, value);
2948        }
2949        if changed.contains(CompositionVisualChangedFields::TRANSLATION_ANIMATED) {
2950            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
2951                panic!("a batch starts an animation of `Translation` without an animation instance");
2952            };
2953            host.set_animated_value(
2954                Self::id_of_translation_property().base(),
2955                ExpressionVariant::create(self.translation.get()),
2956                committed_at,
2957                animation,
2958            );
2959        } else if changed.contains(CompositionVisualChangedFields::TRANSLATION) {
2960            let value = reader.read::<Vector3D>();
2961            self.set_translation(host, value);
2962        }
2963        if changed.contains(CompositionVisualChangedFields::SIZE_ANIMATED) {
2964            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
2965                panic!("a batch starts an animation of `Size` without an animation instance");
2966            };
2967            host.set_animated_value(
2968                Self::id_of_size_property().base(),
2969                ExpressionVariant::create(self.size.get()),
2970                committed_at,
2971                animation,
2972            );
2973        } else if changed.contains(CompositionVisualChangedFields::SIZE) {
2974            let value = reader.read::<Vector>();
2975            self.set_size(host, value);
2976        }
2977        if changed.contains(CompositionVisualChangedFields::ANCHOR_POINT_ANIMATED) {
2978            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
2979                panic!("a batch starts an animation of `AnchorPoint` without an animation instance");
2980            };
2981            host.set_animated_value(
2982                Self::id_of_anchor_point_property().base(),
2983                ExpressionVariant::create(self.anchor_point.get()),
2984                committed_at,
2985                animation,
2986            );
2987        } else if changed.contains(CompositionVisualChangedFields::ANCHOR_POINT) {
2988            let value = reader.read::<Vector>();
2989            self.set_anchor_point(host, value);
2990        }
2991        if changed.contains(CompositionVisualChangedFields::CENTER_POINT_ANIMATED) {
2992            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
2993                panic!("a batch starts an animation of `CenterPoint` without an animation instance");
2994            };
2995            host.set_animated_value(
2996                Self::id_of_center_point_property().base(),
2997                ExpressionVariant::create(self.center_point.get()),
2998                committed_at,
2999                animation,
3000            );
3001        } else if changed.contains(CompositionVisualChangedFields::CENTER_POINT) {
3002            let value = reader.read::<Vector3D>();
3003            self.set_center_point(host, value);
3004        }
3005        if changed.contains(CompositionVisualChangedFields::ROTATION_ANGLE_ANIMATED) {
3006            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
3007                panic!("a batch starts an animation of `RotationAngle` without an animation instance");
3008            };
3009            host.set_animated_value(
3010                Self::id_of_rotation_angle_property().base(),
3011                ExpressionVariant::create(self.rotation_angle.get()),
3012                committed_at,
3013                animation,
3014            );
3015        } else if changed.contains(CompositionVisualChangedFields::ROTATION_ANGLE) {
3016            let value = reader.read::<f32>();
3017            self.set_rotation_angle(host, value);
3018        }
3019        if changed.contains(CompositionVisualChangedFields::ORIENTATION_ANIMATED) {
3020            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
3021                panic!("a batch starts an animation of `Orientation` without an animation instance");
3022            };
3023            host.set_animated_value(
3024                Self::id_of_orientation_property().base(),
3025                ExpressionVariant::create(self.orientation.get()),
3026                committed_at,
3027                animation,
3028            );
3029        } else if changed.contains(CompositionVisualChangedFields::ORIENTATION) {
3030            let value = reader.read::<Quaternion>();
3031            self.set_orientation(host, value);
3032        }
3033        if changed.contains(CompositionVisualChangedFields::SCALE_ANIMATED) {
3034            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
3035                panic!("a batch starts an animation of `Scale` without an animation instance");
3036            };
3037            host.set_animated_value(
3038                Self::id_of_scale_property().base(),
3039                ExpressionVariant::create(self.scale.get()),
3040                committed_at,
3041                animation,
3042            );
3043        } else if changed.contains(CompositionVisualChangedFields::SCALE) {
3044            let value = reader.read::<Vector3D>();
3045            self.set_scale(host, value);
3046        }
3047        if changed.contains(CompositionVisualChangedFields::TRANSFORM_MATRIX_ANIMATED) {
3048            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
3049                panic!("a batch starts an animation of `TransformMatrix` without an animation instance");
3050            };
3051            host.set_animated_value(
3052                Self::id_of_transform_matrix_property().base(),
3053                ExpressionVariant::create(self.transform_matrix.get()),
3054                committed_at,
3055                animation,
3056            );
3057        } else if changed.contains(CompositionVisualChangedFields::TRANSFORM_MATRIX) {
3058            let value = reader.read::<Matrix>();
3059            self.set_transform_matrix(host, value);
3060        }
3061        if changed.contains(CompositionVisualChangedFields::ADORNED_VISUAL) {
3062            let value = read_server_object(reader, compositor.as_ref());
3063            self.set_adorned_visual(host, value);
3064        }
3065        if changed.contains(CompositionVisualChangedFields::ADORNER_IS_CLIPPED) {
3066            let value = reader.read::<bool>();
3067            self.set_adorner_is_clipped(host, value);
3068        }
3069        if changed.contains(CompositionVisualChangedFields::OPACITY_MASK_BRUSH) {
3070            let value = read_resource(reader, compositor.as_ref(), |o| o.as_brush());
3071            self.set_opacity_mask_brush(host, value);
3072        }
3073        if changed.contains(CompositionVisualChangedFields::EFFECT) {
3074            let value = reader.read_value::<Arc<dyn IImmutableEffect>>();
3075            self.set_effect(host, value);
3076        }
3077        if changed.contains(CompositionVisualChangedFields::RENDER_OPTIONS) {
3078            let value = reader.read::<RenderOptions>();
3079            self.set_render_options(host, value);
3080        }
3081        if changed.contains(CompositionVisualChangedFields::TEXT_OPTIONS) {
3082            let value = reader.read::<TextOptions>();
3083            self.set_text_options(host, value);
3084        }
3085        if changed.contains(CompositionVisualChangedFields::CACHE_MODE) {
3086            let value = read_server_object(reader, compositor.as_ref());
3087            self.set_cache_mode(host, value);
3088        }
3089        if changed.contains(CompositionVisualChangedFields::COMPOSITION_CLIP) {
3090            let value = read_server_object(reader, compositor.as_ref());
3091            self.set_composition_clip(host, value);
3092        }
3093        if changed.contains(CompositionVisualChangedFields::ROTATION_AXIS_ANIMATED) {
3094            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
3095                panic!("a batch starts an animation of `RotationAxis` without an animation instance");
3096            };
3097            host.set_animated_value(
3098                Self::id_of_rotation_axis_property().base(),
3099                ExpressionVariant::create(self.rotation_axis.get()),
3100                committed_at,
3101                animation,
3102            );
3103        } else if changed.contains(CompositionVisualChangedFields::ROTATION_AXIS) {
3104            let value = reader.read::<Vector3D>();
3105            self.set_rotation_axis(host, value);
3106        }
3107        if changed.contains(CompositionVisualChangedFields::RELATIVE_OFFSET_ADJUSTMENT_ANIMATED) {
3108            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
3109                panic!("a batch starts an animation of `RelativeOffsetAdjustment` without an animation instance");
3110            };
3111            host.set_animated_value(
3112                Self::id_of_relative_offset_adjustment_property().base(),
3113                ExpressionVariant::create(self.relative_offset_adjustment.get()),
3114                committed_at,
3115                animation,
3116            );
3117        } else if changed.contains(CompositionVisualChangedFields::RELATIVE_OFFSET_ADJUSTMENT) {
3118            let value = reader.read::<Vector3D>();
3119            self.set_relative_offset_adjustment(host, value);
3120        }
3121        if changed.contains(CompositionVisualChangedFields::RELATIVE_SIZE_ADJUSTMENT_ANIMATED) {
3122            let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
3123                panic!("a batch starts an animation of `RelativeSizeAdjustment` without an animation instance");
3124            };
3125            host.set_animated_value(
3126                Self::id_of_relative_size_adjustment_property().base(),
3127                ExpressionVariant::create(self.relative_size_adjustment.get()),
3128                committed_at,
3129                animation,
3130            );
3131        } else if changed.contains(CompositionVisualChangedFields::RELATIVE_SIZE_ADJUSTMENT) {
3132            let value = reader.read::<Vector>();
3133            self.set_relative_size_adjustment(host, value);
3134        }
3135        if changed.contains(CompositionVisualChangedFields::IS_HIT_TEST_VISIBLE) {
3136            let value = reader.read::<bool>();
3137            self.set_is_hit_test_visible(host, value);
3138        }
3139        if changed.contains(CompositionVisualChangedFields::IS_PIXEL_SNAPPING_ENABLED) {
3140            let value = reader.read::<bool>();
3141            self.set_is_pixel_snapping_enabled(host, value);
3142        }
3143        if changed.contains(CompositionVisualChangedFields::BORDER_MODE) {
3144            let value = reader.read::<CompositionBorderMode>();
3145            self.set_border_mode(host, value);
3146        }
3147        if changed.contains(CompositionVisualChangedFields::BACKFACE_VISIBILITY) {
3148            let value = reader.read::<CompositionBackfaceVisibility>();
3149            self.set_backface_visibility(host, value);
3150        }
3151        if changed.contains(CompositionVisualChangedFields::COMPOSITE_MODE) {
3152            let value = reader.read::<CompositionCompositeMode>();
3153            self.set_composite_mode(host, value);
3154        }
3155        if changed.contains(CompositionVisualChangedFields::PARENT_FOR_TRANSFORM) {
3156            let value = read_server_object(reader, compositor.as_ref());
3157            self.set_parent_for_transform(host, value);
3158        }
3159        ServerCompositionVisualHooks::on_fields_deserialized(host, changed);
3160    }
3161
3162    /// The composition property with the given name, among the properties
3163    /// of this class and of its generated bases that have a variant form.
3164    pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
3165        if name == "Visible" {
3166            return Some(Self::id_of_visible_property().base());
3167        }
3168        if name == "Opacity" {
3169            return Some(Self::id_of_opacity_property().base());
3170        }
3171        if name == "ClipToBounds" {
3172            return Some(Self::id_of_clip_to_bounds_property().base());
3173        }
3174        if name == "Offset" {
3175            return Some(Self::id_of_offset_property().base());
3176        }
3177        if name == "Translation" {
3178            return Some(Self::id_of_translation_property().base());
3179        }
3180        if name == "Size" {
3181            return Some(Self::id_of_size_property().base());
3182        }
3183        if name == "AnchorPoint" {
3184            return Some(Self::id_of_anchor_point_property().base());
3185        }
3186        if name == "CenterPoint" {
3187            return Some(Self::id_of_center_point_property().base());
3188        }
3189        if name == "RotationAngle" {
3190            return Some(Self::id_of_rotation_angle_property().base());
3191        }
3192        if name == "Orientation" {
3193            return Some(Self::id_of_orientation_property().base());
3194        }
3195        if name == "Scale" {
3196            return Some(Self::id_of_scale_property().base());
3197        }
3198        if name == "AdornerIsClipped" {
3199            return Some(Self::id_of_adorner_is_clipped_property().base());
3200        }
3201        if name == "RotationAxis" {
3202            return Some(Self::id_of_rotation_axis_property().base());
3203        }
3204        if name == "RelativeOffsetAdjustment" {
3205            return Some(Self::id_of_relative_offset_adjustment_property().base());
3206        }
3207        if name == "RelativeSizeAdjustment" {
3208            return Some(Self::id_of_relative_size_adjustment_property().base());
3209        }
3210        if name == "IsHitTestVisible" {
3211            return Some(Self::id_of_is_hit_test_visible_property().base());
3212        }
3213        if name == "IsPixelSnappingEnabled" {
3214            return Some(Self::id_of_is_pixel_snapping_enabled_property().base());
3215        }
3216        None
3217    }
3218}