use crate::core::{Core, Object, ObjectRef, OnAdded, Property};
use crate::draw_rules::DrawRules;
use crate::dyn_vec::DynVec;
use crate::math::Mat;
use crate::node::Node;
use crate::option_cell::OptionCell;
use crate::shapes::paint::BlendMode;
use crate::shapes::{ClippingShape, CommandPath, CommandPathBuilder, Shape};
use crate::Renderer;
#[derive(Debug)]
pub struct Drawable {
node: Node,
blend_mode: Property<BlendMode>,
drawable_flags: Property<u64>,
clipping_shapes: DynVec<Object<ClippingShape>>,
pub(crate) flattened_draw_rules: OptionCell<Object<DrawRules>>,
pub(crate) prev: OptionCell<Object<Self>>,
pub(crate) next: OptionCell<Object<Self>>,
}
impl ObjectRef<'_, Drawable> {
pub fn blend_mode(&self) -> BlendMode {
self.blend_mode.get()
}
pub fn set_blend_mode(&self, blend_mode: BlendMode) {
self.blend_mode.set(blend_mode);
}
pub fn drawable_flags(&self) -> u64 {
self.drawable_flags.get()
}
pub fn set_drawable_flags(&self, drawable_flags: u64) {
self.drawable_flags.set(drawable_flags);
}
}
impl ObjectRef<'_, Drawable> {
pub fn push_clipping_shape(&self, clipping_shape: Object<ClippingShape>) {
self.clipping_shapes.push(clipping_shape);
}
pub fn clip(&self) -> Option<CommandPath> {
self.clipping_shapes
.iter()
.fold(None, |mut option, clipping_shape| {
let builder = option.get_or_insert_with(CommandPathBuilder::new);
clipping_shape.as_ref().with_command_path(|path| {
if let Some(path) = path {
builder.path(path, None);
}
});
option
})
.map(|builder| builder.build())
}
pub fn draw(&self, renderer: &mut impl Renderer, transform: Mat) {
if let Some(shape) = self.try_cast::<Shape>() {
return shape.draw(renderer, transform);
}
unreachable!()
}
}
impl Core for Drawable {
parent_types![(node, Node)];
properties![(23, blend_mode, set_blend_mode), (129, drawable_flags, set_drawable_flags), node];
}
impl OnAdded for ObjectRef<'_, Drawable> {
on_added!(Node);
}
impl Default for Drawable {
fn default() -> Self {
Self {
node: Node::default(),
blend_mode: Property::new(BlendMode::SrcOver),
drawable_flags: Property::new(0),
clipping_shapes: DynVec::new(),
flattened_draw_rules: OptionCell::new(),
prev: OptionCell::new(),
next: OptionCell::new(),
}
}
}