utilities/src/helperfunctions.rs
2023-01-16 10:47:56 +01:00

143 lines
3.5 KiB
Rust

//! Basic helper functions
use std::fs;
use std::io::ErrorKind;
use std::rc::Rc;
use std::sync::Arc;
use std::ffi::CStr;
use std::os::raw::c_char;
use assetpath::AssetPath;
use cgmath;
use cgmath::One;
pub fn erase_by_ptr<T>(vector: &mut Vec<T>, object: &T) -> bool {
match vector
.iter()
.position(|t| t as *const T == object as *const T)
{
Some(i) => {
vector.remove(i);
true
}
None => false,
}
}
pub fn erase_arc<T: ?Sized>(vector: &mut Vec<Arc<T>>, object: &Arc<T>) -> Option<Arc<T>> {
match vector.iter().position(|t| Arc::ptr_eq(t, object)) {
Some(i) => Some(vector.remove(i)),
None => None,
}
}
pub fn erase_rc<T: ?Sized>(vector: &mut Vec<Rc<T>>, object: &Rc<T>) -> Option<Rc<T>> {
match vector.iter().position(|t| Rc::ptr_eq(t, object)) {
Some(i) => Some(vector.remove(i)),
None => None,
}
}
pub fn ortho(
left: f32,
right: f32,
bottom: f32,
top: f32,
z_near: f32,
z_far: f32,
) -> cgmath::Matrix4<f32> {
let mut mat = cgmath::Matrix4::one();
mat[0][0] = 2.0 / (right - left);
mat[1][1] = -2.0 / (top - bottom);
mat[2][2] = -2.0 / (z_far - z_near);
mat[3][0] = -(right + left) / (right - left);
mat[3][1] = -(top + bottom) / (top - bottom);
mat[3][2] = -(z_far + z_near) / (z_far - z_near);
mat
}
pub fn search_dir_recursively(
base_dir: &str,
suffix: &str,
) -> Result<Vec<AssetPath>, std::io::Error> {
let mut files = Vec::new();
// simply return an empty result when the path could not be found
// or the user has a lack of permissions
let dir_content = match fs::read_dir(base_dir) {
Ok(dir) => dir,
Err(err) => match err.kind() {
ErrorKind::NotFound | ErrorKind::PermissionDenied => return Ok(files),
_ => return Err(err),
},
};
for fs_object in dir_content {
let obj = fs_object?;
let path = obj.path();
if path.is_file() {
if let Some(os_str) = path.file_name() {
if let Some(string) = os_str.to_str() {
if string.ends_with(suffix) {
files.push(AssetPath::from((base_dir, string)));
}
}
}
} else {
if let Some(string) = path.to_str() {
let more_files = search_dir_recursively(string, suffix)?;
files.extend(more_files);
}
}
}
Ok(files)
}
pub unsafe fn c_char_to_string(cchar: *const c_char) -> String {
CStr::from_ptr(cchar).to_str().unwrap().to_string()
}
#[inline]
pub fn perspective(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) -> cgmath::Matrix4<f32> {
debug_assert!(z_near != 0.0);
let zero = 0.0;
let one = 1.0;
let two = 2.0;
let q = one / (fov_y / two).tan();
let a = q / aspect;
let b = (z_near + z_far) / (z_near - z_far);
let c = (two * z_near * z_far) / (z_near - z_far);
#[cfg_attr(rustfmt, rustfmt_skip)]
cgmath::Matrix4::new(
a, zero, zero, zero,
zero, -q, zero, zero,
zero, zero, b, zero - one,
zero, zero, c, zero,
)
}
#[inline]
pub fn rotate_z(v: cgmath::Vector3<f32>, angle: f32) -> cgmath::Vector3<f32> {
let mut result = v;
let cos = angle.cos();
let sin = angle.sin();
result.x = v.x * cos - v.y * sin;
result.y = v.x * sin + v.y * cos;
result
}
#[inline]
pub fn almost_eq(f1: f32, f2: f32) -> bool {
(f1 - f2).abs() <= std::f32::EPSILON
}