use crate::prelude::*;
use std::{
fmt,
ops::{Deref, DerefMut},
};
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct TextureId(pub(crate) usize);
impl fmt::Display for TextureId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl Deref for TextureId {
type Target = usize;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for TextureId {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl PixState {
pub fn texture<R1, R2>(&mut self, texture_id: TextureId, src: R1, dst: R2) -> PixResult<()>
where
R1: Into<Option<Rect<i32>>>,
R2: Into<Option<Rect<i32>>>,
{
self.renderer
.texture(texture_id, src.into(), dst.into(), 0.0, None, None, None)
}
pub fn texture_transformed<R1, R2, C, F>(
&mut self,
texture_id: TextureId,
src: R1,
dst: R2,
mut angle: f64,
center: C,
flipped: F,
) -> PixResult<()>
where
R1: Into<Option<Rect<i32>>>,
R2: Into<Option<Rect<i32>>>,
C: Into<Option<Point<i32>>>,
F: Into<Option<Flipped>>,
{
let s = &self.settings;
if s.angle_mode == AngleMode::Radians {
angle = angle.to_degrees();
};
self.renderer.texture(
texture_id,
src.into(),
dst.into(),
angle,
center.into(),
flipped.into(),
s.image_tint,
)
}
pub fn create_texture<F>(&mut self, width: u32, height: u32, format: F) -> PixResult<TextureId>
where
F: Into<Option<PixelFormat>>,
{
self.renderer.create_texture(width, height, format.into())
}
pub fn delete_texture(&mut self, texture_id: TextureId) -> PixResult<()> {
self.renderer.delete_texture(texture_id)
}
pub fn update_texture<R, P>(
&mut self,
texture_id: TextureId,
rect: R,
pixels: P,
pitch: usize,
) -> PixResult<()>
where
R: Into<Option<Rect<i32>>>,
P: AsRef<[u8]>,
{
let rect = rect.into();
let pixels = pixels.as_ref();
self.renderer
.update_texture(texture_id, rect, pixels, pitch)
}
pub fn set_texture_target(&mut self, id: TextureId) -> PixResult<()> {
if self.renderer.texture_target().is_none() {
self.push();
self.ui.push_cursor();
self.set_cursor_pos(self.theme.spacing.frame_pad);
self.renderer.set_texture_target(id)
} else {
Ok(())
}
}
pub fn clear_texture_target(&mut self) {
if self.renderer.texture_target().is_some() {
self.renderer.clear_texture_target();
self.ui.pop_cursor();
self.pop();
}
}
}
pub(crate) trait TextureRenderer {
fn create_texture(
&mut self,
width: u32,
height: u32,
format: Option<PixelFormat>,
) -> PixResult<TextureId>;
fn delete_texture(&mut self, texture_id: TextureId) -> PixResult<()>;
fn update_texture<P: AsRef<[u8]>>(
&mut self,
texture_id: TextureId,
rect: Option<Rect<i32>>,
pixels: P,
pitch: usize,
) -> PixResult<()>;
#[allow(clippy::too_many_arguments)]
fn texture(
&mut self,
texture_id: TextureId,
src: Option<Rect<i32>>,
dst: Option<Rect<i32>>,
angle: f64,
center: Option<Point<i32>>,
flipped: Option<Flipped>,
tint: Option<Color>,
) -> PixResult<()>;
fn texture_target(&self) -> Option<TextureId>;
fn set_texture_target(&mut self, texture_id: TextureId) -> PixResult<()>;
fn clear_texture_target(&mut self);
fn has_texture_target(&self) -> bool;
fn clear_texture_cache(&mut self);
}