pub mod advance_front;
pub mod app;
pub mod background;
pub mod basic_front;
use egui::Ui;
use std::{
any::{Any, type_name, type_name_of_val},
error::Error,
fmt::{Debug, Display, Formatter},
time::Instant,
vec::Vec,
};
pub trait RustConstructorResource: Debug + Send + Sync {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn display_display_info(&self) -> Option<DisplayInfo>;
fn modify_display_info(&mut self, display_info: DisplayInfo);
fn display_tags(&self) -> Vec<[String; 2]>;
fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool);
}
pub trait BasicFrontResource: RustConstructorResource {
fn display_basic_front_resource_config(&self) -> BasicFrontResourceConfig;
fn display_position_size_config(&self) -> PositionSizeConfig;
fn display_clip_rect(&self) -> Option<PositionSizeConfig>;
fn display_position(&self) -> [f32; 2];
fn display_size(&self) -> [f32; 2];
fn modify_basic_front_resource_config(
&mut self,
basic_front_resource_config: BasicFrontResourceConfig,
);
fn modify_position_size_config(&mut self, position_size_config: PositionSizeConfig);
fn modify_clip_rect(&mut self, clip_rect: Option<PositionSizeConfig>);
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct RustConstructorId {
pub name: String,
pub discern_type: String,
}
#[derive(Debug)]
pub struct RustConstructorResourceBox {
pub id: RustConstructorId,
pub content: Box<dyn RustConstructorResource>,
}
unsafe impl Send for RustConstructorResourceBox {}
unsafe impl Sync for RustConstructorResourceBox {}
impl RustConstructorResourceBox {
pub fn new(name: &str, discern_type: &str, content: Box<dyn RustConstructorResource>) -> Self {
Self {
id: RustConstructorId {
name: name.to_string(),
discern_type: discern_type.to_string(),
},
content,
}
}
}
#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
pub struct BasicFrontResourceConfig {
pub position_size_config: PositionSizeConfig,
pub clip_rect: Option<PositionSizeConfig>,
}
impl BasicFrontResourceConfig {
#[inline]
pub fn position_size_config(mut self, position_size_config: PositionSizeConfig) -> Self {
self.position_size_config = position_size_config;
self
}
#[inline]
pub fn clip_rect(mut self, clip_rect: Option<PositionSizeConfig>) -> Self {
self.clip_rect = clip_rect;
self
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct PositionSizeConfig {
pub origin_position: [f32; 2],
pub origin_size: [f32; 2],
pub x_location_grid: [f32; 2],
pub y_location_grid: [f32; 2],
pub x_size_grid: [f32; 2],
pub y_size_grid: [f32; 2],
pub display_method: (HorizontalAlign, VerticalAlign),
pub offset: [f32; 2],
}
impl Default for PositionSizeConfig {
fn default() -> Self {
PositionSizeConfig {
origin_position: [0_f32, 0_f32],
origin_size: [0_f32, 0_f32],
x_location_grid: [0_f32, 0_f32],
y_location_grid: [0_f32, 0_f32],
x_size_grid: [0_f32, 0_f32],
y_size_grid: [0_f32, 0_f32],
display_method: (HorizontalAlign::default(), VerticalAlign::default()),
offset: [0_f32, 0_f32],
}
}
}
impl PositionSizeConfig {
#[inline]
pub fn origin_position(mut self, x: f32, y: f32) -> Self {
self.origin_position = [x, y];
self
}
#[inline]
pub fn origin_size(mut self, width: f32, height: f32) -> Self {
self.origin_size = [width, height];
self
}
#[inline]
pub fn x_size_grid(mut self, fetch: f32, total: f32) -> Self {
self.x_size_grid = [fetch, total];
self
}
#[inline]
pub fn y_size_grid(mut self, fetch: f32, total: f32) -> Self {
self.y_size_grid = [fetch, total];
self
}
#[inline]
pub fn x_location_grid(mut self, fetch: f32, total: f32) -> Self {
self.x_location_grid = [fetch, total];
self
}
#[inline]
pub fn y_location_grid(mut self, fetch: f32, total: f32) -> Self {
self.y_location_grid = [fetch, total];
self
}
#[inline]
pub fn display_method(
mut self,
horizontal_align: HorizontalAlign,
vertical_align: VerticalAlign,
) -> Self {
self.display_method = (horizontal_align, vertical_align);
self
}
#[inline]
pub fn offset(mut self, x: f32, y: f32) -> Self {
self.offset = [x, y];
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Timer {
pub start_time: u128,
pub total_time: u128,
pub timer: Instant,
pub now_time: u128,
}
impl Default for Timer {
fn default() -> Self {
Timer {
start_time: 0,
total_time: 0,
timer: Instant::now(),
now_time: 0,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct RustConstructorError {
pub error_id: String,
pub description: String,
}
impl Display for RustConstructorError {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
Debug::fmt(self, f)
}
}
impl Error for RustConstructorError {}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum HorizontalAlign {
#[default]
Left,
Center,
Right,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum VerticalAlign {
#[default]
Top,
Center,
Bottom,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum BorderKind {
#[default]
Inside,
Middle,
Outside,
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum RenderConfig {
Line(f32, [u8; 4]),
Rect([u8; 4], [u8; 4], [u8; 4], f32, BorderKind),
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct DisplayInfo {
pub enable: bool,
pub hidden: bool,
pub ignore_render_layer: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum RequestMethod {
Id(RustConstructorId),
Citer(RustConstructorId),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum RequestType {
Top,
Up(usize),
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum ListInfoDescribeMethod {
Detailed(bool),
#[default]
Simple,
}
pub fn type_processor(target: &impl RustConstructorResource) -> String {
let result: Vec<_> = if let Some(list) = type_name_of_val(target).split_once("<") {
list.0
} else {
type_name_of_val(&target)
}
.split("::")
.collect();
result[result.len() - 1].to_string()
}
pub fn get_tag(tag_name: &str, target: &[[String; 2]]) -> Option<(usize, String)> {
target
.iter()
.position(|x| x[0] == tag_name)
.map(|index| (index, target[index][1].clone()))
}
pub fn downcast_resource<T: RustConstructorResource + 'static>(
resource: &dyn RustConstructorResource,
) -> Result<&T, RustConstructorError> {
if let Some(resource) = resource.as_any().downcast_ref::<T>() {
Ok(resource)
} else {
Err(RustConstructorError {
error_id: "ResourceDowncastTypeMismatch".to_string(),
description: format!(
"Failed to downcast resource to type '{}'.",
type_name::<T>()
),
})
}
}
pub fn downcast_resource_mut<T: RustConstructorResource + 'static>(
resource: &mut dyn RustConstructorResource,
) -> Result<&mut T, RustConstructorError> {
if let Some(resource) = resource.as_any_mut().downcast_mut::<T>() {
Ok(resource)
} else {
Err(RustConstructorError {
error_id: "ResourceDowncastTypeMismatch".to_string(),
description: format!(
"Failed to downcast resource to type '{}'.",
type_name::<T>()
),
})
}
}
pub fn position_size_processor(position_size_config: PositionSizeConfig, ui: &Ui) -> [[f32; 2]; 2] {
let mut position = [0_f32, 0_f32];
let mut size = [0_f32, 0_f32];
size[0] = match position_size_config.x_size_grid[0] {
0_f32 => position_size_config.origin_size[0],
_ => {
(ui.available_width() / position_size_config.x_size_grid[1]
* position_size_config.x_size_grid[0])
+ position_size_config.origin_size[0]
}
};
size[1] = match position_size_config.y_size_grid[0] {
0_f32 => position_size_config.origin_size[1],
_ => {
(ui.available_height() / position_size_config.y_size_grid[1]
* position_size_config.y_size_grid[0])
+ position_size_config.origin_size[1]
}
};
position[0] = match position_size_config.x_location_grid[1] {
0_f32 => position_size_config.origin_position[0],
_ => {
(ui.available_width() / position_size_config.x_location_grid[1]
* position_size_config.x_location_grid[0])
+ position_size_config.origin_position[0]
}
};
position[1] = match position_size_config.y_location_grid[1] {
0_f32 => position_size_config.origin_position[1],
_ => {
(ui.available_height() / position_size_config.y_location_grid[1]
* position_size_config.y_location_grid[0])
+ position_size_config.origin_position[1]
}
};
match position_size_config.display_method.0 {
HorizontalAlign::Left => {}
HorizontalAlign::Center => position[0] -= size[0] / 2.0,
HorizontalAlign::Right => position[0] -= size[0],
};
match position_size_config.display_method.1 {
VerticalAlign::Top => {}
VerticalAlign::Center => position[1] -= size[1] / 2.0,
VerticalAlign::Bottom => position[1] -= size[1],
};
position[0] += position_size_config.offset[0];
position[1] += position_size_config.offset[1];
[position, size]
}