use crate::{exec, get_context, types::Rect};
use glam::{vec2, Vec2};
use quad_gl::{Color, DrawMode, FilterMode, Vertex};
pub use quad_gl::{Image, Texture2D};
pub fn load_texture(path: &str) -> exec::TextureLoadingFuture {
use std::cell::RefCell;
use std::rc::Rc;
let texture = Rc::new(RefCell::new(None));
let path = path.to_owned();
{
let texture = texture.clone();
let path0 = path.clone();
miniquad::fs::load_file(&path, move |bytes| {
let bytes = bytes.unwrap_or_else(|_| panic!("Not such texture: {}", path0));
let context = &mut get_context().quad_context;
*texture.borrow_mut() =
Some(Texture2D::from_file_with_format(context, &bytes[..], None));
});
}
exec::TextureLoadingFuture { texture }
}
pub fn set_texture_filter(texture: Texture2D, filter_mode: FilterMode) {
let context = &mut get_context().quad_context;
texture.set_filter(context, filter_mode);
}
pub fn update_texture(mut texture: Texture2D, image: &Image) {
let context = &mut get_context().quad_context;
texture.update(context, image);
}
pub fn load_texture_from_image(image: &Image) -> Texture2D {
let context = &mut get_context().quad_context;
Texture2D::from_rgba8(context, image.width, image.height, &image.bytes)
}
pub struct DrawTextureParams {
pub dest_size: Option<Vec2>,
pub source: Option<Rect>,
pub rotation: f32,
}
impl Default for DrawTextureParams {
fn default() -> DrawTextureParams {
DrawTextureParams {
dest_size: None,
source: None,
rotation: 0.,
}
}
}
pub fn draw_texture(texture: Texture2D, x: f32, y: f32, color: Color) {
draw_texture_ex(texture, x, y, color, Default::default());
}
pub fn draw_texture_ex(
texture: Texture2D,
x: f32,
y: f32,
color: Color,
params: DrawTextureParams,
) {
let context = &mut get_context().draw_context;
let Rect {
x: sx,
y: sy,
w: sw,
h: sh,
} = params.source.unwrap_or(Rect {
x: 0.,
y: 0.,
w: texture.width(),
h: texture.height(),
});
let (w, h) = params
.dest_size
.map_or((texture.width(), texture.height()), |dst| {
(dst.x(), dst.y())
});
let m = vec2(x + w / 2., y + h / 2.);
let p = [
vec2(-w / 2., -h / 2.),
vec2(w / 2., -h / 2.),
vec2(w / 2., h / 2.),
vec2(-w / 2., h / 2.),
];
let r = params.rotation;
let p = [
vec2(
p[0].x() * r.cos() - p[0].y() * r.sin(),
p[0].x() * r.sin() + p[0].y() * r.cos(),
) + m,
vec2(
p[1].x() * r.cos() - p[1].y() * r.sin(),
p[1].x() * r.sin() + p[1].y() * r.cos(),
) + m,
vec2(
p[2].x() * r.cos() - p[2].y() * r.sin(),
p[2].x() * r.sin() + p[2].y() * r.cos(),
) + m,
vec2(
p[3].x() * r.cos() - p[3].y() * r.sin(),
p[3].x() * r.sin() + p[3].y() * r.cos(),
) + m,
];
#[rustfmt::skip]
let vertices = [
Vertex::new(p[0].x(), p[0].y(), 0., sx /texture.width(), sy /texture.height(), color),
Vertex::new(p[1].x(), p[1].y(), 0., (sx + sw)/texture.width(), sy /texture.height(), color),
Vertex::new(p[2].x(), p[2].y(), 0., (sx + sw)/texture.width(), (sy + sh)/texture.height(), color),
Vertex::new(p[3].x(), p[3].y(), 0., sx /texture.width(), (sy + sh)/texture.height(), color),
];
let indices: [u16; 6] = [0, 1, 2, 0, 2, 3];
context.gl.texture(Some(texture));
context.gl.draw_mode(DrawMode::Triangles);
context.gl.geometry(&vertices, &indices);
}
#[deprecated(since = "0.3.0", note = "Use draw_texture_ex instead")]
pub fn draw_texture_rec(
texture: Texture2D,
x: f32,
y: f32,
w: f32,
h: f32,
sx: f32,
sy: f32,
sw: f32,
sh: f32,
color: Color,
) {
draw_texture_ex(
texture,
x,
y,
color,
DrawTextureParams {
dest_size: Some(vec2(w, h)),
source: Some(Rect {
x: sx,
y: sy,
w: sw,
h: sh,
}),
..Default::default()
},
);
}