1use bitflags::bitflags;
10use crate::Matrix;
11use crate::Vector;
12use crate::rendering::composition::ICompositionObjectHost;
13use crate::rendering::composition::animations::AnimationInstanceFactory;
14use crate::rendering::composition::animations::ICompositionAnimation;
15use crate::rendering::composition::expressions::ExpressionVariant;
16use crate::rendering::composition::server::CompositionProperty;
17use crate::rendering::composition::server::CompositionPropertyOf;
18use crate::rendering::composition::server::IServerAnimatedPropertyHost;
19use crate::rendering::composition::server::ServerPropertyValue;
20use crate::rendering::composition::server::props_of;
21use crate::rendering::composition::transport::BatchStreamReader;
22use crate::rendering::composition::transport::BatchStreamWriter;
23use crate::rendering::composition::transport::BatchValue;
24use crate::rendering::composition::transport::BatchValueReader;
25use std::any::Any;
26use std::any::TypeId;
27use std::cell::Cell;
28use std::sync::OnceLock;
29use std::time::Duration;
30
31bitflags! {
32 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
34 pub struct CompositionShapeChangedFields: u16 {
35 const CENTER_POINT = 1;
36 const CENTER_POINT_ANIMATED = 2;
37 const OFFSET = 4;
38 const OFFSET_ANIMATED = 8;
39 const ROTATION_ANGLE = 16;
40 const ROTATION_ANGLE_ANIMATED = 32;
41 const SCALE = 64;
42 const SCALE_ANIMATED = 128;
43 const TRANSFORM_MATRIX = 256;
44 const TRANSFORM_MATRIX_ANIMATED = 512;
45 }
46}
47
48impl BatchValue for CompositionShapeChangedFields {
49 #[inline]
50 fn write_to(&self, out: &mut Vec<u8>) {
51 self.bits().write_to(out);
52 }
53
54 #[inline]
55 fn read_from(input: &mut BatchValueReader<'_>) -> Self {
56 CompositionShapeChangedFields::from_bits_retain(u16::read_from(input))
57 }
58}
59
60pub trait CompositionShapeHooks: ICompositionObjectHost {
63 fn initialize_defaults_extra(&self) {}
64
65 fn validate_center_point_change(&self, _old_value: Vector, _new_value: Vector) {}
66 fn on_center_point_changed(&self) {}
67 fn on_center_point_changing(&self) {}
68
69 fn validate_offset_change(&self, _old_value: Vector, _new_value: Vector) {}
70 fn on_offset_changed(&self) {}
71 fn on_offset_changing(&self) {}
72
73 fn validate_rotation_angle_change(&self, _old_value: f32, _new_value: f32) {}
74 fn on_rotation_angle_changed(&self) {}
75 fn on_rotation_angle_changing(&self) {}
76
77 fn validate_scale_change(&self, _old_value: Vector, _new_value: Vector) {}
78 fn on_scale_changed(&self) {}
79 fn on_scale_changing(&self) {}
80
81 fn validate_transform_matrix_change(&self, _old_value: Matrix, _new_value: Matrix) {}
82 fn on_transform_matrix_changed(&self) {}
83 fn on_transform_matrix_changing(&self) {}
84}
85
86pub struct CompositionShapeProps {
88 changed_fields_of_composition_shape: Cell<CompositionShapeChangedFields>,
89 center_point: Cell<Vector>,
90 offset: Cell<Vector>,
91 rotation_angle: Cell<f32>,
92 scale: Cell<Vector>,
93 transform_matrix: Cell<Matrix>,
94}
95
96impl Default for CompositionShapeProps {
97 fn default() -> Self {
98 Self::new()
99 }
100}
101
102impl CompositionShapeProps {
103 pub fn new() -> Self {
107 Self {
108 changed_fields_of_composition_shape: Cell::new(CompositionShapeChangedFields::empty()),
109 center_point: Cell::new(Default::default()),
110 offset: Cell::new(Default::default()),
111 rotation_angle: Cell::new(Default::default()),
112 scale: Cell::new(Default::default()),
113 transform_matrix: Cell::new(Default::default()),
114 }
115 }
116
117 pub fn initialize_defaults(&self, host: &dyn CompositionShapeHooks) {
120 self.initialize_own_defaults(host);
121 }
122
123 pub fn initialize_own_defaults(&self, host: &dyn CompositionShapeHooks) {
125 CompositionShapeHooks::initialize_defaults_extra(host);
126 self.set_scale(host, Vector::new(1.0, 1.0));
127 self.set_transform_matrix(host, Matrix::IDENTITY);
128 }
129
130 pub fn center_point(&self) -> Vector {
132 self.center_point.get()
133 }
134
135 pub fn set_center_point(&self, host: &dyn CompositionShapeHooks, value: Vector) {
137 let mut changed = false;
138 let old_value = self.center_point.get();
139 if old_value.differs(&value) {
140 CompositionShapeHooks::validate_center_point_change(host, old_value, value);
141 CompositionShapeHooks::on_center_point_changing(host);
142 changed = true;
143 self.center_point.set(value);
145 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::CENTER_POINT);
147 host.register_for_serialization();
148 host.pending_animations().remove(ServerCompositionShapeProps::id_of_center_point_property().base());
150 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() & !CompositionShapeChangedFields::CENTER_POINT_ANIMATED);
151 if let Some(animation) = host.implicit_animation("CenterPoint") {
153 if let Some(a) = animation.as_composition_animation() {
155 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::CENTER_POINT_ANIMATED);
156 host.pending_animations().set(
157 ServerCompositionShapeProps::id_of_center_point_property().base(),
158 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
159 );
160 }
161 host.start_animation_group(&animation, "CenterPoint", ExpressionVariant::create(value));
163 }
164 }
165 self.center_point.set(value);
166 if changed {
167 CompositionShapeHooks::on_center_point_changed(host);
168 }
169 }
170
171 pub fn offset(&self) -> Vector {
173 self.offset.get()
174 }
175
176 pub fn set_offset(&self, host: &dyn CompositionShapeHooks, value: Vector) {
178 let mut changed = false;
179 let old_value = self.offset.get();
180 if old_value.differs(&value) {
181 CompositionShapeHooks::validate_offset_change(host, old_value, value);
182 CompositionShapeHooks::on_offset_changing(host);
183 changed = true;
184 self.offset.set(value);
186 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::OFFSET);
188 host.register_for_serialization();
189 host.pending_animations().remove(ServerCompositionShapeProps::id_of_offset_property().base());
191 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() & !CompositionShapeChangedFields::OFFSET_ANIMATED);
192 if let Some(animation) = host.implicit_animation("Offset") {
194 if let Some(a) = animation.as_composition_animation() {
196 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::OFFSET_ANIMATED);
197 host.pending_animations().set(
198 ServerCompositionShapeProps::id_of_offset_property().base(),
199 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
200 );
201 }
202 host.start_animation_group(&animation, "Offset", ExpressionVariant::create(value));
204 }
205 }
206 self.offset.set(value);
207 if changed {
208 CompositionShapeHooks::on_offset_changed(host);
209 }
210 }
211
212 pub fn rotation_angle(&self) -> f32 {
214 self.rotation_angle.get()
215 }
216
217 pub fn set_rotation_angle(&self, host: &dyn CompositionShapeHooks, value: f32) {
219 let mut changed = false;
220 let old_value = self.rotation_angle.get();
221 if old_value.differs(&value) {
222 CompositionShapeHooks::validate_rotation_angle_change(host, old_value, value);
223 CompositionShapeHooks::on_rotation_angle_changing(host);
224 changed = true;
225 self.rotation_angle.set(value);
227 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::ROTATION_ANGLE);
229 host.register_for_serialization();
230 host.pending_animations().remove(ServerCompositionShapeProps::id_of_rotation_angle_property().base());
232 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() & !CompositionShapeChangedFields::ROTATION_ANGLE_ANIMATED);
233 if let Some(animation) = host.implicit_animation("RotationAngle") {
235 if let Some(a) = animation.as_composition_animation() {
237 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::ROTATION_ANGLE_ANIMATED);
238 host.pending_animations().set(
239 ServerCompositionShapeProps::id_of_rotation_angle_property().base(),
240 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
241 );
242 }
243 host.start_animation_group(&animation, "RotationAngle", ExpressionVariant::create(value));
245 }
246 }
247 self.rotation_angle.set(value);
248 if changed {
249 CompositionShapeHooks::on_rotation_angle_changed(host);
250 }
251 }
252
253 pub fn scale(&self) -> Vector {
255 self.scale.get()
256 }
257
258 pub fn set_scale(&self, host: &dyn CompositionShapeHooks, value: Vector) {
260 let mut changed = false;
261 let old_value = self.scale.get();
262 if old_value.differs(&value) {
263 CompositionShapeHooks::validate_scale_change(host, old_value, value);
264 CompositionShapeHooks::on_scale_changing(host);
265 changed = true;
266 self.scale.set(value);
268 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::SCALE);
270 host.register_for_serialization();
271 host.pending_animations().remove(ServerCompositionShapeProps::id_of_scale_property().base());
273 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() & !CompositionShapeChangedFields::SCALE_ANIMATED);
274 if let Some(animation) = host.implicit_animation("Scale") {
276 if let Some(a) = animation.as_composition_animation() {
278 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::SCALE_ANIMATED);
279 host.pending_animations().set(
280 ServerCompositionShapeProps::id_of_scale_property().base(),
281 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
282 );
283 }
284 host.start_animation_group(&animation, "Scale", ExpressionVariant::create(value));
286 }
287 }
288 self.scale.set(value);
289 if changed {
290 CompositionShapeHooks::on_scale_changed(host);
291 }
292 }
293
294 pub fn transform_matrix(&self) -> Matrix {
296 self.transform_matrix.get()
297 }
298
299 pub fn set_transform_matrix(&self, host: &dyn CompositionShapeHooks, value: Matrix) {
301 let mut changed = false;
302 let old_value = self.transform_matrix.get();
303 if old_value.differs(&value) {
304 CompositionShapeHooks::validate_transform_matrix_change(host, old_value, value);
305 CompositionShapeHooks::on_transform_matrix_changing(host);
306 changed = true;
307 self.transform_matrix.set(value);
309 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::TRANSFORM_MATRIX);
311 host.register_for_serialization();
312 host.pending_animations().remove(ServerCompositionShapeProps::id_of_transform_matrix_property().base());
314 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() & !CompositionShapeChangedFields::TRANSFORM_MATRIX_ANIMATED);
315 if let Some(animation) = host.implicit_animation("TransformMatrix") {
317 if let Some(a) = animation.as_composition_animation() {
319 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::TRANSFORM_MATRIX_ANIMATED);
320 host.pending_animations().set(
321 ServerCompositionShapeProps::id_of_transform_matrix_property().base(),
322 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
323 );
324 }
325 host.start_animation_group(&animation, "TransformMatrix", ExpressionVariant::create(value));
327 }
328 }
329 self.transform_matrix.set(value);
330 if changed {
331 CompositionShapeHooks::on_transform_matrix_changed(host);
332 }
333 }
334
335 pub fn start_animation(
339 &self,
340 host: &dyn CompositionShapeHooks,
341 property_name: &str,
342 animation: &dyn ICompositionAnimation,
343 final_value: Option<ExpressionVariant>,
344 ) -> bool {
345 if property_name == "CenterPoint" {
346 let server = animation.create_instance(host.server(), final_value);
347 host.pending_animations().set(ServerCompositionShapeProps::id_of_center_point_property().base(), server);
348 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::CENTER_POINT_ANIMATED);
349 host.register_for_serialization();
350 return true;
351 }
352 if property_name == "Offset" {
353 let server = animation.create_instance(host.server(), final_value);
354 host.pending_animations().set(ServerCompositionShapeProps::id_of_offset_property().base(), server);
355 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::OFFSET_ANIMATED);
356 host.register_for_serialization();
357 return true;
358 }
359 if property_name == "RotationAngle" {
360 let server = animation.create_instance(host.server(), final_value);
361 host.pending_animations().set(ServerCompositionShapeProps::id_of_rotation_angle_property().base(), server);
362 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::ROTATION_ANGLE_ANIMATED);
363 host.register_for_serialization();
364 return true;
365 }
366 if property_name == "Scale" {
367 let server = animation.create_instance(host.server(), final_value);
368 host.pending_animations().set(ServerCompositionShapeProps::id_of_scale_property().base(), server);
369 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::SCALE_ANIMATED);
370 host.register_for_serialization();
371 return true;
372 }
373 if property_name == "TransformMatrix" {
374 let server = animation.create_instance(host.server(), final_value);
375 host.pending_animations().set(ServerCompositionShapeProps::id_of_transform_matrix_property().base(), server);
376 self.changed_fields_of_composition_shape.set(self.changed_fields_of_composition_shape.get() | CompositionShapeChangedFields::TRANSFORM_MATRIX_ANIMATED);
377 host.register_for_serialization();
378 return true;
379 }
380 false
381 }
382
383 pub fn serialize_changes_core(&self, host: &dyn CompositionShapeHooks, writer: &mut BatchStreamWriter<'_>) {
386 let changed = self.changed_fields_of_composition_shape.get();
387 writer.write(changed);
388 if changed.contains(CompositionShapeChangedFields::CENTER_POINT_ANIMATED) {
389 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionShapeProps::id_of_center_point_property().base()));
390 } else if changed.contains(CompositionShapeChangedFields::CENTER_POINT) {
391 writer.write(self.center_point.get());
392 }
393 if changed.contains(CompositionShapeChangedFields::OFFSET_ANIMATED) {
394 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionShapeProps::id_of_offset_property().base()));
395 } else if changed.contains(CompositionShapeChangedFields::OFFSET) {
396 writer.write(self.offset.get());
397 }
398 if changed.contains(CompositionShapeChangedFields::ROTATION_ANGLE_ANIMATED) {
399 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionShapeProps::id_of_rotation_angle_property().base()));
400 } else if changed.contains(CompositionShapeChangedFields::ROTATION_ANGLE) {
401 writer.write(self.rotation_angle.get());
402 }
403 if changed.contains(CompositionShapeChangedFields::SCALE_ANIMATED) {
404 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionShapeProps::id_of_scale_property().base()));
405 } else if changed.contains(CompositionShapeChangedFields::SCALE) {
406 writer.write(self.scale.get());
407 }
408 if changed.contains(CompositionShapeChangedFields::TRANSFORM_MATRIX_ANIMATED) {
409 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionShapeProps::id_of_transform_matrix_property().base()));
410 } else if changed.contains(CompositionShapeChangedFields::TRANSFORM_MATRIX) {
411 writer.write(self.transform_matrix.get());
412 }
413 self.changed_fields_of_composition_shape.set(CompositionShapeChangedFields::empty());
414 }
415}
416
417pub trait ServerCompositionShapeHooks: IServerAnimatedPropertyHost {
420 fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
421 fn on_fields_deserialized(&self, _changed: CompositionShapeChangedFields) {}
422}
423
424pub struct ServerCompositionShapeProps {
426 center_point: Cell<Vector>,
427 offset: Cell<Vector>,
428 rotation_angle: Cell<f32>,
429 scale: Cell<Vector>,
430 transform_matrix: Cell<Matrix>,
431}
432
433impl Default for ServerCompositionShapeProps {
434 fn default() -> Self {
435 Self::new()
436 }
437}
438
439impl ServerCompositionShapeProps {
440 pub fn new() -> Self {
443 Self {
444 center_point: Cell::new(Default::default()),
445 offset: Cell::new(Default::default()),
446 rotation_angle: Cell::new(Default::default()),
447 scale: Cell::new(Default::default()),
448 transform_matrix: Cell::new(Default::default()),
449 }
450 }
451
452 pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
455 if type_id == TypeId::of::<Self>() {
456 return Some(self);
457 }
458 None
459 }
460
461 pub fn id_of_center_point_property() -> &'static CompositionPropertyOf<Vector> {
463 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
464 PROPERTY.get_or_init(|| {
465 CompositionProperty::register::<ServerCompositionShapeProps, Vector>(
466 "CenterPoint",
467 "ServerCompositionShape",
468 |obj| props_of::<ServerCompositionShapeProps>(obj).center_point.get(),
469 |obj, v| props_of::<ServerCompositionShapeProps>(obj).center_point.set(v),
470 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionShapeProps>(obj).center_point.get())),
471 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionShapeProps>(obj).center_point.set(v.cast_or_default::<Vector>())),
472 )
473 })
474 }
475
476 pub fn center_point(&self) -> Vector {
478 self.center_point.get()
479 }
480
481 pub fn set_center_point(&self, host: &dyn ServerCompositionShapeHooks, value: Vector) {
482 self.center_point.set(value);
483 host.remove_animation_for_property(Self::id_of_center_point_property().base());
484 }
485
486 pub fn id_of_offset_property() -> &'static CompositionPropertyOf<Vector> {
488 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
489 PROPERTY.get_or_init(|| {
490 CompositionProperty::register::<ServerCompositionShapeProps, Vector>(
491 "Offset",
492 "ServerCompositionShape",
493 |obj| props_of::<ServerCompositionShapeProps>(obj).offset.get(),
494 |obj, v| props_of::<ServerCompositionShapeProps>(obj).offset.set(v),
495 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionShapeProps>(obj).offset.get())),
496 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionShapeProps>(obj).offset.set(v.cast_or_default::<Vector>())),
497 )
498 })
499 }
500
501 pub fn offset(&self) -> Vector {
503 self.offset.get()
504 }
505
506 pub fn set_offset(&self, host: &dyn ServerCompositionShapeHooks, value: Vector) {
507 self.offset.set(value);
508 host.remove_animation_for_property(Self::id_of_offset_property().base());
509 }
510
511 pub fn id_of_rotation_angle_property() -> &'static CompositionPropertyOf<f32> {
513 static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
514 PROPERTY.get_or_init(|| {
515 CompositionProperty::register::<ServerCompositionShapeProps, f32>(
516 "RotationAngle",
517 "ServerCompositionShape",
518 |obj| props_of::<ServerCompositionShapeProps>(obj).rotation_angle.get(),
519 |obj, v| props_of::<ServerCompositionShapeProps>(obj).rotation_angle.set(v),
520 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionShapeProps>(obj).rotation_angle.get())),
521 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionShapeProps>(obj).rotation_angle.set(v.cast_or_default::<f32>())),
522 )
523 })
524 }
525
526 pub fn rotation_angle(&self) -> f32 {
528 self.rotation_angle.get()
529 }
530
531 pub fn set_rotation_angle(&self, host: &dyn ServerCompositionShapeHooks, value: f32) {
532 self.rotation_angle.set(value);
533 host.remove_animation_for_property(Self::id_of_rotation_angle_property().base());
534 }
535
536 pub fn id_of_scale_property() -> &'static CompositionPropertyOf<Vector> {
538 static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
539 PROPERTY.get_or_init(|| {
540 CompositionProperty::register::<ServerCompositionShapeProps, Vector>(
541 "Scale",
542 "ServerCompositionShape",
543 |obj| props_of::<ServerCompositionShapeProps>(obj).scale.get(),
544 |obj, v| props_of::<ServerCompositionShapeProps>(obj).scale.set(v),
545 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionShapeProps>(obj).scale.get())),
546 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionShapeProps>(obj).scale.set(v.cast_or_default::<Vector>())),
547 )
548 })
549 }
550
551 pub fn scale(&self) -> Vector {
553 self.scale.get()
554 }
555
556 pub fn set_scale(&self, host: &dyn ServerCompositionShapeHooks, value: Vector) {
557 self.scale.set(value);
558 host.remove_animation_for_property(Self::id_of_scale_property().base());
559 }
560
561 pub fn id_of_transform_matrix_property() -> &'static CompositionPropertyOf<Matrix> {
563 static PROPERTY: OnceLock<CompositionPropertyOf<Matrix>> = OnceLock::new();
564 PROPERTY.get_or_init(|| {
565 CompositionProperty::register::<ServerCompositionShapeProps, Matrix>(
566 "TransformMatrix",
567 "ServerCompositionShape",
568 |obj| props_of::<ServerCompositionShapeProps>(obj).transform_matrix.get(),
569 |obj, v| props_of::<ServerCompositionShapeProps>(obj).transform_matrix.set(v),
570 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionShapeProps>(obj).transform_matrix.get())),
571 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionShapeProps>(obj).transform_matrix.set(v.cast_or_default::<Matrix>())),
572 )
573 })
574 }
575
576 pub fn transform_matrix(&self) -> Matrix {
578 self.transform_matrix.get()
579 }
580
581 pub fn set_transform_matrix(&self, host: &dyn ServerCompositionShapeHooks, value: Matrix) {
582 self.transform_matrix.set(value);
583 host.remove_animation_for_property(Self::id_of_transform_matrix_property().base());
584 }
585
586 pub fn deserialize_changes_core(
589 &self,
590 host: &dyn ServerCompositionShapeHooks,
591 reader: &mut BatchStreamReader<'_>,
592 committed_at: Duration,
593 ) {
594 ServerCompositionShapeHooks::deserialize_changes_extra(host, reader);
595 let changed = reader.read::<CompositionShapeChangedFields>();
596 if changed.contains(CompositionShapeChangedFields::CENTER_POINT_ANIMATED) {
597 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
598 panic!("a batch starts an animation of `CenterPoint` without an animation instance");
599 };
600 host.set_animated_value(
601 Self::id_of_center_point_property().base(),
602 ExpressionVariant::create(self.center_point.get()),
603 committed_at,
604 animation,
605 );
606 } else if changed.contains(CompositionShapeChangedFields::CENTER_POINT) {
607 let value = reader.read::<Vector>();
608 self.set_center_point(host, value);
609 }
610 if changed.contains(CompositionShapeChangedFields::OFFSET_ANIMATED) {
611 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
612 panic!("a batch starts an animation of `Offset` without an animation instance");
613 };
614 host.set_animated_value(
615 Self::id_of_offset_property().base(),
616 ExpressionVariant::create(self.offset.get()),
617 committed_at,
618 animation,
619 );
620 } else if changed.contains(CompositionShapeChangedFields::OFFSET) {
621 let value = reader.read::<Vector>();
622 self.set_offset(host, value);
623 }
624 if changed.contains(CompositionShapeChangedFields::ROTATION_ANGLE_ANIMATED) {
625 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
626 panic!("a batch starts an animation of `RotationAngle` without an animation instance");
627 };
628 host.set_animated_value(
629 Self::id_of_rotation_angle_property().base(),
630 ExpressionVariant::create(self.rotation_angle.get()),
631 committed_at,
632 animation,
633 );
634 } else if changed.contains(CompositionShapeChangedFields::ROTATION_ANGLE) {
635 let value = reader.read::<f32>();
636 self.set_rotation_angle(host, value);
637 }
638 if changed.contains(CompositionShapeChangedFields::SCALE_ANIMATED) {
639 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
640 panic!("a batch starts an animation of `Scale` without an animation instance");
641 };
642 host.set_animated_value(
643 Self::id_of_scale_property().base(),
644 ExpressionVariant::create(self.scale.get()),
645 committed_at,
646 animation,
647 );
648 } else if changed.contains(CompositionShapeChangedFields::SCALE) {
649 let value = reader.read::<Vector>();
650 self.set_scale(host, value);
651 }
652 if changed.contains(CompositionShapeChangedFields::TRANSFORM_MATRIX_ANIMATED) {
653 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
654 panic!("a batch starts an animation of `TransformMatrix` without an animation instance");
655 };
656 host.set_animated_value(
657 Self::id_of_transform_matrix_property().base(),
658 ExpressionVariant::create(self.transform_matrix.get()),
659 committed_at,
660 animation,
661 );
662 } else if changed.contains(CompositionShapeChangedFields::TRANSFORM_MATRIX) {
663 let value = reader.read::<Matrix>();
664 self.set_transform_matrix(host, value);
665 }
666 ServerCompositionShapeHooks::on_fields_deserialized(host, changed);
667 }
668
669 pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
672 if name == "CenterPoint" {
673 return Some(Self::id_of_center_point_property().base());
674 }
675 if name == "Offset" {
676 return Some(Self::id_of_offset_property().base());
677 }
678 if name == "RotationAngle" {
679 return Some(Self::id_of_rotation_angle_property().base());
680 }
681 if name == "Scale" {
682 return Some(Self::id_of_scale_property().base());
683 }
684 if name == "TransformMatrix" {
685 return Some(Self::id_of_transform_matrix_property().base());
686 }
687 None
688 }
689}