2023-10-04 10:41:21 +00:00
|
|
|
use std::{iter::Peekable, mem, slice};
|
2023-09-26 17:29:44 +00:00
|
|
|
|
2023-10-03 19:52:10 +00:00
|
|
|
use super::{Bounds, Hsla, Point};
|
2023-10-04 02:04:17 +00:00
|
|
|
use crate::{AtlasTextureId, AtlasTile, Corners, Edges, ScaledContentMask, ScaledPixels};
|
2023-10-03 15:36:12 +00:00
|
|
|
use collections::BTreeMap;
|
|
|
|
use smallvec::SmallVec;
|
2023-09-19 19:19:22 +00:00
|
|
|
|
2023-09-23 17:06:10 +00:00
|
|
|
// Exported to metal
|
|
|
|
pub type PointF = Point<f32>;
|
2023-10-03 23:58:11 +00:00
|
|
|
pub type LayerId = SmallVec<[u32; 16]>;
|
2023-09-23 17:06:10 +00:00
|
|
|
|
2023-09-26 17:34:41 +00:00
|
|
|
#[derive(Debug)]
|
2023-09-19 19:19:22 +00:00
|
|
|
pub struct Scene {
|
2023-10-03 14:53:49 +00:00
|
|
|
pub(crate) scale_factor: f32,
|
2023-10-03 23:58:11 +00:00
|
|
|
pub(crate) layers: BTreeMap<LayerId, SceneLayer>,
|
2023-09-24 22:52:33 +00:00
|
|
|
}
|
|
|
|
|
2023-09-19 19:19:22 +00:00
|
|
|
impl Scene {
|
2023-09-23 20:20:07 +00:00
|
|
|
pub fn new(scale_factor: f32) -> Scene {
|
2023-09-19 19:19:22 +00:00
|
|
|
Scene {
|
2023-09-23 20:20:07 +00:00
|
|
|
scale_factor,
|
2023-10-03 04:14:45 +00:00
|
|
|
layers: BTreeMap::new(),
|
2023-09-19 19:19:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-26 17:29:44 +00:00
|
|
|
pub fn take(&mut self) -> Scene {
|
|
|
|
Scene {
|
|
|
|
scale_factor: self.scale_factor,
|
2023-10-03 04:14:45 +00:00
|
|
|
layers: mem::take(&mut self.layers),
|
2023-09-26 17:29:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-03 23:58:11 +00:00
|
|
|
pub fn insert(&mut self, stacking_order: LayerId, primitive: impl Into<Primitive>) {
|
2023-10-03 14:53:49 +00:00
|
|
|
let layer = self.layers.entry(stacking_order).or_default();
|
2023-10-03 04:14:45 +00:00
|
|
|
|
|
|
|
let primitive = primitive.into();
|
2023-09-23 18:21:52 +00:00
|
|
|
match primitive {
|
2023-10-03 19:52:10 +00:00
|
|
|
Primitive::Quad(quad) => {
|
2023-10-03 04:14:45 +00:00
|
|
|
layer.quads.push(quad);
|
|
|
|
}
|
2023-10-04 09:53:20 +00:00
|
|
|
Primitive::MonochromeSprite(sprite) => {
|
|
|
|
layer.monochrome_sprites.push(sprite);
|
|
|
|
}
|
|
|
|
Primitive::PolychromeSprite(sprite) => {
|
|
|
|
layer.polychrome_sprites.push(sprite);
|
2023-10-03 04:14:45 +00:00
|
|
|
}
|
2023-09-19 19:19:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-03 04:14:45 +00:00
|
|
|
pub(crate) fn layers(&mut self) -> impl Iterator<Item = &mut SceneLayer> {
|
|
|
|
self.layers.values_mut()
|
2023-09-23 17:06:10 +00:00
|
|
|
}
|
2023-09-19 19:19:22 +00:00
|
|
|
}
|
|
|
|
|
2023-10-03 04:14:45 +00:00
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub(crate) struct SceneLayer {
|
|
|
|
pub quads: Vec<Quad>,
|
2023-10-04 09:53:20 +00:00
|
|
|
pub monochrome_sprites: Vec<MonochromeSprite>,
|
|
|
|
pub polychrome_sprites: Vec<PolychromeSprite>,
|
2023-10-03 04:14:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SceneLayer {
|
|
|
|
pub fn batches(&mut self) -> impl Iterator<Item = PrimitiveBatch> {
|
2023-10-03 15:36:12 +00:00
|
|
|
self.quads.sort_unstable();
|
2023-10-04 09:53:20 +00:00
|
|
|
self.monochrome_sprites.sort_unstable();
|
2023-10-04 10:41:21 +00:00
|
|
|
self.polychrome_sprites.sort_unstable();
|
|
|
|
BatchIterator {
|
|
|
|
quads: &self.quads,
|
|
|
|
quads_start: 0,
|
|
|
|
quads_iter: self.quads.iter().peekable(),
|
|
|
|
monochrome_sprites: &self.monochrome_sprites,
|
|
|
|
monochrome_sprites_start: 0,
|
|
|
|
monochrome_sprites_iter: self.monochrome_sprites.iter().peekable(),
|
|
|
|
polychrome_sprites: &self.polychrome_sprites,
|
|
|
|
polychrome_sprites_start: 0,
|
|
|
|
polychrome_sprites_iter: self.polychrome_sprites.iter().peekable(),
|
|
|
|
}
|
2023-10-03 04:14:45 +00:00
|
|
|
}
|
2023-09-19 19:19:22 +00:00
|
|
|
}
|
|
|
|
|
2023-10-04 10:41:21 +00:00
|
|
|
struct BatchIterator<'a> {
|
2023-10-03 04:14:45 +00:00
|
|
|
quads: &'a [Quad],
|
|
|
|
quads_start: usize,
|
2023-10-04 10:41:21 +00:00
|
|
|
quads_iter: Peekable<slice::Iter<'a, Quad>>,
|
|
|
|
monochrome_sprites: &'a [MonochromeSprite],
|
|
|
|
monochrome_sprites_start: usize,
|
|
|
|
monochrome_sprites_iter: Peekable<slice::Iter<'a, MonochromeSprite>>,
|
|
|
|
polychrome_sprites: &'a [PolychromeSprite],
|
|
|
|
polychrome_sprites_start: usize,
|
|
|
|
polychrome_sprites_iter: Peekable<slice::Iter<'a, PolychromeSprite>>,
|
2023-10-03 04:14:45 +00:00
|
|
|
}
|
|
|
|
|
2023-10-04 10:41:21 +00:00
|
|
|
impl<'a> Iterator for BatchIterator<'a> {
|
2023-10-03 04:14:45 +00:00
|
|
|
type Item = PrimitiveBatch<'a>;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
2023-10-03 15:36:12 +00:00
|
|
|
let mut kinds_and_orders = [
|
|
|
|
(PrimitiveKind::Quad, self.quads_iter.peek().map(|q| q.order)),
|
|
|
|
(
|
2023-10-04 10:41:21 +00:00
|
|
|
PrimitiveKind::MonochromeSprite,
|
|
|
|
self.monochrome_sprites_iter.peek().map(|s| s.order),
|
|
|
|
),
|
|
|
|
(
|
|
|
|
PrimitiveKind::PolychromeSprite,
|
|
|
|
self.polychrome_sprites_iter.peek().map(|s| s.order),
|
2023-10-03 15:36:12 +00:00
|
|
|
),
|
|
|
|
];
|
|
|
|
kinds_and_orders.sort_by_key(|(_, order)| order.unwrap_or(u32::MAX));
|
|
|
|
|
|
|
|
let first = kinds_and_orders[0];
|
|
|
|
let second = kinds_and_orders[1];
|
|
|
|
let (batch_kind, max_order) = if first.1.is_some() {
|
|
|
|
(first.0, second.1.unwrap_or(u32::MAX))
|
2023-10-03 04:14:45 +00:00
|
|
|
} else {
|
2023-10-03 15:36:12 +00:00
|
|
|
return None;
|
|
|
|
};
|
|
|
|
|
|
|
|
match batch_kind {
|
|
|
|
PrimitiveKind::Quad => {
|
|
|
|
let quads_start = self.quads_start;
|
|
|
|
let quads_end = quads_start
|
|
|
|
+ self
|
|
|
|
.quads_iter
|
|
|
|
.by_ref()
|
|
|
|
.take_while(|quad| quad.order <= max_order)
|
|
|
|
.count();
|
|
|
|
self.quads_start = quads_end;
|
|
|
|
Some(PrimitiveBatch::Quads(&self.quads[quads_start..quads_end]))
|
|
|
|
}
|
2023-10-04 10:41:21 +00:00
|
|
|
PrimitiveKind::MonochromeSprite => {
|
|
|
|
let texture_id = self.monochrome_sprites_iter.peek().unwrap().tile.texture_id;
|
|
|
|
let sprites_start = self.monochrome_sprites_start;
|
2023-10-03 15:36:12 +00:00
|
|
|
let sprites_end = sprites_start
|
|
|
|
+ self
|
2023-10-04 10:41:21 +00:00
|
|
|
.monochrome_sprites_iter
|
2023-10-03 15:36:12 +00:00
|
|
|
.by_ref()
|
|
|
|
.take_while(|sprite| {
|
|
|
|
sprite.order <= max_order && sprite.tile.texture_id == texture_id
|
|
|
|
})
|
|
|
|
.count();
|
2023-10-04 10:41:21 +00:00
|
|
|
self.monochrome_sprites_start = sprites_end;
|
2023-10-04 09:53:20 +00:00
|
|
|
Some(PrimitiveBatch::MonochromeSprites {
|
2023-10-03 15:36:12 +00:00
|
|
|
texture_id,
|
2023-10-04 10:41:21 +00:00
|
|
|
sprites: &self.monochrome_sprites[sprites_start..sprites_end],
|
|
|
|
})
|
|
|
|
}
|
|
|
|
PrimitiveKind::PolychromeSprite => {
|
|
|
|
let texture_id = self.polychrome_sprites_iter.peek().unwrap().tile.texture_id;
|
|
|
|
let sprites_start = self.polychrome_sprites_start;
|
|
|
|
let sprites_end = sprites_start
|
|
|
|
+ self
|
|
|
|
.polychrome_sprites_iter
|
|
|
|
.by_ref()
|
|
|
|
.take_while(|sprite| {
|
|
|
|
sprite.order <= max_order && sprite.tile.texture_id == texture_id
|
|
|
|
})
|
|
|
|
.count();
|
|
|
|
self.polychrome_sprites_start = sprites_end;
|
|
|
|
Some(PrimitiveBatch::PolychromeSprites {
|
|
|
|
texture_id,
|
|
|
|
sprites: &self.polychrome_sprites[sprites_start..sprites_end],
|
2023-10-03 15:36:12 +00:00
|
|
|
})
|
|
|
|
}
|
2023-10-03 04:14:45 +00:00
|
|
|
}
|
2023-09-19 19:19:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-03 04:14:45 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
|
|
pub enum PrimitiveKind {
|
|
|
|
Quad,
|
2023-10-04 10:41:21 +00:00
|
|
|
MonochromeSprite,
|
|
|
|
PolychromeSprite,
|
2023-10-03 04:14:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum Primitive {
|
|
|
|
Quad(Quad),
|
2023-10-04 09:53:20 +00:00
|
|
|
MonochromeSprite(MonochromeSprite),
|
|
|
|
PolychromeSprite(PolychromeSprite),
|
2023-10-03 04:14:45 +00:00
|
|
|
}
|
|
|
|
|
2023-10-03 15:36:12 +00:00
|
|
|
pub(crate) enum PrimitiveBatch<'a> {
|
2023-10-03 04:14:45 +00:00
|
|
|
Quads(&'a [Quad]),
|
2023-10-04 09:53:20 +00:00
|
|
|
MonochromeSprites {
|
2023-10-03 15:36:12 +00:00
|
|
|
texture_id: AtlasTextureId,
|
|
|
|
sprites: &'a [MonochromeSprite],
|
|
|
|
},
|
2023-10-04 09:53:20 +00:00
|
|
|
PolychromeSprites {
|
|
|
|
texture_id: AtlasTextureId,
|
|
|
|
sprites: &'a [PolychromeSprite],
|
|
|
|
},
|
2023-10-03 04:14:45 +00:00
|
|
|
}
|
|
|
|
|
2023-10-03 16:04:45 +00:00
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
2023-09-19 19:19:22 +00:00
|
|
|
#[repr(C)]
|
|
|
|
pub struct Quad {
|
2023-09-23 17:06:10 +00:00
|
|
|
pub order: u32,
|
2023-10-03 19:03:29 +00:00
|
|
|
pub bounds: Bounds<ScaledPixels>,
|
|
|
|
pub clip_bounds: Bounds<ScaledPixels>,
|
|
|
|
pub clip_corner_radii: Corners<ScaledPixels>,
|
2023-09-19 19:19:22 +00:00
|
|
|
pub background: Hsla,
|
|
|
|
pub border_color: Hsla,
|
2023-10-03 19:03:29 +00:00
|
|
|
pub corner_radii: Corners<ScaledPixels>,
|
|
|
|
pub border_widths: Edges<ScaledPixels>,
|
2023-09-19 19:19:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Quad {
|
2023-10-03 19:03:29 +00:00
|
|
|
pub fn vertices(&self) -> impl Iterator<Item = Point<ScaledPixels>> {
|
2023-09-19 19:19:22 +00:00
|
|
|
let x1 = self.bounds.origin.x;
|
|
|
|
let y1 = self.bounds.origin.y;
|
|
|
|
let x2 = x1 + self.bounds.size.width;
|
|
|
|
let y2 = y1 + self.bounds.size.height;
|
|
|
|
[
|
|
|
|
Point::new(x1, y1),
|
|
|
|
Point::new(x2, y1),
|
|
|
|
Point::new(x2, y2),
|
|
|
|
Point::new(x1, y2),
|
|
|
|
]
|
|
|
|
.into_iter()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-03 15:36:12 +00:00
|
|
|
impl Ord for Quad {
|
|
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
|
|
self.order.cmp(&other.order)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for Quad {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-23 20:20:07 +00:00
|
|
|
impl From<Quad> for Primitive {
|
|
|
|
fn from(quad: Quad) -> Self {
|
|
|
|
Primitive::Quad(quad)
|
2023-09-19 19:19:22 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-02 21:43:03 +00:00
|
|
|
|
2023-10-03 15:36:12 +00:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
2023-10-02 21:43:03 +00:00
|
|
|
#[repr(C)]
|
2023-10-03 04:14:45 +00:00
|
|
|
pub struct MonochromeSprite {
|
2023-10-02 21:43:03 +00:00
|
|
|
pub order: u32,
|
2023-10-03 19:52:10 +00:00
|
|
|
pub bounds: Bounds<ScaledPixels>,
|
2023-10-04 02:04:17 +00:00
|
|
|
pub content_mask: ScaledContentMask,
|
2023-10-03 12:48:08 +00:00
|
|
|
pub color: Hsla,
|
|
|
|
pub tile: AtlasTile,
|
2023-10-02 21:43:03 +00:00
|
|
|
}
|
|
|
|
|
2023-10-03 15:36:12 +00:00
|
|
|
impl Ord for MonochromeSprite {
|
|
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
|
|
match self.order.cmp(&other.order) {
|
|
|
|
std::cmp::Ordering::Equal => self.tile.tile_id.cmp(&other.tile.tile_id),
|
|
|
|
order => order,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for MonochromeSprite {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
|
|
Some(self.cmp(other))
|
2023-10-02 21:43:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-03 04:14:45 +00:00
|
|
|
impl From<MonochromeSprite> for Primitive {
|
|
|
|
fn from(sprite: MonochromeSprite) -> Self {
|
2023-10-04 09:53:20 +00:00
|
|
|
Primitive::MonochromeSprite(sprite)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
|
|
#[repr(C)]
|
|
|
|
pub struct PolychromeSprite {
|
|
|
|
pub order: u32,
|
|
|
|
pub bounds: Bounds<ScaledPixels>,
|
|
|
|
pub content_mask: ScaledContentMask,
|
|
|
|
pub tile: AtlasTile,
|
2023-10-04 13:27:51 +00:00
|
|
|
pub grayscale: bool,
|
2023-10-04 09:53:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Ord for PolychromeSprite {
|
|
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
|
|
match self.order.cmp(&other.order) {
|
|
|
|
std::cmp::Ordering::Equal => self.tile.tile_id.cmp(&other.tile.tile_id),
|
|
|
|
order => order,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for PolychromeSprite {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<PolychromeSprite> for Primitive {
|
|
|
|
fn from(sprite: PolychromeSprite) -> Self {
|
|
|
|
Primitive::PolychromeSprite(sprite)
|
2023-10-02 21:43:03 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-03 04:14:45 +00:00
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub struct AtlasId(pub(crate) usize);
|