use crate::coord::CanvasRect;
use crate::gpu::blend_mode::{self, BlendModeRegistration};
use crate::gpu::params::ParamValue;
slotmap::new_key_type! {
pub struct LayerId;
}
impl LayerId {
pub fn to_ffi(self) -> u64 {
slotmap::Key::data(&self).as_ffi()
}
pub fn from_ffi(v: u64) -> Self {
slotmap::KeyData::from_ffi(v).into()
}
}
pub struct NodeCommon {
pub name: String,
pub visible: bool,
pub locked: bool,
}
impl NodeCommon {
pub fn new(name: String) -> Self {
NodeCommon {
name,
visible: true,
locked: false,
}
}
}
pub struct BlendProps {
pub opacity: f32,
pub blend_mode: &'static BlendModeRegistration,
}
impl BlendProps {
pub fn new() -> Self {
BlendProps {
opacity: 1.0,
blend_mode: blend_mode::registry().default(),
}
}
}
impl Default for BlendProps {
fn default() -> Self {
Self::new()
}
}
pub struct PixelBuffer {
pub bounds: CanvasRect,
pub format: wgpu::TextureFormat,
}
impl PixelBuffer {
pub fn new(bounds: CanvasRect, format: wgpu::TextureFormat) -> Self {
PixelBuffer { bounds, format }
}
}
pub struct RasterLayer {
pub id: LayerId,
pub common: NodeCommon,
pub blend: BlendProps,
pub pixels: PixelBuffer,
pub filters: Vec<LayerId>,
}
impl RasterLayer {
pub fn new(id: LayerId, bounds: CanvasRect, name: String) -> Self {
RasterLayer {
id,
common: NodeCommon::new(name),
blend: BlendProps::new(),
pixels: PixelBuffer::new(bounds, wgpu::TextureFormat::Rgba8Unorm),
filters: Vec::new(),
}
}
}
pub struct VoidLayer {
pub id: LayerId,
pub common: NodeCommon,
pub blend: BlendProps,
pub void_type: String,
pub params: Vec<ParamValue>,
pub transform: crate::transform::Transform,
pub filters: Vec<LayerId>,
pub frame: Option<crate::format::manifest::ManifestPixelRef>,
}
impl VoidLayer {
pub fn new(id: LayerId, name: String, void_type: String, params: Vec<ParamValue>) -> Self {
VoidLayer {
id,
common: NodeCommon::new(name),
blend: BlendProps::new(),
void_type,
params,
transform: crate::transform::Transform::identity(),
filters: Vec::new(),
frame: None,
}
}
}
pub struct FilterLayer {
pub id: LayerId,
pub common: NodeCommon,
pub blend: BlendProps,
pub pipeline: String,
pub params: Vec<ParamValue>,
pub filters: Vec<LayerId>,
}
impl FilterLayer {
pub fn new(id: LayerId, name: String, pipeline: String, params: Vec<ParamValue>) -> Self {
FilterLayer {
id,
common: NodeCommon::new(name),
blend: BlendProps::new(),
pipeline,
params,
filters: Vec::new(),
}
}
}
pub struct LayerGroup {
pub id: LayerId,
pub common: NodeCommon,
pub blend: BlendProps,
pub children: Vec<LayerId>,
pub filters: Vec<LayerId>,
pub passthrough: bool,
pub collapsed: bool,
}
impl LayerGroup {
pub fn new(id: LayerId, name: String) -> Self {
LayerGroup {
id,
common: NodeCommon::new(name),
blend: BlendProps::new(),
children: Vec::new(),
filters: Vec::new(),
passthrough: true,
collapsed: false,
}
}
}
pub enum LayerNode {
Layer(Layer),
Group(LayerGroup),
}
impl LayerNode {
pub fn id(&self) -> LayerId {
match self {
LayerNode::Layer(l) => l.id(),
LayerNode::Group(g) => g.id,
}
}
pub fn common(&self) -> &NodeCommon {
match self {
LayerNode::Layer(l) => l.common(),
LayerNode::Group(g) => &g.common,
}
}
pub fn common_mut(&mut self) -> &mut NodeCommon {
match self {
LayerNode::Layer(l) => l.common_mut(),
LayerNode::Group(g) => &mut g.common,
}
}
pub fn blend(&self) -> &BlendProps {
match self {
LayerNode::Layer(l) => l.blend(),
LayerNode::Group(g) => &g.blend,
}
}
pub fn blend_mut(&mut self) -> &mut BlendProps {
match self {
LayerNode::Layer(l) => l.blend_mut(),
LayerNode::Group(g) => &mut g.blend,
}
}
pub fn filters(&self) -> &[LayerId] {
match self {
LayerNode::Layer(l) => l.filters(),
LayerNode::Group(g) => &g.filters,
}
}
pub fn modifiers_mut(&mut self) -> &mut Vec<LayerId> {
match self {
LayerNode::Layer(l) => l.modifiers_mut(),
LayerNode::Group(g) => &mut g.filters,
}
}
pub fn pixels(&self) -> Option<&PixelBuffer> {
match self {
LayerNode::Layer(l) => l.pixels(),
LayerNode::Group(_) => None,
}
}
pub fn pixels_mut(&mut self) -> Option<&mut PixelBuffer> {
match self {
LayerNode::Layer(l) => l.pixels_mut(),
LayerNode::Group(_) => None,
}
}
pub fn visible(&self) -> bool {
self.common().visible
}
pub fn locked(&self) -> bool {
self.common().locked
}
pub fn kind(&self) -> &'static crate::document::LayerKindRegistration {
use crate::document::layer_kind::registry;
use crate::document::layer_kinds::{filter, group, raster, void};
match self {
LayerNode::Layer(Layer::Raster(_)) => registry().get(raster::TYPE_ID).unwrap(),
LayerNode::Layer(Layer::Void(_)) => registry().get(void::TYPE_ID).unwrap(),
LayerNode::Layer(Layer::Filter(_)) => registry().get(filter::TYPE_ID).unwrap(),
LayerNode::Group(_) => registry().get(group::TYPE_ID).unwrap(),
}
}
pub fn type_id(&self) -> &'static str {
self.kind().type_id
}
pub fn compose_into(&self, ctx: &mut crate::gpu::compositor::CompositionContext<'_>) {
match self {
LayerNode::Layer(layer) => ctx.compose_layer(layer),
LayerNode::Group(group) => ctx.compose_group(group),
}
}
pub fn composites_in_place(&self) -> bool {
match self {
LayerNode::Group(g) => g.passthrough,
LayerNode::Layer(Layer::Filter(_)) => true,
LayerNode::Layer(_) => false,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TransformCapability {
Live,
Destructive,
None,
}
pub enum Layer {
Raster(RasterLayer),
Void(VoidLayer),
Filter(FilterLayer),
}
impl Layer {
pub fn transform_capability(
&self,
reg: &crate::gpu::void::VoidRegistry,
) -> TransformCapability {
match self {
Layer::Raster(_) => TransformCapability::Destructive,
Layer::Void(v) => {
if reg.supports_live_transform(&v.void_type) {
TransformCapability::Live
} else {
TransformCapability::None
}
}
Layer::Filter(_) => TransformCapability::None,
}
}
pub fn is_blend_content(&self) -> bool {
!matches!(self, Layer::Filter(_))
}
pub fn id(&self) -> LayerId {
match self {
Layer::Raster(r) => r.id,
Layer::Void(v) => v.id,
Layer::Filter(f) => f.id,
}
}
pub fn common(&self) -> &NodeCommon {
match self {
Layer::Raster(r) => &r.common,
Layer::Void(v) => &v.common,
Layer::Filter(f) => &f.common,
}
}
pub fn common_mut(&mut self) -> &mut NodeCommon {
match self {
Layer::Raster(r) => &mut r.common,
Layer::Void(v) => &mut v.common,
Layer::Filter(f) => &mut f.common,
}
}
pub fn blend(&self) -> &BlendProps {
match self {
Layer::Raster(r) => &r.blend,
Layer::Void(v) => &v.blend,
Layer::Filter(f) => &f.blend,
}
}
pub fn blend_mut(&mut self) -> &mut BlendProps {
match self {
Layer::Raster(r) => &mut r.blend,
Layer::Void(v) => &mut v.blend,
Layer::Filter(f) => &mut f.blend,
}
}
pub fn filters(&self) -> &[LayerId] {
match self {
Layer::Raster(r) => &r.filters,
Layer::Void(v) => &v.filters,
Layer::Filter(f) => &f.filters,
}
}
pub fn modifiers_mut(&mut self) -> &mut Vec<LayerId> {
match self {
Layer::Raster(r) => &mut r.filters,
Layer::Void(v) => &mut v.filters,
Layer::Filter(f) => &mut f.filters,
}
}
pub fn pixels(&self) -> Option<&PixelBuffer> {
match self {
Layer::Raster(r) => Some(&r.pixels),
Layer::Void(_) | Layer::Filter(_) => None,
}
}
pub fn pixels_mut(&mut self) -> Option<&mut PixelBuffer> {
match self {
Layer::Raster(r) => Some(&mut r.pixels),
Layer::Void(_) | Layer::Filter(_) => None,
}
}
pub fn visible(&self) -> bool {
self.common().visible
}
pub fn locked(&self) -> bool {
self.common().locked
}
pub fn void_state(&self) -> Option<(&[ParamValue], &crate::transform::Transform)> {
match self {
Layer::Void(v) => Some((&v.params, &v.transform)),
Layer::Raster(_) | Layer::Filter(_) => None,
}
}
}