1extern crate tea;
2extern crate stb_image;
3
4use crate::render::{Image, Canvas, Drawable, Batch, Buffer, Movement};
5
6use tea::vertex::{VertexArray, VertexData, VertexFormatBuilder, VertexFormat};
7use tea::{glsl::*, EnableFlags};
8use tea::texture::{Texture2D, PixelFormat, Sampler2D};
9use tea::target::Framebuffer;
10use tea::impl_vertexdata;
11use tea::vec::*;
12use tea::{GlBind, GlUniform, GlObject, GlTarget, GlUse, DrawMode, BlendFunc};
13use tea::buffer::{ArrayBuffer, ElementArrayBuffer, GlBuffer, BufferUsage};
14use crate::render::{Effect, Render, Camera};
15use crate::{Rect, Color};
16
17
18impl_vertexdata!(Vertex2D, Vec2, Vec4, Vec2);
19
20type Index = (i32, i32, i32, i32, i32, i32);
21
22pub type VertexBuffer = Buffer<ArrayBuffer, Vertex2D>;
23pub type IndexBuffer = Buffer<ElementArrayBuffer, Index>;
24
25impl VertexBuffer {
26 pub fn new(size: usize) -> Result<Self, String> {
27 let handle = ArrayBuffer::new();
28 let data: Vec<Vertex2D> = Vec::with_capacity(size);
29 handle.bind();
30 handle.data(&data, BufferUsage::DynamicDraw);
31 handle.unbind();
32 Ok(Self {
33 handle,
34 data
35 })
36 }
37}
38
39impl IndexBuffer {
40 pub fn new(size: usize) -> Result<Self, String> {
41 let handle = ElementArrayBuffer::new();
42 let mut data: Vec<Index> = Vec::with_capacity(size);
43 for i in 0..(size as i32) {
44 let index = (i, i+1, i+2, i+3, i+1, i);
45 data.push(index);
46 }
47 handle.bind();
48 handle.data(&data, BufferUsage::StaticDraw);
49 handle.unbind();
50 Ok(Self {
51 handle,
52 data
53 })
54 }
55}
56
57#[derive(Default, Debug, PartialEq, Copy, Clone)]
58pub struct Camera2D {
59 position: Vec3,
60 right: Vec3,
61 width: f32, height: f32,
62 near: f32, far: f32,
63 move_speed: f32,
64
65 zoom: f32
66}
67
68impl Camera for Camera2D {
69 fn position(&self) -> &Vec3 { &self.position }
70 fn set_position(&mut self, position: Vec3) { self.position = position; }
71
72 fn set_width(&mut self, width: f32) { self.width = width; }
73 fn set_height(&mut self, height: f32) { self.height = height; }
74
75 fn projection(&self) -> Mat4 {
76 Mat4::ortho(0.0, self.width, self.height, 0.0, self.near, self.far)
77 }
78
79 fn view(&self) -> Mat4 {
80 Mat4::identity()
81 }
82
83 fn move_camera(&mut self, dir: Movement, dt: f32) {
84 let velocity = self.move_speed * dt;
85 match dir {
86 Movement::Right => { self.position += self.right.scalar(velocity); },
87 Movement::Left => { self.position -= self.right.scalar(velocity); },
88 _ => {}
89 }
90 }
91}
92
93impl Camera2D {
94 pub fn new(width: f32, height: f32) -> Self {
95 let position = Vec3::zero();
96 let right = Vec3::new(1.0, 0.0, 0.0);
97 let near = -0.1;
98 let far = 0.1;
99 let move_speed = 60.0;
100 let zoom = 1.0;
101
102 Self {
103 position,
104 right,
105 width, height,
106 near, far,
107 move_speed,
108 zoom
109 }
110 }
111}
112
113pub type ImageFormat = PixelFormat;
114
115#[derive(Default, Debug, PartialEq)]
116pub struct Effect2D {
117 program: Program,
118 projection: i32,
119 modelview: i32
120}
121
122impl Effect2D {
123 pub fn new(position: Option<String>, pixel: Option<String>) -> Result<Effect2D, String> {
124 let mut pos: Option<String> = position.clone();
125 let mut pix: Option<String> = pixel.clone();
126 if position == None {
127 pos = Some("vec4 position(vec2 pos, mat4 mvp) {
128 return mvp * vec4(pos, 0.0, 1.0);
129 // return projection * modelview * vec4(pos, 0.0, 1.0);
130 }".to_string());
131 }
132 if pixel == None {
133 pix = Some("vec4 pixel(vec4 color, vec2 texcoord, sampler2D text) {
134 return color * texture(text, texcoord);
135 }".to_string());
136 }
137
138 let vertex = ShaderBuilder::new()
139 .add_input::<Vec2>("a_Position")
140 .add_input::<Vec4>("a_Color")
141 .add_input::<Vec2>("a_Texcoord")
142 .add_output::<Vec4>("v_Color")
143 .add_output::<Vec2>("v_Texcoord")
144 .add_uniform::<Mat4>("u_MVP")
145 .push_pre_main(pos.unwrap().as_str())
146 .set_main("void main() {
147 gl_Position = position(a_Position, u_MVP);
148 v_Color = a_Color;
149 v_Texcoord = a_Texcoord;
150 }")
151 .build(ShaderType::VertexShader)
152 .unwrap();
153
154 let fragment = ShaderBuilder::new()
155 .add_input::<Vec4>("v_Color")
156 .add_input::<Vec2>("v_Texcoord")
157 .add_uniform::<Sampler2D>("u_Texture")
158 .push_pre_main(pix.unwrap().as_str())
159 .set_main("void main() {
160 gl_FragColor = pixel(v_Color, v_Texcoord, u_Texture);
161 }")
162 .build(ShaderType::FragmentShader)
163 .unwrap();
164
165 let program = Program::new().unwrap();
166 program.attach_shader(&vertex);
167 program.attach_shader(&fragment);
168 program.link().expect("Failed to link program");
169
170 let projection = program.get_uniform_location("u_Projection");
171 let modelview = program.get_uniform_location("u_Modelview");
172 Ok(Effect2D {
174 program,
175 projection,
176 modelview
177 })
178 }
179}
180
181impl Effect for Effect2D {
182 fn send_uniform<T: GlUniform>(&self, name: &str, value: T) {
183 let location = self.program.get_uniform_location(name);
184 self.program.send_uniform(location, value);
185 }
186}
187
188#[derive(Default, Debug, PartialEq)]
189pub struct SpriteBatch {
190 vbo: VertexBuffer,
191 ibo: IndexBuffer,
192}
193
194#[derive(Default, Debug)]
195pub struct Render2D {
196 vao: VertexArray,
197 batch: SpriteBatch,
198 default_effect: Effect2D,
199 white_image: Image,
200 default_canvas: Canvas,
201
202 draw_mode: DrawMode,
203
204 clear_color: Color,
205 draw_color: Color,
206
207 camera: Camera2D,
208}
209
210impl Render2D {
211 pub fn clear_batch(&mut self) {
212 self.batch.clear();
213 }
214
215 pub fn set_clear_color(&mut self, color: Color) {
216 let v = color.to_vec4();
217 self.clear_color = color;
218 tea::clear_color(v.x, v.y, v.z, v.w);
219 }
220
221 pub fn set_draw_color(&mut self, color: Color) {
222 let v = color.to_vec4();
223 self.draw_color = color;
224 tea::clear_color(v.x, v.y, v.z, v.w);
225 }
226
227 pub fn clear_color(&self) -> Color { self.clear_color }
228 pub fn draw_color(&self) -> Color { self.draw_color }
229
230 fn set_draw_mode(&mut self, mode: DrawMode) {
231 if self.draw_mode != mode {
232 self.draw_and_clean();
233 self.draw_mode = mode;
234 }
235 }
236
237 fn set_image(&mut self, image: Option<&Image>) {
238 let i: &Image;
239 if image == None { i = &self.white_image; }
240 else { i = image.unwrap(); }
241 if Texture2D::current_bind() == i.texture.get_id() { return }
242 self.draw();
243 self.batch.clear();
244 i.texture.bind();
245 }
246
247 pub fn hello_triangle(&mut self) {
248 self.set_image(None);
249 self.set_draw_mode(DrawMode::Triangles);
250 let mut data: Vec<Vertex2D> = vec![];
251 data.push(Vertex2D::new(Vec2::new(128.0, 64.0), Vec4::new(1.0, 0.0, 0.0, 1.0), Vec2::new(0.0, 0.0)));
252 data.push(Vertex2D::new(Vec2::new(64.0, 128.0), Vec4::new(0.0, 1.0, 0.0, 1.0), Vec2::new(0.0, 0.0)));
253 data.push(Vertex2D::new(Vec2::new(196.0, 128.0), Vec4::new(0.0, 0.0, 1.0, 1.0), Vec2::new(0.0, 0.0)));
254 self.batch.push_vec(data);
255 }
256
257 pub fn blit(&mut self, draw: &impl Drawable, src: Option<&Rect>, x: f32, y: f32) {
258 self.set_draw_mode(DrawMode::Triangles);
259 let texture = draw.get_handle();
260 if Texture2D::current_bind() != texture.get_id() {
261 self.draw_and_clean();
262 texture.bind();
263 }
264 let mut rect = Rect::new(x, y, draw.get_width() as f32, draw.get_height() as f32);
265 let mut uv: Vec4 = Vec4::new(0.0, 0.0, 1.0, 1.0);
266 if src != None {
267 let rr = src.unwrap();
268 let width = draw.get_width() as f32;
269 let height = draw.get_height() as f32;
270 uv.x = rr.x / width;
271 uv.y = rr.y / height;
272 uv.z = (rr.x + rr.w) / width;
273 uv.w = (rr.y + rr.h) / height;
274
275 rect.w = rr.w;
276 rect.h = rr.h;
277 }
278
279 if draw.flip_y() {
280 uv.y = 1.0 - uv.y;
281 uv.w = 1.0 - uv.w;
282 }
286
287 self.batch.add_quad(
288 Vec4::new(rect.x, rect.y, uv.x, uv.y),
289 Vec4::new(rect.x+rect.w, rect.y, uv.z, uv.y),
290 Vec4::new(rect.x+rect.w, rect.y+rect.h, uv.z, uv.w),
291 Vec4::new(rect.x, rect.y+rect.h, uv.x, uv.w),
292 );
293 }
294
295 pub fn blit_scale(&mut self, draw: &impl Drawable, src: Option<&Rect>, x: f32, y: f32, sx: f32, sy: f32) {
296 self.set_draw_mode(DrawMode::Triangles);
297 let texture = draw.get_handle();
298 if Texture2D::current_bind() != texture.get_id() {
299 self.draw_and_clean();
300 texture.bind();
301 }
302 let mut rect = Rect::new(x, y, draw.get_width() as f32, draw.get_height() as f32);
303 let mut uv = Vec4::new(0.0, 0.0, 1.0, 1.0);
304 if src != None {
305 let rr = src.unwrap();
306 let width = draw.get_width() as f32;
307 let height = draw.get_height() as f32;
308 uv.x = rr.x / width;
309 uv.y = rr.y / height;
310 uv.z = (rr.x + rr.w) / width;
311 uv.w = (rr.y + rr.h) / height;
312
313 rect.w = rr.w;
314 rect.h = rr.h;
315 }
316
317 if draw.flip_y() {
318 uv.y = 1.0 - uv.y;
319 uv.w = 1.0 - uv.w;
320 }
321 let width = rect.w * sx;
322 let height = rect.h * sy;
323 self.batch.add_quad(
324 Vec4::new(rect.x, rect.y, uv.x, uv.y),
325 Vec4::new(rect.x+width, rect.y, uv.z, uv.y),
326 Vec4::new(rect.x+width, rect.y+height, uv.z, uv.w),
327 Vec4::new(rect.x, rect.y+height, uv.x, uv.w),
328 );
329 }
330
331 pub fn blit_rotate(&mut self, draw: &impl Drawable, src: Option<&Rect>, x: f32, y: f32, angle: f32) {
332 self.set_draw_mode(DrawMode::Triangles);
333 let texture = draw.get_handle();
334 if Texture2D::current_bind() != texture.get_id() {
335 self.draw_and_clean();
336 texture.bind();
337 }
338 let mut rect = Rect::new(x, y, draw.get_width() as f32, draw.get_height() as f32);
339 let mut uv = Vec4::new(0.0, 0.0, 1.0, 1.0);
340 if src != None {
341 let rr = src.unwrap();
342 let width = draw.get_width() as f32;
343 let height = draw.get_height() as f32;
344 uv.x = rr.x / width;
345 uv.y = rr.y / height;
346 uv.z = (rr.x + rr.w) / width;
347 uv.w = (rr.y + rr.h) / height;
348
349 rect.w = rr.w;
350 rect.h = rr.h;
351 }
352
353 if draw.flip_y() {
354 uv.y = 1.0 - uv.y;
355 uv.w = 1.0 - uv.w;
356 }
357 let width = rect.w;
358 let height = rect.h;
359 let mut data: [Vec4; 4] = [
360 Vec4::new(rect.x, rect.y, 0.0, 1.0),
361 Vec4::new(rect.x+width, rect.y, 0.0, 1.0),
362 Vec4::new(rect.x+width, rect.y+height, 0.0, 1.0),
363 Vec4::new(rect.x, rect.y+height, 0.0, 1.0),
364 ];
365 let mut m = Mat4::identity();
378 m.translate(Vec3::new(-x, -y, 0.0));
379 m.rotate(angle);
380 m.translate(Vec3::new(x, y, 0.0));
381 for d in &mut data {
383 d.apply_matrix(m);
384 }
385 data[0].z = uv.x;
386 data[0].w = uv.y;
387
388 data[1].z = uv.z;
389 data[1].w = uv.y;
390
391 data[2].z = uv.z;
392 data[2].w = uv.w;
393
394 data[3].z = uv.x;
395 data[3].w = uv.w;
396
397 self.batch.add_quad(
398 data[0], data[1], data[2], data[3],
399 );
400 }
401
402 pub fn blit_ex(&mut self, draw: &impl Drawable, src: Option<&Rect>, x: f32, y: f32, angle: f32, sx: f32, sy: f32) {
403 self.set_draw_mode(DrawMode::Triangles);
404 let texture = draw.get_handle();
405 if Texture2D::current_bind() != texture.get_id() {
406 self.draw_and_clean();
407 texture.bind();
408 }
409 let mut rect = Rect::new(x, y, draw.get_width() as f32, draw.get_height() as f32);
410 let mut uv = Vec4::new(0.0, 0.0, 1.0, 1.0);
411 if src != None {
412 let rr = src.unwrap();
413 let width = draw.get_width() as f32;
414 let height = draw.get_height() as f32;
415 uv.x = rr.x / width;
416 uv.y = rr.y / height;
417 uv.z = (rr.x + rr.w) / width;
418 uv.w = (rr.y + rr.h) / height;
419
420 rect.w = rr.w;
421 rect.h = rr.h;
422 }
423
424 if draw.flip_y() {
425 uv.y = 1.0 - uv.y;
426 uv.w = 1.0 - uv.w;
427 }
428 let width = rect.w;
429 let height = rect.h;
430 let mut data: [Vec4; 4] = [
431 Vec4::new(rect.x, rect.y, 0.0, 1.0),
432 Vec4::new(rect.x+width, rect.y, 0.0, 1.0),
433 Vec4::new(rect.x+width, rect.y+height, 0.0, 1.0),
434 Vec4::new(rect.x, rect.y+height, 0.0, 1.0),
435 ];
436
437 let mut m = Mat4::identity();
438 m.translate(Vec3::new(-x, -y, 0.0));
439 m.rotate(angle);
440 m.translate(Vec3::new(x, y, 0.0));
441 m.scale(Vec3::new(sx, sy, 1.0));
442 for d in &mut data {
444 d.apply_matrix(m);
445 }
446 data[0].z = uv.x;
447 data[0].w = uv.y;
448
449 data[1].z = uv.z;
450 data[1].w = uv.y;
451
452 data[2].z = uv.z;
453 data[2].w = uv.w;
454
455 data[3].z = uv.x;
456 data[3].w = uv.w;
457
458 self.batch.add_quad(
459 data[0], data[1], data[2], data[3],
460 );
461 }
462
463 pub fn draw_triangle(&mut self, p0: Vec2, p1: Vec2, p2: Vec2) {
464 self.set_draw_mode(DrawMode::Lines);
465 self.set_image(None);
466 self.batch.push(Vertex2D::from_position(p0.x, p0.y));
467 self.batch.push(Vertex2D::from_position(p1.x, p1.y));
468
469 self.batch.push(Vertex2D::from_position(p1.x, p1.y));
470 self.batch.push(Vertex2D::from_position(p2.x, p2.y));
471
472 self.batch.push(Vertex2D::from_position(p2.x, p2.y));
473 self.batch.push(Vertex2D::from_position(p0.x, p0.y));
474 }
475
476 pub fn fill_triangle(&mut self, p0: Vec2, p1: Vec2, p2: Vec2) {
477 self.set_draw_mode(DrawMode::Triangles);
478 self.set_image(None);
479
480 let mut data: Vec<Vertex2D> = vec![];
481
482 data.push(Vertex2D::from_position(p0.x, p0.y));
483 data.push(Vertex2D::from_position(p1.x, p1.y));
484 data.push(Vertex2D::from_position(p2.x, p2.y));
485
486 self.batch.push_vec(data);
487 }
488
489 pub fn fill_rect(&mut self, rect: &Rect) {
490 self.set_draw_mode(DrawMode::Triangles);
491 self.set_image(None);
492 self.batch.add_rect(rect);
493 }
494
495 pub fn draw_rect(&mut self, rect: &Rect) {
496 self.set_draw_mode(DrawMode::Lines);
497 self.set_image(None);
498 let mut data: Vec<Vertex2D> = vec![];
499 data.push(Vertex2D::from_position(rect.x, rect.y));
500 data.push(Vertex2D::from_position(rect.x+rect.w, rect.y));
501
502 data.push(Vertex2D::from_position(rect.x+rect.w, rect.y));
503 data.push(Vertex2D::from_position(rect.x+rect.w, rect.y+rect.h));
504
505 data.push(Vertex2D::from_position(rect.x, rect.y+rect.h));
506 data.push(Vertex2D::from_position(rect.x+rect.w, rect.y+rect.h));
507
508 data.push(Vertex2D::from_position(rect.x, rect.y));
509 data.push(Vertex2D::from_position(rect.x, rect.y+rect.h));
510
511 self.batch.push_vec(data);
512 }
513
514 pub fn draw_circle(&mut self, cx: f32, cy: f32, radius: f32) {
515 self.set_draw_mode(DrawMode::Lines);
516 self.set_image(None);
517 let sides = 32;
518 let p0 = Vec2::new(cx, cy);
519 let pi2 = std::f32::consts::PI * 2.0;
520 let mut data: Vec<Vertex2D> = vec![];
521 for i in 0..sides {
522 let tetha = (i as f32 * pi2) / sides as f32;
523 let tetha2 = ((i + 1) as f32 * pi2) / sides as f32;
524 let p1 = p0 + Vec2::new(tetha.cos() * radius, tetha.sin() * radius);
525 let p2 = p0 + Vec2::new(tetha2.cos() * radius, tetha2.sin() * radius);
526 data.push(Vertex2D::from_position(p1.x, p1.y));
527 data.push(Vertex2D::from_position(p2.x, p2.y));
528 }
529 self.batch.push_vec(data);
530 }
531
532 pub fn fill_circle(&mut self, cx: f32, cy: f32, radius: f32) {
533 self.set_draw_mode(DrawMode::Triangles);
534 self.set_image(None);
535 let sides = 32;
536 let pi2 = std::f32::consts::PI * 2.0;
537 let p0 = Vec2::new(cx, cy);
538 let mut data: Vec<Vertex2D> = vec![];
539 for i in 0..sides {
540 let tetha = (i as f32 * pi2) / sides as f32;
541 let tetha2 = ((i + 1) as f32 * pi2) / sides as f32;
542 let p1 = p0 + Vec2::new(tetha.cos() * radius, tetha.sin() * radius);
543 let p2 = p0 + Vec2::new(tetha2.cos() * radius, tetha2.sin() * radius);
544 data.push(Vertex2D::from_position(p0.x, p0.y));
545 data.push(Vertex2D::from_position(p1.x, p1.y));
546 data.push(Vertex2D::from_position(p2.x, p2.y));
547 }
548 self.batch.push_vec(data);
549 }
550
551 fn draw(&self) {
552 if self.batch.count() <= 0 { return }
553 self.batch.flush();
554 self.vao.bind();
555 tea::draw_arrays(self.draw_mode, 0, self.batch.count() as i32);
556 self.vao.unbind();
557 }
558
559 fn draw_and_clean(&mut self) {
560 let mvp = self.camera().view() * self.camera.projection();
561 mvp.send_uniform(0);
562 self.draw();
563 self.batch.clear();
564 }
565}
566
567impl Render for Render2D {
568 type Effect = Effect2D;
569 fn new() -> Self {
570 let vao = VertexArray::new().unwrap();
571 let batch = SpriteBatch::new(1000).unwrap();
572 vao.bind();
575 batch.vbo.handle.bind();
576 vao.setup_for::<Vertex2D>();
577 vao.unbind();
578 batch.vbo.handle.unbind();
579
580 let default_effect = Effect2D::new(None, None).unwrap();
582 let default_canvas = Canvas::default();
583 let white_image = Image::new(1, 1, ImageFormat::RGBA, vec![255, 255, 255, 255]).unwrap();
584 let clear_color = Color::black();
586 let draw_color = Color::white();
587 let camera = Camera2D::new(640.0, 380.0);
588 Render2D {
589 vao,
590 batch,
591 default_effect,
592 white_image,
593 default_canvas,
594 clear_color,
595 draw_color,
596 camera,
597 ..Default::default()
598 }
599 }
600
601 fn begin(&mut self) {
602 self.set_image(None);
603 self.set_canvas(None);
604 self.set_effect(None);
605 self.batch.clear();
606 tea::enable(&[EnableFlags::Blend]);
607 tea::blend_func(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha);
608 }
609
610 fn end(&self) {
611 self.draw();
612 tea::disable(&[EnableFlags::Blend]);
613 }
614
615 fn set_canvas(&mut self, canvas: Option<&Canvas>) {
616 let c: &Canvas;
617 if canvas == None { c = &self.default_canvas; }
618 else { c = canvas.unwrap(); }
619 if Framebuffer::current_bind() == c.framebuffer.get_id() { return }
620 self.draw();
621 self.batch.clear();
622 c.framebuffer.bind();
623 let right = c.width as f32;
624 let bottom = c.height as f32;
625 self.camera.set_size(right, bottom);
626 tea::viewport(0, 0, c.width, c.height);
627 }
628
629 fn set_effect(&mut self, effect: Option<&Self::Effect>) {
630 let e: &Self::Effect;
631 if effect == None { e = &self.default_effect; }
632 else { e = effect.unwrap(); }
633 e.program.set_used();
634 (self.camera.view() * self.camera.projection()).send_uniform(0);
635 }
636
637 fn on_resize(&mut self, width: i32, height: i32) {
638 self.default_canvas.width = width;
639 self.default_canvas.height = height;
640 self.camera.set_size(width as f32, height as f32);
641 tea::viewport(0, 0, width, height);
642 }
643
644 fn camera(&mut self) -> &mut dyn Camera {
645 &mut self.camera
646 }
647}
648
649impl SpriteBatch {
651 pub fn new(count: usize) -> Result<Self, String> {
652 let vbo = VertexBuffer::new(count).unwrap();
653 let ibo = IndexBuffer::new(count).unwrap();
654 Ok(SpriteBatch {
655 vbo,
656 ibo,
657 })
658 }
659
660 #[cfg(target = "")]
661 fn grow(&mut self) {
662 let count = self.data.capacity();
663 let mut v: Vec<Vertex2D> = Vec::with_capacity(count);
664 self.data.append(&mut v);
665 self.vbo.bind();
666 self.vbo.data(self.data.len() * Vertex2D::stride(), self.data.as_ptr() as *const c_void, BufferUsage::DynamicDraw);
667 self.vbo.unbind();
668 }
669
670 pub fn push(&mut self, data: Vertex2D) {
671 if self.vbo.len() + 1 >= self.vbo.capacity() {
672 self.vbo.grow();
673 self.ibo.grow();
674 }
675 self.vbo.push(data);
676 }
683
684 pub fn push_vec(&mut self, data: Vec<Vertex2D>) {
685 if self.vbo.len() + data.len() >= self.vbo.capacity() {
686 self.vbo.grow();
687 self.ibo.grow();
688 }
689 self.vbo.push_vec(data);
690 }
691
692 pub fn add_rect(&mut self, rect: &Rect) {
693 self.add_quad(
694 Vec4::new(rect.x, rect.y, 0.0, 0.0),
695 Vec4::new(rect.x+rect.w, rect.y, 1.0, 0.0),
696 Vec4::new(rect.x+rect.w, rect.y+rect.h, 1.0, 1.0),
697 Vec4::new(rect.x, rect.y+rect.h, 0.0, 1.0),
698 );
699 }
700
701 pub fn add_quad(&mut self, v0: Vec4, v1: Vec4, v2: Vec4, v3: Vec4) {
702 let mut data: Vec<Vertex2D> = vec![];
703 data.push(Vertex2D::from_pos_uv(v0.x, v0.y, v0.z, v0.w));
704 data.push(Vertex2D::from_pos_uv(v1.x, v1.y, v1.z, v1.w));
705 data.push(Vertex2D::from_pos_uv(v2.x, v2.y, v2.z, v2.w));
706
707 data.push(Vertex2D::from_pos_uv(v0.x, v0.y, v0.z, v0.w));
708 data.push(Vertex2D::from_pos_uv(v2.x, v2.y, v2.z, v2.w));
709 data.push(Vertex2D::from_pos_uv(v3.x, v3.y, v3.z, v3.w));
710 self.push_vec(data);
711 }
712
713 pub fn flush(&self) {
714 self.vbo.flush();
715 }
716
717 pub fn count(&self) -> usize { self.vbo.len() }
718
719 pub fn clear(&mut self) {
720 self.vbo.clear();
721 }
722}
723
724impl Default for Vertex2D {
726 fn default() -> Self {
727 Vertex2D (
728 Vec2::new(0.0, 0.0),
729 Vec4::new(0.0, 0.0, 0.0, 0.0),
730 Vec2::new(0.0, 0.0),
731 )
732 }
733}
734
735impl Vertex2D {
736 pub fn new(pos: Vec2, color: Vec4, texcoord: Vec2) -> Self {
737 Vertex2D(
738 pos,
739 color,
740 texcoord
741 )
742 }
743
744 pub fn from_position(x: f32, y: f32) -> Self {
745
746 Vertex2D(
747 Vec2::new(x, y),
748 Vec4::new(1.0, 1.0, 1.0, 1.0),
749 Vec2::new(0.0, 0.0)
750 )
751 }
752
753 pub fn from_pos_uv(x: f32, y: f32, u: f32, v: f32) -> Self {
754 Vertex2D (
755 Vec2::new(x, y),
756 Vec4::new(1.0, 1.0, 1.0, 1.0),
757 Vec2::new(u, v)
758 )
759 }
760}