1extern crate tea;
2
3use tea::{GlUniform, GlBind};
4use tea::texture::{Texture2D, GlTexture};
5use crate::{Mat4, Vec4, Vec3, Rect};
6
7use tea::buffer::{GlBuffer, BufferUsage};
8use tea::target::{Framebuffer, FramebufferAttachment};
9
10pub use tea::texture::{TexTarget, TexFilter, TexWrap, TexParam, PixelFormat, PixelDataType};
11
12#[allow(non_snake_case)]
13pub mod render2D;
14#[allow(non_snake_case)]
15pub mod render3D;
16
17#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
18pub struct Color(u8, u8, u8, u8);
19
20impl Color {
21 pub fn rgb(r: u8, g: u8, b: u8) -> Color { Color(r, g, b, 255) }
22 pub fn rgba(r: u8, g: u8, b: u8, a: u8) -> Color { Color(r, g, b, a) }
23
24 pub fn black() -> Self { Self::rgb(0, 0, 0) }
25 pub fn white() -> Self { Self::rgb(255, 255, 255) }
26
27 pub fn to_vec4(&self) -> Vec4 {
28 let r = self.0 as f32 / 255.0;
29 let g = self.1 as f32 / 255.0;
30 let b = self.2 as f32 / 255.0;
31 let a = self.3 as f32 / 255.0;
32 Vec4::new(r, g, b, a)
33 }
34}
35
36pub enum Movement {
37 Left,
38 Right,
39 Up,
40 Down,
41 Forward,
42 Backward,
43}
44
45pub trait Camera {
46 fn position(&self) -> &Vec3;
47 fn set_position(&mut self, position: Vec3);
48
49 fn set_width(&mut self, width: f32);
50 fn set_height(&mut self, height: f32);
51 fn set_size(&mut self, width: f32, height: f32) { self.set_width(width); self.set_height(height); }
52 fn projection(&self) -> Mat4;
53 fn view(&self) -> Mat4;
54
55 fn move_camera(&mut self, dir: Movement, dt: f32);
56}
57
58pub trait Drawable {
59 fn get_handle(&self) -> &Texture2D;
60 fn get_width(&self) -> i32;
61 fn get_height(&self) -> i32;
62 fn flip_y(&self) -> bool { false }
63}
64
65pub trait Batch {
66 type DataType;
67 fn clear(&mut self);
68 fn capacity(&self) -> usize;
69 fn len(&self) -> usize;
70 fn grow(&mut self);
71 fn push(&mut self, value: Self::DataType);
72 fn push_vec(&mut self, values: Vec<Self::DataType>);
73 fn flush(&self);
74 fn flush_part(&self, offset: isize, size: usize);
75}
76
77#[derive(Default, Debug, PartialEq, Eq)]
78pub struct Image {
79 texture: Texture2D,
80 width: i32, height: i32,
81 filter: (TexFilter, TexFilter),
82 wrap: (TexWrap, TexWrap)
83}
84
85#[derive(Default, Debug, PartialEq, Eq)]
86pub struct Canvas {
87 framebuffer: Framebuffer,
88 texture: Texture2D,
89 width: i32, height: i32,
90 filter: (TexFilter, TexFilter),
91 wrap: (TexWrap, TexWrap),
92}
93
94#[derive(Default, Debug)]
95pub struct Buffer<K: GlBuffer, T> {
96 handle: K,
97 data: Vec<T>
98}
99
100impl<K: GlBuffer, T> PartialEq for Buffer<K, T> {
101 fn eq(&self, other: &Self) -> bool { self.handle.get_id() == other.handle.get_id() }
102}
103
104impl<K: GlBuffer, T> Batch for Buffer<K, T> {
105 type DataType = T;
106 fn clear(&mut self) { self.data.clear() }
107 fn capacity(&self) -> usize { self.data.capacity() }
108 fn len(&self) -> usize { self.data.len() }
109 fn push(&mut self, value: T) {
110 self.data.push(value);
111 }
112
113 fn push_vec(&mut self, values: Vec<T>) {
114 self.data.extend(values);
115 }
116
117 fn grow(&mut self) {
118 let count = self.data.capacity();
119 let v: Vec<T> = Vec::with_capacity(count);
120 let len = self.data.len();
121 self.data.extend(v);
122 unsafe { self.data.set_len(len); }
123 self.handle.bind();
124 self.handle.data(&self.data, BufferUsage::DynamicDraw);
125 }
126
127 fn flush(&self) {
128 self.handle.bind();
129 self.handle.subdata(0, self.data.len(), &self.data);
130 self.handle.unbind();
131 }
132
133 fn flush_part(&self, offset: isize, count: usize) {
134 self.handle.bind();
135 self.handle.subdata(offset, count, &self.data);
136 self.handle.unbind();
137 }
138}
139
140#[cfg(target="")]
141#[derive(Default, Debug)]
142pub struct VertexBuffer<T> {
143 handle: ArrayBuffer,
144 data: Vec<T>
145}
146
147impl Image {
148 fn new(width: i32, height: i32, format: PixelFormat, data: Vec<u8>) -> Result<Self, String> {
149 let texture = Texture2D::new().unwrap();
150 texture.bind();
151 texture.data(0, format, (width, height), PixelDataType::UByte, data);
152 texture.set_min_filter(TexFilter::default());
153 texture.set_mag_filter(TexFilter::default());
154 texture.unbind();
155 Ok(Image{
156 texture,
157 width, height,
158 ..Default::default()
159 })
160 }
161
162 pub fn load(filename: &str) -> Result<Self, String> {
163 let res = stb_image::image::load(filename);
164 match res {
165 stb_image::image::LoadResult::Error(s) => {
166 let err = format!("Failed to load image: {filename}: {s}");
167 return Err(err)
168 },
169 stb_image::image::LoadResult::ImageU8(i) => {
170 let format: PixelFormat;
171 match i.depth {
172 3 => { format = PixelFormat::RGB },
173 4 => { format = PixelFormat::RGBA },
174 _ => { format = PixelFormat::RGBA }
175 }
176 return Image::new(i.width as i32, i.height as i32, format, i.data);
177 },
178 _ => {}
179 }
180 Ok(Image::default())
181 }
182
183 pub fn pixel_art(&self) {
184 self.texture.bind();
185 self.texture.set_min_filter(TexFilter::Nearest);
186 self.texture.set_mag_filter(TexFilter::Nearest);
187 self.texture.unbind();
188 }
189
190 pub fn pixel(&self, x: i32, y: i32) -> Color {
191 Color::rgb(255, 255, 255)
192 }
193}
194
195impl Drawable for Image {
196 fn get_handle(&self) -> &Texture2D { &self.texture }
197 fn get_width(&self) -> i32 { self.width }
198 fn get_height(&self) -> i32 { self.height }
199}
200
201impl Canvas {
202 pub fn new(width: i32, height: i32) -> Result<Self, String> {
203 let framebuffer = Framebuffer::new().unwrap();
204 let texture = Texture2D::new().unwrap();
205 texture.bind();
206 texture.data(0, PixelFormat::RGBA, (width, height), PixelDataType::UByte, vec![]);
207 texture.set_min_filter(TexFilter::Linear);
208 texture.set_mag_filter(TexFilter::Linear);
209 texture.unbind();
210 framebuffer.bind();
211 framebuffer.attach_texture(FramebufferAttachment::ColorAttachment(0), &texture);
212 framebuffer.unbind();
213 Ok(Canvas{
214 framebuffer,
215 texture,
216 width,
217 height,
218 ..Default::default()
219 })
220 }
221
222 pub fn pixel_art(&self) {
223 self.texture.bind();
224 self.texture.set_min_filter(TexFilter::Nearest);
225 self.texture.set_mag_filter(TexFilter::Nearest);
226 self.texture.unbind();
227 }
228}
229
230impl Drawable for Canvas {
231 fn get_handle(&self) -> &Texture2D { &self.texture }
232 fn get_width(&self) -> i32 { self.width }
233 fn get_height(&self) -> i32 { self.height }
234 fn flip_y(&self) -> bool { true }
235}
236
237#[allow(dead_code)]
238#[derive(Default, Debug, PartialEq)]
239pub struct Font {
240 texture: Texture2D,
241 rect: Vec<Rect>,
242 size: u16
243}
244
245impl Font {
246 pub fn load(filename: &str) -> Result<Self, String> {
247 Ok(Font::default())
248 }
249}
250
251pub trait Effect {
252 fn send_uniform<T: GlUniform>(&self, name: &str, value: T);
253}
254
255pub trait Render {
256 type Effect: Effect;
257 fn new() -> Self;
258
259 fn clear_color(&self, color: Vec4) { tea::clear_color(color.x, color.y, color.z, color.w); }
260 fn clear(&self) { tea::clear(&[tea::ClearFlags::ColorBufferBit]) }
261
262 fn begin(&mut self);
263 fn end(&self);
264
265 fn camera(&mut self) -> &mut dyn Camera;
266
267 fn set_canvas(&mut self, canvas: Option<&Canvas>);
268 fn set_effect(&mut self, effect: Option<&Self::Effect>);
269
270 fn on_resize(&mut self, width: i32, height: i32);
271}