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() | ||||
|    print("Hello from \"init\"") | ||||
|    print(couch.root:find_node("cube"):get_transform()) | ||||
|    couch.debug("init") | ||||
|    couch.say_hello("dane", "Hi!") | ||||
| end | ||||
|  | ||||
| @ -2,34 +2,35 @@ use nalgebra_glm as glm; | ||||
| 
 | ||||
| use crate::model::Model; | ||||
| 
 | ||||
| use std::rc::Rc; | ||||
| use std::cell::RefCell; | ||||
| 
 | ||||
| pub type NodeRef = Rc<RefCell<Node>>; | ||||
| 
 | ||||
| pub struct Node { | ||||
|     pub name: String, | ||||
|     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 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 { | ||||
|     ($t:ty, $e:path) => { | ||||
| 	impl Childbearing<$t> for Node { | ||||
| 	    fn add_child(&mut self, name: &str, child: $t) { | ||||
| 		self.children.push(Node::new(name.to_string(), $e(Box::new(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, | ||||
| 		} | ||||
| 		self.children.push(Rc::new(RefCell::new(Node::new(name.to_string(), $e(child))))); | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
| @ -49,8 +50,8 @@ impl Node { | ||||
| 
 | ||||
| pub enum GameObject { | ||||
|     Null, | ||||
|     Camera(Box<Camera>), | ||||
|     Mesh(Box<Mesh>), | ||||
|     Camera(Camera), | ||||
|     Mesh(Mesh), | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Copy)] | ||||
|  | ||||
							
								
								
									
										50
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								src/main.rs
									
									
									
									
									
								
							| @ -1,17 +1,20 @@ | ||||
| mod device; | ||||
| 
 | ||||
| mod model; | ||||
| use model::Model; | ||||
| 
 | ||||
| mod scripting; | ||||
| use scripting::{ ScriptLang, Lua }; | ||||
| 
 | ||||
| mod gameobject; | ||||
| use gameobject::*; | ||||
| 
 | ||||
| #[macro_use] | ||||
| extern crate glium; | ||||
| extern crate nalgebra_glm as glm; | ||||
| 
 | ||||
| use model::Model; | ||||
| 
 | ||||
| use scripting::{ ScriptLang, Lua }; | ||||
| 
 | ||||
| use gameobject::*; | ||||
| use std::rc::Rc; | ||||
| use std::cell::RefCell; | ||||
| 
 | ||||
| fn main() { | ||||
|     use glium::{glutin, Surface}; | ||||
| @ -30,18 +33,22 @@ fn main() { | ||||
| 
 | ||||
|     let mut device_manager = crate::device::DeviceManager::new(); | ||||
| 
 | ||||
|     let mut root = Node::new("_root_".to_string(), GameObject::Null); | ||||
|     root.add_child("camera", Camera::new()); | ||||
|     let root = Rc::new(RefCell::new(Node::new("_root_".to_string(), GameObject::Null))); | ||||
|     { | ||||
| 	// 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")); | ||||
|     cube.set_transform(gameobject::Transform { | ||||
| 	position: glm::vec3(0.0, 0.0, -10.0), | ||||
| 	rotation: glm::vec3(0.0, 15.0_f32.to_radians(), 0.0), | ||||
| 	scale: glm::vec3(1.0, 1.0, 1.0), | ||||
|     }); | ||||
|     root.add_child("cube", cube); | ||||
| 	let mut cube = Mesh::new(Model::new(&display, "Box.glb")); | ||||
| 	cube.set_transform(gameobject::Transform { | ||||
| 	    position: glm::vec3(0.0, 0.0, -10.0), | ||||
| 	    rotation: glm::vec3(0.0, 15.0_f32.to_radians(), 0.0), | ||||
| 	    scale: glm::vec3(1.0, 1.0, 1.0), | ||||
| 	}); | ||||
| 	root.add_child("cube", cube); | ||||
|     } | ||||
| 	
 | ||||
|     let mut script_lang = Lua::new(); | ||||
|     let mut script_lang = Lua::new(Rc::clone(&root)); | ||||
|     script_lang.init(); | ||||
| 
 | ||||
|     let mut last_draw = std::time::Instant::now(); | ||||
| @ -77,8 +84,15 @@ fn main() { | ||||
| 		    .. Default::default() | ||||
| 		}; | ||||
| 		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(); | ||||
| 		if device_manager.is_pressed(&device::Key::W) { | ||||
| 		    transform.position.z += 1.0 * delta; | ||||
| @ -101,8 +115,6 @@ fn main() { | ||||
| 		}; | ||||
| 		cube.model.draw(&mut target, &program, &uniforms, ¶ms); | ||||
| 
 | ||||
| 		let _camera: &mut Box<Camera> = root.find_node("camera").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::chunk; | ||||
| 
 | ||||
| use std::rc::Rc; | ||||
| use std::cell::RefCell; | ||||
| 
 | ||||
| pub trait ScriptLang { | ||||
|     fn init(&mut self); | ||||
|     fn update(&mut self, delta: f32); | ||||
| @ -12,12 +16,35 @@ pub struct Lua { | ||||
|     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 { | ||||
|     pub fn new() -> Self { | ||||
|     pub fn new(root: Rc<RefCell<Node>>) -> Self { | ||||
| 	// Create a lua context, load std libraries
 | ||||
| 	let ctx = LuaContext::new(); | ||||
| 	// Create the ``couch'' api
 | ||||
| 	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("say_hello", ctx.create_function(say_hello).unwrap()).unwrap(); | ||||
| 	// Hook in to globals
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user