1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
use super::obj::*; use super::sprite::{gui__pos_col_tex_vs, sampler}; use super::sprite9::{sprite9_idxs, write_sprite9}; use crate::uses::{math::*, *}; use crate::GL::{shader::*, window::*, VTex2d, VaoBinding, RGBA}; pub struct Frame9<'a> { pub pos: Vec2, pub size: Vec2, pub corner: f32, pub color: Color, pub theme: &'a VTex2d<RGBA, u8>, } impl<'a> Frame9<'a> { #[inline(always)] pub fn compare(&self, crop: &Crop, r: &Frame9Impl) -> State { let &Self { pos, size, corner, color, theme } = self; let xyzw = (State::XYZW | State::UV).or_def(geom_cmp(pos, size, crop, &r.base) || corner != r.corner); let rgba = State::RGBA.or_def(color != r.base.color); let tex = State::UV.or_def(!ptr::eq(theme, r.tex)); let ord = State::MISMATCH.or_def(!tex.is_empty() && atlas_cmp(theme, r.tex)); ord | xyzw | rgba | tex } pub fn obj(self, crop: Crop) -> Frame9Impl { let Self { pos, size, corner, color, theme } = self; Frame9Impl { base: Base { pos, size, crop, color }, corner, tex: theme, } } } pub struct Frame9Impl { base: Base, corner: f32, tex: *const VTex2d<RGBA, u8>, } impl Frame9Impl { pub fn batchable(&self, r: &Self) -> bool { self.tex == r.tex } } impl Object for Frame9Impl { fn base(&self) -> &Base { &self.base } fn write_mesh(&self, range: BatchRange) { let (crop, &Base { pos, size, color, .. }) = (self.base.bound_box(), self.base()); let c = size.x().min(size.y()) * self.corner.min(0.5).max(0.); write_sprite9((Window::aspect(), pos, size, (c, c), crop, (0., 0., 1., 1.), color), range); } fn batch_draw(&self, b: &VaoBinding<u16>, (offset, num): (u16, u16)) { let s = UnsafeOnce!(Shader, { EXPECT!(Shader::new((gui__pos_col_tex_vs, gui__frame_ps))) }); let tex = unsafe { &*self.tex }; let t = tex.tex.Bind(sampler()); let (x, y, w, _) = tex.region; let _ = Uniforms!(s, ("src", &t), ("theme_coords", (x, y, w - x))); b.Draw((num, offset, gl::TRIANGLES)); } fn vert_count(&self) -> u32 { 16 } fn gen_idxs(&self, (start, size): (u16, u16)) -> Vec<u16> { sprite9_idxs((start, size)) } } SHADER!( gui__frame_ps, r"#version 330 core in vec4 glColor; in vec2 glTexCoord; layout(location = 0)out vec4 glFragColor; uniform sampler2D src; uniform vec3 theme_coords; void main() { float d = min(0.9, length(glTexCoord)); vec4 c = texture(src, theme_coords.xy + vec2(d * theme_coords.z, 0.)); glFragColor = glColor * c; }" );