use bitflags::bitflags;
use crate::Size;
use crate::rendering::LayoutPassTiming;
use crate::rendering::RendererDebugOverlays;
use crate::rendering::composition::CompositionTransparencyLevel;
use crate::rendering::composition::ICompositionObject;
use crate::rendering::composition::ICompositionObjectHost;
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::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::Arc;
use std::sync::OnceLock;
use std::time::Duration;
bitflags! {
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct CompositionTargetChangedFields: u8 {
const ROOT = 1;
const IS_ENABLED = 2;
const DEBUG_OVERLAYS = 4;
const LAST_LAYOUT_PASS_TIMING = 8;
const SCALING = 16;
const SIZE = 32;
const TRANSPARENCY_LEVEL = 64;
const PLATFORM_SPECIFIC_SCENE_INFO = 128;
}
}
impl BatchValue for CompositionTargetChangedFields {
#[inline]
fn write_to(&self, out: &mut Vec<u8>) {
self.bits().write_to(out);
}
#[inline]
fn read_from(input: &mut BatchValueReader<'_>) -> Self {
CompositionTargetChangedFields::from_bits_retain(u8::read_from(input))
}
}
pub trait CompositionTargetHooks: 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_is_enabled_change(&self, _old_value: bool, _new_value: bool) {}
fn on_is_enabled_changed(&self) {}
fn on_is_enabled_changing(&self) {}
fn validate_debug_overlays_change(&self, _old_value: RendererDebugOverlays, _new_value: RendererDebugOverlays) {}
fn on_debug_overlays_changed(&self) {}
fn on_debug_overlays_changing(&self) {}
fn validate_last_layout_pass_timing_change(&self, _old_value: LayoutPassTiming, _new_value: LayoutPassTiming) {}
fn on_last_layout_pass_timing_changed(&self) {}
fn on_last_layout_pass_timing_changing(&self) {}
fn validate_scaling_change(&self, _old_value: f64, _new_value: f64) {}
fn on_scaling_changed(&self) {}
fn on_scaling_changing(&self) {}
fn validate_size_change(&self, _old_value: Size, _new_value: Size) {}
fn on_size_changed(&self) {}
fn on_size_changing(&self) {}
fn validate_transparency_level_change(&self, _old_value: CompositionTransparencyLevel, _new_value: CompositionTransparencyLevel) {}
fn on_transparency_level_changed(&self) {}
fn on_transparency_level_changing(&self) {}
fn validate_platform_specific_scene_info_change(&self, _old_value: &Option<Arc<dyn Any + Send + Sync>>, _new_value: &Option<Arc<dyn Any + Send + Sync>>) {}
fn on_platform_specific_scene_info_changed(&self) {}
fn on_platform_specific_scene_info_changing(&self) {}
}
pub struct CompositionTargetProps {
changed_fields_of_composition_target: Cell<CompositionTargetChangedFields>,
root: RefCell<Option<Rc<dyn ICompositionObject>>>,
is_enabled: Cell<bool>,
debug_overlays: Cell<RendererDebugOverlays>,
last_layout_pass_timing: Cell<LayoutPassTiming>,
scaling: Cell<f64>,
size: Cell<Size>,
transparency_level: Cell<CompositionTransparencyLevel>,
platform_specific_scene_info: RefCell<Option<Arc<dyn Any + Send + Sync>>>,
}
impl Default for CompositionTargetProps {
fn default() -> Self {
Self::new()
}
}
impl CompositionTargetProps {
pub fn new() -> Self {
Self {
changed_fields_of_composition_target: Cell::new(CompositionTargetChangedFields::empty()),
root: RefCell::new(None),
is_enabled: Cell::new(Default::default()),
debug_overlays: Cell::new(Default::default()),
last_layout_pass_timing: Cell::new(Default::default()),
scaling: Cell::new(Default::default()),
size: Cell::new(Default::default()),
transparency_level: Cell::new(Default::default()),
platform_specific_scene_info: RefCell::new(None),
}
}
pub fn initialize_defaults(&self, host: &dyn CompositionTargetHooks) {
self.initialize_own_defaults(host);
}
pub fn initialize_own_defaults(&self, host: &dyn CompositionTargetHooks) {
CompositionTargetHooks::initialize_defaults_extra(host);
}
pub fn root(&self) -> Option<Rc<dyn ICompositionObject>> {
self.root.borrow().clone()
}
pub fn set_root(&self, host: &dyn CompositionTargetHooks, value: Option<Rc<dyn ICompositionObject>>) {
let mut changed = false;
let old_value = self.root.borrow().clone();
if old_value.differs(&value) {
CompositionTargetHooks::validate_root_change(host, &old_value, &value);
CompositionTargetHooks::on_root_changing(host);
changed = true;
*self.root.borrow_mut() = value.clone();
self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::ROOT);
host.register_for_serialization();
}
*self.root.borrow_mut() = value;
if changed {
CompositionTargetHooks::on_root_changed(host);
}
}
pub fn is_enabled(&self) -> bool {
self.is_enabled.get()
}
pub fn set_is_enabled(&self, host: &dyn CompositionTargetHooks, value: bool) {
let mut changed = false;
let old_value = self.is_enabled.get();
if old_value.differs(&value) {
CompositionTargetHooks::validate_is_enabled_change(host, old_value, value);
CompositionTargetHooks::on_is_enabled_changing(host);
changed = true;
self.is_enabled.set(value);
self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::IS_ENABLED);
host.register_for_serialization();
}
self.is_enabled.set(value);
if changed {
CompositionTargetHooks::on_is_enabled_changed(host);
}
}
pub fn debug_overlays(&self) -> RendererDebugOverlays {
self.debug_overlays.get()
}
pub fn set_debug_overlays(&self, host: &dyn CompositionTargetHooks, value: RendererDebugOverlays) {
let mut changed = false;
let old_value = self.debug_overlays.get();
if old_value.differs(&value) {
CompositionTargetHooks::validate_debug_overlays_change(host, old_value, value);
CompositionTargetHooks::on_debug_overlays_changing(host);
changed = true;
self.debug_overlays.set(value);
self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::DEBUG_OVERLAYS);
host.register_for_serialization();
}
self.debug_overlays.set(value);
if changed {
CompositionTargetHooks::on_debug_overlays_changed(host);
}
}
pub fn last_layout_pass_timing(&self) -> LayoutPassTiming {
self.last_layout_pass_timing.get()
}
pub fn set_last_layout_pass_timing(&self, host: &dyn CompositionTargetHooks, value: LayoutPassTiming) {
let mut changed = false;
let old_value = self.last_layout_pass_timing.get();
if old_value.differs(&value) {
CompositionTargetHooks::validate_last_layout_pass_timing_change(host, old_value, value);
CompositionTargetHooks::on_last_layout_pass_timing_changing(host);
changed = true;
self.last_layout_pass_timing.set(value);
self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::LAST_LAYOUT_PASS_TIMING);
host.register_for_serialization();
}
self.last_layout_pass_timing.set(value);
if changed {
CompositionTargetHooks::on_last_layout_pass_timing_changed(host);
}
}
pub fn scaling(&self) -> f64 {
self.scaling.get()
}
pub fn set_scaling(&self, host: &dyn CompositionTargetHooks, value: f64) {
let mut changed = false;
let old_value = self.scaling.get();
if old_value.differs(&value) {
CompositionTargetHooks::validate_scaling_change(host, old_value, value);
CompositionTargetHooks::on_scaling_changing(host);
changed = true;
self.scaling.set(value);
self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::SCALING);
host.register_for_serialization();
}
self.scaling.set(value);
if changed {
CompositionTargetHooks::on_scaling_changed(host);
}
}
pub fn size(&self) -> Size {
self.size.get()
}
pub fn set_size(&self, host: &dyn CompositionTargetHooks, value: Size) {
let mut changed = false;
let old_value = self.size.get();
if old_value.differs(&value) {
CompositionTargetHooks::validate_size_change(host, old_value, value);
CompositionTargetHooks::on_size_changing(host);
changed = true;
self.size.set(value);
self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::SIZE);
host.register_for_serialization();
}
self.size.set(value);
if changed {
CompositionTargetHooks::on_size_changed(host);
}
}
pub fn transparency_level(&self) -> CompositionTransparencyLevel {
self.transparency_level.get()
}
pub fn set_transparency_level(&self, host: &dyn CompositionTargetHooks, value: CompositionTransparencyLevel) {
let mut changed = false;
let old_value = self.transparency_level.get();
if old_value.differs(&value) {
CompositionTargetHooks::validate_transparency_level_change(host, old_value, value);
CompositionTargetHooks::on_transparency_level_changing(host);
changed = true;
self.transparency_level.set(value);
self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::TRANSPARENCY_LEVEL);
host.register_for_serialization();
}
self.transparency_level.set(value);
if changed {
CompositionTargetHooks::on_transparency_level_changed(host);
}
}
pub fn platform_specific_scene_info(&self) -> Option<Arc<dyn Any + Send + Sync>> {
self.platform_specific_scene_info.borrow().clone()
}
pub fn set_platform_specific_scene_info(&self, host: &dyn CompositionTargetHooks, value: Option<Arc<dyn Any + Send + Sync>>) {
let mut changed = false;
let old_value = self.platform_specific_scene_info.borrow().clone();
if old_value.differs(&value) {
CompositionTargetHooks::validate_platform_specific_scene_info_change(host, &old_value, &value);
CompositionTargetHooks::on_platform_specific_scene_info_changing(host);
changed = true;
*self.platform_specific_scene_info.borrow_mut() = value.clone();
self.changed_fields_of_composition_target.set(self.changed_fields_of_composition_target.get() | CompositionTargetChangedFields::PLATFORM_SPECIFIC_SCENE_INFO);
host.register_for_serialization();
}
*self.platform_specific_scene_info.borrow_mut() = value;
if changed {
CompositionTargetHooks::on_platform_specific_scene_info_changed(host);
}
}
pub fn serialize_changes_core(&self, _host: &dyn CompositionTargetHooks, writer: &mut BatchStreamWriter<'_>) {
let changed = self.changed_fields_of_composition_target.get();
writer.write(changed);
if changed.contains(CompositionTargetChangedFields::ROOT) {
writer.write_server_object(self.root.borrow().clone().map(|o| o.server()));
}
if changed.contains(CompositionTargetChangedFields::IS_ENABLED) {
writer.write(self.is_enabled.get());
}
if changed.contains(CompositionTargetChangedFields::DEBUG_OVERLAYS) {
writer.write(self.debug_overlays.get());
}
if changed.contains(CompositionTargetChangedFields::LAST_LAYOUT_PASS_TIMING) {
writer.write(self.last_layout_pass_timing.get());
}
if changed.contains(CompositionTargetChangedFields::SCALING) {
writer.write(self.scaling.get());
}
if changed.contains(CompositionTargetChangedFields::SIZE) {
writer.write(self.size.get());
}
if changed.contains(CompositionTargetChangedFields::TRANSPARENCY_LEVEL) {
writer.write(self.transparency_level.get());
}
if changed.contains(CompositionTargetChangedFields::PLATFORM_SPECIFIC_SCENE_INFO) {
writer.write_value(self.platform_specific_scene_info.borrow().clone());
}
self.changed_fields_of_composition_target.set(CompositionTargetChangedFields::empty());
}
}
pub trait ServerCompositionTargetHooks: IServerAnimatedPropertyHost {
fn deserialize_changes_extra(&self, _reader: &mut BatchStreamReader<'_>) {}
fn on_fields_deserialized(&self, _changed: CompositionTargetChangedFields) {}
fn on_root_changed(&self) {}
fn on_root_changing(&self) {}
fn on_is_enabled_changed(&self) {}
fn on_is_enabled_changing(&self) {}
fn on_debug_overlays_changed(&self) {}
fn on_debug_overlays_changing(&self) {}
fn on_last_layout_pass_timing_changed(&self) {}
fn on_last_layout_pass_timing_changing(&self) {}
fn on_scaling_changed(&self) {}
fn on_scaling_changing(&self) {}
fn on_size_changed(&self) {}
fn on_size_changing(&self) {}
fn on_transparency_level_changed(&self) {}
fn on_transparency_level_changing(&self) {}
fn on_platform_specific_scene_info_changed(&self) {}
fn on_platform_specific_scene_info_changing(&self) {}
}
pub struct ServerCompositionTargetProps {
root: RefCell<Option<Rc<dyn IServerObject>>>,
is_enabled: Cell<bool>,
debug_overlays: Cell<RendererDebugOverlays>,
last_layout_pass_timing: Cell<LayoutPassTiming>,
scaling: Cell<f64>,
size: Cell<Size>,
transparency_level: Cell<CompositionTransparencyLevel>,
platform_specific_scene_info: RefCell<Option<Arc<dyn Any + Send + Sync>>>,
}
impl Default for ServerCompositionTargetProps {
fn default() -> Self {
Self::new()
}
}
impl ServerCompositionTargetProps {
pub fn new() -> Self {
Self {
root: RefCell::new(None),
is_enabled: Cell::new(Default::default()),
debug_overlays: Cell::new(Default::default()),
last_layout_pass_timing: Cell::new(Default::default()),
scaling: Cell::new(Default::default()),
size: Cell::new(Default::default()),
transparency_level: Cell::new(Default::default()),
platform_specific_scene_info: 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::<ServerCompositionTargetProps, Option<Rc<dyn IServerObject>>>(
"Root",
"ServerCompositionTarget",
|obj| props_of::<ServerCompositionTargetProps>(obj).root.borrow().clone(),
|obj, v| *props_of::<ServerCompositionTargetProps>(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 ServerCompositionTargetHooks, value: Option<Rc<dyn IServerObject>>) {
let old_value = self.root.borrow().clone();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionTargetHooks::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 {
ServerCompositionTargetHooks::on_root_changed(host);
}
}
pub fn id_of_is_enabled_property() -> &'static CompositionPropertyOf<bool> {
static PROPERTY: OnceLock<CompositionPropertyOf<bool>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionTargetProps, bool>(
"IsEnabled",
"ServerCompositionTarget",
|obj| props_of::<ServerCompositionTargetProps>(obj).is_enabled.get(),
|obj, v| props_of::<ServerCompositionTargetProps>(obj).is_enabled.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionTargetProps>(obj).is_enabled.get())),
None,
)
})
}
pub fn is_enabled(&self) -> bool {
self.is_enabled.get()
}
pub fn set_is_enabled(&self, host: &dyn ServerCompositionTargetHooks, value: bool) {
let old_value = self.is_enabled.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionTargetHooks::on_is_enabled_changing(host);
changed = true;
}
host.set_value(
Self::id_of_is_enabled_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.is_enabled.set(value),
},
);
if changed {
ServerCompositionTargetHooks::on_is_enabled_changed(host);
}
}
pub fn id_of_debug_overlays_property() -> &'static CompositionPropertyOf<RendererDebugOverlays> {
static PROPERTY: OnceLock<CompositionPropertyOf<RendererDebugOverlays>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionTargetProps, RendererDebugOverlays>(
"DebugOverlays",
"ServerCompositionTarget",
|obj| props_of::<ServerCompositionTargetProps>(obj).debug_overlays.get(),
|obj, v| props_of::<ServerCompositionTargetProps>(obj).debug_overlays.set(v),
None,
None,
)
})
}
pub fn debug_overlays(&self) -> RendererDebugOverlays {
self.debug_overlays.get()
}
pub fn set_debug_overlays(&self, host: &dyn ServerCompositionTargetHooks, value: RendererDebugOverlays) {
let old_value = self.debug_overlays.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionTargetHooks::on_debug_overlays_changing(host);
changed = true;
}
host.set_value(
Self::id_of_debug_overlays_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.debug_overlays.set(value),
},
);
if changed {
ServerCompositionTargetHooks::on_debug_overlays_changed(host);
}
}
pub fn id_of_last_layout_pass_timing_property() -> &'static CompositionPropertyOf<LayoutPassTiming> {
static PROPERTY: OnceLock<CompositionPropertyOf<LayoutPassTiming>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionTargetProps, LayoutPassTiming>(
"LastLayoutPassTiming",
"ServerCompositionTarget",
|obj| props_of::<ServerCompositionTargetProps>(obj).last_layout_pass_timing.get(),
|obj, v| props_of::<ServerCompositionTargetProps>(obj).last_layout_pass_timing.set(v),
None,
None,
)
})
}
pub fn last_layout_pass_timing(&self) -> LayoutPassTiming {
self.last_layout_pass_timing.get()
}
pub fn set_last_layout_pass_timing(&self, host: &dyn ServerCompositionTargetHooks, value: LayoutPassTiming) {
let old_value = self.last_layout_pass_timing.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionTargetHooks::on_last_layout_pass_timing_changing(host);
changed = true;
}
host.set_value(
Self::id_of_last_layout_pass_timing_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.last_layout_pass_timing.set(value),
},
);
if changed {
ServerCompositionTargetHooks::on_last_layout_pass_timing_changed(host);
}
}
pub fn id_of_scaling_property() -> &'static CompositionPropertyOf<f64> {
static PROPERTY: OnceLock<CompositionPropertyOf<f64>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionTargetProps, f64>(
"Scaling",
"ServerCompositionTarget",
|obj| props_of::<ServerCompositionTargetProps>(obj).scaling.get(),
|obj, v| props_of::<ServerCompositionTargetProps>(obj).scaling.set(v),
Some(|obj| ExpressionVariant::create(props_of::<ServerCompositionTargetProps>(obj).scaling.get())),
None,
)
})
}
pub fn scaling(&self) -> f64 {
self.scaling.get()
}
pub fn set_scaling(&self, host: &dyn ServerCompositionTargetHooks, value: f64) {
let old_value = self.scaling.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionTargetHooks::on_scaling_changing(host);
changed = true;
}
host.set_value(
Self::id_of_scaling_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.scaling.set(value),
},
);
if changed {
ServerCompositionTargetHooks::on_scaling_changed(host);
}
}
pub fn id_of_size_property() -> &'static CompositionPropertyOf<Size> {
static PROPERTY: OnceLock<CompositionPropertyOf<Size>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionTargetProps, Size>(
"Size",
"ServerCompositionTarget",
|obj| props_of::<ServerCompositionTargetProps>(obj).size.get(),
|obj, v| props_of::<ServerCompositionTargetProps>(obj).size.set(v),
None,
None,
)
})
}
pub fn size(&self) -> Size {
self.size.get()
}
pub fn set_size(&self, host: &dyn ServerCompositionTargetHooks, value: Size) {
let old_value = self.size.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionTargetHooks::on_size_changing(host);
changed = true;
}
host.set_value(
Self::id_of_size_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.size.set(value),
},
);
if changed {
ServerCompositionTargetHooks::on_size_changed(host);
}
}
pub fn id_of_transparency_level_property() -> &'static CompositionPropertyOf<CompositionTransparencyLevel> {
static PROPERTY: OnceLock<CompositionPropertyOf<CompositionTransparencyLevel>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionTargetProps, CompositionTransparencyLevel>(
"TransparencyLevel",
"ServerCompositionTarget",
|obj| props_of::<ServerCompositionTargetProps>(obj).transparency_level.get(),
|obj, v| props_of::<ServerCompositionTargetProps>(obj).transparency_level.set(v),
None,
None,
)
})
}
pub fn transparency_level(&self) -> CompositionTransparencyLevel {
self.transparency_level.get()
}
pub fn set_transparency_level(&self, host: &dyn ServerCompositionTargetHooks, value: CompositionTransparencyLevel) {
let old_value = self.transparency_level.get();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionTargetHooks::on_transparency_level_changing(host);
changed = true;
}
host.set_value(
Self::id_of_transparency_level_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || self.transparency_level.set(value),
},
);
if changed {
ServerCompositionTargetHooks::on_transparency_level_changed(host);
}
}
pub fn id_of_platform_specific_scene_info_property() -> &'static CompositionPropertyOf<Option<Arc<dyn Any + Send + Sync>>> {
static PROPERTY: OnceLock<CompositionPropertyOf<Option<Arc<dyn Any + Send + Sync>>>> = OnceLock::new();
PROPERTY.get_or_init(|| {
CompositionProperty::register::<ServerCompositionTargetProps, Option<Arc<dyn Any + Send + Sync>>>(
"PlatformSpecificSceneInfo",
"ServerCompositionTarget",
|obj| props_of::<ServerCompositionTargetProps>(obj).platform_specific_scene_info.borrow().clone(),
|obj, v| *props_of::<ServerCompositionTargetProps>(obj).platform_specific_scene_info.borrow_mut() = v,
None,
None,
)
})
}
pub fn platform_specific_scene_info(&self) -> Option<Arc<dyn Any + Send + Sync>> {
self.platform_specific_scene_info.borrow().clone()
}
pub fn set_platform_specific_scene_info(&self, host: &dyn ServerCompositionTargetHooks, value: Option<Arc<dyn Any + Send + Sync>>) {
let old_value = self.platform_specific_scene_info.borrow().clone();
let mut changed = false;
if old_value.differs(&value) {
ServerCompositionTargetHooks::on_platform_specific_scene_info_changing(host);
changed = true;
}
host.set_value(
Self::id_of_platform_specific_scene_info_property().base(),
ServerValueChange {
equal: old_value.default_equals(&value),
old_resource: None,
new_resource: None,
assign: &mut || *self.platform_specific_scene_info.borrow_mut() = value.clone(),
},
);
if changed {
ServerCompositionTargetHooks::on_platform_specific_scene_info_changed(host);
}
}
pub fn deserialize_changes_core(
&self,
host: &dyn ServerCompositionTargetHooks,
reader: &mut BatchStreamReader<'_>,
_committed_at: Duration,
) {
let compositor = host.server_compositor();
ServerCompositionTargetHooks::deserialize_changes_extra(host, reader);
let changed = reader.read::<CompositionTargetChangedFields>();
if changed.contains(CompositionTargetChangedFields::ROOT) {
let value = read_server_object(reader, compositor.as_ref());
self.set_root(host, value);
}
if changed.contains(CompositionTargetChangedFields::IS_ENABLED) {
let value = reader.read::<bool>();
self.set_is_enabled(host, value);
}
if changed.contains(CompositionTargetChangedFields::DEBUG_OVERLAYS) {
let value = reader.read::<RendererDebugOverlays>();
self.set_debug_overlays(host, value);
}
if changed.contains(CompositionTargetChangedFields::LAST_LAYOUT_PASS_TIMING) {
let value = reader.read::<LayoutPassTiming>();
self.set_last_layout_pass_timing(host, value);
}
if changed.contains(CompositionTargetChangedFields::SCALING) {
let value = reader.read::<f64>();
self.set_scaling(host, value);
}
if changed.contains(CompositionTargetChangedFields::SIZE) {
let value = reader.read::<Size>();
self.set_size(host, value);
}
if changed.contains(CompositionTargetChangedFields::TRANSPARENCY_LEVEL) {
let value = reader.read::<CompositionTransparencyLevel>();
self.set_transparency_level(host, value);
}
if changed.contains(CompositionTargetChangedFields::PLATFORM_SPECIFIC_SCENE_INFO) {
let value = reader.read_value::<Arc<dyn Any + Send + Sync>>();
self.set_platform_specific_scene_info(host, value);
}
ServerCompositionTargetHooks::on_fields_deserialized(host, changed);
}
pub fn get_composition_property(name: &str) -> Option<&'static CompositionProperty> {
if name == "IsEnabled" {
return Some(Self::id_of_is_enabled_property().base());
}
if name == "Scaling" {
return Some(Self::id_of_scaling_property().base());
}
None
}
}