use gl;
use nalgebra::Matrix4;
use nalgebra::Vector2;
use shader::Shader;
use shader::DEFAULT_SHADER;
use texture::Texture;
lazy_static! {
static ref DEFAULT_CONTEXT: Context<'static> = Context::default();
}
lazy_static! {
pub static ref IDENTITY: Matrix4<f32> = Matrix4::identity();
}
#[derive(Debug)]
pub enum BlendMode {
Alpha,
Beta,
Ceta,
}
impl BlendMode {
fn blend_to_gl(&self) {
match self {
BlendMode::Alpha => unsafe { gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA) },
_ => {}
}
}
pub fn unactive(&self) {
unsafe {
gl::Disable(gl::BLEND);
}
}
pub fn active(&self) {
unsafe {
gl::Enable(gl::BLEND);
match self {
BlendMode::Alpha => {
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
}
BlendMode::Beta => {
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
}
BlendMode::Ceta => {
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
}
}
}
}
}
#[derive(Debug)]
pub struct Context<'a> {
texture: Option<&'a Texture>,
shader: &'a Shader,
transform: Vec<(String, &'a Matrix4<f32>)>,
blend_mode: BlendMode,
}
impl<'a> Context<'a> {
pub fn new(
texture: Option<&'a Texture>,
shader: &'a Shader,
transform: Vec<(String, &'a Matrix4<f32>)>,
blend_mode: BlendMode,
) -> Context<'a> {
Context {
texture,
shader,
transform,
blend_mode,
}
}
pub fn apply_texture(&mut self, id: i32) {
if let Some(texture) = self.texture {
texture.active(id);
}
}
pub fn apply_blendmode(&mut self) {
self.blend_mode.active();
}
pub fn setup_shader(&self) {
self.shader.activate();
for (name, mat) in &self.transform {
self.shader.uniform_mat4f(name.as_str(), mat);
}
}
}
impl<'a> Default for Context<'a> {
fn default() -> Context<'a> {
Context {
texture: None,
shader: &*DEFAULT_SHADER,
transform: vec![("transform".to_string(), &*IDENTITY)],
blend_mode: BlendMode::Alpha,
}
}
}
pub trait Drawer {
fn draw<T: Drawable>(&mut self, drawable: &T);
fn draw_with_context_mut<T: DrawableMut>(&mut self, drawable: &mut T, context: &mut Context) {
self.draw_with_context(drawable, context);
}
fn draw_mut<T: DrawableMut>(&mut self, drawable: &mut T) {
self.draw(drawable);
}
fn draw_with_context<T: Drawable>(&mut self, drawable: &mut T, context: &mut Context) {
drawable.draw_with_context(context);
}
fn get_center(&self) -> Vector2<f32>;
fn get_sizes(&self) -> Vector2<f32>;
fn projection(&self) -> &Matrix4<f32>;
}
pub trait Drawable {
fn draw<T: Drawer>(&self, window: &mut T);
fn draw_with_context(&self, context: &mut Context);
fn update(&mut self);
fn setup_draw(&self, context: &mut Context) {
context.apply_texture(0);
context.apply_blendmode();
context.setup_shader();
}
}
pub trait DrawableMut: Drawable {
fn draw_mut<T: Drawer>(&mut self, window: &mut T) {
self.draw(window);
}
fn draw_with_context_mut(&mut self, context: &mut Context) {
self.draw_with_context(context);
}
}