use crate::{Id, *};
use epaint::{ClippedShape, Shape};
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Order {
Background,
PanelResizeLine,
Middle,
Foreground,
Tooltip,
Debug,
}
impl Order {
const COUNT: usize = 6;
const ALL: [Order; Self::COUNT] = [
Self::Background,
Self::PanelResizeLine,
Self::Middle,
Self::Foreground,
Self::Tooltip,
Self::Debug,
];
#[inline(always)]
pub fn allow_interaction(&self) -> bool {
match self {
Self::Background
| Self::PanelResizeLine
| Self::Middle
| Self::Foreground
| Self::Debug => true,
Self::Tooltip => false,
}
}
pub fn short_debug_format(&self) -> &'static str {
match self {
Self::Background => "backg",
Self::PanelResizeLine => "panel",
Self::Middle => "middl",
Self::Foreground => "foreg",
Self::Tooltip => "toolt",
Self::Debug => "debug",
}
}
}
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct LayerId {
pub order: Order,
pub id: Id,
}
impl LayerId {
pub fn new(order: Order, id: Id) -> Self {
Self { order, id }
}
pub fn debug() -> Self {
Self {
order: Order::Debug,
id: Id::new("debug"),
}
}
pub fn background() -> Self {
Self {
order: Order::Background,
id: Id::background(),
}
}
#[inline(always)]
pub fn allow_interaction(&self) -> bool {
self.order.allow_interaction()
}
pub fn short_debug_format(&self) -> String {
format!(
"{} {}",
self.order.short_debug_format(),
self.id.short_debug_format()
)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct ShapeIdx(usize);
#[derive(Clone, Default)]
pub struct PaintList(Vec<ClippedShape>);
impl PaintList {
#[inline(always)]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline(always)]
pub fn add(&mut self, clip_rect: Rect, shape: Shape) -> ShapeIdx {
let idx = ShapeIdx(self.0.len());
self.0.push(ClippedShape(clip_rect, shape));
idx
}
pub fn extend<I: IntoIterator<Item = Shape>>(&mut self, clip_rect: Rect, shapes: I) {
self.0.extend(
shapes
.into_iter()
.map(|shape| ClippedShape(clip_rect, shape)),
);
}
#[inline(always)]
pub fn set(&mut self, idx: ShapeIdx, clip_rect: Rect, shape: Shape) {
self.0[idx.0] = ClippedShape(clip_rect, shape);
}
pub fn translate(&mut self, delta: Vec2) {
for ClippedShape(clip_rect, shape) in &mut self.0 {
*clip_rect = clip_rect.translate(delta);
shape.translate(delta);
}
}
}
#[derive(Clone, Default)]
pub(crate) struct GraphicLayers([IdMap<PaintList>; Order::COUNT]);
impl GraphicLayers {
pub fn list(&mut self, layer_id: LayerId) -> &mut PaintList {
self.0[layer_id.order as usize]
.entry(layer_id.id)
.or_default()
}
pub fn drain(&mut self, area_order: &[LayerId]) -> impl ExactSizeIterator<Item = ClippedShape> {
let mut all_shapes: Vec<_> = Default::default();
for &order in &Order::ALL {
let order_map = &mut self.0[order as usize];
order_map.retain(|_, list| !list.is_empty());
for layer_id in area_order {
if layer_id.order == order {
if let Some(list) = order_map.get_mut(&layer_id.id) {
all_shapes.append(&mut list.0);
}
}
}
for shapes in order_map.values_mut() {
all_shapes.append(&mut shapes.0);
}
}
all_shapes.into_iter()
}
}