use crate::ecs::registry::Registry;
use crate::render::{
camera::Camera,
utils::{init_buffers, init_texture},
};
use crate::rlua::{UserData, UserDataMethods};
use crate::{
math::{
projection_type::ProjectionType,
transform::{self, Transform},
},
render::{
shader::{self, ShaderValue},
shape::{
buffers::{self, Buffers},
shape_vertices::ShapeVertices,
vertices::{DrawType, Vertex},
},
texture_2d::{self, TextureFilter},
utils,
},
};
use std::sync::{Arc, Mutex};
#[derive(Clone)]
pub struct Renderer2D {
registry: Arc<Mutex<Registry>>,
vertices: Vec<Vertex>,
buffers: Buffers,
shader_id: u32,
}
#[derive(Clone, Copy, Debug)]
pub struct TextureID(u32);
const Z_NEAR: f32 = 0.1;
const Z_FAR: f32 = 100.0;
const FOV: f32 = 45.0;
const ORTHO_DISTANCE: f32 = 1.75;
pub fn generate_sprite_2d_buffers(vertices: &mut Vec<Vertex>) -> Buffers {
let buffers = unsafe { buffers::generate_buffers() };
unsafe {
init_buffers(&buffers, vertices);
}
return buffers;
}
pub fn generate_sprite_2d_vertices() -> Vec<Vertex> {
return ShapeVertices::Rectangle(glm::vec2(0.5, 0.5), glm::vec2(-0.5, -0.5)).value();
}
impl UserData for Renderer2D {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_method_mut(
"add_sprite",
|_,
renderer,
(entity_id, pos_x, pos_y, scale_x, scale_y, texture_id): (
usize,
f32,
f32,
f32,
f32,
u32,
)| {
renderer.add_sprite(
entity_id,
glm::vec3(pos_x, pos_y, 0.0),
glm::vec3(scale_x, scale_y, 0.0),
texture_id,
);
Ok(())
},
);
methods.add_method_mut(
"set_sprite_position",
|_, renderer, (entity_id, pos_x, pos_y): (usize, f32, f32)| {
renderer.set_sprite_position(entity_id, glm::vec3(pos_x, pos_y, 0.0));
Ok(())
},
);
methods.add_method_mut(
"set_camera_position",
|_, renderer, (entity_id, pos_x, pos_y): (usize, f32, f32)| {
renderer.set_camera_position(entity_id, glm::vec3(pos_x, pos_y, 0.0));
Ok(())
},
);
}
}
impl Renderer2D {
pub fn new(
registry: Arc<Mutex<Registry>>,
buffers: Buffers,
vertices: Vec<Vertex>,
shader_id: u32,
) -> Self {
Self {
registry: registry,
buffers: buffers,
vertices: vertices,
shader_id: shader_id,
}
}
pub fn add_texture(image: &str) -> u32 {
let texture_id = unsafe { texture_2d::generate_texture_id(TextureFilter::Pixelated) };
unsafe {
init_texture(texture_id, image, false);
}
return texture_id;
}
pub fn add_sprite(
&mut self,
entity_id: usize,
position: glm::Vec3,
scale: glm::Vec3,
texture_id: u32,
) {
let mut transform = transform::create_transform_by_position(position);
transform.scale = scale;
let mut registry = self.registry.lock().unwrap();
registry.add_component(entity_id, TextureID { 0: texture_id });
registry.add_component(entity_id, transform);
}
pub fn set_sprite_position(&mut self, entity_id: usize, position: glm::Vec3) {
self.registry
.lock()
.unwrap()
.get_component::<Transform>(entity_id)
.unwrap()
.borrow_mut()
.lock()
.unwrap()
.position = position;
}
pub fn set_camera_position(&mut self, entity_id: usize, position: glm::Vec3) {
let cam_pos_z = self
.registry
.lock()
.unwrap()
.get_component::<Camera>(entity_id)
.unwrap()
.borrow_mut()
.lock()
.unwrap()
.get_position_z();
self.registry
.lock()
.unwrap()
.get_component::<Camera>(entity_id)
.unwrap()
.borrow_mut()
.lock()
.unwrap()
.set_position(glm::vec3(position.x, position.y, cam_pos_z));
}
pub fn render(&self, screen_size: glm::Vec2, view: &glm::Mat4) {
let mut registry = self.registry.lock().unwrap();
let shape_entities;
match registry.get_view::<TextureID>() {
Some(entities) => shape_entities = entities,
None => return,
}
unsafe {
shader::use_program(self.shader_id);
}
for entity_id in shape_entities {
unsafe {
texture_2d::bind(
registry
.get_component::<TextureID>(entity_id)
.unwrap()
.borrow_mut()
.lock()
.unwrap()
.0,
);
shader::set_value(
self.shader_id,
"translation",
ShaderValue::Mat4(transform::translate(
®istry
.get_component::<Transform>(entity_id)
.unwrap()
.borrow_mut()
.lock()
.unwrap(),
Z_NEAR,
Z_FAR,
FOV,
*view,
glm::vec2(screen_size.x, screen_size.y),
ORTHO_DISTANCE,
ProjectionType::Orthographic,
)),
);
buffers::bind_vao(self.buffers.vao);
utils::draw_arrays(DrawType::Triangles, self.vertices.len() as i32);
}
}
}
pub fn delete_all_sprites(&mut self) {
let shape_entities = self
.registry
.lock()
.unwrap()
.get_view::<TextureID>()
.unwrap();
unsafe {
buffers::delete_buffers(&mut self.buffers);
}
for entity_id in shape_entities {
unsafe {
texture_2d::delete_texture(
&mut self
.registry
.lock()
.unwrap()
.get_component::<TextureID>(entity_id)
.unwrap()
.borrow_mut()
.lock()
.unwrap()
.0,
);
}
}
}
}