ferroui_base/rendering/composition/generated/
composition_brush.rs1use bitflags::bitflags;
6use crate::RelativePoint;
7use crate::media::ITransform;
8use crate::rendering::composition::ICompositionObjectHost;
9use crate::rendering::composition::animations::AnimationInstanceFactory;
10use crate::rendering::composition::animations::ICompositionAnimation;
11use crate::rendering::composition::expressions::ExpressionVariant;
12use crate::rendering::composition::server::AsServerRenderResource;
13use crate::rendering::composition::server::CompositionProperty;
14use crate::rendering::composition::server::CompositionPropertyOf;
15use crate::rendering::composition::server::IServerAnimatedPropertyHost;
16use crate::rendering::composition::server::ServerPropertyValue;
17use crate::rendering::composition::server::ServerResourceRef;
18use crate::rendering::composition::server::ServerValueChange;
19use crate::rendering::composition::server::props_of;
20use crate::rendering::composition::server::read_resource;
21use crate::rendering::composition::transport::BatchResource;
22use crate::rendering::composition::transport::BatchStreamReader;
23use crate::rendering::composition::transport::BatchStreamWriter;
24use crate::rendering::composition::transport::BatchValue;
25use crate::rendering::composition::transport::BatchValueReader;
26use std::any::Any;
27use std::any::TypeId;
28use std::cell::Cell;
29use std::cell::RefCell;
30use std::sync::OnceLock;
31use std::time::Duration;
32
33bitflags! {
34 #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
36 pub struct CompositionBrushChangedFields: u8 {
37 const OPACITY = 1;
38 const OPACITY_ANIMATED = 2;
39 const TRANSFORM_ORIGIN = 4;
40 const TRANSFORM = 8;
41 const RELATIVE_TRANSFORM = 16;
42 }
43}
44
45impl BatchValue for CompositionBrushChangedFields {
46 #[inline]
47 fn write_to(&self, out: &mut Vec<u8>) {
48 self.bits().write_to(out);
49 }
50
51 #[inline]
52 fn read_from(input: &mut BatchValueReader<'_>) -> Self {
53 CompositionBrushChangedFields::from_bits_retain(u8::read_from(input))
54 }
55}
56
57pub trait CompositionBrushHooks: ICompositionObjectHost {
60 fn initialize_defaults_extra(&self) {}
61
62 fn validate_opacity_change(&self, _old_value: f64, _new_value: f64) {}
63 fn on_opacity_changed(&self) {}
64 fn on_opacity_changing(&self) {}
65
66 fn validate_transform_origin_change(&self, _old_value: RelativePoint, _new_value: RelativePoint) {}
67 fn on_transform_origin_changed(&self) {}
68 fn on_transform_origin_changing(&self) {}
69
70 fn validate_transform_change(&self, _old_value: &Option<BatchResource<dyn ITransform>>, _new_value: &Option<BatchResource<dyn ITransform>>) {}
71 fn on_transform_changed(&self) {}
72 fn on_transform_changing(&self) {}
73
74 fn validate_relative_transform_change(&self, _old_value: &Option<BatchResource<dyn ITransform>>, _new_value: &Option<BatchResource<dyn ITransform>>) {}
75 fn on_relative_transform_changed(&self) {}
76 fn on_relative_transform_changing(&self) {}
77}
78
79pub struct CompositionBrushProps {
81 changed_fields_of_composition_brush: Cell<CompositionBrushChangedFields>,
82 opacity: Cell<f64>,
83 transform_origin: Cell<RelativePoint>,
84 transform: RefCell<Option<BatchResource<dyn ITransform>>>,
85 relative_transform: RefCell<Option<BatchResource<dyn ITransform>>>,
86}
87
88impl Default for CompositionBrushProps {
89 fn default() -> Self {
90 Self::new()
91 }
92}
93
94impl CompositionBrushProps {
95 pub fn new() -> Self {
99 Self {
100 changed_fields_of_composition_brush: Cell::new(CompositionBrushChangedFields::empty()),
101 opacity: Cell::new(Default::default()),
102 transform_origin: Cell::new(Default::default()),
103 transform: RefCell::new(None),
104 relative_transform: RefCell::new(None),
105 }
106 }
107
108 pub fn initialize_defaults(&self, host: &dyn CompositionBrushHooks) {
111 self.initialize_own_defaults(host);
112 }
113
114 pub fn initialize_own_defaults(&self, host: &dyn CompositionBrushHooks) {
116 CompositionBrushHooks::initialize_defaults_extra(host);
117 self.set_opacity(host, 1.0);
118 }
119
120 pub fn opacity(&self) -> f64 {
122 self.opacity.get()
123 }
124
125 pub fn set_opacity(&self, host: &dyn CompositionBrushHooks, value: f64) {
127 let mut changed = false;
128 let old_value = self.opacity.get();
129 if old_value.differs(&value) {
130 CompositionBrushHooks::validate_opacity_change(host, old_value, value);
131 CompositionBrushHooks::on_opacity_changing(host);
132 changed = true;
133 self.opacity.set(value);
135 self.changed_fields_of_composition_brush.set(self.changed_fields_of_composition_brush.get() | CompositionBrushChangedFields::OPACITY);
137 host.register_for_serialization();
138 host.pending_animations().remove(ServerCompositionBrushProps::id_of_opacity_property().base());
140 self.changed_fields_of_composition_brush.set(self.changed_fields_of_composition_brush.get() & !CompositionBrushChangedFields::OPACITY_ANIMATED);
141 if let Some(animation) = host.implicit_animation("Opacity") {
143 if let Some(a) = animation.as_composition_animation() {
145 self.changed_fields_of_composition_brush.set(self.changed_fields_of_composition_brush.get() | CompositionBrushChangedFields::OPACITY_ANIMATED);
146 host.pending_animations().set(
147 ServerCompositionBrushProps::id_of_opacity_property().base(),
148 a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
149 );
150 }
151 host.start_animation_group(&animation, "Opacity", ExpressionVariant::create(value));
153 }
154 }
155 self.opacity.set(value);
156 if changed {
157 CompositionBrushHooks::on_opacity_changed(host);
158 }
159 }
160
161 pub fn transform_origin(&self) -> RelativePoint {
163 self.transform_origin.get()
164 }
165
166 pub fn set_transform_origin(&self, host: &dyn CompositionBrushHooks, value: RelativePoint) {
168 let mut changed = false;
169 let old_value = self.transform_origin.get();
170 if old_value.differs(&value) {
171 CompositionBrushHooks::validate_transform_origin_change(host, old_value, value);
172 CompositionBrushHooks::on_transform_origin_changing(host);
173 changed = true;
174 self.transform_origin.set(value);
176 self.changed_fields_of_composition_brush.set(self.changed_fields_of_composition_brush.get() | CompositionBrushChangedFields::TRANSFORM_ORIGIN);
178 host.register_for_serialization();
179 }
180 self.transform_origin.set(value);
181 if changed {
182 CompositionBrushHooks::on_transform_origin_changed(host);
183 }
184 }
185
186 pub fn transform(&self) -> Option<BatchResource<dyn ITransform>> {
188 self.transform.borrow().clone()
189 }
190
191 pub fn set_transform(&self, host: &dyn CompositionBrushHooks, value: Option<BatchResource<dyn ITransform>>) {
193 let mut changed = false;
194 let old_value = self.transform.borrow().clone();
195 if old_value.differs(&value) {
196 CompositionBrushHooks::validate_transform_change(host, &old_value, &value);
197 CompositionBrushHooks::on_transform_changing(host);
198 changed = true;
199 *self.transform.borrow_mut() = value.clone();
201 self.changed_fields_of_composition_brush.set(self.changed_fields_of_composition_brush.get() | CompositionBrushChangedFields::TRANSFORM);
203 host.register_for_serialization();
204 }
205 *self.transform.borrow_mut() = value;
206 if changed {
207 CompositionBrushHooks::on_transform_changed(host);
208 }
209 }
210
211 pub fn relative_transform(&self) -> Option<BatchResource<dyn ITransform>> {
213 self.relative_transform.borrow().clone()
214 }
215
216 pub fn set_relative_transform(&self, host: &dyn CompositionBrushHooks, value: Option<BatchResource<dyn ITransform>>) {
218 let mut changed = false;
219 let old_value = self.relative_transform.borrow().clone();
220 if old_value.differs(&value) {
221 CompositionBrushHooks::validate_relative_transform_change(host, &old_value, &value);
222 CompositionBrushHooks::on_relative_transform_changing(host);
223 changed = true;
224 *self.relative_transform.borrow_mut() = value.clone();
226 self.changed_fields_of_composition_brush.set(self.changed_fields_of_composition_brush.get() | CompositionBrushChangedFields::RELATIVE_TRANSFORM);
228 host.register_for_serialization();
229 }
230 *self.relative_transform.borrow_mut() = value;
231 if changed {
232 CompositionBrushHooks::on_relative_transform_changed(host);
233 }
234 }
235
236 pub fn start_animation(
240 &self,
241 host: &dyn CompositionBrushHooks,
242 property_name: &str,
243 animation: &dyn ICompositionAnimation,
244 final_value: Option<ExpressionVariant>,
245 ) -> bool {
246 if property_name == "Opacity" {
247 let server = animation.create_instance(host.server(), final_value);
248 host.pending_animations().set(ServerCompositionBrushProps::id_of_opacity_property().base(), server);
249 self.changed_fields_of_composition_brush.set(self.changed_fields_of_composition_brush.get() | CompositionBrushChangedFields::OPACITY_ANIMATED);
250 host.register_for_serialization();
251 return true;
252 }
253 false
254 }
255
256 pub fn serialize_changes_core(&self, host: &dyn CompositionBrushHooks, writer: &mut BatchStreamWriter<'_>) {
259 let changed = self.changed_fields_of_composition_brush.get();
260 writer.write(changed);
261 if changed.contains(CompositionBrushChangedFields::OPACITY_ANIMATED) {
262 writer.write_value(host.pending_animations().get_and_remove(ServerCompositionBrushProps::id_of_opacity_property().base()));
263 } else if changed.contains(CompositionBrushChangedFields::OPACITY) {
264 writer.write(self.opacity.get());
265 }
266 if changed.contains(CompositionBrushChangedFields::TRANSFORM_ORIGIN) {
267 writer.write(self.transform_origin.get());
268 }
269 if changed.contains(CompositionBrushChangedFields::TRANSFORM) {
270 writer.write_resource(self.transform.borrow().clone());
271 }
272 if changed.contains(CompositionBrushChangedFields::RELATIVE_TRANSFORM) {
273 writer.write_resource(self.relative_transform.borrow().clone());
274 }
275 self.changed_fields_of_composition_brush.set(CompositionBrushChangedFields::empty());
276 }
277}
278
279pub trait ServerCompositionBrushHooks: IServerAnimatedPropertyHost {
282 fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
283 fn on_fields_deserialized(&self, _changed: CompositionBrushChangedFields) {}
284
285 fn on_transform_origin_changed(&self) {}
286 fn on_transform_origin_changing(&self) {}
287
288 fn on_transform_changed(&self) {}
289 fn on_transform_changing(&self) {}
290
291 fn on_relative_transform_changed(&self) {}
292 fn on_relative_transform_changing(&self) {}
293}
294
295pub struct ServerCompositionBrushProps {
297 opacity: Cell<f64>,
298 transform_origin: Cell<RelativePoint>,
299 transform: RefCell<Option<ServerResourceRef<dyn ITransform>>>,
300 relative_transform: RefCell<Option<ServerResourceRef<dyn ITransform>>>,
301}
302
303impl Default for ServerCompositionBrushProps {
304 fn default() -> Self {
305 Self::new()
306 }
307}
308
309impl ServerCompositionBrushProps {
310 pub fn new() -> Self {
313 Self {
314 opacity: Cell::new(Default::default()),
315 transform_origin: Cell::new(Default::default()),
316 transform: RefCell::new(None),
317 relative_transform: RefCell::new(None),
318 }
319 }
320
321 pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
324 if type_id == TypeId::of::<Self>() {
325 return Some(self);
326 }
327 None
328 }
329
330 pub fn id_of_opacity_property() -> &'static CompositionPropertyOf<f64> {
332 static PROPERTY: OnceLock<CompositionPropertyOf<f64>> = OnceLock::new();
333 PROPERTY.get_or_init(|| {
334 CompositionProperty::register::<ServerCompositionBrushProps, f64>(
335 "Opacity",
336 "ServerCompositionBrush",
337 |obj| props_of::<ServerCompositionBrushProps>(obj).opacity.get(),
338 |obj, v| props_of::<ServerCompositionBrushProps>(obj).opacity.set(v),
339 Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionBrushProps>(obj).opacity.get())),
340 Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionBrushProps>(obj).opacity.set(v.cast_or_default::<f64>())),
341 )
342 })
343 }
344
345 pub fn opacity(&self) -> f64 {
347 self.opacity.get()
348 }
349
350 pub fn set_opacity(&self, host: &dyn ServerCompositionBrushHooks, value: f64) {
351 self.opacity.set(value);
352 host.remove_animation_for_property(Self::id_of_opacity_property().base());
353 }
354
355 pub fn id_of_transform_origin_property() -> &'static CompositionPropertyOf<RelativePoint> {
357 static PROPERTY: OnceLock<CompositionPropertyOf<RelativePoint>> = OnceLock::new();
358 PROPERTY.get_or_init(|| {
359 CompositionProperty::register::<ServerCompositionBrushProps, RelativePoint>(
360 "TransformOrigin",
361 "ServerCompositionBrush",
362 |obj| props_of::<ServerCompositionBrushProps>(obj).transform_origin.get(),
363 |obj, v| props_of::<ServerCompositionBrushProps>(obj).transform_origin.set(v),
364 None,
365 None,
366 )
367 })
368 }
369
370 pub fn transform_origin(&self) -> RelativePoint {
372 self.transform_origin.get()
373 }
374
375 pub fn set_transform_origin(&self, host: &dyn ServerCompositionBrushHooks, value: RelativePoint) {
376 let old_value = self.transform_origin.get();
377 let mut changed = false;
378 if old_value.differs(&value) {
379 ServerCompositionBrushHooks::on_transform_origin_changing(host);
380 changed = true;
381 }
382 host.set_value(
383 Self::id_of_transform_origin_property().base(),
384 ServerValueChange {
385 equal: old_value.default_equals(&value),
386 old_resource: None,
387 new_resource: None,
388 assign: &mut || self.transform_origin.set(value),
389 },
390 );
391 if changed {
392 ServerCompositionBrushHooks::on_transform_origin_changed(host);
393 }
394 }
395
396 pub fn id_of_transform_property() -> &'static CompositionPropertyOf<Option<ServerResourceRef<dyn ITransform>>> {
398 static PROPERTY: OnceLock<CompositionPropertyOf<Option<ServerResourceRef<dyn ITransform>>>> = OnceLock::new();
399 PROPERTY.get_or_init(|| {
400 CompositionProperty::register::<ServerCompositionBrushProps, Option<ServerResourceRef<dyn ITransform>>>(
401 "Transform",
402 "ServerCompositionBrush",
403 |obj| props_of::<ServerCompositionBrushProps>(obj).transform.borrow().clone(),
404 |obj, v| *props_of::<ServerCompositionBrushProps>(obj).transform.borrow_mut() = v,
405 None,
406 None,
407 )
408 })
409 }
410
411 pub fn transform(&self) -> Option<ServerResourceRef<dyn ITransform>> {
413 self.transform.borrow().clone()
414 }
415
416 pub fn set_transform(&self, host: &dyn ServerCompositionBrushHooks, value: Option<ServerResourceRef<dyn ITransform>>) {
417 let old_value = self.transform.borrow().clone();
418 let mut changed = false;
419 if old_value.differs(&value) {
420 ServerCompositionBrushHooks::on_transform_changing(host);
421 changed = true;
422 }
423 host.set_value(
424 Self::id_of_transform_property().base(),
425 ServerValueChange {
426 equal: old_value.default_equals(&value),
427 old_resource: old_value.as_server_render_resource(),
428 new_resource: value.as_server_render_resource(),
429 assign: &mut || *self.transform.borrow_mut() = value.clone(),
430 },
431 );
432 if changed {
433 ServerCompositionBrushHooks::on_transform_changed(host);
434 }
435 }
436
437 pub fn id_of_relative_transform_property() -> &'static CompositionPropertyOf<Option<ServerResourceRef<dyn ITransform>>> {
439 static PROPERTY: OnceLock<CompositionPropertyOf<Option<ServerResourceRef<dyn ITransform>>>> = OnceLock::new();
440 PROPERTY.get_or_init(|| {
441 CompositionProperty::register::<ServerCompositionBrushProps, Option<ServerResourceRef<dyn ITransform>>>(
442 "RelativeTransform",
443 "ServerCompositionBrush",
444 |obj| props_of::<ServerCompositionBrushProps>(obj).relative_transform.borrow().clone(),
445 |obj, v| *props_of::<ServerCompositionBrushProps>(obj).relative_transform.borrow_mut() = v,
446 None,
447 None,
448 )
449 })
450 }
451
452 pub fn relative_transform(&self) -> Option<ServerResourceRef<dyn ITransform>> {
454 self.relative_transform.borrow().clone()
455 }
456
457 pub fn set_relative_transform(&self, host: &dyn ServerCompositionBrushHooks, value: Option<ServerResourceRef<dyn ITransform>>) {
458 let old_value = self.relative_transform.borrow().clone();
459 let mut changed = false;
460 if old_value.differs(&value) {
461 ServerCompositionBrushHooks::on_relative_transform_changing(host);
462 changed = true;
463 }
464 host.set_value(
465 Self::id_of_relative_transform_property().base(),
466 ServerValueChange {
467 equal: old_value.default_equals(&value),
468 old_resource: old_value.as_server_render_resource(),
469 new_resource: value.as_server_render_resource(),
470 assign: &mut || *self.relative_transform.borrow_mut() = value.clone(),
471 },
472 );
473 if changed {
474 ServerCompositionBrushHooks::on_relative_transform_changed(host);
475 }
476 }
477
478 pub fn deserialize_changes_core(
481 &self,
482 host: &dyn ServerCompositionBrushHooks,
483 reader: &mut BatchStreamReader<'_>,
484 committed_at: Duration,
485 ) {
486 let compositor = host.server_compositor();
487 ServerCompositionBrushHooks::deserialize_changes_extra(host, reader);
488 let changed = reader.read::<CompositionBrushChangedFields>();
489 if changed.contains(CompositionBrushChangedFields::OPACITY_ANIMATED) {
490 let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
491 panic!("a batch starts an animation of `Opacity` without an animation instance");
492 };
493 host.set_animated_value(
494 Self::id_of_opacity_property().base(),
495 ExpressionVariant::create(self.opacity.get()),
496 committed_at,
497 animation,
498 );
499 } else if changed.contains(CompositionBrushChangedFields::OPACITY) {
500 let value = reader.read::<f64>();
501 self.set_opacity(host, value);
502 }
503 if changed.contains(CompositionBrushChangedFields::TRANSFORM_ORIGIN) {
504 let value = reader.read::<RelativePoint>();
505 self.set_transform_origin(host, value);
506 }
507 if changed.contains(CompositionBrushChangedFields::TRANSFORM) {
508 let value = read_resource(reader, compositor.as_ref(), |o| o.as_transform());
509 self.set_transform(host, value);
510 }
511 if changed.contains(CompositionBrushChangedFields::RELATIVE_TRANSFORM) {
512 let value = read_resource(reader, compositor.as_ref(), |o| o.as_transform());
513 self.set_relative_transform(host, value);
514 }
515 ServerCompositionBrushHooks::on_fields_deserialized(host, changed);
516 }
517
518 pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
521 if name == "Opacity" {
522 return Some(Self::id_of_opacity_property().base());
523 }
524 None
525 }
526}