use crate::render::batch::{VertexData, Target};
use crate::{Rect, Sprite, Program, Buffer, Vect};
use crate::math::rgba::{WHITE, RGBA};
use crate::math::angle::PI2;
pub enum LineMode {
Sharp,
Smooth(usize),
None
}
pub struct GeomDrawer {
data: VertexData,
program: Program,
buffer: Buffer,
offset: u32,
pub color: RGBA,
}
impl GeomDrawer {
#[inline]
pub fn new() -> Self {
Self {
offset: 0,
color: WHITE,
data: VertexData::no_texture(),
program: Program::no_texture(),
buffer: Buffer::no_texture(),
}
}
#[inline]
pub fn rect(&mut self, rect: Rect) {
self.add_rectangle(&rect.verts())
}
pub fn empty_rect(&mut self, rect: Rect, thickness: f32, mode: LineMode) {
let verts = rect.verts();
self.line(&[verts[0], verts[1], verts[2], verts[3], verts[0]], thickness, mode);
}
#[inline]
pub fn add_rectangle(&mut self, points: &[Vect; 4]) {
for p in points.iter() {
self.data.vertices.push(p.x);
self.data.vertices.push(p.y);
self.data.vertices.extend(&self.color);
}
for i in Sprite::PATTERN.iter() {
self.data.indices.push(*i + self.offset);
}
self.offset += 4;
}
pub fn line(&mut self, points: &[Vect], thickness: f32, mode: LineMode) {
if points.len() < 2 {
return
}
let mut prev0 = points[0];
let start_offset = prev0.to(points[1]).normal().norm() * thickness;
let mut prev1 = points[0];
let mut prev2 = points[0];
for i in 1..points.len() {
let curr = points[i];
let offset = prev0.to(curr).normal().norm() * thickness;
println!("{:?}", offset);
let verts = [
prev0 - offset,
curr - offset,
curr + offset,
prev0 + offset,
];
self.add_rectangle(&verts);
match mode {
LineMode::Sharp => {
self.add_rectangle(&[verts[0], verts[3], prev2, prev1]);
prev1 = verts[1];
prev2 = verts[2];
}
LineMode::Smooth(_) => {}
LineMode::None => {}
}
prev0 = curr;
}
if points[0] == prev0 { match mode {
LineMode::Sharp => self.add_rectangle(&[prev0 - start_offset, prev0 + start_offset, prev2, prev1]),
LineMode::Smooth(_) => {}
LineMode::None => {}
}}
}
pub fn polynomial(&mut self, position: Vect, thickness: f32, radius: f32, rotation: f32, sides: usize, mode: LineMode) {
let vec = Vect::rad(rotation, radius);
let mut points = Vec::with_capacity(sides);
for i in 0..sides {
points.push(position + vec.rot(PI2/sides as f32 * i as f32))
}
points.push(points[0]);
self.line(&points, thickness, mode);
}
#[inline]
pub fn point(&mut self ,pos: Vect) {
self.data.vertices.push(pos.x);
self.data.vertices.push(pos.y);
self.data.vertices.extend(&self.color);
self.offset += 1;
self.data.indices.push(self.offset);
}
#[inline]
pub fn clear(&mut self) {
self.data.clear();
self.offset = 0;
}
#[inline]
pub fn draw<T: Target>(&self, target: &mut T) {
target.append(&self.data.vertices, &self.data.indices, self.data.vertex_size, Some(&self.program), None, Some(&self.buffer));
}
}