use libc::{c_void, c_float, c_uint};
use std::{ptr, mem};
use traits::Wrappable;
use graphics::shape::ShapeImpl;
use graphics::{Drawable, Transformable, RenderTarget, RenderStates, Texture, Color,
Transform, IntRect, FloatRect};
use sfml_types::{sfBool, Vector2f};
use csfml_graphics_sys as ffi;
struct WrapObj {
shape_impl: Box<ShapeImpl + Send>
}
pub struct CustomShape<'s> {
shape: *mut ffi::sfShape,
texture: Option<&'s Texture>
}
extern fn get_point_count_callback(obj: *mut c_void) -> u32 {
let shape = unsafe { mem::transmute::<*mut c_void, Box<Box<WrapObj>>>(obj) };
let ret = shape.shape_impl.get_point_count();
mem::forget(shape);
ret
}
extern fn get_point_callback(point: u32, obj: *mut c_void) -> Vector2f {
let shape = unsafe { mem::transmute::<*mut c_void, Box<Box<WrapObj>>>(obj) };
let ret = shape.shape_impl.get_point(point);
mem::forget(shape);
ret
}
impl<'s> CustomShape<'s> {
pub fn new(shape_impl: Box<ShapeImpl + Send>) -> Option<CustomShape<'s>> {
let w_o = Box::new(WrapObj { shape_impl: shape_impl});
let sp = unsafe { ffi::sfShape_create(get_point_count_callback,
get_point_callback,
mem::transmute::<Box<Box<WrapObj>>, *mut c_void>(Box::new(w_o))) };
if sp.is_null() {
None
} else {
Some(CustomShape {
shape: sp,
texture: None
})
}
}
pub fn new_with_texture(shape_impl: Box<ShapeImpl + Send>,
texture: &'s Texture) -> Option<CustomShape<'s>> {
let w_o = Box::new(WrapObj { shape_impl: shape_impl });
let sp = unsafe { ffi::sfShape_create(get_point_count_callback,
get_point_callback,
mem::transmute::<Box<Box<WrapObj>>, *mut c_void>(Box::new(w_o))) };
if sp.is_null() {
None
} else {
unsafe {
ffi::sfShape_setTexture(sp, texture.unwrap(), sfBool::SFTRUE);
}
Some(CustomShape {
shape: sp,
texture: Some(texture)
})
}
}
pub fn set_texture(&mut self,
texture: &'s Texture,
reset_rect: bool) {
self.texture = Some(texture);
unsafe {
ffi::sfShape_setTexture(self.shape, texture.unwrap(), sfBool::from_bool(reset_rect))
}
}
pub fn disable_texture(&mut self) {
self.texture = None;
unsafe {
ffi::sfShape_setTexture(self.shape, ptr::null_mut(), sfBool::SFTRUE)
}
}
pub fn set_texture_rect(&mut self, rect: &IntRect) {
unsafe {
ffi::sfShape_setTextureRect(self.shape, *rect)
}
}
pub fn set_fill_color(&mut self, color: &Color) {
unsafe {
ffi::sfShape_setFillColor(self.shape, color.0)
}
}
pub fn set_outline_color(&mut self, color: &Color) {
unsafe {
ffi::sfShape_setOutlineColor(self.shape, color.0)
}
}
pub fn set_outline_thickness(&mut self, thickness: f32) {
unsafe {
ffi::sfShape_setOutlineThickness(self.shape, thickness as c_float)
}
}
pub fn get_texture(&self) -> Option<&'s Texture> {
self.texture
}
pub fn get_texture_rect(&self) -> IntRect {
unsafe {
ffi::sfShape_getTextureRect(self.shape)
}
}
pub fn get_fill_color(&self) -> Color {
unsafe {
Color(ffi::sfShape_getFillColor(self.shape))
}
}
pub fn get_outline_color(&self) -> Color {
unsafe {
Color(ffi::sfShape_getOutlineColor(self.shape))
}
}
pub fn get_outline_thickness(&self) -> f32 {
unsafe {
ffi::sfShape_getOutlineThickness(self.shape) as f32
}
}
pub fn get_point_count(&self) -> u32 {
unsafe {
ffi::sfShape_getPointCount(self.shape) as u32
}
}
pub fn get_point(&self, index: u32) -> Vector2f {
unsafe {
ffi::sfShape_getPoint(self.shape, index as c_uint)
}
}
pub fn get_local_bounds(&self) -> FloatRect {
unsafe {
ffi::sfShape_getLocalBounds(self.shape)
}
}
pub fn get_global_bounds(&self) -> FloatRect {
unsafe {
ffi::sfShape_getGlobalBounds(self.shape)
}
}
pub fn update(&mut self) {
unsafe {
ffi::sfShape_update(self.shape)
}
}
#[doc(hidden)]
pub fn unwrap(&self) -> *mut ffi::sfShape {
self.shape
}
}
impl<'s> Drawable for CustomShape<'s> {
fn draw<RT: RenderTarget>(&self,
render_target: &mut RT,
render_states: &mut RenderStates) {
render_target.draw_shape(self, render_states)
}
}
impl<'s> Transformable for CustomShape<'s> {
fn set_position(&mut self, position: &Vector2f) {
unsafe {
ffi::sfShape_setPosition(self.shape, *position)
}
}
fn set_position2f(&mut self, x: f32, y: f32) {
unsafe {
ffi::sfShape_setPosition(self.shape, Vector2f::new(x, y))
}
}
fn set_rotation(&mut self, angle: f32) {
unsafe {
ffi::sfShape_setRotation(self.shape, angle as c_float)
}
}
fn set_scale(&mut self, scale: &Vector2f) {
unsafe {
ffi::sfShape_setScale(self.shape, *scale)
}
}
fn set_scale2f(&mut self, scale_x: f32, scale_y: f32) {
unsafe {
ffi::sfShape_setScale(self.shape, Vector2f::new(scale_x, scale_y))
}
}
fn set_origin(&mut self, origin: &Vector2f) {
unsafe {
ffi::sfShape_setOrigin(self.shape, *origin)
}
}
fn set_origin2f(&mut self, x: f32, y: f32) {
unsafe {
ffi::sfShape_setOrigin(self.shape, Vector2f::new(x, y))
}
}
fn get_position(&self) -> Vector2f {
unsafe {
ffi::sfShape_getPosition(self.shape)
}
}
fn get_rotation(&self) -> f32 {
unsafe {
ffi::sfShape_getRotation(self.shape) as f32
}
}
fn get_scale(&self) -> Vector2f {
unsafe {
ffi::sfShape_getScale(self.shape)
}
}
fn get_origin(&self) -> Vector2f {
unsafe {
ffi::sfShape_getOrigin(self.shape)
}
}
fn move_(&mut self, offset: &Vector2f) {
unsafe {
ffi::sfShape_move(self.shape, *offset)
}
}
fn move2f(&mut self, offset_x: f32, offset_y: f32) {
unsafe {
ffi::sfShape_move(self.shape, Vector2f::new(offset_x, offset_y))
}
}
fn rotate(&mut self, angle: f32) {
unsafe {
ffi::sfShape_rotate(self.shape, angle as c_float)
}
}
fn scale(&mut self, factors: &Vector2f) {
unsafe {
ffi::sfShape_scale(self.shape, *factors)
}
}
fn scale2f(&mut self, factor_x: f32, factor_y: f32) {
unsafe {
ffi::sfShape_scale(self.shape, Vector2f::new(factor_x, factor_y))
}
}
fn get_transform(&self) -> Transform {
unsafe {
Transform(ffi::sfShape_getTransform(self.shape))
}
}
fn get_inverse_transform(&self) -> Transform {
unsafe {
Transform(ffi::sfShape_getInverseTransform(self.shape))
}
}
}
impl<'s> Drop for CustomShape<'s> {
fn drop(&mut self) {
unsafe {
ffi::sfShape_destroy(self.shape)
}
}
}