use std::rc::Rc;
use glam::{UVec2, Vec2, uvec2};
use glow::HasContext;
use crate::common::{TextureInterpolation, TextureWrapping};
use super::{
RawImage,
common::{upload_subtexture, upload_texture},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct Land {
pub pos: UVec2,
pub size: UVec2,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct LandUv {
pub pos: Vec2,
pub size: Vec2,
}
pub struct Texas {
gl: Rc<glow::Context>,
size: u32,
texture: glow::Texture,
curr_pos: UVec2,
curr_row_height: u32,
}
impl Texas {
pub fn new(gl: Rc<glow::Context>, size: u32, interpolation: TextureInterpolation) -> Self {
unsafe {
let texture = gl.create_texture().unwrap();
upload_texture(
&gl,
texture,
size,
size,
None,
TextureWrapping::ClampToBorder,
interpolation,
);
Self {
gl,
size,
texture,
curr_pos: UVec2::ZERO,
curr_row_height: 0,
}
}
}
pub fn alloc_land(&mut self, gl: &glow::Context, image: RawImage) -> Option<Land> {
if self.curr_pos.x + image.width > self.size {
self.curr_pos = uvec2(0, self.curr_pos.y + self.curr_row_height);
self.curr_row_height = 0;
}
if self.curr_pos.y + image.height > self.size {
return None;
}
let land = Land {
pos: self.curr_pos,
size: uvec2(image.width, image.height),
};
self.curr_pos.x += image.width;
self.curr_row_height = self.curr_row_height.max(image.height);
unsafe {
upload_subtexture(
gl,
self.texture,
land.pos.x,
land.pos.y,
land.size.x,
land.size.y,
Some(image.pixels),
);
}
Some(land)
}
pub fn clear_all(&mut self) {
self.curr_pos = UVec2::ZERO;
self.curr_row_height = 0;
}
pub fn uv_for_land(&self, land: Land) -> LandUv {
LandUv {
pos: land.pos.as_vec2() / self.size as f32,
size: land.size.as_vec2() / self.size as f32,
}
}
pub fn size(&self) -> u32 {
self.size
}
pub fn texture(&self) -> glow::Texture {
self.texture
}
}