Start implementing lua scripting
This commit is contained in:
parent
0e6cc64c89
commit
d6b5f82d72
1
main.lua
1
main.lua
@ -2,6 +2,7 @@ print("Hello from a lua script!")
|
|||||||
|
|
||||||
function init()
|
function init()
|
||||||
print("Hello from \"init\"")
|
print("Hello from \"init\"")
|
||||||
|
print(couch.root:find_node("cube"):get_transform())
|
||||||
couch.debug("init")
|
couch.debug("init")
|
||||||
couch.say_hello("dane", "Hi!")
|
couch.say_hello("dane", "Hi!")
|
||||||
end
|
end
|
||||||
|
@ -2,34 +2,35 @@ use nalgebra_glm as glm;
|
|||||||
|
|
||||||
use crate::model::Model;
|
use crate::model::Model;
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
pub type NodeRef = Rc<RefCell<Node>>;
|
||||||
|
|
||||||
pub struct Node {
|
pub struct Node {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub gameobject: GameObject,
|
pub gameobject: GameObject,
|
||||||
pub children: Vec<Node>,
|
pub children: Vec<NodeRef>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Childbearing<T> {
|
pub trait Childbearing<T> { // TODO remove this
|
||||||
fn add_child(&mut self, name: &str, child: T);
|
fn add_child(&mut self, name: &str, child: T);
|
||||||
fn find_node(&mut self, name: &str) -> Option<&mut Box<T>>;
|
}
|
||||||
|
|
||||||
|
impl Node {
|
||||||
|
pub fn find_node(&mut self, name: &str) -> Option<NodeRef> {
|
||||||
|
match self.children.iter().find(|node| node.borrow().name == name) {
|
||||||
|
Some(node) => Some(Rc::clone(node)),
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_childbearing {
|
macro_rules! impl_childbearing {
|
||||||
($t:ty, $e:path) => {
|
($t:ty, $e:path) => {
|
||||||
impl Childbearing<$t> for Node {
|
impl Childbearing<$t> for Node {
|
||||||
fn add_child(&mut self, name: &str, child: $t) {
|
fn add_child(&mut self, name: &str, child: $t) {
|
||||||
self.children.push(Node::new(name.to_string(), $e(Box::new(child))));
|
self.children.push(Rc::new(RefCell::new(Node::new(name.to_string(), $e(child)))));
|
||||||
}
|
|
||||||
fn find_node(&mut self, name: &str) -> Option<&mut Box<$t>> {
|
|
||||||
match self.children.iter_mut().find(|node| node.name == name) {
|
|
||||||
Some(node) => {
|
|
||||||
if let $e(child) = &mut node.gameobject {
|
|
||||||
Some(child)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,8 +50,8 @@ impl Node {
|
|||||||
|
|
||||||
pub enum GameObject {
|
pub enum GameObject {
|
||||||
Null,
|
Null,
|
||||||
Camera(Box<Camera>),
|
Camera(Camera),
|
||||||
Mesh(Box<Mesh>),
|
Mesh(Mesh),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
50
src/main.rs
50
src/main.rs
@ -1,17 +1,20 @@
|
|||||||
mod device;
|
mod device;
|
||||||
|
|
||||||
mod model;
|
mod model;
|
||||||
|
use model::Model;
|
||||||
|
|
||||||
mod scripting;
|
mod scripting;
|
||||||
|
use scripting::{ ScriptLang, Lua };
|
||||||
|
|
||||||
mod gameobject;
|
mod gameobject;
|
||||||
|
use gameobject::*;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate glium;
|
extern crate glium;
|
||||||
extern crate nalgebra_glm as glm;
|
extern crate nalgebra_glm as glm;
|
||||||
|
|
||||||
use model::Model;
|
use std::rc::Rc;
|
||||||
|
use std::cell::RefCell;
|
||||||
use scripting::{ ScriptLang, Lua };
|
|
||||||
|
|
||||||
use gameobject::*;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
use glium::{glutin, Surface};
|
use glium::{glutin, Surface};
|
||||||
@ -30,18 +33,22 @@ fn main() {
|
|||||||
|
|
||||||
let mut device_manager = crate::device::DeviceManager::new();
|
let mut device_manager = crate::device::DeviceManager::new();
|
||||||
|
|
||||||
let mut root = Node::new("_root_".to_string(), GameObject::Null);
|
let root = Rc::new(RefCell::new(Node::new("_root_".to_string(), GameObject::Null)));
|
||||||
root.add_child("camera", Camera::new());
|
{
|
||||||
|
// Initial scene setup
|
||||||
|
let mut root = root.borrow_mut();
|
||||||
|
root.add_child("camera", Camera::new());
|
||||||
|
|
||||||
let mut cube = Mesh::new(Model::new(&display, "Box.glb"));
|
let mut cube = Mesh::new(Model::new(&display, "Box.glb"));
|
||||||
cube.set_transform(gameobject::Transform {
|
cube.set_transform(gameobject::Transform {
|
||||||
position: glm::vec3(0.0, 0.0, -10.0),
|
position: glm::vec3(0.0, 0.0, -10.0),
|
||||||
rotation: glm::vec3(0.0, 15.0_f32.to_radians(), 0.0),
|
rotation: glm::vec3(0.0, 15.0_f32.to_radians(), 0.0),
|
||||||
scale: glm::vec3(1.0, 1.0, 1.0),
|
scale: glm::vec3(1.0, 1.0, 1.0),
|
||||||
});
|
});
|
||||||
root.add_child("cube", cube);
|
root.add_child("cube", cube);
|
||||||
|
}
|
||||||
|
|
||||||
let mut script_lang = Lua::new();
|
let mut script_lang = Lua::new(Rc::clone(&root));
|
||||||
script_lang.init();
|
script_lang.init();
|
||||||
|
|
||||||
let mut last_draw = std::time::Instant::now();
|
let mut last_draw = std::time::Instant::now();
|
||||||
@ -77,8 +84,15 @@ fn main() {
|
|||||||
.. Default::default()
|
.. Default::default()
|
||||||
};
|
};
|
||||||
target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
|
target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
|
||||||
|
|
||||||
let cube: &mut Box<Mesh> = root.find_node("cube").unwrap();
|
let mut root = root.borrow_mut();
|
||||||
|
|
||||||
|
let cube = root.find_node("cube").unwrap();
|
||||||
|
let mut cube = cube.borrow_mut();
|
||||||
|
let cube: &mut Mesh = match &mut cube.gameobject {
|
||||||
|
GameObject::Mesh(mesh) => mesh,
|
||||||
|
_ => panic!("cube is not a mesh"),
|
||||||
|
};
|
||||||
let mut transform = cube.get_transform();
|
let mut transform = cube.get_transform();
|
||||||
if device_manager.is_pressed(&device::Key::W) {
|
if device_manager.is_pressed(&device::Key::W) {
|
||||||
transform.position.z += 1.0 * delta;
|
transform.position.z += 1.0 * delta;
|
||||||
@ -101,8 +115,6 @@ fn main() {
|
|||||||
};
|
};
|
||||||
cube.model.draw(&mut target, &program, &uniforms, ¶ms);
|
cube.model.draw(&mut target, &program, &uniforms, ¶ms);
|
||||||
|
|
||||||
let _camera: &mut Box<Camera> = root.find_node("camera").unwrap();
|
|
||||||
|
|
||||||
target.finish().unwrap();
|
target.finish().unwrap();
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
extern crate mlua;
|
use crate::gameobject::{ Node, Transform, Spatial };
|
||||||
|
|
||||||
|
extern crate mlua;
|
||||||
use mlua::Lua as LuaContext;
|
use mlua::Lua as LuaContext;
|
||||||
use mlua::chunk;
|
use mlua::chunk;
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
pub trait ScriptLang {
|
pub trait ScriptLang {
|
||||||
fn init(&mut self);
|
fn init(&mut self);
|
||||||
fn update(&mut self, delta: f32);
|
fn update(&mut self, delta: f32);
|
||||||
@ -12,12 +16,35 @@ pub struct Lua {
|
|||||||
ctx: LuaContext,
|
ctx: LuaContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl mlua::UserData for Node {
|
||||||
|
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
use crate::gameobject::GameObject::*;
|
||||||
|
methods.add_method_mut("find_node", |_, this, name: String| {
|
||||||
|
let child = this.find_node(&name);
|
||||||
|
match child {
|
||||||
|
Some(child) => Ok(child),
|
||||||
|
None => Err(mlua::Error::RuntimeError("Could not find child".to_string())),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
methods.add_method("get_transform", |_, this, _: ()| {
|
||||||
|
match &this.gameobject {
|
||||||
|
Mesh(mesh) => Ok(mesh.get_transform()),
|
||||||
|
Camera(camera) => Ok(camera.get_transform()),
|
||||||
|
_ => Err(mlua::Error::RuntimeError("Node does not implement get_transform".to_string()))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl mlua::UserData for Transform {}
|
||||||
|
|
||||||
impl Lua {
|
impl Lua {
|
||||||
pub fn new() -> Self {
|
pub fn new(root: Rc<RefCell<Node>>) -> Self {
|
||||||
// Create a lua context, load std libraries
|
// Create a lua context, load std libraries
|
||||||
let ctx = LuaContext::new();
|
let ctx = LuaContext::new();
|
||||||
// Create the ``couch'' api
|
// Create the ``couch'' api
|
||||||
let couch = ctx.create_table().unwrap();
|
let couch = ctx.create_table().unwrap();
|
||||||
|
couch.set("root", ctx.create_userdata(root).unwrap()).unwrap();
|
||||||
couch.set("debug", ctx.create_function(debug).unwrap()).unwrap();
|
couch.set("debug", ctx.create_function(debug).unwrap()).unwrap();
|
||||||
couch.set("say_hello", ctx.create_function(say_hello).unwrap()).unwrap();
|
couch.set("say_hello", ctx.create_function(say_hello).unwrap()).unwrap();
|
||||||
// Hook in to globals
|
// Hook in to globals
|
||||||
|
Loading…
Reference in New Issue
Block a user