use crate::{
asset::{AssetManager, AssetState, AssetType},
render::buffer::Buffer,
util::{PointF32, Rect},
};
#[cfg(graphics_mode)]
use crate::render::graph::{get_ratio_x, get_ratio_y, PIXEL_SYM_HEIGHT, PIXEL_SYM_WIDTH};
use std::ops::{Deref, DerefMut};
mod layer;
pub use layer::Layer;
pub use crate::render::buffer::{SYMBOL_LINE, Borders, BorderType};
#[macro_export]
macro_rules! asset2sprite {
($spr:expr, $ctx:expr, $loc:expr $(, $arg:expr)* ) => {{
let ll = $loc.to_lowercase();
let mut at = AssetType::ImgPix;
if ll.ends_with(".txt") {
at = AssetType::ImgEsc;
}
if ll.ends_with(".pix") {
at = AssetType::ImgPix;
}
if ll.ends_with(".ssf") {
at = AssetType::ImgSsf;
}
let mut va = Vec::new();
$( va.push($arg); )*
let mut frame_idx = 0;
let mut x = 0;
let mut y = 0;
match va.len() {
1 => {
frame_idx = va[0];
},
3 => {
frame_idx = va[0];
x = va[1] as u16;
y = va[2] as u16;
},
_ => {},
}
let nl = if cfg!(not(target_arch = "wasm32")) {
&format!("{}{}assets{}{}",
rust_pixel::get_game_config().project_path,
std::path::MAIN_SEPARATOR,
std::path::MAIN_SEPARATOR,
$loc)
} else {
&format!("assets{}{}", std::path::MAIN_SEPARATOR, $loc)
};
$spr.set_content_by_asset(
&mut $ctx.asset_manager,
at,
nl,
frame_idx,
x,
y,
);
$spr.check_asset_request(&mut $ctx.asset_manager)
}};
}
#[macro_export]
macro_rules! asset2sprite_raw {
($spr:expr, $ctx:expr, $loc:expr $(, $arg:expr)* ) => {{
let ll = $loc.to_lowercase();
let mut at = AssetType::ImgPix;
if ll.ends_with(".txt") {
at = AssetType::ImgEsc;
}
if ll.ends_with(".pix") {
at = AssetType::ImgPix;
}
if ll.ends_with(".ssf") {
at = AssetType::ImgSsf;
}
let mut va = Vec::new();
$( va.push($arg); )*
let mut frame_idx = 0;
let mut x = 0;
let mut y = 0;
match va.len() {
1 => {
frame_idx = va[0];
},
3 => {
frame_idx = va[0];
x = va[1] as u16;
y = va[2] as u16;
},
_ => {},
}
let nl = $loc;
$spr.set_content_by_asset(
&mut $ctx.asset_manager,
at,
nl,
frame_idx,
x,
y,
);
}};
}
pub trait Widget {
fn render(&mut self, am: &mut AssetManager, buf: &mut Buffer);
}
#[derive(Clone)]
pub struct Sprite {
pub content: Buffer,
pub angle: f64,
pub alpha: u8,
pub scale_x: f32, pub scale_y: f32, pub use_tui: bool, asset_request: Option<(AssetType, String, usize, u16, u16)>,
render_weight: i32,
}
impl Widget for Sprite {
fn render(&mut self, am: &mut AssetManager, buf: &mut Buffer) {
if !self.is_hidden() {
self.check_asset_request(am);
buf.merge(&self.content, self.alpha, true);
}
}
}
impl Deref for Sprite {
type Target = Buffer;
fn deref(&self) -> &Buffer {
&self.content
}
}
impl DerefMut for Sprite {
fn deref_mut(&mut self) -> &mut Buffer {
&mut self.content
}
}
impl Sprite {
pub fn new(x: u16, y: u16, width: u16, height: u16) -> Self {
let area = Rect::new(x, y, width, height);
let buffer = Buffer::empty_sprite(area); Self {
content: buffer,
angle: 0.0,
alpha: 255,
scale_x: 1.0, scale_y: 1.0, use_tui: false, asset_request: None,
render_weight: 1,
}
}
pub fn new_tui(x: u16, y: u16, width: u16, height: u16) -> Self {
let area = Rect::new(x, y, width, height);
let buffer = Buffer::empty(area); Self {
content: buffer,
angle: 0.0,
alpha: 255,
scale_x: 1.0,
scale_y: 1.0,
use_tui: true, asset_request: None,
render_weight: 1,
}
}
pub fn set_alpha(&mut self, a: u8) {
self.alpha = a;
}
pub fn set_scale_x(&mut self, scale: f32) {
self.scale_x = scale;
}
pub fn set_scale_y(&mut self, scale: f32) {
self.scale_y = scale;
}
pub fn set_scale(&mut self, scale: f32) {
self.scale_x = scale;
self.scale_y = scale;
}
pub fn set_use_tui(&mut self, use_tui: bool) {
self.use_tui = use_tui;
}
pub fn new_half_width(x: u16, y: u16, width: u16, height: u16) -> Self {
let mut sprite = Self::new(x, y, width, height);
sprite.set_scale_x(0.5); sprite
}
pub fn set_content_by_asset(
&mut self,
am: &mut AssetManager,
atype: AssetType,
location: &str,
frame_idx: usize,
off_x: u16,
off_y: u16,
) {
self.asset_request = Some((atype, location.to_string(), frame_idx, off_x, off_y));
am.load(atype, location);
self.check_asset_request(am);
}
pub fn check_asset_request(&mut self, am: &mut AssetManager) -> bool {
if let Some(req) = &self.asset_request {
if let Some(ast) = am.get(&req.1) {
if ast.get_state() == AssetState::Ready {
ast.set_sprite(self, req.2, req.3, req.4);
self.asset_request = None;
return true;
}
}
} else {
return true;
}
false
}
pub fn set_angle(&mut self, a: f64) {
self.angle = a;
}
pub fn get_center_point(&self) -> PointF32 {
PointF32 {
x: self.content.area.x as f32 + self.content.area.width as f32 / 2.0,
y: self.content.area.y as f32 + self.content.area.height as f32 / 2.0,
}
}
pub fn set_hidden(&mut self, flag: bool) {
if flag {
self.render_weight = -self.render_weight.abs();
} else {
self.render_weight = self.render_weight.abs();
}
}
pub fn is_hidden(&self) -> bool {
self.render_weight < 0
}
pub fn copy_content(&mut self, sp: &Sprite) {
let backup_area = self.content.area;
self.content.area = Rect::new(0, 0, backup_area.width, backup_area.height);
self.content.reset();
self.content.merge(&sp.content, sp.alpha, false);
self.content.area = backup_area;
}
pub fn set_pos(&mut self, x: u16, y: u16) {
self.content.area = Rect::new(x, y, self.content.area.width, self.content.area.height);
}
#[cfg(not(graphics_mode))]
pub fn set_cell_pos(&mut self, x: u16, y: u16) {
self.set_pos(x, y);
}
#[cfg(graphics_mode)]
pub fn set_cell_pos(&mut self, x: u16, y: u16) {
let sym_w = PIXEL_SYM_WIDTH.get().copied().unwrap_or(16.0);
let sym_h = PIXEL_SYM_HEIGHT.get().copied().unwrap_or(16.0);
let rx = get_ratio_x();
let ry = get_ratio_y();
let pixel_x = (x as f32 * sym_w / rx) as u16;
let pixel_y = (y as f32 * sym_h / ry) as u16;
self.set_pos(pixel_x, pixel_y);
}
pub fn set_pixel_pos(&mut self, x: f32, y: f32) {
self.set_pos(x.round() as u16, y.round() as u16);
}
pub fn pixel_pos(&self) -> (f32, f32) {
(self.content.area.x as f32, self.content.area.y as f32)
}
}