prime-forge 0.3.21

Forged in Lost Lands is a simple game engine built in Rust that focuses on data control and ease of use
Documentation
use std::{
    cell::RefCell,
    rc::{Rc, Weak},
};

use crate::lost_realm::LostRealm;

use super::EtherealFlow;

use nalgebra_glm as glm;

pub trait ForgedTrait: ForgedHierarchy {
    #[allow(unused_variables)]
    fn start(&mut self, lost_realm: &mut LostRealm) {}
    #[allow(unused_variables)]
    fn update(&mut self, lost_realm: &mut LostRealm, dt: f32) {}
}

pub trait ForgedHierarchy: EtherealFlow {
    fn set_father(&mut self, father_id: String);
    fn get_father(&self) -> Option<String>;
}

pub struct TransformSpecialTrait {
    pub position: glm::Vec3,
    pub rotation: glm::Vec3,
    pub scale: glm::Vec3,
    id: uuid::Uuid,
    parent: Option<Weak<RefCell<TransformSpecialTrait>>>,
    children: Vec<Rc<RefCell<TransformSpecialTrait>>>,
    pub model_matrix: glm::Mat4,
}

impl Default for TransformSpecialTrait {
    fn default() -> Self {
        Self {
            position: glm::vec3(0.0, 0.0, 0.0),
            rotation: glm::vec3(0.0, 0.0, 0.0),
            scale: glm::vec3(1.0, 1.0, 1.0),
            children: Vec::new(),
            parent: None,
            model_matrix: glm::Mat4::identity(),
            id: uuid::Uuid::new_v4(),
        }
    }
}

impl TransformSpecialTrait {
    pub fn new() -> Self {
        Self {
            ..Default::default()
        }
    }

    pub fn with_position(mut self, position: glm::Vec3) -> Self {
        self.position = position;
        self.update_self_and_children();
        self
    }

    pub fn with_rotation(mut self, rotation: glm::Vec3) -> Self {
        self.rotation = rotation;
        self.update_self_and_children();
        self
    }

    pub fn with_scale(mut self, scale: glm::Vec3) -> Self {
        self.scale = scale;
        self.update_self_and_children();
        self
    }

    pub(crate) fn set_parent(&mut self, parent: Rc<RefCell<TransformSpecialTrait>>) {
        if let Some(parent) = self.get_parent() {
            parent
                .borrow_mut()
                .children
                .retain(|child| child.borrow().id != self.id);
        }
        self.parent = Some(Rc::downgrade(&parent));
    }

    pub(crate) fn set_children(&mut self, children: Vec<Rc<RefCell<TransformSpecialTrait>>>) {
        if children.len() > 0 {
            self.children.extend(children.iter().cloned());
        } else {
            self.children = children;
        }
    }

    pub fn get_parent(&self) -> Option<Rc<RefCell<TransformSpecialTrait>>> {
        self.parent.as_ref().and_then(|parent| parent.upgrade())
    }

    pub fn get_children(&self) -> Vec<Rc<RefCell<TransformSpecialTrait>>> {
        self.children.clone()
    }

    pub fn get_local_model_matrix(&self) -> glm::Mat4 {
        let transform_x = glm::rotate(
            &glm::Mat4::identity(),
            self.rotation.x.to_radians(),
            &glm::vec3(1.0, 0.0, 0.0),
        );

        let transform_y = glm::rotate(
            &glm::Mat4::identity(),
            self.rotation.y.to_radians(),
            &glm::vec3(0.0, 1.0, 0.0),
        );

        let transform_z = glm::rotate(
            &glm::Mat4::identity(),
            self.rotation.z.to_radians(),
            &glm::vec3(0.0, 0.0, 1.0),
        );

        let rotation = transform_x * transform_y * transform_z;

        let model = glm::Mat4::identity();
        let model = glm::translate(&model, &self.position);
        let model = model * rotation;
        let model = glm::scale(&model, &self.scale);

        model
    }

    pub fn update_self_and_children(&mut self) {
        self.model_matrix = if let Some(parent) = self.get_parent() {
            let parent = unsafe {
                let ptr = parent.as_ptr() as *const TransformSpecialTrait;
                &*ptr
            };
            parent.model_matrix * self.get_local_model_matrix()
        } else {
            self.get_local_model_matrix()
        };

        println!("Model Matrix: {:?}", self.model_matrix);

        for child in self.children.iter() {
            child.borrow_mut().update_self_and_children();
        }
    }
}