use bitflags::bitflags;
use crate::Matrix;
use crate::Vector;
use crate::Vector3D;
use crate::media::IBrush;
use crate::media::IImmutableEffect;
use crate::media::RenderOptions;
use crate::media::TextOptions;
use crate::numerics::Quaternion;
use crate::platform::IGeometryImpl;
use crate::rendering::composition::ICompositionObject;
use crate::rendering::composition::ICompositionObjectHost;
use crate::rendering::composition::animations::AnimationInstanceFactory;
use crate::rendering::composition::animations::ICompositionAnimation;
use crate::rendering::composition::expressions::ExpressionVariant;
use crate::rendering::composition::server::AsServerRenderResource;
use crate::rendering::composition::server::CompositionProperty;
use crate::rendering::composition::server::CompositionPropertyOf;
use crate::rendering::composition::server::IServerAnimatedPropertyHost;
use crate::rendering::composition::server::IServerObject;
use crate::rendering::composition::server::ServerPropertyValue;
use crate::rendering::composition::server::ServerResourceRef;
use crate::rendering::composition::server::ServerValueChange;
use crate::rendering::composition::server::props_of;
use crate::rendering::composition::server::read_resource;
use crate::rendering::composition::server::read_server_object;
use crate::rendering::composition::transport::BatchResource;
use crate::rendering::composition::transport::BatchStreamReader;
use crate::rendering::composition::transport::BatchStreamWriter;
use crate::rendering::composition::transport::BatchValue;
use crate::rendering::composition::transport::BatchValueReader;
use std::any::Any;
use std::any::TypeId;
use std::cell::Cell;
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::OnceLock;
use std::time::Duration;
bitflags! {
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct CompositionVisualChangedFields: u64 {
const ROOT = 1;
const PARENT = 2;
const VISIBLE = 4;
const VISIBLE_ANIMATED = 8;
const OPACITY = 16;
const OPACITY_ANIMATED = 32;
const CLIP = 64;
const CLIP_TO_BOUNDS = 128;
const CLIP_TO_BOUNDS_ANIMATED = 256;
const OFFSET = 512;
const OFFSET_ANIMATED = 1024;
const TRANSLATION = 2048;
const TRANSLATION_ANIMATED = 4096;
const SIZE = 8192;
const SIZE_ANIMATED = 16384;
const ANCHOR_POINT = 32768;
const ANCHOR_POINT_ANIMATED = 65536;
const CENTER_POINT = 131072;
const CENTER_POINT_ANIMATED = 262144;
const ROTATION_ANGLE = 524288;
const ROTATION_ANGLE_ANIMATED = 1048576;
const ORIENTATION = 2097152;
const ORIENTATION_ANIMATED = 4194304;
const SCALE = 8388608;
const SCALE_ANIMATED = 16777216;
const TRANSFORM_MATRIX = 33554432;
const TRANSFORM_MATRIX_ANIMATED = 67108864;
const ADORNED_VISUAL = 134217728;
const ADORNER_IS_CLIPPED = 268435456;
const OPACITY_MASK_BRUSH = 536870912;
const EFFECT = 1073741824;
const RENDER_OPTIONS = 2147483648;
const TEXT_OPTIONS = 4294967296;
const CACHE_MODE = 8589934592;
}
}
impl BatchValue for CompositionVisualChangedFields {
#[inline]
fn write_to(&self, out: &mut Vec<u8>) {
self.bits().write_to(out);
}
#[inline]
fn read_from(input: &mut BatchValueReader<'_>) -> Self {
CompositionVisualChangedFields::from_bits_retain(u64::read_from(input))
}
}
pub trait CompositionVisualHooks: ICompositionObjectHost {
fn initialize_defaults_extra(&self) {}
fn validate_root_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
fn on_root_changed(&self) {}
fn on_root_changing(&self) {}
fn validate_parent_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
fn on_parent_changed(&self) {}
fn on_parent_changing(&self) {}
fn validate_visible_change(&self, _old_value: bool, _new_value: bool) {}
fn on_visible_changed(&self) {}
fn on_visible_changing(&self) {}
fn validate_opacity_change(&self, _old_value: f32, _new_value: f32) {}
fn on_opacity_changed(&self) {}
fn on_opacity_changing(&self) {}
fn validate_clip_change(&self, _old_value: &Option<Arc<dyn IGeometryImpl>>, _new_value: &Option<Arc<dyn IGeometryImpl>>) {}
fn on_clip_changed(&self) {}
fn on_clip_changing(&self) {}
fn validate_clip_to_bounds_change(&self, _old_value: bool, _new_value: bool) {}
fn on_clip_to_bounds_changed(&self) {}
fn on_clip_to_bounds_changing(&self) {}
fn validate_offset_change(&self, _old_value: Vector3D, _new_value: Vector3D) {}
fn on_offset_changed(&self) {}
fn on_offset_changing(&self) {}
fn validate_translation_change(&self, _old_value: Vector3D, _new_value: Vector3D) {}
fn on_translation_changed(&self) {}
fn on_translation_changing(&self) {}
fn validate_size_change(&self, _old_value: Vector, _new_value: Vector) {}
fn on_size_changed(&self) {}
fn on_size_changing(&self) {}
fn validate_anchor_point_change(&self, _old_value: Vector, _new_value: Vector) {}
fn on_anchor_point_changed(&self) {}
fn on_anchor_point_changing(&self) {}
fn validate_center_point_change(&self, _old_value: Vector3D, _new_value: Vector3D) {}
fn on_center_point_changed(&self) {}
fn on_center_point_changing(&self) {}
fn validate_rotation_angle_change(&self, _old_value: f32, _new_value: f32) {}
fn on_rotation_angle_changed(&self) {}
fn on_rotation_angle_changing(&self) {}
fn validate_orientation_change(&self, _old_value: Quaternion, _new_value: Quaternion) {}
fn on_orientation_changed(&self) {}
fn on_orientation_changing(&self) {}
fn validate_scale_change(&self, _old_value: Vector3D, _new_value: Vector3D) {}
fn on_scale_changed(&self) {}
fn on_scale_changing(&self) {}
fn validate_transform_matrix_change(&self, _old_value: Matrix, _new_value: Matrix) {}
fn on_transform_matrix_changed(&self) {}
fn on_transform_matrix_changing(&self) {}
fn validate_adorned_visual_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
fn on_adorned_visual_changed(&self) {}
fn on_adorned_visual_changing(&self) {}
fn validate_adorner_is_clipped_change(&self, _old_value: bool, _new_value: bool) {}
fn on_adorner_is_clipped_changed(&self) {}
fn on_adorner_is_clipped_changing(&self) {}
fn validate_opacity_mask_brush_change(&self, _old_value: &Option<BatchResource<dyn IBrush>>, _new_value: &Option<BatchResource<dyn IBrush>>) {}
fn on_opacity_mask_brush_changed(&self) {}
fn on_opacity_mask_brush_changing(&self) {}
fn validate_effect_change(&self, _old_value: &Option<Arc<dyn IImmutableEffect>>, _new_value: &Option<Arc<dyn IImmutableEffect>>) {}
fn on_effect_changed(&self) {}
fn on_effect_changing(&self) {}
fn validate_render_options_change(&self, _old_value: RenderOptions, _new_value: RenderOptions) {}
fn on_render_options_changed(&self) {}
fn on_render_options_changing(&self) {}
fn validate_text_options_change(&self, _old_value: TextOptions, _new_value: TextOptions) {}
fn on_text_options_changed(&self) {}
fn on_text_options_changing(&self) {}
fn validate_cache_mode_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
fn on_cache_mode_changed(&self) {}
fn on_cache_mode_changing(&self) {}
}
pub struct CompositionVisualProps {
changed_fields_of_composition_visual: Cell<CompositionVisualChangedFields>,
root: RefCell<Option<Rc<dyn ICompositionObject>>>,
parent: RefCell<Option<Rc<dyn ICompositionObject>>>,
visible: Cell<bool>,
opacity: Cell<f32>,
clip: RefCell<Option<Arc<dyn IGeometryImpl>>>,
clip_to_bounds: Cell<bool>,
offset: Cell<Vector3D>,
translation: Cell<Vector3D>,
size: Cell<Vector>,
anchor_point: Cell<Vector>,
center_point: Cell<Vector3D>,
rotation_angle: Cell<f32>,
orientation: Cell<Quaternion>,
scale: Cell<Vector3D>,
transform_matrix: Cell<Matrix>,
adorned_visual: RefCell<Option<Rc<dyn ICompositionObject>>>,
adorner_is_clipped: Cell<bool>,
opacity_mask_brush: RefCell<Option<BatchResource<dyn IBrush>>>,
effect: RefCell<Option<Arc<dyn IImmutableEffect>>>,
render_options: Cell<RenderOptions>,
text_options: Cell<TextOptions>,
cache_mode: RefCell<Option<Rc<dyn ICompositionObject>>>,
}
impl Default for CompositionVisualProps {
fn default() -> Self {
Self::new()
}
}
impl CompositionVisualProps {
pub fn new() -> Self {
Self {
changed_fields_of_composition_visual: Cell::new(CompositionVisualChangedFields::empty()),
root: RefCell::new(None),
parent: RefCell::new(None),
visible: Cell::new(Default::default()),
opacity: Cell::new(Default::default()),
clip: RefCell::new(None),
clip_to_bounds: Cell::new(Default::default()),
offset: Cell::new(Default::default()),
translation: Cell::new(Default::default()),
size: Cell::new(Default::default()),
anchor_point: Cell::new(Default::default()),
center_point: Cell::new(Default::default()),
rotation_angle: Cell::new(Default::default()),
orientation: Cell::new(Default::default()),
scale: Cell::new(Default::default()),
transform_matrix: Cell::new(Default::default()),
adorned_visual: RefCell::new(None),
adorner_is_clipped: Cell::new(Default::default()),
opacity_mask_brush: RefCell::new(None),
effect: RefCell::new(None),
render_options: Cell::new(Default::default()),
text_options: Cell::new(Default::default()),
cache_mode: RefCell::new(None),
}
}
pub fn initialize_defaults(&self, host: &dyn CompositionVisualHooks) {
self.initialize_own_defaults(host);
}
pub fn initialize_own_defaults(&self, host: &dyn CompositionVisualHooks) {
CompositionVisualHooks::initialize_defaults_extra(host);
self.set_visible(host, true);
self.set_opacity(host, 1.0);
self.set_clip_to_bounds(host, true);
self.set_orientation(host, Quaternion::IDENTITY);
self.set_scale(host, Vector3D::new(1.0, 1.0, 1.0));
self.set_transform_matrix(host, Matrix::IDENTITY);
}
pub fn root(&self) -> Option<Rc<dyn ICompositionObject>> {
self.root.borrow().clone()
}
pub fn set_root(&self, host: &dyn CompositionVisualHooks, value: Option<Rc<dyn ICompositionObject>>) {
let mut changed = false;
let old_value = self.root.borrow().clone();
if old_value.differs(&value) {
CompositionVisualHooks::validate_root_change(host, &old_value, &value);
CompositionVisualHooks::on_root_changing(host);
changed = true;
*self.root.borrow_mut() = value.clone();
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROOT);
host.register_for_serialization();
}
*self.root.borrow_mut() = value;
if changed {
CompositionVisualHooks::on_root_changed(host);
}
}
pub fn parent(&self) -> Option<Rc<dyn ICompositionObject>> {
self.parent.borrow().clone()
}
pub fn set_parent(&self, host: &dyn CompositionVisualHooks, value: Option<Rc<dyn ICompositionObject>>) {
let mut changed = false;
let old_value = self.parent.borrow().clone();
if old_value.differs(&value) {
CompositionVisualHooks::validate_parent_change(host, &old_value, &value);
CompositionVisualHooks::on_parent_changing(host);
changed = true;
*self.parent.borrow_mut() = value.clone();
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::PARENT);
host.register_for_serialization();
}
*self.parent.borrow_mut() = value;
if changed {
CompositionVisualHooks::on_parent_changed(host);
}
}
pub fn visible(&self) -> bool {
self.visible.get()
}
pub fn set_visible(&self, host: &dyn CompositionVisualHooks, value: bool) {
let mut changed = false;
let old_value = self.visible.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_visible_change(host, old_value, value);
CompositionVisualHooks::on_visible_changing(host);
changed = true;
self.visible.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::VISIBLE);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_visible_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::VISIBLE_ANIMATED);
if let Some(animation) = host.implicit_animation("Visible") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::VISIBLE_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_visible_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "Visible", ExpressionVariant::create(value));
}
}
self.visible.set(value);
if changed {
CompositionVisualHooks::on_visible_changed(host);
}
}
pub fn opacity(&self) -> f32 {
self.opacity.get()
}
pub fn set_opacity(&self, host: &dyn CompositionVisualHooks, value: f32) {
let mut changed = false;
let old_value = self.opacity.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_opacity_change(host, old_value, value);
CompositionVisualHooks::on_opacity_changing(host);
changed = true;
self.opacity.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OPACITY);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_opacity_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::OPACITY_ANIMATED);
if let Some(animation) = host.implicit_animation("Opacity") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OPACITY_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_opacity_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "Opacity", ExpressionVariant::create(value));
}
}
self.opacity.set(value);
if changed {
CompositionVisualHooks::on_opacity_changed(host);
}
}
pub fn clip(&self) -> Option<Arc<dyn IGeometryImpl>> {
self.clip.borrow().clone()
}
pub fn set_clip(&self, host: &dyn CompositionVisualHooks, value: Option<Arc<dyn IGeometryImpl>>) {
let mut changed = false;
let old_value = self.clip.borrow().clone();
if old_value.differs(&value) {
CompositionVisualHooks::validate_clip_change(host, &old_value, &value);
CompositionVisualHooks::on_clip_changing(host);
changed = true;
*self.clip.borrow_mut() = value.clone();
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CLIP);
host.register_for_serialization();
}
*self.clip.borrow_mut() = value;
if changed {
CompositionVisualHooks::on_clip_changed(host);
}
}
pub fn clip_to_bounds(&self) -> bool {
self.clip_to_bounds.get()
}
pub fn set_clip_to_bounds(&self, host: &dyn CompositionVisualHooks, value: bool) {
let mut changed = false;
let old_value = self.clip_to_bounds.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_clip_to_bounds_change(host, old_value, value);
CompositionVisualHooks::on_clip_to_bounds_changing(host);
changed = true;
self.clip_to_bounds.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CLIP_TO_BOUNDS);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_clip_to_bounds_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::CLIP_TO_BOUNDS_ANIMATED);
if let Some(animation) = host.implicit_animation("ClipToBounds") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CLIP_TO_BOUNDS_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_clip_to_bounds_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "ClipToBounds", ExpressionVariant::create(value));
}
}
self.clip_to_bounds.set(value);
if changed {
CompositionVisualHooks::on_clip_to_bounds_changed(host);
}
}
pub fn offset(&self) -> Vector3D {
self.offset.get()
}
pub fn set_offset(&self, host: &dyn CompositionVisualHooks, value: Vector3D) {
let mut changed = false;
let old_value = self.offset.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_offset_change(host, old_value, value);
CompositionVisualHooks::on_offset_changing(host);
changed = true;
self.offset.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OFFSET);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_offset_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::OFFSET_ANIMATED);
if let Some(animation) = host.implicit_animation("Offset") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OFFSET_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_offset_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "Offset", ExpressionVariant::create(value));
}
}
self.offset.set(value);
if changed {
CompositionVisualHooks::on_offset_changed(host);
}
}
pub fn translation(&self) -> Vector3D {
self.translation.get()
}
pub fn set_translation(&self, host: &dyn CompositionVisualHooks, value: Vector3D) {
let mut changed = false;
let old_value = self.translation.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_translation_change(host, old_value, value);
CompositionVisualHooks::on_translation_changing(host);
changed = true;
self.translation.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSLATION);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_translation_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::TRANSLATION_ANIMATED);
if let Some(animation) = host.implicit_animation("Translation") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSLATION_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_translation_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "Translation", ExpressionVariant::create(value));
}
}
self.translation.set(value);
if changed {
CompositionVisualHooks::on_translation_changed(host);
}
}
pub fn size(&self) -> Vector {
self.size.get()
}
pub fn set_size(&self, host: &dyn CompositionVisualHooks, value: Vector) {
let mut changed = false;
let old_value = self.size.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_size_change(host, old_value, value);
CompositionVisualHooks::on_size_changing(host);
changed = true;
self.size.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SIZE);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_size_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::SIZE_ANIMATED);
if let Some(animation) = host.implicit_animation("Size") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SIZE_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_size_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "Size", ExpressionVariant::create(value));
}
}
self.size.set(value);
if changed {
CompositionVisualHooks::on_size_changed(host);
}
}
pub fn anchor_point(&self) -> Vector {
self.anchor_point.get()
}
pub fn set_anchor_point(&self, host: &dyn CompositionVisualHooks, value: Vector) {
let mut changed = false;
let old_value = self.anchor_point.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_anchor_point_change(host, old_value, value);
CompositionVisualHooks::on_anchor_point_changing(host);
changed = true;
self.anchor_point.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ANCHOR_POINT);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_anchor_point_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::ANCHOR_POINT_ANIMATED);
if let Some(animation) = host.implicit_animation("AnchorPoint") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ANCHOR_POINT_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_anchor_point_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "AnchorPoint", ExpressionVariant::create(value));
}
}
self.anchor_point.set(value);
if changed {
CompositionVisualHooks::on_anchor_point_changed(host);
}
}
pub fn center_point(&self) -> Vector3D {
self.center_point.get()
}
pub fn set_center_point(&self, host: &dyn CompositionVisualHooks, value: Vector3D) {
let mut changed = false;
let old_value = self.center_point.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_center_point_change(host, old_value, value);
CompositionVisualHooks::on_center_point_changing(host);
changed = true;
self.center_point.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CENTER_POINT);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_center_point_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::CENTER_POINT_ANIMATED);
if let Some(animation) = host.implicit_animation("CenterPoint") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CENTER_POINT_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_center_point_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "CenterPoint", ExpressionVariant::create(value));
}
}
self.center_point.set(value);
if changed {
CompositionVisualHooks::on_center_point_changed(host);
}
}
pub fn rotation_angle(&self) -> f32 {
self.rotation_angle.get()
}
pub fn set_rotation_angle(&self, host: &dyn CompositionVisualHooks, value: f32) {
let mut changed = false;
let old_value = self.rotation_angle.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_rotation_angle_change(host, old_value, value);
CompositionVisualHooks::on_rotation_angle_changing(host);
changed = true;
self.rotation_angle.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROTATION_ANGLE);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_rotation_angle_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::ROTATION_ANGLE_ANIMATED);
if let Some(animation) = host.implicit_animation("RotationAngle") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROTATION_ANGLE_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_rotation_angle_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "RotationAngle", ExpressionVariant::create(value));
}
}
self.rotation_angle.set(value);
if changed {
CompositionVisualHooks::on_rotation_angle_changed(host);
}
}
pub fn orientation(&self) -> Quaternion {
self.orientation.get()
}
pub fn set_orientation(&self, host: &dyn CompositionVisualHooks, value: Quaternion) {
let mut changed = false;
let old_value = self.orientation.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_orientation_change(host, old_value, value);
CompositionVisualHooks::on_orientation_changing(host);
changed = true;
self.orientation.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ORIENTATION);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_orientation_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::ORIENTATION_ANIMATED);
if let Some(animation) = host.implicit_animation("Orientation") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ORIENTATION_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_orientation_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "Orientation", ExpressionVariant::create(value));
}
}
self.orientation.set(value);
if changed {
CompositionVisualHooks::on_orientation_changed(host);
}
}
pub fn scale(&self) -> Vector3D {
self.scale.get()
}
pub fn set_scale(&self, host: &dyn CompositionVisualHooks, value: Vector3D) {
let mut changed = false;
let old_value = self.scale.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_scale_change(host, old_value, value);
CompositionVisualHooks::on_scale_changing(host);
changed = true;
self.scale.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SCALE);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_scale_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::SCALE_ANIMATED);
if let Some(animation) = host.implicit_animation("Scale") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SCALE_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_scale_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "Scale", ExpressionVariant::create(value));
}
}
self.scale.set(value);
if changed {
CompositionVisualHooks::on_scale_changed(host);
}
}
pub fn transform_matrix(&self) -> Matrix {
self.transform_matrix.get()
}
pub fn set_transform_matrix(&self, host: &dyn CompositionVisualHooks, value: Matrix) {
let mut changed = false;
let old_value = self.transform_matrix.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_transform_matrix_change(host, old_value, value);
CompositionVisualHooks::on_transform_matrix_changing(host);
changed = true;
self.transform_matrix.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSFORM_MATRIX);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionVisualProps::id_of_transform_matrix_property().base());
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() & !CompositionVisualChangedFields::TRANSFORM_MATRIX_ANIMATED);
if let Some(animation) = host.implicit_animation("TransformMatrix") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSFORM_MATRIX_ANIMATED);
host.pending_animations().set(
ServerCompositionVisualProps::id_of_transform_matrix_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "TransformMatrix", ExpressionVariant::create(value));
}
}
self.transform_matrix.set(value);
if changed {
CompositionVisualHooks::on_transform_matrix_changed(host);
}
}
pub fn adorned_visual(&self) -> Option<Rc<dyn ICompositionObject>> {
self.adorned_visual.borrow().clone()
}
pub fn set_adorned_visual(&self, host: &dyn CompositionVisualHooks, value: Option<Rc<dyn ICompositionObject>>) {
let mut changed = false;
let old_value = self.adorned_visual.borrow().clone();
if old_value.differs(&value) {
CompositionVisualHooks::validate_adorned_visual_change(host, &old_value, &value);
CompositionVisualHooks::on_adorned_visual_changing(host);
changed = true;
*self.adorned_visual.borrow_mut() = value.clone();
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ADORNED_VISUAL);
host.register_for_serialization();
}
*self.adorned_visual.borrow_mut() = value;
if changed {
CompositionVisualHooks::on_adorned_visual_changed(host);
}
}
pub fn adorner_is_clipped(&self) -> bool {
self.adorner_is_clipped.get()
}
pub fn set_adorner_is_clipped(&self, host: &dyn CompositionVisualHooks, value: bool) {
let mut changed = false;
let old_value = self.adorner_is_clipped.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_adorner_is_clipped_change(host, old_value, value);
CompositionVisualHooks::on_adorner_is_clipped_changing(host);
changed = true;
self.adorner_is_clipped.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ADORNER_IS_CLIPPED);
host.register_for_serialization();
}
self.adorner_is_clipped.set(value);
if changed {
CompositionVisualHooks::on_adorner_is_clipped_changed(host);
}
}
pub fn opacity_mask_brush_transport_field(&self) -> Option<BatchResource<dyn IBrush>> {
self.opacity_mask_brush.borrow().clone()
}
pub fn set_opacity_mask_brush_transport_field(&self, host: &dyn CompositionVisualHooks, value: Option<BatchResource<dyn IBrush>>) {
let mut changed = false;
let old_value = self.opacity_mask_brush.borrow().clone();
if old_value.differs(&value) {
CompositionVisualHooks::validate_opacity_mask_brush_change(host, &old_value, &value);
CompositionVisualHooks::on_opacity_mask_brush_changing(host);
changed = true;
*self.opacity_mask_brush.borrow_mut() = value.clone();
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OPACITY_MASK_BRUSH);
host.register_for_serialization();
}
*self.opacity_mask_brush.borrow_mut() = value;
if changed {
CompositionVisualHooks::on_opacity_mask_brush_changed(host);
}
}
pub fn effect(&self) -> Option<Arc<dyn IImmutableEffect>> {
self.effect.borrow().clone()
}
pub fn set_effect(&self, host: &dyn CompositionVisualHooks, value: Option<Arc<dyn IImmutableEffect>>) {
let mut changed = false;
let old_value = self.effect.borrow().clone();
if old_value.differs(&value) {
CompositionVisualHooks::validate_effect_change(host, &old_value, &value);
CompositionVisualHooks::on_effect_changing(host);
changed = true;
*self.effect.borrow_mut() = value.clone();
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::EFFECT);
host.register_for_serialization();
}
*self.effect.borrow_mut() = value;
if changed {
CompositionVisualHooks::on_effect_changed(host);
}
}
pub fn render_options(&self) -> RenderOptions {
self.render_options.get()
}
pub fn set_render_options(&self, host: &dyn CompositionVisualHooks, value: RenderOptions) {
let mut changed = false;
let old_value = self.render_options.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_render_options_change(host, old_value, value);
CompositionVisualHooks::on_render_options_changing(host);
changed = true;
self.render_options.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::RENDER_OPTIONS);
host.register_for_serialization();
}
self.render_options.set(value);
if changed {
CompositionVisualHooks::on_render_options_changed(host);
}
}
pub fn text_options(&self) -> TextOptions {
self.text_options.get()
}
pub fn set_text_options(&self, host: &dyn CompositionVisualHooks, value: TextOptions) {
let mut changed = false;
let old_value = self.text_options.get();
if old_value.differs(&value) {
CompositionVisualHooks::validate_text_options_change(host, old_value, value);
CompositionVisualHooks::on_text_options_changing(host);
changed = true;
self.text_options.set(value);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TEXT_OPTIONS);
host.register_for_serialization();
}
self.text_options.set(value);
if changed {
CompositionVisualHooks::on_text_options_changed(host);
}
}
pub fn cache_mode(&self) -> Option<Rc<dyn ICompositionObject>> {
self.cache_mode.borrow().clone()
}
pub fn set_cache_mode(&self, host: &dyn CompositionVisualHooks, value: Option<Rc<dyn ICompositionObject>>) {
let mut changed = false;
let old_value = self.cache_mode.borrow().clone();
if old_value.differs(&value) {
CompositionVisualHooks::validate_cache_mode_change(host, &old_value, &value);
CompositionVisualHooks::on_cache_mode_changing(host);
changed = true;
*self.cache_mode.borrow_mut() = value.clone();
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CACHE_MODE);
host.register_for_serialization();
}
*self.cache_mode.borrow_mut() = value;
if changed {
CompositionVisualHooks::on_cache_mode_changed(host);
}
}
pub fn start_animation(
&self,
host: &dyn CompositionVisualHooks,
property_name: &str,
animation: &dyn ICompositionAnimation,
final_value: Option<ExpressionVariant>,
) -> bool {
if property_name == "Visible" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_visible_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::VISIBLE_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "Opacity" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_opacity_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OPACITY_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "ClipToBounds" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_clip_to_bounds_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CLIP_TO_BOUNDS_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "Offset" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_offset_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::OFFSET_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "Translation" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_translation_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSLATION_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "Size" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_size_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SIZE_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "AnchorPoint" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_anchor_point_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ANCHOR_POINT_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "CenterPoint" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_center_point_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::CENTER_POINT_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "RotationAngle" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_rotation_angle_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ROTATION_ANGLE_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "Orientation" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_orientation_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::ORIENTATION_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "Scale" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_scale_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::SCALE_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "TransformMatrix" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionVisualProps::id_of_transform_matrix_property().base(), server);
self.changed_fields_of_composition_visual.set(self.changed_fields_of_composition_visual.get() | CompositionVisualChangedFields::TRANSFORM_MATRIX_ANIMATED);
host.register_for_serialization();
return true;
}
false
}
pub fn serialize_changes_core(&self, host: &dyn CompositionVisualHooks, writer: &mut BatchStreamWriter<'_>) {
let changed = self.changed_fields_of_composition_visual.get();
writer.write(changed);
if changed.contains(CompositionVisualChangedFields::ROOT) {
writer.write_server_object(self.root.borrow().clone().map(|o| o.server()));
}
if changed.contains(CompositionVisualChangedFields::PARENT) {
writer.write_server_object(self.parent.borrow().clone().map(|o| o.server()));
}
if changed.contains(CompositionVisualChangedFields::VISIBLE_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_visible_property().base()));
} else if changed.contains(CompositionVisualChangedFields::VISIBLE) {
writer.write(self.visible.get());
}
if changed.contains(CompositionVisualChangedFields::OPACITY_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_opacity_property().base()));
} else if changed.contains(CompositionVisualChangedFields::OPACITY) {
writer.write(self.opacity.get());
}
if changed.contains(CompositionVisualChangedFields::CLIP) {
writer.write_value(self.clip.borrow().clone());
}
if changed.contains(CompositionVisualChangedFields::CLIP_TO_BOUNDS_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_clip_to_bounds_property().base()));
} else if changed.contains(CompositionVisualChangedFields::CLIP_TO_BOUNDS) {
writer.write(self.clip_to_bounds.get());
}
if changed.contains(CompositionVisualChangedFields::OFFSET_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_offset_property().base()));
} else if changed.contains(CompositionVisualChangedFields::OFFSET) {
writer.write(self.offset.get());
}
if changed.contains(CompositionVisualChangedFields::TRANSLATION_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_translation_property().base()));
} else if changed.contains(CompositionVisualChangedFields::TRANSLATION) {
writer.write(self.translation.get());
}
if changed.contains(CompositionVisualChangedFields::SIZE_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_size_property().base()));
} else if changed.contains(CompositionVisualChangedFields::SIZE) {
writer.write(self.size.get());
}
if changed.contains(CompositionVisualChangedFields::ANCHOR_POINT_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_anchor_point_property().base()));
} else if changed.contains(CompositionVisualChangedFields::ANCHOR_POINT) {
writer.write(self.anchor_point.get());
}
if changed.contains(CompositionVisualChangedFields::CENTER_POINT_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_center_point_property().base()));
} else if changed.contains(CompositionVisualChangedFields::CENTER_POINT) {
writer.write(self.center_point.get());
}
if changed.contains(CompositionVisualChangedFields::ROTATION_ANGLE_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_rotation_angle_property().base()));
} else if changed.contains(CompositionVisualChangedFields::ROTATION_ANGLE) {
writer.write(self.rotation_angle.get());
}
if changed.contains(CompositionVisualChangedFields::ORIENTATION_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_orientation_property().base()));
} else if changed.contains(CompositionVisualChangedFields::ORIENTATION) {
writer.write(self.orientation.get());
}
if changed.contains(CompositionVisualChangedFields::SCALE_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_scale_property().base()));
} else if changed.contains(CompositionVisualChangedFields::SCALE) {
writer.write(self.scale.get());
}
if changed.contains(CompositionVisualChangedFields::TRANSFORM_MATRIX_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionVisualProps::id_of_transform_matrix_property().base()));
} else if changed.contains(CompositionVisualChangedFields::TRANSFORM_MATRIX) {
writer.write(self.transform_matrix.get());
}
if changed.contains(CompositionVisualChangedFields::ADORNED_VISUAL) {
writer.write_server_object(self.adorned_visual.borrow().clone().map(|o| o.server()));
}
if changed.contains(CompositionVisualChangedFields::ADORNER_IS_CLIPPED) {
writer.write(self.adorner_is_clipped.get());
}
if changed.contains(CompositionVisualChangedFields::OPACITY_MASK_BRUSH) {
writer.write_resource(self.opacity_mask_brush.borrow().clone());
}
if changed.contains(CompositionVisualChangedFields::EFFECT) {
writer.write_value(self.effect.borrow().clone());
}
if changed.contains(CompositionVisualChangedFields::RENDER_OPTIONS) {
writer.write(self.render_options.get());
}
if changed.contains(CompositionVisualChangedFields::TEXT_OPTIONS) {
writer.write(self.text_options.get());
}
if changed.contains(CompositionVisualChangedFields::CACHE_MODE) {
writer.write_server_object(self.cache_mode.borrow().clone().map(|o| o.server()));
}
self.changed_fields_of_composition_visual.set(CompositionVisualChangedFields::empty());
}
}
pub trait ServerCompositionVisualHooks: IServerAnimatedPropertyHost {
fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
fn on_fields_deserialized(&self, _changed: CompositionVisualChangedFields) {}
fn on_root_changed(&self) {}
fn on_root_changing(&self) {}
fn on_parent_changed(&self) {}
fn on_parent_changing(&self) {}
fn on_clip_changed(&self) {}
fn on_clip_changing(&self) {}
fn on_adorned_visual_changed(&self) {}
fn on_adorned_visual_changing(&self) {}
fn on_adorner_is_clipped_changed(&self) {}
fn on_adorner_is_clipped_changing(&self) {}
fn on_opacity_mask_brush_changed(&self) {}
fn on_opacity_mask_brush_changing(&self) {}
fn on_effect_changed(&self) {}
fn on_effect_changing(&self) {}
fn on_render_options_changed(&self) {}
fn on_render_options_changing(&self) {}
fn on_text_options_changed(&self) {}
fn on_text_options_changing(&self) {}
fn on_cache_mode_changed(&self) {}
fn on_cache_mode_changing(&self) {}
}
pub struct ServerCompositionVisualProps {
root: RefCell<Option<Rc<dyn IServerObject>>>,
parent: RefCell<Option<Rc<dyn IServerObject>>>,
visible: Cell<bool>,
opacity: Cell<f32>,
clip: RefCell<Option<Arc<dyn IGeometryImpl>>>,
clip_to_bounds: Cell<bool>,
offset: Cell<Vector3D>,
translation: Cell<Vector3D>,
size: Cell<Vector>,
anchor_point: Cell<Vector>,
center_point: Cell<Vector3D>,
rotation_angle: Cell<f32>,
orientation: Cell<Quaternion>,
scale: Cell<Vector3D>,
transform_matrix: Cell<Matrix>,
adorned_visual: RefCell<Option<Rc<dyn IServerObject>>>,
adorner_is_clipped: Cell<bool>,
opacity_mask_brush: RefCell<Option<ServerResourceRef<dyn IBrush>>>,
effect: RefCell<Option<Arc<dyn IImmutableEffect>>>,
render_options: Cell<RenderOptions>,
text_options: Cell<TextOptions>,
cache_mode: RefCell<Option<Rc<dyn IServerObject>>>,
}
impl Default for ServerCompositionVisualProps {
fn default() -> Self {
Self::new()
}
}
impl ServerCompositionVisualProps {
pub fn new() -> Self {
Self {
root: RefCell::new(None),
parent: RefCell::new(None),
visible: Cell::new(Default::default()),
opacity: Cell::new(Default::default()),
clip: RefCell::new(None),
clip_to_bounds: Cell::new(Default::default()),
offset: Cell::new(Default::default()),
translation: Cell::new(Default::default()),
size: Cell::new(Default::default()),
anchor_point: Cell::new(Default::default()),
center_point: Cell::new(Default::default()),
rotation_angle: Cell::new(Default::default()),
orientation: Cell::new(Default::default()),
scale: Cell::new(Default::default()),
transform_matrix: Cell::new(Default::default()),
adorned_visual: RefCell::new(None),
adorner_is_clipped: Cell::new(Default::default()),
opacity_mask_brush: RefCell::new(None),
effect: RefCell::new(None),
render_options: Cell::new(Default::default()),
text_options: Cell::new(Default::default()),
cache_mode: RefCell::new(None),
}
}
pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
if type_id == TypeId::of::<Self>() {
return Some(self);
}
None
}
pub fn id_of_root_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Option<Rc<dyn IServerObject>>>(
"Root",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).root.borrow().clone(),
|obj, v| *props_of::<ServerCompositionVisualProps>(obj).root.borrow_mut() = v,
None,
None,
)
})
}
pub fn root(&self) -> Option<Rc<dyn IServerObject>> {
self.root.borrow().clone()
}
pub fn set_root(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Rc<dyn IServerObject>>) {
let old_value = self.root.borrow().clone();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionVisualHooks::on_root_changing(host);
changed = true;
}
host.set_value(
Self::id_of_root_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: old_value.as_server_render_resource(),
new_resource: value.as_server_render_resource(),
assign: &mut || *self.root.borrow_mut() = value.clone(),
},
);
if changed {
ServerCompositionVisualHooks::on_root_changed(host);
}
}
pub fn id_of_parent_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Option<Rc<dyn IServerObject>>>(
"Parent",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).parent.borrow().clone(),
|obj, v| *props_of::<ServerCompositionVisualProps>(obj).parent.borrow_mut() = v,
None,
None,
)
})
}
pub fn parent(&self) -> Option<Rc<dyn IServerObject>> {
self.parent.borrow().clone()
}
pub fn set_parent(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Rc<dyn IServerObject>>) {
let old_value = self.parent.borrow().clone();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionVisualHooks::on_parent_changing(host);
changed = true;
}
host.set_value(
Self::id_of_parent_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: old_value.as_server_render_resource(),
new_resource: value.as_server_render_resource(),
assign: &mut || *self.parent.borrow_mut() = value.clone(),
},
);
if changed {
ServerCompositionVisualHooks::on_parent_changed(host);
}
}
pub fn id_of_visible_property() -> &'static CompositionPropertyOf<bool> {
static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, bool>(
"Visible",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).visible.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).visible.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).visible.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).visible.set(v.cast_or_default::<bool>())),
)
})
}
pub fn visible(&self) -> bool {
self.visible.get()
}
pub fn set_visible(&self, host: &dyn ServerCompositionVisualHooks, value: bool) {
self.visible.set(value);
host.remove_animation_for_property(Self::id_of_visible_property().base());
}
pub fn id_of_opacity_property() -> &'static CompositionPropertyOf<f32> {
static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, f32>(
"Opacity",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).opacity.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).opacity.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).opacity.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).opacity.set(v.cast_or_default::<f32>())),
)
})
}
pub fn opacity(&self) -> f32 {
self.opacity.get()
}
pub fn set_opacity(&self, host: &dyn ServerCompositionVisualHooks, value: f32) {
self.opacity.set(value);
host.remove_animation_for_property(Self::id_of_opacity_property().base());
}
pub fn id_of_clip_property() -> &'static CompositionPropertyOf<Option<Arc<dyn IGeometryImpl>>> {
static PROPERTY: OnceLock<CompositionPropertyOf<Option<Arc<dyn IGeometryImpl>>>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Option<Arc<dyn IGeometryImpl>>>(
"Clip",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).clip.borrow().clone(),
|obj, v| *props_of::<ServerCompositionVisualProps>(obj).clip.borrow_mut() = v,
None,
None,
)
})
}
pub fn clip(&self) -> Option<Arc<dyn IGeometryImpl>> {
self.clip.borrow().clone()
}
pub fn set_clip(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Arc<dyn IGeometryImpl>>) {
let old_value = self.clip.borrow().clone();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionVisualHooks::on_clip_changing(host);
changed = true;
}
host.set_value(
Self::id_of_clip_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || *self.clip.borrow_mut() = value.clone(),
},
);
if changed {
ServerCompositionVisualHooks::on_clip_changed(host);
}
}
pub fn id_of_clip_to_bounds_property() -> &'static CompositionPropertyOf<bool> {
static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, bool>(
"ClipToBounds",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).clip_to_bounds.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).clip_to_bounds.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).clip_to_bounds.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).clip_to_bounds.set(v.cast_or_default::<bool>())),
)
})
}
pub fn clip_to_bounds(&self) -> bool {
self.clip_to_bounds.get()
}
pub fn set_clip_to_bounds(&self, host: &dyn ServerCompositionVisualHooks, value: bool) {
self.clip_to_bounds.set(value);
host.remove_animation_for_property(Self::id_of_clip_to_bounds_property().base());
}
pub fn id_of_offset_property() -> &'static CompositionPropertyOf<Vector3D> {
static PROPERTY: OnceLock<CompositionPropertyOf<Vector3D>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Vector3D>(
"Offset",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).offset.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).offset.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).offset.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).offset.set(v.cast_or_default::<Vector3D>())),
)
})
}
pub fn offset(&self) -> Vector3D {
self.offset.get()
}
pub fn set_offset(&self, host: &dyn ServerCompositionVisualHooks, value: Vector3D) {
self.offset.set(value);
host.remove_animation_for_property(Self::id_of_offset_property().base());
}
pub fn id_of_translation_property() -> &'static CompositionPropertyOf<Vector3D> {
static PROPERTY: OnceLock<CompositionPropertyOf<Vector3D>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Vector3D>(
"Translation",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).translation.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).translation.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).translation.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).translation.set(v.cast_or_default::<Vector3D>())),
)
})
}
pub fn translation(&self) -> Vector3D {
self.translation.get()
}
pub fn set_translation(&self, host: &dyn ServerCompositionVisualHooks, value: Vector3D) {
self.translation.set(value);
host.remove_animation_for_property(Self::id_of_translation_property().base());
}
pub fn id_of_size_property() -> &'static CompositionPropertyOf<Vector> {
static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Vector>(
"Size",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).size.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).size.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).size.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).size.set(v.cast_or_default::<Vector>())),
)
})
}
pub fn size(&self) -> Vector {
self.size.get()
}
pub fn set_size(&self, host: &dyn ServerCompositionVisualHooks, value: Vector) {
self.size.set(value);
host.remove_animation_for_property(Self::id_of_size_property().base());
}
pub fn id_of_anchor_point_property() -> &'static CompositionPropertyOf<Vector> {
static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Vector>(
"AnchorPoint",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).anchor_point.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).anchor_point.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).anchor_point.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).anchor_point.set(v.cast_or_default::<Vector>())),
)
})
}
pub fn anchor_point(&self) -> Vector {
self.anchor_point.get()
}
pub fn set_anchor_point(&self, host: &dyn ServerCompositionVisualHooks, value: Vector) {
self.anchor_point.set(value);
host.remove_animation_for_property(Self::id_of_anchor_point_property().base());
}
pub fn id_of_center_point_property() -> &'static CompositionPropertyOf<Vector3D> {
static PROPERTY: OnceLock<CompositionPropertyOf<Vector3D>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Vector3D>(
"CenterPoint",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).center_point.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).center_point.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).center_point.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).center_point.set(v.cast_or_default::<Vector3D>())),
)
})
}
pub fn center_point(&self) -> Vector3D {
self.center_point.get()
}
pub fn set_center_point(&self, host: &dyn ServerCompositionVisualHooks, value: Vector3D) {
self.center_point.set(value);
host.remove_animation_for_property(Self::id_of_center_point_property().base());
}
pub fn id_of_rotation_angle_property() -> &'static CompositionPropertyOf<f32> {
static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, f32>(
"RotationAngle",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).rotation_angle.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).rotation_angle.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).rotation_angle.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).rotation_angle.set(v.cast_or_default::<f32>())),
)
})
}
pub fn rotation_angle(&self) -> f32 {
self.rotation_angle.get()
}
pub fn set_rotation_angle(&self, host: &dyn ServerCompositionVisualHooks, value: f32) {
self.rotation_angle.set(value);
host.remove_animation_for_property(Self::id_of_rotation_angle_property().base());
}
pub fn id_of_orientation_property() -> &'static CompositionPropertyOf<Quaternion> {
static PROPERTY: OnceLock<CompositionPropertyOf<Quaternion>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Quaternion>(
"Orientation",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).orientation.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).orientation.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).orientation.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).orientation.set(v.cast_or_default::<Quaternion>())),
)
})
}
pub fn orientation(&self) -> Quaternion {
self.orientation.get()
}
pub fn set_orientation(&self, host: &dyn ServerCompositionVisualHooks, value: Quaternion) {
self.orientation.set(value);
host.remove_animation_for_property(Self::id_of_orientation_property().base());
}
pub fn id_of_scale_property() -> &'static CompositionPropertyOf<Vector3D> {
static PROPERTY: OnceLock<CompositionPropertyOf<Vector3D>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Vector3D>(
"Scale",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).scale.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).scale.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).scale.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).scale.set(v.cast_or_default::<Vector3D>())),
)
})
}
pub fn scale(&self) -> Vector3D {
self.scale.get()
}
pub fn set_scale(&self, host: &dyn ServerCompositionVisualHooks, value: Vector3D) {
self.scale.set(value);
host.remove_animation_for_property(Self::id_of_scale_property().base());
}
pub fn id_of_transform_matrix_property() -> &'static CompositionPropertyOf<Matrix> {
static PROPERTY: OnceLock<CompositionPropertyOf<Matrix>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Matrix>(
"TransformMatrix",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).transform_matrix.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).transform_matrix.set(v),
None,
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionVisualProps>(obj).transform_matrix.set(v.cast_or_default::<Matrix>())),
)
})
}
pub fn transform_matrix(&self) -> Matrix {
self.transform_matrix.get()
}
pub fn set_transform_matrix(&self, host: &dyn ServerCompositionVisualHooks, value: Matrix) {
self.transform_matrix.set(value);
host.remove_animation_for_property(Self::id_of_transform_matrix_property().base());
}
pub fn id_of_adorned_visual_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Option<Rc<dyn IServerObject>>>(
"AdornedVisual",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).adorned_visual.borrow().clone(),
|obj, v| *props_of::<ServerCompositionVisualProps>(obj).adorned_visual.borrow_mut() = v,
None,
None,
)
})
}
pub fn adorned_visual(&self) -> Option<Rc<dyn IServerObject>> {
self.adorned_visual.borrow().clone()
}
pub fn set_adorned_visual(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Rc<dyn IServerObject>>) {
let old_value = self.adorned_visual.borrow().clone();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionVisualHooks::on_adorned_visual_changing(host);
changed = true;
}
host.set_value(
Self::id_of_adorned_visual_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: old_value.as_server_render_resource(),
new_resource: value.as_server_render_resource(),
assign: &mut || *self.adorned_visual.borrow_mut() = value.clone(),
},
);
if changed {
ServerCompositionVisualHooks::on_adorned_visual_changed(host);
}
}
pub fn id_of_adorner_is_clipped_property() -> &'static CompositionPropertyOf<bool> {
static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, bool>(
"AdornerIsClipped",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).adorner_is_clipped.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).adorner_is_clipped.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionVisualProps>(obj).adorner_is_clipped.get())),
None,
)
})
}
pub fn adorner_is_clipped(&self) -> bool {
self.adorner_is_clipped.get()
}
pub fn set_adorner_is_clipped(&self, host: &dyn ServerCompositionVisualHooks, value: bool) {
let old_value = self.adorner_is_clipped.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionVisualHooks::on_adorner_is_clipped_changing(host);
changed = true;
}
host.set_value(
Self::id_of_adorner_is_clipped_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.adorner_is_clipped.set(value),
},
);
if changed {
ServerCompositionVisualHooks::on_adorner_is_clipped_changed(host);
}
}
pub fn id_of_opacity_mask_brush_property() -> &'static CompositionPropertyOf<Option<ServerResourceRef<dyn IBrush>>> {
static PROPERTY: OnceLock<CompositionPropertyOf<Option<ServerResourceRef<dyn IBrush>>>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Option<ServerResourceRef<dyn IBrush>>>(
"OpacityMaskBrush",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).opacity_mask_brush.borrow().clone(),
|obj, v| *props_of::<ServerCompositionVisualProps>(obj).opacity_mask_brush.borrow_mut() = v,
None,
None,
)
})
}
pub fn opacity_mask_brush(&self) -> Option<ServerResourceRef<dyn IBrush>> {
self.opacity_mask_brush.borrow().clone()
}
pub fn set_opacity_mask_brush(&self, host: &dyn ServerCompositionVisualHooks, value: Option<ServerResourceRef<dyn IBrush>>) {
let old_value = self.opacity_mask_brush.borrow().clone();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionVisualHooks::on_opacity_mask_brush_changing(host);
changed = true;
}
host.set_value(
Self::id_of_opacity_mask_brush_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: old_value.as_server_render_resource(),
new_resource: value.as_server_render_resource(),
assign: &mut || *self.opacity_mask_brush.borrow_mut() = value.clone(),
},
);
if changed {
ServerCompositionVisualHooks::on_opacity_mask_brush_changed(host);
}
}
pub fn id_of_effect_property() -> &'static CompositionPropertyOf<Option<Arc<dyn IImmutableEffect>>> {
static PROPERTY: OnceLock<CompositionPropertyOf<Option<Arc<dyn IImmutableEffect>>>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Option<Arc<dyn IImmutableEffect>>>(
"Effect",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).effect.borrow().clone(),
|obj, v| *props_of::<ServerCompositionVisualProps>(obj).effect.borrow_mut() = v,
None,
None,
)
})
}
pub fn effect(&self) -> Option<Arc<dyn IImmutableEffect>> {
self.effect.borrow().clone()
}
pub fn set_effect(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Arc<dyn IImmutableEffect>>) {
let old_value = self.effect.borrow().clone();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionVisualHooks::on_effect_changing(host);
changed = true;
}
host.set_value(
Self::id_of_effect_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || *self.effect.borrow_mut() = value.clone(),
},
);
if changed {
ServerCompositionVisualHooks::on_effect_changed(host);
}
}
pub fn id_of_render_options_property() -> &'static CompositionPropertyOf<RenderOptions> {
static PROPERTY: OnceLock<CompositionPropertyOf<RenderOptions>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, RenderOptions>(
"RenderOptions",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).render_options.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).render_options.set(v),
None,
None,
)
})
}
pub fn render_options(&self) -> RenderOptions {
self.render_options.get()
}
pub fn set_render_options(&self, host: &dyn ServerCompositionVisualHooks, value: RenderOptions) {
let old_value = self.render_options.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionVisualHooks::on_render_options_changing(host);
changed = true;
}
host.set_value(
Self::id_of_render_options_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.render_options.set(value),
},
);
if changed {
ServerCompositionVisualHooks::on_render_options_changed(host);
}
}
pub fn id_of_text_options_property() -> &'static CompositionPropertyOf<TextOptions> {
static PROPERTY: OnceLock<CompositionPropertyOf<TextOptions>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, TextOptions>(
"TextOptions",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).text_options.get(),
|obj, v| props_of::<ServerCompositionVisualProps>(obj).text_options.set(v),
None,
None,
)
})
}
pub fn text_options(&self) -> TextOptions {
self.text_options.get()
}
pub fn set_text_options(&self, host: &dyn ServerCompositionVisualHooks, value: TextOptions) {
let old_value = self.text_options.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionVisualHooks::on_text_options_changing(host);
changed = true;
}
host.set_value(
Self::id_of_text_options_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.text_options.set(value),
},
);
if changed {
ServerCompositionVisualHooks::on_text_options_changed(host);
}
}
pub fn id_of_cache_mode_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionVisualProps, Option<Rc<dyn IServerObject>>>(
"CacheMode",
"ServerCompositionVisual",
|obj| props_of::<ServerCompositionVisualProps>(obj).cache_mode.borrow().clone(),
|obj, v| *props_of::<ServerCompositionVisualProps>(obj).cache_mode.borrow_mut() = v,
None,
None,
)
})
}
pub fn cache_mode(&self) -> Option<Rc<dyn IServerObject>> {
self.cache_mode.borrow().clone()
}
pub fn set_cache_mode(&self, host: &dyn ServerCompositionVisualHooks, value: Option<Rc<dyn IServerObject>>) {
let old_value = self.cache_mode.borrow().clone();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionVisualHooks::on_cache_mode_changing(host);
changed = true;
}
host.set_value(
Self::id_of_cache_mode_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: old_value.as_server_render_resource(),
new_resource: value.as_server_render_resource(),
assign: &mut || *self.cache_mode.borrow_mut() = value.clone(),
},
);
if changed {
ServerCompositionVisualHooks::on_cache_mode_changed(host);
}
}
pub fn deserialize_changes_core(
&self,
host: &dyn ServerCompositionVisualHooks,
reader: &mut BatchStreamReader<'_>,
committed_at: Duration,
) {
let compositor = host.server_compositor();
ServerCompositionVisualHooks::deserialize_changes_extra(host, reader);
let changed = reader.read::<CompositionVisualChangedFields>();
if changed.contains(CompositionVisualChangedFields::ROOT) {
let value = read_server_object(reader, compositor.as_ref());
self.set_root(host, value);
}
if changed.contains(CompositionVisualChangedFields::PARENT) {
let value = read_server_object(reader, compositor.as_ref());
self.set_parent(host, value);
}
if changed.contains(CompositionVisualChangedFields::VISIBLE_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `Visible` without an animation instance");
};
host.set_animated_value(
Self::id_of_visible_property().base(),
ExpressionVariant::create(self.visible.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::VISIBLE) {
let value = reader.read::<bool>();
self.set_visible(host, value);
}
if changed.contains(CompositionVisualChangedFields::OPACITY_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `Opacity` without an animation instance");
};
host.set_animated_value(
Self::id_of_opacity_property().base(),
ExpressionVariant::create(self.opacity.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::OPACITY) {
let value = reader.read::<f32>();
self.set_opacity(host, value);
}
if changed.contains(CompositionVisualChangedFields::CLIP) {
let value = reader.read_value::<Arc<dyn IGeometryImpl>>();
self.set_clip(host, value);
}
if changed.contains(CompositionVisualChangedFields::CLIP_TO_BOUNDS_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `ClipToBounds` without an animation instance");
};
host.set_animated_value(
Self::id_of_clip_to_bounds_property().base(),
ExpressionVariant::create(self.clip_to_bounds.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::CLIP_TO_BOUNDS) {
let value = reader.read::<bool>();
self.set_clip_to_bounds(host, value);
}
if changed.contains(CompositionVisualChangedFields::OFFSET_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `Offset` without an animation instance");
};
host.set_animated_value(
Self::id_of_offset_property().base(),
ExpressionVariant::create(self.offset.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::OFFSET) {
let value = reader.read::<Vector3D>();
self.set_offset(host, value);
}
if changed.contains(CompositionVisualChangedFields::TRANSLATION_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `Translation` without an animation instance");
};
host.set_animated_value(
Self::id_of_translation_property().base(),
ExpressionVariant::create(self.translation.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::TRANSLATION) {
let value = reader.read::<Vector3D>();
self.set_translation(host, value);
}
if changed.contains(CompositionVisualChangedFields::SIZE_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `Size` without an animation instance");
};
host.set_animated_value(
Self::id_of_size_property().base(),
ExpressionVariant::create(self.size.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::SIZE) {
let value = reader.read::<Vector>();
self.set_size(host, value);
}
if changed.contains(CompositionVisualChangedFields::ANCHOR_POINT_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `AnchorPoint` without an animation instance");
};
host.set_animated_value(
Self::id_of_anchor_point_property().base(),
ExpressionVariant::create(self.anchor_point.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::ANCHOR_POINT) {
let value = reader.read::<Vector>();
self.set_anchor_point(host, value);
}
if changed.contains(CompositionVisualChangedFields::CENTER_POINT_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `CenterPoint` without an animation instance");
};
host.set_animated_value(
Self::id_of_center_point_property().base(),
ExpressionVariant::create(self.center_point.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::CENTER_POINT) {
let value = reader.read::<Vector3D>();
self.set_center_point(host, value);
}
if changed.contains(CompositionVisualChangedFields::ROTATION_ANGLE_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `RotationAngle` without an animation instance");
};
host.set_animated_value(
Self::id_of_rotation_angle_property().base(),
ExpressionVariant::create(self.rotation_angle.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::ROTATION_ANGLE) {
let value = reader.read::<f32>();
self.set_rotation_angle(host, value);
}
if changed.contains(CompositionVisualChangedFields::ORIENTATION_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `Orientation` without an animation instance");
};
host.set_animated_value(
Self::id_of_orientation_property().base(),
ExpressionVariant::create(self.orientation.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::ORIENTATION) {
let value = reader.read::<Quaternion>();
self.set_orientation(host, value);
}
if changed.contains(CompositionVisualChangedFields::SCALE_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `Scale` without an animation instance");
};
host.set_animated_value(
Self::id_of_scale_property().base(),
ExpressionVariant::create(self.scale.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::SCALE) {
let value = reader.read::<Vector3D>();
self.set_scale(host, value);
}
if changed.contains(CompositionVisualChangedFields::TRANSFORM_MATRIX_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `TransformMatrix` without an animation instance");
};
host.set_animated_value(
Self::id_of_transform_matrix_property().base(),
ExpressionVariant::create(self.transform_matrix.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionVisualChangedFields::TRANSFORM_MATRIX) {
let value = reader.read::<Matrix>();
self.set_transform_matrix(host, value);
}
if changed.contains(CompositionVisualChangedFields::ADORNED_VISUAL) {
let value = read_server_object(reader, compositor.as_ref());
self.set_adorned_visual(host, value);
}
if changed.contains(CompositionVisualChangedFields::ADORNER_IS_CLIPPED) {
let value = reader.read::<bool>();
self.set_adorner_is_clipped(host, value);
}
if changed.contains(CompositionVisualChangedFields::OPACITY_MASK_BRUSH) {
let value = read_resource(reader, compositor.as_ref(), |o| o.as_brush());
self.set_opacity_mask_brush(host, value);
}
if changed.contains(CompositionVisualChangedFields::EFFECT) {
let value = reader.read_value::<Arc<dyn IImmutableEffect>>();
self.set_effect(host, value);
}
if changed.contains(CompositionVisualChangedFields::RENDER_OPTIONS) {
let value = reader.read::<RenderOptions>();
self.set_render_options(host, value);
}
if changed.contains(CompositionVisualChangedFields::TEXT_OPTIONS) {
let value = reader.read::<TextOptions>();
self.set_text_options(host, value);
}
if changed.contains(CompositionVisualChangedFields::CACHE_MODE) {
let value = read_server_object(reader, compositor.as_ref());
self.set_cache_mode(host, value);
}
ServerCompositionVisualHooks::on_fields_deserialized(host, changed);
}
pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
if name == "Visible" {
return Some(Self::id_of_visible_property().base());
}
if name == "Opacity" {
return Some(Self::id_of_opacity_property().base());
}
if name == "ClipToBounds" {
return Some(Self::id_of_clip_to_bounds_property().base());
}
if name == "Offset" {
return Some(Self::id_of_offset_property().base());
}
if name == "Translation" {
return Some(Self::id_of_translation_property().base());
}
if name == "Size" {
return Some(Self::id_of_size_property().base());
}
if name == "AnchorPoint" {
return Some(Self::id_of_anchor_point_property().base());
}
if name == "CenterPoint" {
return Some(Self::id_of_center_point_property().base());
}
if name == "RotationAngle" {
return Some(Self::id_of_rotation_angle_property().base());
}
if name == "Orientation" {
return Some(Self::id_of_orientation_property().base());
}
if name == "Scale" {
return Some(Self::id_of_scale_property().base());
}
if name == "AdornerIsClipped" {
return Some(Self::id_of_adorner_is_clipped_property().base());
}
None
}
}