Skip to main content

grafix_toolbox/gui/
primitive.rs

1pub mod prim {
2	pub use super::{Frame9, Rect, Sprite, Sprite9, Text};
3}
4
5pub use {frame9::*, rect::*, sprite::*, sprite9::*, text::*};
6
7mod frame9;
8mod rect;
9mod sprite;
10mod sprite9;
11mod text;
12
13pub trait Primitive {
14	fn base(&self) -> &Base;
15	fn write_mesh(&self, aspect: Vec2, _: BatchedObj);
16	fn batch_draw(&self, _: &VaoBind<u16>, range: (u16, u16));
17
18	fn vert_count(&self) -> u32 {
19		4
20	}
21	fn ordered(&self) -> bool {
22		true
23	}
24	fn gen_idxs(&self, (start, size): (u16, u16)) -> Box<[u16]> {
25		rect_idxs((start, size))
26	}
27}
28pub struct BatchedObj<'a> {
29	pub z: f16,
30	pub state: State,
31	pub xyzw: &'a mut [f16],
32	pub rgba: &'a mut [u8],
33	pub uv: &'a mut [f16],
34}
35bitflags! {#[derive(Default, Debug, Clone, Copy, PartialEq)]
36pub struct State: u8 {
37	const BATCH_RESIZED = 0x2;
38	const XYZW = 0x10;
39	const RGBA = 0x20;
40	const UV = 0x40;
41	const FULL = Self::XYZW.bits() | Self::RGBA.bits() | Self::UV.bits();
42	const MISMATCH = 0x1 | Self::FULL.bits() | Self::BATCH_RESIZED.bits();
43}}
44
45#[derive(Debug)]
46pub struct Base {
47	pos: Vec2,
48	size: Vec2,
49	crop: Geom,
50	color: Color,
51}
52impl Base {
53	pub fn bound_box(&self) -> Geom {
54		let Self { pos, size, crop: (p1, p2), .. } = *self;
55		(pos.clmp(p1, p2), pos.sum(size).clmp(p1, p2))
56	}
57	pub fn intersects(&self, r: &Self) -> bool {
58		intersects(self.bound_box(), r.bound_box())
59	}
60}
61
62fn ordered(c: Color) -> bool {
63	c.3 < 0.996
64}
65
66fn geom_cmp(pos: Vec2, size: Vec2, bb: &Geom, r: &Base) -> bool {
67	pos != r.pos || size != r.size || *bb != r.crop
68}
69
70fn ordering_cmp<S: TexSize, T: Primitive>(c: Color, r: &T) -> bool {
71	(S::TYPE == gl::RGBA || ordered(c)) != r.ordered()
72}
73
74fn atlas_cmp<S, F>(l: *const VTex2d<S, F>, r: *const VTex2d<S, F>) -> bool {
75	unsafe { (*l).eq_atlas(&*r) }
76}
77
78fn bound_uv(crop @ (p1, p2): Geom, base @ (xy1, xy2): Geom, uv @ (u1, v1, u2, v2): TexCoord) -> TexCoord {
79	if contains(crop, base) {
80		return uv;
81	}
82
83	if !intersects(crop, base) {
84		return Def();
85	}
86
87	let wh = (u2 - u1, v2 - v1).div(xy2.sub(xy1));
88	let (u1, v1) = (u1, v1).sum(wh.mul(p1.sub(xy1)).mul(p1.gt(xy1)));
89	let (u2, v2) = (u2, v2).sub(wh.mul(xy2.sub(p2)).mul(p2.ls(xy2)));
90	(u1, v1, u2, v2)
91}
92
93fn rect_idxs((start, size): (u16, u16)) -> Box<[u16]> {
94	(start..(start + size)).step_by(4).flat_map(|i| [i, i + 1, i + 3, i + 3, i + 1, i + 2]).collect()
95}
96
97use super::*;