use crate::model::LoadedModel; use crate::render::RenderState; use mlua::{Lua, LuaSerdeExt, Result, Value}; use parking_lot::RwLock; use serde::{Deserialize, Serialize}; use std::path::{Path, PathBuf}; use std::sync::Arc; impl mlua::UserData for LoadedModel {} pub struct ScriptData { root_path: PathBuf, render_state: Arc>, } #[derive(Copy, Clone, Debug, Deserialize, Serialize)] pub struct Transform { #[serde(default)] pub position: glam::Vec3, #[serde(default)] pub orientation: glam::Quat, } impl Transform { pub fn to_mat4(&self) -> glam::Mat4 { glam::Mat4::from_rotation_translation(self.orientation, self.position) } } fn load_gltf(lua: &Lua, filename: String) -> Result { let data = lua.app_data_ref::().unwrap(); let model = crate::import::load_gltf(data.root_path.join(filename).into()); let loaded = data.render_state.write().load_model(&model); Ok(loaded) } fn spawn_model(lua: &Lua, model: (LoadedModel, Value)) -> Result<()> { let data = lua.app_data_ref::().unwrap(); let transform: Transform = lua.from_value(model.1)?; let transform = transform.to_mat4(); data.render_state.write().spawn_model(&model.0, &transform); Ok(()) } pub struct Script { lua: Lua, } impl Script { pub fn new(file: &Path, render_state: Arc>) -> Self { let lua = Lua::new(); let data = ScriptData { root_path: file.parent().unwrap().into(), render_state, }; lua.set_app_data(data); Self::load_cyborg_lib(&lua).unwrap(); let src = std::fs::read_to_string(file).unwrap(); lua.load(&src).eval::().unwrap(); Self { lua } } pub fn load_cyborg_lib(lua: &Lua) -> Result<()> { let lib = lua.create_table()?; lib.set("load_gltf", lua.create_function(load_gltf)?)?; lib.set("spawn_model", lua.create_function(spawn_model)?)?; lua.globals().set("cyborg", lib)?; Ok(()) } }