use bitflags::bitflags;
use crate::Matrix;
use crate::Vector;
use crate::rendering::composition::CompositionBitmapInterpolationMode;
use crate::rendering::composition::CompositionStretch;
use crate::rendering::composition::ICompositionObject;
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::IServerObject;
use crate::rendering::composition::server::ServerPropertyValue;
use crate::rendering::composition::server::ServerValueChange;
use crate::rendering::composition::server::props_of;
use crate::rendering::composition::server::read_server_object;
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::OnceLock;
use std::time::Duration;
use super::CompositionBrushHooks;
use super::CompositionBrushProps;
use super::ServerCompositionBrushHooks;
use super::ServerCompositionBrushProps;
bitflags! {
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct CompositionSurfaceBrushChangedFields: u32 {
const SURFACE = 1;
const STRETCH = 2;
const HORIZONTAL_ALIGNMENT_RATIO = 4;
const HORIZONTAL_ALIGNMENT_RATIO_ANIMATED = 8;
const VERTICAL_ALIGNMENT_RATIO = 16;
const VERTICAL_ALIGNMENT_RATIO_ANIMATED = 32;
const BITMAP_INTERPOLATION_MODE = 64;
const ANCHOR_POINT = 128;
const ANCHOR_POINT_ANIMATED = 256;
const CENTER_POINT = 512;
const CENTER_POINT_ANIMATED = 1024;
const OFFSET = 2048;
const OFFSET_ANIMATED = 4096;
const ROTATION_ANGLE = 8192;
const ROTATION_ANGLE_ANIMATED = 16384;
const SCALE = 32768;
const SCALE_ANIMATED = 65536;
const TRANSFORM_MATRIX = 131072;
const TRANSFORM_MATRIX_ANIMATED = 262144;
const SNAP_TO_PIXELS = 524288;
}
}
impl BatchValue for CompositionSurfaceBrushChangedFields {
#[inline]
fn write_to(&self, out: &mut Vec<u8>) {
self.bits().write_to(out);
}
#[inline]
fn read_from(input: &mut BatchValueReader<'_>) -> Self {
CompositionSurfaceBrushChangedFields::from_bits_retain(u32::read_from(input))
}
}
pub trait CompositionSurfaceBrushHooks: CompositionBrushHooks {
fn initialize_defaults_extra(&self) {}
fn validate_surface_change(&self, _old_value: &Option<Rc<dyn ICompositionObject>>, _new_value: &Option<Rc<dyn ICompositionObject>>) {}
fn on_surface_changed(&self) {}
fn on_surface_changing(&self) {}
fn validate_stretch_change(&self, _old_value: CompositionStretch, _new_value: CompositionStretch) {}
fn on_stretch_changed(&self) {}
fn on_stretch_changing(&self) {}
fn validate_horizontal_alignment_ratio_change(&self, _old_value: f32, _new_value: f32) {}
fn on_horizontal_alignment_ratio_changed(&self) {}
fn on_horizontal_alignment_ratio_changing(&self) {}
fn validate_vertical_alignment_ratio_change(&self, _old_value: f32, _new_value: f32) {}
fn on_vertical_alignment_ratio_changed(&self) {}
fn on_vertical_alignment_ratio_changing(&self) {}
fn validate_bitmap_interpolation_mode_change(&self, _old_value: CompositionBitmapInterpolationMode, _new_value: CompositionBitmapInterpolationMode) {}
fn on_bitmap_interpolation_mode_changed(&self) {}
fn on_bitmap_interpolation_mode_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: Vector, _new_value: Vector) {}
fn on_center_point_changed(&self) {}
fn on_center_point_changing(&self) {}
fn validate_offset_change(&self, _old_value: Vector, _new_value: Vector) {}
fn on_offset_changed(&self) {}
fn on_offset_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_scale_change(&self, _old_value: Vector, _new_value: Vector) {}
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_snap_to_pixels_change(&self, _old_value: bool, _new_value: bool) {}
fn on_snap_to_pixels_changed(&self) {}
fn on_snap_to_pixels_changing(&self) {}
}
pub struct CompositionSurfaceBrushProps {
base: CompositionBrushProps,
changed_fields_of_composition_surface_brush: Cell<CompositionSurfaceBrushChangedFields>,
surface: RefCell<Option<Rc<dyn ICompositionObject>>>,
stretch: Cell<CompositionStretch>,
horizontal_alignment_ratio: Cell<f32>,
vertical_alignment_ratio: Cell<f32>,
bitmap_interpolation_mode: Cell<CompositionBitmapInterpolationMode>,
anchor_point: Cell<Vector>,
center_point: Cell<Vector>,
offset: Cell<Vector>,
rotation_angle: Cell<f32>,
scale: Cell<Vector>,
transform_matrix: Cell<Matrix>,
snap_to_pixels: Cell<bool>,
}
impl Default for CompositionSurfaceBrushProps {
fn default() -> Self {
Self::new()
}
}
impl CompositionSurfaceBrushProps {
pub fn new() -> Self {
Self {
base: CompositionBrushProps::new(),
changed_fields_of_composition_surface_brush: Cell::new(CompositionSurfaceBrushChangedFields::empty()),
surface: RefCell::new(None),
stretch: Cell::new(Default::default()),
horizontal_alignment_ratio: Cell::new(Default::default()),
vertical_alignment_ratio: Cell::new(Default::default()),
bitmap_interpolation_mode: Cell::new(Default::default()),
anchor_point: Cell::new(Default::default()),
center_point: Cell::new(Default::default()),
offset: Cell::new(Default::default()),
rotation_angle: Cell::new(Default::default()),
scale: Cell::new(Default::default()),
transform_matrix: Cell::new(Default::default()),
snap_to_pixels: Cell::new(Default::default()),
}
}
pub fn base(&self) -> &CompositionBrushProps {
&self.base
}
pub fn initialize_defaults(&self, host: &dyn CompositionSurfaceBrushHooks) {
self.base.initialize_defaults(host);
self.initialize_own_defaults(host);
}
pub fn initialize_own_defaults(&self, host: &dyn CompositionSurfaceBrushHooks) {
CompositionSurfaceBrushHooks::initialize_defaults_extra(host);
self.set_stretch(host, CompositionStretch::Fill);
self.set_horizontal_alignment_ratio(host, 0.5);
self.set_vertical_alignment_ratio(host, 0.5);
self.set_bitmap_interpolation_mode(host, CompositionBitmapInterpolationMode::Linear);
self.set_scale(host, Vector::new(1.0, 1.0));
self.set_transform_matrix(host, Matrix::IDENTITY);
}
pub fn surface(&self) -> Option<Rc<dyn ICompositionObject>> {
self.surface.borrow().clone()
}
pub fn set_surface(&self, host: &dyn CompositionSurfaceBrushHooks, value: Option<Rc<dyn ICompositionObject>>) {
let mut changed = false;
let old_value = self.surface.borrow().clone();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_surface_change(host, &old_value, &value);
CompositionSurfaceBrushHooks::on_surface_changing(host);
changed = true;
*self.surface.borrow_mut() = value.clone();
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::SURFACE);
host.register_for_serialization();
}
*self.surface.borrow_mut() = value;
if changed {
CompositionSurfaceBrushHooks::on_surface_changed(host);
}
}
pub fn stretch(&self) -> CompositionStretch {
self.stretch.get()
}
pub fn set_stretch(&self, host: &dyn CompositionSurfaceBrushHooks, value: CompositionStretch) {
let mut changed = false;
let old_value = self.stretch.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_stretch_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_stretch_changing(host);
changed = true;
self.stretch.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::STRETCH);
host.register_for_serialization();
}
self.stretch.set(value);
if changed {
CompositionSurfaceBrushHooks::on_stretch_changed(host);
}
}
pub fn horizontal_alignment_ratio(&self) -> f32 {
self.horizontal_alignment_ratio.get()
}
pub fn set_horizontal_alignment_ratio(&self, host: &dyn CompositionSurfaceBrushHooks, value: f32) {
let mut changed = false;
let old_value = self.horizontal_alignment_ratio.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_horizontal_alignment_ratio_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_horizontal_alignment_ratio_changing(host);
changed = true;
self.horizontal_alignment_ratio.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_horizontal_alignment_ratio_property().base());
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO_ANIMATED);
if let Some(animation) = host.implicit_animation("HorizontalAlignmentRatio") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO_ANIMATED);
host.pending_animations().set(
ServerCompositionSurfaceBrushProps::id_of_horizontal_alignment_ratio_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "HorizontalAlignmentRatio", ExpressionVariant::create(value));
}
}
self.horizontal_alignment_ratio.set(value);
if changed {
CompositionSurfaceBrushHooks::on_horizontal_alignment_ratio_changed(host);
}
}
pub fn vertical_alignment_ratio(&self) -> f32 {
self.vertical_alignment_ratio.get()
}
pub fn set_vertical_alignment_ratio(&self, host: &dyn CompositionSurfaceBrushHooks, value: f32) {
let mut changed = false;
let old_value = self.vertical_alignment_ratio.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_vertical_alignment_ratio_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_vertical_alignment_ratio_changing(host);
changed = true;
self.vertical_alignment_ratio.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_vertical_alignment_ratio_property().base());
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO_ANIMATED);
if let Some(animation) = host.implicit_animation("VerticalAlignmentRatio") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO_ANIMATED);
host.pending_animations().set(
ServerCompositionSurfaceBrushProps::id_of_vertical_alignment_ratio_property().base(),
a.create_instance(host.server(), Some(ExpressionVariant::create(value))),
);
}
host.start_animation_group(&animation, "VerticalAlignmentRatio", ExpressionVariant::create(value));
}
}
self.vertical_alignment_ratio.set(value);
if changed {
CompositionSurfaceBrushHooks::on_vertical_alignment_ratio_changed(host);
}
}
pub fn bitmap_interpolation_mode(&self) -> CompositionBitmapInterpolationMode {
self.bitmap_interpolation_mode.get()
}
pub fn set_bitmap_interpolation_mode(&self, host: &dyn CompositionSurfaceBrushHooks, value: CompositionBitmapInterpolationMode) {
let mut changed = false;
let old_value = self.bitmap_interpolation_mode.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_bitmap_interpolation_mode_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_bitmap_interpolation_mode_changing(host);
changed = true;
self.bitmap_interpolation_mode.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::BITMAP_INTERPOLATION_MODE);
host.register_for_serialization();
}
self.bitmap_interpolation_mode.set(value);
if changed {
CompositionSurfaceBrushHooks::on_bitmap_interpolation_mode_changed(host);
}
}
pub fn anchor_point(&self) -> Vector {
self.anchor_point.get()
}
pub fn set_anchor_point(&self, host: &dyn CompositionSurfaceBrushHooks, value: Vector) {
let mut changed = false;
let old_value = self.anchor_point.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_anchor_point_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_anchor_point_changing(host);
changed = true;
self.anchor_point.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ANCHOR_POINT);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_anchor_point_property().base());
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::ANCHOR_POINT_ANIMATED);
if let Some(animation) = host.implicit_animation("AnchorPoint") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ANCHOR_POINT_ANIMATED);
host.pending_animations().set(
ServerCompositionSurfaceBrushProps::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 {
CompositionSurfaceBrushHooks::on_anchor_point_changed(host);
}
}
pub fn center_point(&self) -> Vector {
self.center_point.get()
}
pub fn set_center_point(&self, host: &dyn CompositionSurfaceBrushHooks, value: Vector) {
let mut changed = false;
let old_value = self.center_point.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_center_point_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_center_point_changing(host);
changed = true;
self.center_point.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::CENTER_POINT);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_center_point_property().base());
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::CENTER_POINT_ANIMATED);
if let Some(animation) = host.implicit_animation("CenterPoint") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::CENTER_POINT_ANIMATED);
host.pending_animations().set(
ServerCompositionSurfaceBrushProps::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 {
CompositionSurfaceBrushHooks::on_center_point_changed(host);
}
}
pub fn offset(&self) -> Vector {
self.offset.get()
}
pub fn set_offset(&self, host: &dyn CompositionSurfaceBrushHooks, value: Vector) {
let mut changed = false;
let old_value = self.offset.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_offset_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_offset_changing(host);
changed = true;
self.offset.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::OFFSET);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_offset_property().base());
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::OFFSET_ANIMATED);
if let Some(animation) = host.implicit_animation("Offset") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::OFFSET_ANIMATED);
host.pending_animations().set(
ServerCompositionSurfaceBrushProps::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 {
CompositionSurfaceBrushHooks::on_offset_changed(host);
}
}
pub fn rotation_angle(&self) -> f32 {
self.rotation_angle.get()
}
pub fn set_rotation_angle(&self, host: &dyn CompositionSurfaceBrushHooks, value: f32) {
let mut changed = false;
let old_value = self.rotation_angle.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_rotation_angle_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_rotation_angle_changing(host);
changed = true;
self.rotation_angle.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ROTATION_ANGLE);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_rotation_angle_property().base());
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::ROTATION_ANGLE_ANIMATED);
if let Some(animation) = host.implicit_animation("RotationAngle") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ROTATION_ANGLE_ANIMATED);
host.pending_animations().set(
ServerCompositionSurfaceBrushProps::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 {
CompositionSurfaceBrushHooks::on_rotation_angle_changed(host);
}
}
pub fn scale(&self) -> Vector {
self.scale.get()
}
pub fn set_scale(&self, host: &dyn CompositionSurfaceBrushHooks, value: Vector) {
let mut changed = false;
let old_value = self.scale.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_scale_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_scale_changing(host);
changed = true;
self.scale.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::SCALE);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_scale_property().base());
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::SCALE_ANIMATED);
if let Some(animation) = host.implicit_animation("Scale") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::SCALE_ANIMATED);
host.pending_animations().set(
ServerCompositionSurfaceBrushProps::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 {
CompositionSurfaceBrushHooks::on_scale_changed(host);
}
}
pub fn transform_matrix(&self) -> Matrix {
self.transform_matrix.get()
}
pub fn set_transform_matrix(&self, host: &dyn CompositionSurfaceBrushHooks, value: Matrix) {
let mut changed = false;
let old_value = self.transform_matrix.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_transform_matrix_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_transform_matrix_changing(host);
changed = true;
self.transform_matrix.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX);
host.register_for_serialization();
host.pending_animations().remove(ServerCompositionSurfaceBrushProps::id_of_transform_matrix_property().base());
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() & !CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX_ANIMATED);
if let Some(animation) = host.implicit_animation("TransformMatrix") {
if let Some(a) = animation.as_composition_animation() {
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX_ANIMATED);
host.pending_animations().set(
ServerCompositionSurfaceBrushProps::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 {
CompositionSurfaceBrushHooks::on_transform_matrix_changed(host);
}
}
pub fn snap_to_pixels(&self) -> bool {
self.snap_to_pixels.get()
}
pub fn set_snap_to_pixels(&self, host: &dyn CompositionSurfaceBrushHooks, value: bool) {
let mut changed = false;
let old_value = self.snap_to_pixels.get();
if old_value.differs(&value) {
CompositionSurfaceBrushHooks::validate_snap_to_pixels_change(host, old_value, value);
CompositionSurfaceBrushHooks::on_snap_to_pixels_changing(host);
changed = true;
self.snap_to_pixels.set(value);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::SNAP_TO_PIXELS);
host.register_for_serialization();
}
self.snap_to_pixels.set(value);
if changed {
CompositionSurfaceBrushHooks::on_snap_to_pixels_changed(host);
}
}
pub fn start_animation(
&self,
host: &dyn CompositionSurfaceBrushHooks,
property_name: &str,
animation: &dyn ICompositionAnimation,
final_value: Option<ExpressionVariant>,
) -> bool {
if property_name == "HorizontalAlignmentRatio" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_horizontal_alignment_ratio_property().base(), server);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "VerticalAlignmentRatio" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_vertical_alignment_ratio_property().base(), server);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "AnchorPoint" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_anchor_point_property().base(), server);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::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(ServerCompositionSurfaceBrushProps::id_of_center_point_property().base(), server);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::CENTER_POINT_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "Offset" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_offset_property().base(), server);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::OFFSET_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "RotationAngle" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_rotation_angle_property().base(), server);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::ROTATION_ANGLE_ANIMATED);
host.register_for_serialization();
return true;
}
if property_name == "Scale" {
let server = animation.create_instance(host.server(), final_value);
host.pending_animations().set(ServerCompositionSurfaceBrushProps::id_of_scale_property().base(), server);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::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(ServerCompositionSurfaceBrushProps::id_of_transform_matrix_property().base(), server);
self.changed_fields_of_composition_surface_brush.set(self.changed_fields_of_composition_surface_brush.get() | CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX_ANIMATED);
host.register_for_serialization();
return true;
}
self.base.start_animation(host, property_name, animation, final_value)
}
pub fn serialize_changes_core(&self, host: &dyn CompositionSurfaceBrushHooks, writer: &mut BatchStreamWriter<'_>) {
self.base.serialize_changes_core(host, writer);
let changed = self.changed_fields_of_composition_surface_brush.get();
writer.write(changed);
if changed.contains(CompositionSurfaceBrushChangedFields::SURFACE) {
writer.write_server_object(self.surface.borrow().clone().map(|o| o.server()));
}
if changed.contains(CompositionSurfaceBrushChangedFields::STRETCH) {
writer.write(self.stretch.get());
}
if changed.contains(CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_horizontal_alignment_ratio_property().base()));
} else if changed.contains(CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO) {
writer.write(self.horizontal_alignment_ratio.get());
}
if changed.contains(CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_vertical_alignment_ratio_property().base()));
} else if changed.contains(CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO) {
writer.write(self.vertical_alignment_ratio.get());
}
if changed.contains(CompositionSurfaceBrushChangedFields::BITMAP_INTERPOLATION_MODE) {
writer.write(self.bitmap_interpolation_mode.get());
}
if changed.contains(CompositionSurfaceBrushChangedFields::ANCHOR_POINT_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_anchor_point_property().base()));
} else if changed.contains(CompositionSurfaceBrushChangedFields::ANCHOR_POINT) {
writer.write(self.anchor_point.get());
}
if changed.contains(CompositionSurfaceBrushChangedFields::CENTER_POINT_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_center_point_property().base()));
} else if changed.contains(CompositionSurfaceBrushChangedFields::CENTER_POINT) {
writer.write(self.center_point.get());
}
if changed.contains(CompositionSurfaceBrushChangedFields::OFFSET_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_offset_property().base()));
} else if changed.contains(CompositionSurfaceBrushChangedFields::OFFSET) {
writer.write(self.offset.get());
}
if changed.contains(CompositionSurfaceBrushChangedFields::ROTATION_ANGLE_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_rotation_angle_property().base()));
} else if changed.contains(CompositionSurfaceBrushChangedFields::ROTATION_ANGLE) {
writer.write(self.rotation_angle.get());
}
if changed.contains(CompositionSurfaceBrushChangedFields::SCALE_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_scale_property().base()));
} else if changed.contains(CompositionSurfaceBrushChangedFields::SCALE) {
writer.write(self.scale.get());
}
if changed.contains(CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX_ANIMATED) {
writer.write_value(host.pending_animations().get_and_remove(ServerCompositionSurfaceBrushProps::id_of_transform_matrix_property().base()));
} else if changed.contains(CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX) {
writer.write(self.transform_matrix.get());
}
if changed.contains(CompositionSurfaceBrushChangedFields::SNAP_TO_PIXELS) {
writer.write(self.snap_to_pixels.get());
}
self.changed_fields_of_composition_surface_brush.set(CompositionSurfaceBrushChangedFields::empty());
}
}
pub trait ServerCompositionSurfaceBrushHooks: ServerCompositionBrushHooks {
fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
fn on_fields_deserialized(&self, _changed: CompositionSurfaceBrushChangedFields) {}
fn on_surface_changed(&self) {}
fn on_surface_changing(&self) {}
fn on_stretch_changed(&self) {}
fn on_stretch_changing(&self) {}
fn on_bitmap_interpolation_mode_changed(&self) {}
fn on_bitmap_interpolation_mode_changing(&self) {}
fn on_snap_to_pixels_changed(&self) {}
fn on_snap_to_pixels_changing(&self) {}
}
pub struct ServerCompositionSurfaceBrushProps {
base: ServerCompositionBrushProps,
surface: RefCell<Option<Rc<dyn IServerObject>>>,
stretch: Cell<CompositionStretch>,
horizontal_alignment_ratio: Cell<f32>,
vertical_alignment_ratio: Cell<f32>,
bitmap_interpolation_mode: Cell<CompositionBitmapInterpolationMode>,
anchor_point: Cell<Vector>,
center_point: Cell<Vector>,
offset: Cell<Vector>,
rotation_angle: Cell<f32>,
scale: Cell<Vector>,
transform_matrix: Cell<Matrix>,
snap_to_pixels: Cell<bool>,
}
impl Default for ServerCompositionSurfaceBrushProps {
fn default() -> Self {
Self::new()
}
}
impl ServerCompositionSurfaceBrushProps {
pub fn new() -> Self {
Self {
base: ServerCompositionBrushProps::new(),
surface: RefCell::new(None),
stretch: Cell::new(Default::default()),
horizontal_alignment_ratio: Cell::new(Default::default()),
vertical_alignment_ratio: Cell::new(Default::default()),
bitmap_interpolation_mode: Cell::new(Default::default()),
anchor_point: Cell::new(Default::default()),
center_point: Cell::new(Default::default()),
offset: Cell::new(Default::default()),
rotation_angle: Cell::new(Default::default()),
scale: Cell::new(Default::default()),
transform_matrix: Cell::new(Default::default()),
snap_to_pixels: Cell::new(Default::default()),
}
}
pub fn base(&self) -> &ServerCompositionBrushProps {
&self.base
}
pub fn find_props(&self, type_id: TypeId) -> Option<&dyn Any> {
if type_id == TypeId::of::<Self>() {
return Some(self);
}
self.base.find_props(type_id)
}
pub fn id_of_surface_property() -> &'static CompositionPropertyOf<Option<Rc<dyn IServerObject>>> {
static PROPERTY: OnceLock<CompositionPropertyOf<Option<Rc<dyn IServerObject>>>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Option<Rc<dyn IServerObject>>>(
"Surface",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).surface.borrow().clone(),
|obj, v| *props_of::<ServerCompositionSurfaceBrushProps>(obj).surface.borrow_mut() = v,
None,
None,
)
})
}
pub fn surface(&self) -> Option<Rc<dyn IServerObject>> {
self.surface.borrow().clone()
}
pub fn set_surface(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: Option<Rc<dyn IServerObject>>) {
let old_value = self.surface.borrow().clone();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionSurfaceBrushHooks::on_surface_changing(host);
changed = true;
}
host.set_value(
Self::id_of_surface_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.surface.borrow_mut() = value.clone(),
},
);
if changed {
ServerCompositionSurfaceBrushHooks::on_surface_changed(host);
}
}
pub fn id_of_stretch_property() -> &'static CompositionPropertyOf<CompositionStretch> {
static PROPERTY: OnceLock<CompositionPropertyOf<CompositionStretch>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionSurfaceBrushProps, CompositionStretch>(
"Stretch",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).stretch.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).stretch.set(v),
None,
None,
)
})
}
pub fn stretch(&self) -> CompositionStretch {
self.stretch.get()
}
pub fn set_stretch(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: CompositionStretch) {
let old_value = self.stretch.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionSurfaceBrushHooks::on_stretch_changing(host);
changed = true;
}
host.set_value(
Self::id_of_stretch_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.stretch.set(value),
},
);
if changed {
ServerCompositionSurfaceBrushHooks::on_stretch_changed(host);
}
}
pub fn id_of_horizontal_alignment_ratio_property() -> &'static CompositionPropertyOf<f32> {
static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionSurfaceBrushProps, f32>(
"HorizontalAlignmentRatio",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).horizontal_alignment_ratio.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).horizontal_alignment_ratio.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).horizontal_alignment_ratio.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).horizontal_alignment_ratio.set(v.cast_or_default::<f32>())),
)
})
}
pub fn horizontal_alignment_ratio(&self) -> f32 {
self.horizontal_alignment_ratio.get()
}
pub fn set_horizontal_alignment_ratio(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: f32) {
self.horizontal_alignment_ratio.set(value);
host.remove_animation_for_property(Self::id_of_horizontal_alignment_ratio_property().base());
}
pub fn id_of_vertical_alignment_ratio_property() -> &'static CompositionPropertyOf<f32> {
static PROPERTY: OnceLock<CompositionPropertyOf<f32>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionSurfaceBrushProps, f32>(
"VerticalAlignmentRatio",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).vertical_alignment_ratio.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).vertical_alignment_ratio.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).vertical_alignment_ratio.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).vertical_alignment_ratio.set(v.cast_or_default::<f32>())),
)
})
}
pub fn vertical_alignment_ratio(&self) -> f32 {
self.vertical_alignment_ratio.get()
}
pub fn set_vertical_alignment_ratio(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: f32) {
self.vertical_alignment_ratio.set(value);
host.remove_animation_for_property(Self::id_of_vertical_alignment_ratio_property().base());
}
pub fn id_of_bitmap_interpolation_mode_property() -> &'static CompositionPropertyOf<CompositionBitmapInterpolationMode> {
static PROPERTY: OnceLock<CompositionPropertyOf<CompositionBitmapInterpolationMode>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionSurfaceBrushProps, CompositionBitmapInterpolationMode>(
"BitmapInterpolationMode",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).bitmap_interpolation_mode.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).bitmap_interpolation_mode.set(v),
None,
None,
)
})
}
pub fn bitmap_interpolation_mode(&self) -> CompositionBitmapInterpolationMode {
self.bitmap_interpolation_mode.get()
}
pub fn set_bitmap_interpolation_mode(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: CompositionBitmapInterpolationMode) {
let old_value = self.bitmap_interpolation_mode.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionSurfaceBrushHooks::on_bitmap_interpolation_mode_changing(host);
changed = true;
}
host.set_value(
Self::id_of_bitmap_interpolation_mode_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.bitmap_interpolation_mode.set(value),
},
);
if changed {
ServerCompositionSurfaceBrushHooks::on_bitmap_interpolation_mode_changed(host);
}
}
pub fn id_of_anchor_point_property() -> &'static CompositionPropertyOf<Vector> {
static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Vector>(
"AnchorPoint",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).anchor_point.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).anchor_point.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).anchor_point.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(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 ServerCompositionSurfaceBrushHooks, 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<Vector> {
static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Vector>(
"CenterPoint",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).center_point.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).center_point.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).center_point.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).center_point.set(v.cast_or_default::<Vector>())),
)
})
}
pub fn center_point(&self) -> Vector {
self.center_point.get()
}
pub fn set_center_point(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: Vector) {
self.center_point.set(value);
host.remove_animation_for_property(Self::id_of_center_point_property().base());
}
pub fn id_of_offset_property() -> &'static CompositionPropertyOf<Vector> {
static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Vector>(
"Offset",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).offset.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).offset.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).offset.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).offset.set(v.cast_or_default::<Vector>())),
)
})
}
pub fn offset(&self) -> Vector {
self.offset.get()
}
pub fn set_offset(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: Vector) {
self.offset.set(value);
host.remove_animation_for_property(Self::id_of_offset_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::<ServerCompositionSurfaceBrushProps, f32>(
"RotationAngle",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).rotation_angle.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).rotation_angle.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).rotation_angle.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(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 ServerCompositionSurfaceBrushHooks, value: f32) {
self.rotation_angle.set(value);
host.remove_animation_for_property(Self::id_of_rotation_angle_property().base());
}
pub fn id_of_scale_property() -> &'static CompositionPropertyOf<Vector> {
static PROPERTY: OnceLock<CompositionPropertyOf<Vector>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionSurfaceBrushProps, Vector>(
"Scale",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).scale.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).scale.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).scale.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(obj).scale.set(v.cast_or_default::<Vector>())),
)
})
}
pub fn scale(&self) -> Vector {
self.scale.get()
}
pub fn set_scale(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: Vector) {
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::<ServerCompositionSurfaceBrushProps, Matrix>(
"TransformMatrix",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).transform_matrix.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).transform_matrix.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).transform_matrix.get())),
Some(|obj, v: ExpressionVariant| props_of::<ServerCompositionSurfaceBrushProps>(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 ServerCompositionSurfaceBrushHooks, value: Matrix) {
self.transform_matrix.set(value);
host.remove_animation_for_property(Self::id_of_transform_matrix_property().base());
}
pub fn id_of_snap_to_pixels_property() -> &'static CompositionPropertyOf<bool> {
static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionSurfaceBrushProps, bool>(
"SnapToPixels",
"ServerCompositionSurfaceBrush",
|obj| props_of::<ServerCompositionSurfaceBrushProps>(obj).snap_to_pixels.get(),
|obj, v| props_of::<ServerCompositionSurfaceBrushProps>(obj).snap_to_pixels.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionSurfaceBrushProps>(obj).snap_to_pixels.get())),
None,
)
})
}
pub fn snap_to_pixels(&self) -> bool {
self.snap_to_pixels.get()
}
pub fn set_snap_to_pixels(&self, host: &dyn ServerCompositionSurfaceBrushHooks, value: bool) {
let old_value = self.snap_to_pixels.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionSurfaceBrushHooks::on_snap_to_pixels_changing(host);
changed = true;
}
host.set_value(
Self::id_of_snap_to_pixels_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.snap_to_pixels.set(value),
},
);
if changed {
ServerCompositionSurfaceBrushHooks::on_snap_to_pixels_changed(host);
}
}
pub fn deserialize_changes_core(
&self,
host: &dyn ServerCompositionSurfaceBrushHooks,
reader: &mut BatchStreamReader<'_>,
committed_at: Duration,
) {
let compositor = host.server_compositor();
self.base.deserialize_changes_core(host, reader, committed_at);
ServerCompositionSurfaceBrushHooks::deserialize_changes_extra(host, reader);
let changed = reader.read::<CompositionSurfaceBrushChangedFields>();
if changed.contains(CompositionSurfaceBrushChangedFields::SURFACE) {
let value = read_server_object(reader, compositor.as_ref());
self.set_surface(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::STRETCH) {
let value = reader.read::<CompositionStretch>();
self.set_stretch(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `HorizontalAlignmentRatio` without an animation instance");
};
host.set_animated_value(
Self::id_of_horizontal_alignment_ratio_property().base(),
ExpressionVariant::create(self.horizontal_alignment_ratio.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionSurfaceBrushChangedFields::HORIZONTAL_ALIGNMENT_RATIO) {
let value = reader.read::<f32>();
self.set_horizontal_alignment_ratio(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO_ANIMATED) {
let Some(animation) = reader.read_value::<AnimationInstanceFactory>().map(AnimationInstanceFactory::create) else {
panic!("a batch starts an animation of `VerticalAlignmentRatio` without an animation instance");
};
host.set_animated_value(
Self::id_of_vertical_alignment_ratio_property().base(),
ExpressionVariant::create(self.vertical_alignment_ratio.get()),
committed_at,
animation,
);
} else if changed.contains(CompositionSurfaceBrushChangedFields::VERTICAL_ALIGNMENT_RATIO) {
let value = reader.read::<f32>();
self.set_vertical_alignment_ratio(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::BITMAP_INTERPOLATION_MODE) {
let value = reader.read::<CompositionBitmapInterpolationMode>();
self.set_bitmap_interpolation_mode(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::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(CompositionSurfaceBrushChangedFields::ANCHOR_POINT) {
let value = reader.read::<Vector>();
self.set_anchor_point(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::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(CompositionSurfaceBrushChangedFields::CENTER_POINT) {
let value = reader.read::<Vector>();
self.set_center_point(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::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(CompositionSurfaceBrushChangedFields::OFFSET) {
let value = reader.read::<Vector>();
self.set_offset(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::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(CompositionSurfaceBrushChangedFields::ROTATION_ANGLE) {
let value = reader.read::<f32>();
self.set_rotation_angle(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::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(CompositionSurfaceBrushChangedFields::SCALE) {
let value = reader.read::<Vector>();
self.set_scale(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::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(CompositionSurfaceBrushChangedFields::TRANSFORM_MATRIX) {
let value = reader.read::<Matrix>();
self.set_transform_matrix(host, value);
}
if changed.contains(CompositionSurfaceBrushChangedFields::SNAP_TO_PIXELS) {
let value = reader.read::<bool>();
self.set_snap_to_pixels(host, value);
}
ServerCompositionSurfaceBrushHooks::on_fields_deserialized(host, changed);
}
pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
if name == "HorizontalAlignmentRatio" {
return Some(Self::id_of_horizontal_alignment_ratio_property().base());
}
if name == "VerticalAlignmentRatio" {
return Some(Self::id_of_vertical_alignment_ratio_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 == "Offset" {
return Some(Self::id_of_offset_property().base());
}
if name == "RotationAngle" {
return Some(Self::id_of_rotation_angle_property().base());
}
if name == "Scale" {
return Some(Self::id_of_scale_property().base());
}
if name == "TransformMatrix" {
return Some(Self::id_of_transform_matrix_property().base());
}
if name == "SnapToPixels" {
return Some(Self::id_of_snap_to_pixels_property().base());
}
ServerCompositionBrushProps::get_composition_property(name)
}
}