use std::ptr;
use std::ffi::CString;
use traits::Wrappable;
use graphics::{Texture, Color};
use sfml_types::Vector2f;
use sfml_types::Vector3f;
use csfml_graphics_sys as ffi;
use csfml_system_sys as sys_ffi;
use std::io::{Read, Seek};
use system::inputstream::InputStream;
pub struct Shader<'s> {
shader: *mut ffi::sfShader,
texture: Option<&'s Texture>
}
impl<'s> Shader<'s> {
pub fn new_from_file(vertex_shader_filename: Option<&str>,
fragment_shader_filename: Option<&str>)
-> Option<Shader<'s>> {
let shader = unsafe {
let c_vertex_shader_filename = if vertex_shader_filename.is_none() {
ptr::null()
} else {
CString::new(vertex_shader_filename.unwrap().as_bytes()).unwrap().as_ptr()
};
let c_fragment_shader_filename = if fragment_shader_filename.is_none() {
ptr::null()
} else {
CString::new(fragment_shader_filename.unwrap().as_bytes()).unwrap().as_ptr()
};
ffi::sfShader_createFromFile(c_vertex_shader_filename,
c_fragment_shader_filename)
};
if shader.is_null() {
None
} else {
Some(Shader {
shader: shader,
texture: None
})
}
}
pub fn new_from_stream<T: Read + Seek>(vertex_shader_stream: Option<&mut T>,
fragment_shader_stream: Option<&mut T>)
-> Option<Shader<'s>> {
let shader = unsafe {
let c_vertex_shader_stream = match vertex_shader_stream {
Some(stream) => &mut InputStream::new(stream) as *mut InputStream,
None => ptr::null_mut()
};
let c_fragment_shader_stream = match fragment_shader_stream {
Some(stream) => &mut InputStream::new(stream) as *mut InputStream,
None => ptr::null_mut()
};
ffi::sfShader_createFromStream(&mut (*c_vertex_shader_stream).0 as *mut sys_ffi::sfInputStream,
&mut (*c_fragment_shader_stream).0 as *mut sys_ffi::sfInputStream)
};
if shader.is_null() {
None
} else {
Some(Shader {
shader: shader,
texture: None
})
}
}
pub fn new_from_memory(vertex_shader: Option<&str>,
fragment_shader: Option<&str>)
-> Option<Shader<'s>> {
let shader = unsafe {
let c_vertex_shader = if vertex_shader.is_none() {
ptr::null()
} else {
CString::new(vertex_shader.unwrap().as_bytes()).unwrap().as_ptr()
};
let c_fragment_shader = if fragment_shader.is_none() {
ptr::null()
} else {
CString::new(fragment_shader.unwrap().as_bytes()).unwrap().as_ptr()
};
ffi::sfShader_createFromFile(c_vertex_shader, c_fragment_shader)
};
if shader.is_null() {
None
} else {
Some(Shader {
shader: shader,
texture: None
})
}
}
pub fn set_float_parameter(&mut self, name: &str, x: f32) {
let c_str = CString::new(name.as_bytes()).unwrap().as_ptr();
unsafe {
ffi::sfShader_setFloatParameter(self.shader, c_str, x)
}
}
pub fn set_float_2_parameter(&mut self, name: &str, x: f32, y: f32) {
let c_str = CString::new(name.as_bytes()).unwrap().as_ptr();
unsafe {
ffi::sfShader_setFloat2Parameter(self.shader, c_str, x, y)
}
}
pub fn set_float_3_parameter(&mut self,
name: &str,
x: f32,
y: f32,
z: f32) {
let c_str = CString::new(name.as_bytes()).unwrap().as_ptr();
unsafe {
ffi::sfShader_setFloat3Parameter(self.shader,
c_str,
x,
y,
z)
}
}
pub fn set_float_4_parameter(&mut self,
name: &str,
x: f32,
y: f32,
z: f32,
w: f32) {
let c_str = CString::new(name.as_bytes()).unwrap().as_ptr();
unsafe {
ffi::sfShader_setFloat4Parameter(self.shader,
c_str,
x,
y,
z,
w)
}
}
pub fn set_texture_parameter(&mut self,
name: &str,
texture: &'s Texture) {
self.texture = Some(texture);
let c_str = CString::new(name.as_bytes()).unwrap().as_ptr();
unsafe {
ffi::sfShader_setTextureParameter(self.shader,
c_str,
texture.unwrap())
}
}
pub fn set_current_texture_parameter(&self, name: &str) {
let c_str = CString::new(name.as_bytes()).unwrap().as_ptr();
unsafe {
ffi::sfShader_setCurrentTextureParameter(self.shader, c_str)
}
}
pub fn bind(&mut self) {
unsafe {
ffi::sfShader_bind(self.shader)
}
}
pub fn is_available() -> bool {
unsafe { ffi::sfShader_isAvailable() }.to_bool()
}
pub fn set_vector2_parameter(&mut self,
name: &str,
vector: &Vector2f) {
let c_str = CString::new(name.as_bytes()).unwrap().as_ptr();
unsafe {
ffi::sfShader_setVector2Parameter(self.shader,
c_str,
*vector)
}
}
pub fn set_vector3_parameter(&mut self,
name: &str,
vector: &Vector3f) {
let c_str = CString::new(name.as_bytes()).unwrap().as_ptr();
unsafe {
ffi::sfShader_setVector3Parameter(self.shader,
c_str,
*vector)
}
}
pub fn set_color_parameter(&mut self,
name: &str,
color: &Color) {
let c_str = CString::new(name.as_bytes()).unwrap().as_ptr();
unsafe {
ffi::sfShader_setColorParameter(self.shader, c_str, color.0)
}
}
}
impl<'s> Wrappable<*mut ffi::sfShader> for Shader<'s> {
fn wrap(shader: *mut ffi::sfShader) -> Shader<'s> {
Shader {
shader: shader,
texture: None
}
}
fn unwrap(&self) -> *mut ffi::sfShader {
self.shader
}
}
impl<'s> Drop for Shader<'s> {
fn drop(&mut self) {
unsafe {
ffi::sfShader_destroy(self.shader)
}
}
}