cyborg/editor/src/script.rs

76 lines
2.0 KiB
Rust

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<RwLock<RenderState>>,
}
#[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<LoadedModel> {
let data = lua.app_data_ref::<ScriptData>().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::<ScriptData>().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<RwLock<RenderState>>) -> 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::<mlua::MultiValue>().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(())
}
}