use std::{marker::PhantomData, pin::Pin};
use autocxx::WithinUniquePtr;
use cxx::UniquePtr;
use super::{Color, FloatColor};
pub unsafe trait TexturePixel: Sized {
#[doc(hidden)]
type Ffi: cxx::memory::UniquePtrTarget;
#[doc(hidden)]
fn ffi_new(width: u32, height: u32) -> UniquePtr<Self::Ffi>;
#[doc(hidden)]
fn ffi_width(ffi: &Self::Ffi) -> u32;
#[doc(hidden)]
fn ffi_height(ffi: &Self::Ffi) -> u32;
#[doc(hidden)]
fn ffi_set_pixel(ffi: Pin<&mut Self::Ffi>, x: u32, y: u32, pixel: Self);
#[doc(hidden)]
fn ffi_get_pixel(ffi: &Self::Ffi, x: u32, y: u32) -> Self;
}
pub struct Texture<T: TexturePixel> {
pub(crate) inner: UniquePtr<T::Ffi>,
_phantom: PhantomData<T>,
}
impl<T: TexturePixel> Texture<T> {
pub fn new(width: u32, height: u32) -> Self {
Self {
inner: T::ffi_new(width, height),
_phantom: PhantomData,
}
}
pub fn width(&self) -> u32 {
T::ffi_width(&self.inner)
}
pub fn height(&self) -> u32 {
T::ffi_height(&self.inner)
}
pub fn set_pixel(&mut self, x: u32, y: u32, pixel: T) {
T::ffi_set_pixel(self.inner.pin_mut(), x, y, pixel);
}
pub fn pixel(&self, x: u32, y: u32) -> T {
T::ffi_get_pixel(&self.inner, x, y)
}
}
unsafe impl TexturePixel for Color {
type Ffi = carla_sys::carla_rust::rpc::FfiTextureColor;
fn ffi_new(width: u32, height: u32) -> UniquePtr<Self::Ffi> {
Self::Ffi::new(width, height).within_unique_ptr()
}
fn ffi_width(ffi: &Self::Ffi) -> u32 {
ffi.GetWidth()
}
fn ffi_height(ffi: &Self::Ffi) -> u32 {
ffi.GetHeight()
}
fn ffi_set_pixel(ffi: Pin<&mut Self::Ffi>, x: u32, y: u32, pixel: Self) {
ffi.SetPixel(x, y, pixel.r, pixel.g, pixel.b, pixel.a);
}
fn ffi_get_pixel(ffi: &Self::Ffi, x: u32, y: u32) -> Self {
Color::rgba(
ffi.GetPixelR(x, y),
ffi.GetPixelG(x, y),
ffi.GetPixelB(x, y),
ffi.GetPixelA(x, y),
)
}
}
unsafe impl TexturePixel for FloatColor {
type Ffi = carla_sys::carla_rust::rpc::FfiTextureFloatColor;
fn ffi_new(width: u32, height: u32) -> UniquePtr<Self::Ffi> {
Self::Ffi::new(width, height).within_unique_ptr()
}
fn ffi_width(ffi: &Self::Ffi) -> u32 {
ffi.GetWidth()
}
fn ffi_height(ffi: &Self::Ffi) -> u32 {
ffi.GetHeight()
}
fn ffi_set_pixel(ffi: Pin<&mut Self::Ffi>, x: u32, y: u32, pixel: Self) {
ffi.SetPixel(x, y, pixel.r, pixel.g, pixel.b, pixel.a);
}
fn ffi_get_pixel(ffi: &Self::Ffi, x: u32, y: u32) -> Self {
FloatColor::rgba(
ffi.GetPixelR(x, y),
ffi.GetPixelG(x, y),
ffi.GetPixelB(x, y),
ffi.GetPixelA(x, y),
)
}
}
pub type TextureColor = Texture<Color>;
pub type TextureFloatColor = Texture<FloatColor>;