use crate::{
ffi::graphics as ffi,
graphics::{
Color, Drawable, FloatRect, IntRect, RenderStates, RenderTarget, Shape, Texture, Transform,
Transformable,
},
system::Vector2f,
};
use std::{marker::PhantomData, ptr};
#[derive(Debug)]
pub struct ConvexShape<'s> {
convex_shape: *mut ffi::sfConvexShape,
texture: PhantomData<&'s Texture>,
}
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub struct ConvexShapePoints {
convex_shape: *mut ffi::sfConvexShape,
pos: usize,
}
impl<'s> ConvexShape<'s> {
#[must_use]
pub fn new(points_count: usize) -> ConvexShape<'s> {
let shape = unsafe { ffi::sfConvexShape_create() };
assert!(!shape.is_null(), "Failed to create ConvexShape");
let mut shape = ConvexShape {
convex_shape: shape,
texture: PhantomData,
};
shape.set_point_count(points_count);
shape
}
#[must_use]
pub fn with_texture(points_count: usize, texture: &'s Texture) -> ConvexShape<'s> {
let mut shape = ConvexShape::new(points_count);
shape.set_texture(texture, true);
shape
}
pub fn set_point<P: Into<Vector2f>>(&mut self, index: usize, point: P) {
assert!(
index < self.point_count(),
"Index out of bounds. Index: {}, len: {}",
index,
self.point_count()
);
unsafe { ffi::sfConvexShape_setPoint(self.convex_shape, index, point.into()) }
}
pub fn set_point_count(&mut self, count: usize) {
unsafe { ffi::sfConvexShape_setPointCount(self.convex_shape, count) }
}
#[must_use]
pub fn points(&self) -> ConvexShapePoints {
ConvexShapePoints {
convex_shape: self.convex_shape,
pos: 0,
}
}
pub(super) fn raw(&self) -> *const ffi::sfConvexShape {
self.convex_shape
}
}
impl<'s> Drawable for ConvexShape<'s> {
fn draw<'a: 'shader, 'texture, 'shader, 'shader_texture>(
&'a self,
target: &mut dyn RenderTarget,
states: &RenderStates<'texture, 'shader, 'shader_texture>,
) {
target.draw_convex_shape(self, states)
}
}
impl<'s> Transformable for ConvexShape<'s> {
fn set_position<P: Into<Vector2f>>(&mut self, position: P) {
unsafe { ffi::sfConvexShape_setPosition(self.convex_shape, position.into()) }
}
fn set_rotation(&mut self, angle: f32) {
unsafe { ffi::sfConvexShape_setRotation(self.convex_shape, angle) }
}
fn set_scale<S: Into<Vector2f>>(&mut self, scale: S) {
unsafe { ffi::sfConvexShape_setScale(self.convex_shape, scale.into()) }
}
fn set_origin<O: Into<Vector2f>>(&mut self, origin: O) {
unsafe { ffi::sfConvexShape_setOrigin(self.convex_shape, origin.into()) }
}
fn position(&self) -> Vector2f {
unsafe { ffi::sfConvexShape_getPosition(self.convex_shape) }
}
fn rotation(&self) -> f32 {
unsafe { ffi::sfConvexShape_getRotation(self.convex_shape) }
}
fn get_scale(&self) -> Vector2f {
unsafe { ffi::sfConvexShape_getScale(self.convex_shape) }
}
fn origin(&self) -> Vector2f {
unsafe { ffi::sfConvexShape_getOrigin(self.convex_shape) }
}
fn move_<O: Into<Vector2f>>(&mut self, offset: O) {
unsafe { ffi::sfConvexShape_move(self.convex_shape, offset.into()) }
}
fn rotate(&mut self, angle: f32) {
unsafe { ffi::sfConvexShape_rotate(self.convex_shape, angle) }
}
fn scale<F: Into<Vector2f>>(&mut self, factors: F) {
unsafe { ffi::sfConvexShape_scale(self.convex_shape, factors.into()) }
}
fn transform(&self) -> &Transform {
unsafe { &*ffi::sfConvexShape_getTransform(self.convex_shape) }
}
fn inverse_transform(&self) -> &Transform {
unsafe { &*ffi::sfConvexShape_getInverseTransform(self.convex_shape) }
}
}
impl<'s> Shape<'s> for ConvexShape<'s> {
fn set_texture(&mut self, texture: &'s Texture, reset_rect: bool) {
unsafe { ffi::sfConvexShape_setTexture(self.convex_shape, texture, reset_rect) }
}
fn disable_texture(&mut self) {
unsafe { ffi::sfConvexShape_setTexture(self.convex_shape, ptr::null_mut(), true) }
}
fn set_texture_rect(&mut self, rect: IntRect) {
unsafe { ffi::sfConvexShape_setTextureRect(self.convex_shape, rect) }
}
fn set_fill_color(&mut self, color: Color) {
unsafe { ffi::sfConvexShape_setFillColor(self.convex_shape, color) }
}
fn set_outline_color(&mut self, color: Color) {
unsafe { ffi::sfConvexShape_setOutlineColor(self.convex_shape, color) }
}
fn set_outline_thickness(&mut self, thickness: f32) {
unsafe { ffi::sfConvexShape_setOutlineThickness(self.convex_shape, thickness) }
}
fn texture(&self) -> Option<&'s Texture> {
unsafe { ffi::sfConvexShape_getTexture(self.convex_shape).as_ref() }
}
fn texture_rect(&self) -> IntRect {
unsafe { ffi::sfConvexShape_getTextureRect(self.convex_shape) }
}
fn fill_color(&self) -> Color {
unsafe { ffi::sfConvexShape_getFillColor(self.convex_shape) }
}
fn outline_color(&self) -> Color {
unsafe { ffi::sfConvexShape_getOutlineColor(self.convex_shape) }
}
fn outline_thickness(&self) -> f32 {
unsafe { ffi::sfConvexShape_getOutlineThickness(self.convex_shape) }
}
fn point_count(&self) -> usize {
unsafe { ffi::sfConvexShape_getPointCount(self.convex_shape) }
}
fn point(&self, index: usize) -> Vector2f {
unsafe {
assert!(
index < self.point_count(),
"Index out of bounds. Index: {}, len: {}",
index,
self.point_count()
);
ffi::sfConvexShape_getPoint(self.convex_shape, index)
}
}
fn local_bounds(&self) -> FloatRect {
unsafe { ffi::sfConvexShape_getLocalBounds(self.convex_shape) }
}
fn global_bounds(&self) -> FloatRect {
unsafe { ffi::sfConvexShape_getGlobalBounds(self.convex_shape) }
}
}
impl<'s> Clone for ConvexShape<'s> {
fn clone(&self) -> ConvexShape<'s> {
let shape = unsafe { ffi::sfConvexShape_copy(self.convex_shape) };
if shape.is_null() {
panic!("Not enough memory to clone ConvexShape")
} else {
ConvexShape {
convex_shape: shape,
texture: self.texture,
}
}
}
}
impl Iterator for ConvexShapePoints {
type Item = Vector2f;
fn next(&mut self) -> Option<Vector2f> {
let point_count = unsafe { ffi::sfConvexShape_getPointCount(self.convex_shape) };
if self.pos == point_count {
None
} else {
let point = unsafe { ffi::sfConvexShape_getPoint(self.convex_shape, self.pos) };
self.pos += 1;
Some(point)
}
}
}
impl<'s> Drop for ConvexShape<'s> {
fn drop(&mut self) {
unsafe { ffi::sfConvexShape_destroy(self.convex_shape) }
}
}