use glam::{BVec2, Vec2};
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct UVOptions {
pub scale_factor: Vec2,
pub flip: BVec2,
pub offset: Vec2,
pub rect: Rect,
}
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct Rect {
pub min: Vec2,
pub max: Vec2,
}
impl UVOptions {
#[must_use]
pub const fn new() -> Self {
Self {
scale_factor: Vec2::ONE,
flip: BVec2::FALSE,
offset: Vec2::ZERO,
rect: Rect::new_uv(),
}
}
#[must_use]
#[inline]
pub const fn with_scale_factor(mut self, scale_factor: Vec2) -> Self {
self.scale_factor = scale_factor;
self
}
#[must_use]
#[inline]
pub const fn with_offset(mut self, offset: Vec2) -> Self {
self.offset = offset;
self
}
#[must_use]
#[inline]
pub const fn with_rect(mut self, min: Vec2, max: Vec2) -> Self {
self.rect = Rect { min, max };
self
}
#[must_use]
#[inline]
pub const fn flip_u(mut self) -> Self {
self.flip.x = true;
self
}
#[must_use]
#[inline]
pub const fn flip_v(mut self) -> Self {
self.flip.y = true;
self
}
#[must_use]
pub fn alter_uv(&self, mut uv: Vec2) -> Vec2 {
if self.flip.x {
uv.x = 1.0 - uv.x;
}
if self.flip.y {
uv.y = 1.0 - uv.y;
}
uv = uv * self.scale_factor + self.offset;
uv = self.rect.remap(uv);
uv
}
pub fn alter_uvs(&self, uvs: &mut [Vec2]) {
for uv in uvs {
*uv = self.alter_uv(*uv);
}
}
#[inline]
pub(crate) fn wrap_uv(p: Vec2) -> Vec2 {
let p = p.try_normalize().unwrap_or(p);
(p / 2.0) + Vec2::splat(0.5)
}
}
impl Default for UVOptions {
fn default() -> Self {
Self::new()
}
}
#[inline]
fn remap(value: f32, min: f32, max: f32) -> f32 {
(max - min).mul_add(value, min)
}
impl Rect {
#[inline]
#[must_use]
pub(crate) const fn new_uv() -> Self {
Self {
min: Vec2::ZERO,
max: Vec2::ONE,
}
}
#[inline]
#[must_use]
pub(crate) fn remap(&self, value: Vec2) -> Vec2 {
Vec2::new(
remap(value.x, self.min.x, self.max.x),
remap(value.y, self.min.y, self.max.y),
)
}
}
impl Default for Rect {
fn default() -> Self {
Self::new_uv()
}
}