Skip to main content

gust_render/
draw.rs

1//! Every traits needed by drawable object
2//!
3
4use gl;
5use nalgebra::Matrix4;
6use nalgebra::Vector2;
7use shader::Shader;
8use shader::DEFAULT_SHADER;
9use texture::Texture;
10
11//----------------------------------------------------------------------------
12//
13//
14//                             BLENDMODE : ENUM
15//
16//
17//----------------------------------------------------------------------------
18
19lazy_static! {
20    static ref DEFAULT_CONTEXT: Context<'static> = Context::default();
21}
22
23lazy_static! {
24    pub static ref IDENTITY: Matrix4<f32> = Matrix4::identity();
25}
26
27#[derive(Debug)]
28/// Blend mode needed to draw
29pub enum BlendMode {
30    Alpha,
31    Beta,
32    Ceta,
33}
34
35impl BlendMode {
36    fn blend_to_gl(&self) {
37        match self {
38            BlendMode::Alpha => unsafe { gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA) },
39            _ => {}
40        }
41    }
42
43    pub fn unactive(&self) {
44        unsafe {
45            gl::Disable(gl::BLEND);
46        }
47    }
48
49    pub fn active(&self) {
50        unsafe {
51            gl::Enable(gl::BLEND);
52            match self {
53                BlendMode::Alpha => {
54                    gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
55                }
56                BlendMode::Beta => {
57                    gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
58                }
59                BlendMode::Ceta => {
60                    gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
61                }
62            }
63        }
64    }
65}
66
67//----------------------------------------------------------------------------
68//
69//
70//                             CONTEXT : STRUCT
71//
72//
73//----------------------------------------------------------------------------
74
75#[derive(Debug)]
76/// Context needed to handle a draw of a vertex array
77/// A context is needed by the drawer to handle the drawing
78/// process a default context can be use ether
79pub struct Context<'a> {
80    texture: Option<&'a Texture>,
81    shader: &'a Shader,
82    transform: Vec<(String, &'a Matrix4<f32>)>,
83    blend_mode: BlendMode,
84}
85
86impl<'a> Context<'a> {
87    /// Create a new context from texture, shader, transform, blend_mode
88    pub fn new(
89        texture: Option<&'a Texture>,
90        shader: &'a Shader,
91        transform: Vec<(String, &'a Matrix4<f32>)>,
92        blend_mode: BlendMode,
93    ) -> Context<'a> {
94        Context {
95            texture,
96            shader,
97            transform,
98            blend_mode,
99        }
100    }
101
102    /// Apply texture on the context
103    pub fn apply_texture(&mut self, id: i32) {
104        if let Some(texture) = self.texture {
105            texture.active(id);
106        }
107    }
108
109    /// Apply the blendmode to the current context
110    pub fn apply_blendmode(&mut self) {
111        self.blend_mode.active();
112    }
113
114    /// Apply final shader (transformation)
115    pub fn setup_shader(&self) {
116        self.shader.activate();
117        for (name, mat) in &self.transform {
118            self.shader.uniform_mat4f(name.as_str(), mat);
119        }
120    }
121}
122
123impl<'a> Default for Context<'a> {
124    /// Default Context implementation
125    fn default() -> Context<'a> {
126        Context {
127            texture: None,
128            shader: &*DEFAULT_SHADER,
129            transform: vec![("transform".to_string(), &*IDENTITY)],
130            blend_mode: BlendMode::Alpha,
131        }
132    }
133}
134
135//----------------------------------------------------------------------------
136//
137//
138//                             TRAIT PART
139//
140//
141//----------------------------------------------------------------------------
142
143/// Trait defining a drawer
144pub trait Drawer {
145    /// Function that draw on itself needed by everything that can be draw.
146    fn draw<T: Drawable>(&mut self, drawable: &T);
147
148    /// Draw with context fonction if you want to define you own fonction
149    fn draw_with_context_mut<T: DrawableMut>(&mut self, drawable: &mut T, context: &mut Context) {
150        self.draw_with_context(drawable, context);
151    }
152
153    /// Function that can draw a DrawableMut.
154    fn draw_mut<T: DrawableMut>(&mut self, drawable: &mut T) {
155        self.draw(drawable);
156    }
157
158    /// Draw with context a Drawable.
159    fn draw_with_context<T: Drawable>(&mut self, drawable: &mut T, context: &mut Context) {
160        drawable.draw_with_context(context);
161    }
162
163    fn get_center(&self) -> Vector2<f32>;
164
165    fn get_sizes(&self) -> Vector2<f32>;
166
167    fn projection(&self) -> &Matrix4<f32>;
168}
169
170/// Trait that can be use to draw on window
171pub trait Drawable {
172    /// Draw the drawable structure, you need a Drawer(Where the struct will be draw)
173    fn draw<T: Drawer>(&self, window: &mut T);
174
175    /// Draw with a particular context
176    fn draw_with_context(&self, context: &mut Context);
177
178    /// Update the openGL state of the drawable entity
179    /// Should be call often so be carefull when implementing.
180    fn update(&mut self);
181
182    /// Setup the draw for the final system you don't have to implement it in a normal drawable
183    fn setup_draw(&self, context: &mut Context) {
184        context.apply_texture(0);
185        context.apply_blendmode();
186        context.setup_shader();
187    }
188}
189
190pub trait DrawableMut: Drawable {
191    /// Mutable version of draw function.
192    fn draw_mut<T: Drawer>(&mut self, window: &mut T) {
193        self.draw(window);
194    }
195
196    /// Mutable draw context function.
197    fn draw_with_context_mut(&mut self, context: &mut Context) {
198        self.draw_with_context(context);
199    }
200}