Bladeren bron

Merge branch 'master' of https://github.com/taylor001/crown

Conflicts:
	engine/lua/LuaVector3.cpp
	engine/world/World.h
Daniele Bartolini 12 jaren geleden
bovenliggende
commit
4b40423e58

+ 1 - 1
CMakeLists.txt

@@ -65,7 +65,7 @@ endif (CROWN_BUILD MATCHES "linux-debug-32")
 
 # executable name
 set (CROWN_EXECUTABLE_NAME crown-${CROWN_BUILD})
-set (CROWN_LIBRARY_NAME crown-${CROWN_BUILD})
+set (CROWN_LIBRARY_NAME crown-lib-${CROWN_BUILD})
 
 # always build the engine
 add_subdirectory(engine)

+ 3 - 0
engine/Android.mk

@@ -181,10 +181,12 @@ LOCAL_SRC_FILES :=\
 	lua/LuaKeyboard.cpp\
 	lua/LuaMath.cpp\
 	lua/LuaMatrix4x4.cpp\
+	lua/LuaMatrix4x4.cpp\
 	lua/LuaMesh.cpp\
 	lua/LuaMouse.cpp\
 	lua/LuaPhysicsWorld.cpp\
 	lua/LuaQuaternion.cpp\
+	lua/LuaQuaternionBox.cpp\
 	lua/LuaRaycast.cpp\
 	lua/LuaResourcePackage.cpp\
 	lua/LuaSoundWorld.cpp\
@@ -195,6 +197,7 @@ LOCAL_SRC_FILES :=\
 	lua/LuaUnit.cpp\
 	lua/LuaVector2.cpp\
 	lua/LuaVector3.cpp\
+	lua/LuaVector3Box.cpp\
 	lua/LuaWindow.cpp\
 	lua/LuaWorld.cpp\
 \

+ 3 - 0
engine/CMakeLists.txt

@@ -337,10 +337,12 @@ set (LUA_SRC
 	lua/LuaKeyboard.cpp
 	lua/LuaMath.cpp
 	lua/LuaMatrix4x4.cpp
+	lua/LuaMatrix4x4Box.cpp
 	lua/LuaMesh.cpp
 	lua/LuaMouse.cpp
 	lua/LuaPhysicsWorld.cpp
 	lua/LuaQuaternion.cpp
+	lua/LuaQuaternionBox.cpp
 	lua/LuaRaycast.cpp
 	lua/LuaResourcePackage.cpp
 	lua/LuaSoundWorld.cpp
@@ -351,6 +353,7 @@ set (LUA_SRC
 	lua/LuaUnit.cpp
 	lua/LuaVector2.cpp
 	lua/LuaVector3.cpp
+	lua/LuaVector3Box.cpp
 	lua/LuaWindow.cpp
 	lua/LuaWorld.cpp
 )

+ 2 - 0
engine/Device.cpp

@@ -390,7 +390,9 @@ void Device::frame()
 	m_last_time = m_current_time;
 	m_time_since_start += m_last_delta_time;
 
+	#if defined(CROWN_DEBUG) || defined(CROWN_DEVELOPMENT)
 	m_console->update();
+	#endif
 
 	if (!m_is_paused)
 	{

+ 1 - 1
engine/core/filesystem/DiskFilesystem.h

@@ -38,7 +38,7 @@ namespace crown
 /// to its absolute counterpart based on the file source's root path.
 /// Accessing files using absolute path directly is also possible,
 /// but platform-specific and thus generally not recommended.
-class DiskFilesystem : public Filesystem
+class CE_EXPORT  DiskFilesystem : public Filesystem
 {
 public:
 

+ 2 - 2
engine/core/json/JSONParser.h

@@ -39,7 +39,7 @@ class DynamicString;
 /// Represents a JSON element.
 /// The objects of this class are valid until the parser
 /// which has generated them, will exist.
-class JSONElement
+class CE_EXPORT JSONElement
 {
 public:
 
@@ -158,7 +158,7 @@ private:
 };
 
 /// Parses JSON documents.
-class JSONParser
+class CE_EXPORT JSONParser
 {
 public:
 

+ 1 - 1
engine/lua/LuaEnvironment.cpp

@@ -109,7 +109,7 @@ void LuaEnvironment::load_module_function(const char* module, const char* name,
 	luaL_register(m_state, module, entry);
 }
 
-//-----------------------------------------------------------
+//-----------------------------------------------------------------------------
 void LuaEnvironment::load_module_enum(const char* module, const char* name, uint32_t value)
 {
 	// Checks table existance

+ 5 - 2
engine/lua/LuaEnvironment.h

@@ -89,6 +89,7 @@ void load_accelerometer(LuaEnvironment& env);
 void load_actor(LuaEnvironment& env);
 void load_camera(LuaEnvironment& env);
 void load_controller(LuaEnvironment& env);
+void load_debug_line(LuaEnvironment& env);
 void load_device(LuaEnvironment& env);
 void load_float_setting(LuaEnvironment& env);
 void load_gui(LuaEnvironment& env);
@@ -96,10 +97,13 @@ void load_int_setting(LuaEnvironment& env);
 void load_keyboard(LuaEnvironment& env);
 void load_math(LuaEnvironment& env);
 void load_matrix4x4(LuaEnvironment& env);
+void load_matrix4x4box(LuaEnvironment& env);
 void load_mesh(LuaEnvironment& env);
 void load_mouse(LuaEnvironment& env);
 void load_physics_world(LuaEnvironment& env);
 void load_quaternion(LuaEnvironment& env);
+void load_quaternionbox(LuaEnvironment& env);
+void load_raycast(LuaEnvironment& env);
 void load_resource_package(LuaEnvironment& env);
 void load_sound_world(LuaEnvironment& env);
 void load_sprite(LuaEnvironment& env);
@@ -108,10 +112,9 @@ void load_touch(LuaEnvironment& env);
 void load_unit(LuaEnvironment& env);
 void load_vector2(LuaEnvironment& env);
 void load_vector3(LuaEnvironment& env);
+void load_vector3box(LuaEnvironment& env);
 void load_window(LuaEnvironment& env);
 void load_world(LuaEnvironment& env);
-void load_debug_line(LuaEnvironment& env);
-void load_raycast(LuaEnvironment& env);
 
 CE_EXPORT int32_t luaopen_libcrown(lua_State* L);
 

+ 83 - 0
engine/lua/LuaMatrix4x4Box.cpp

@@ -0,0 +1,83 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "Matrix4x4.h"
+#include "Vector3.h"
+#include "LuaStack.h"
+#include "LuaEnvironment.h"
+#include "OS.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int matrix4x4box(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Matrix4x4& m = stack.push_matrix4x4box();
+
+	stack.get_global_metatable("Matrix4x4_i_mt");
+	stack.set_metatable();
+
+	Matrix4x4 tm = stack.get_matrix4x4(1);
+
+	m = tm;
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int matrix4x4box_store(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Matrix4x4& m = stack.get_matrix4x4box(1);
+	Matrix4x4 tm = stack.get_matrix4x4(2);
+
+	m = tm;
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int matrix4x4box_unbox(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Matrix4x4& m = stack.get_matrix4x4box(1);
+
+	stack.push_matrix4x4(m);
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+void load_matrix4x4box(LuaEnvironment& env)
+{
+	env.load_module_function("Matrix4x4Box", "new", matrix4x4box);
+	env.load_module_function("Matrix4x4Box", "store", matrix4x4box_store);
+	env.load_module_function("Matrix4x4Box", "unbox", matrix4x4box_unbox);
+}
+
+} // namespace crown

+ 107 - 0
engine/lua/LuaQuaternionBox.cpp

@@ -0,0 +1,107 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "Quaternion.h"
+#include "Vector3.h"
+#include "LuaStack.h"
+#include "LuaEnvironment.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int quaternionbox(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Quaternion& q = stack.push_quaternionbox();
+
+	stack.get_global_metatable("Quaternion_i_mt");
+	stack.set_metatable();
+
+	if (stack.num_args() == 3)
+	{
+		const Vector3& v = stack.get_vector3(1);
+		q.x = v.x;
+		q.y = v.y;
+		q.z = v.z;
+		q.w = stack.get_float(2);
+	}
+	else if (stack.num_args() == 5)
+	{
+		q.x = stack.get_float(1);
+		q.y = stack.get_float(2);
+		q.z = stack.get_float(3);
+		q.w = stack.get_float(4);
+	}
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int quaternionbox_store(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Quaternion& q = stack.get_quaternionbox(1);
+	
+	if (stack.num_args() == 3)
+	{
+		const Vector3& v = stack.get_vector3(1);
+		q.x = v.x;
+		q.y = v.y;
+		q.z = v.z;
+		q.w = stack.get_float(2);
+	}
+	else if (stack.num_args() == 5)
+	{
+		q.x = stack.get_float(1);
+		q.y = stack.get_float(2);
+		q.z = stack.get_float(3);
+		q.w = stack.get_float(4);
+	}
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int quaternionbox_unbox(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Quaternion& q = stack.get_quaternionbox(1);
+
+	stack.push_quaternion(q);
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+void load_quaternionbox(LuaEnvironment& env)
+{
+	env.load_module_function("QuaternionBox", "new", quaternionbox);
+	env.load_module_function("QuaternionBox", "store", quaternionbox_store);
+	env.load_module_function("QuaternionBox", "unbox", quaternionbox_unbox);
+}
+
+} // namespace crown

+ 104 - 20
engine/lua/LuaStack.h

@@ -29,6 +29,11 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "lua.hpp"
 #include "Types.h"
 #include "LuaSystem.h"
+#include "Vector3.h"
+#include "Vector2.h"
+#include "Quaternion.h"
+#include "Matrix4x4.h"
+#include "StringUtils.h"
 
 namespace crown
 {
@@ -40,14 +45,10 @@ struct Actor;
 struct Camera;
 struct Controller;
 struct Gui;
-struct Matrix4x4;
 struct Mesh;
-struct Quaternion;
 struct ResourcePackage;
 struct Sprite;
 struct Unit;
-struct Vector2;
-struct Vector3;
 struct DebugLine;
 struct Raycast;
 
@@ -55,6 +56,8 @@ typedef Id SoundInstanceId;
 typedef Id GuiId;
 typedef Id GuiComponentId;
 
+typedef int (*MetamethodFunction)(lua_State*);
+
 void clear_lua_temporaries();
 
 class LuaStack
@@ -191,6 +194,61 @@ public:
 		lua_settable(m_state, -3);
 	}
 
+	/// Pushes an empty metatable onto the stack.
+	/// When you want to associate a metamethod to a function, you have to use 
+	/// LuaStack::set_metamethod_function(const char* key, MetamethodFunction func).
+	/// Call LuaStack::end_metatable() to associate this metatable to userdata of any kind.
+	///
+	/// stack.push_userdata(); // Could be Vector3Box or a table
+	/// stack.begin_metatable("Foo_mt");
+	/// stack.set_metamethod_function("__index", function_ptr);
+	/// stack.set_metamethod_function("__newindex", another_function_ptr);
+	/// stack.end_metatable();
+	void create_metatable(const char* name)
+	{
+		luaL_newmetatable(m_state, name);
+	}
+
+	/// See LuaStack::begin_metatable()
+	void set_metatable_function(const char* key, MetamethodFunction func)
+	{
+		lua_pushcfunction(m_state, func);
+		lua_setfield(m_state, -2, key);
+	}
+
+	///	Sets table on top of stack to metafield @a key of another table.
+	/// Only '__index' and '__newindex' metamethods are available.
+	void set_metatable_table(const char* key)
+	{
+		CE_ASSERT(string::strcmp(key, "__index") == 0 || string::strcmp(key, "__newindex") == 0, "Illegal metamethod");
+		lua_setfield(m_state, -2, key);		
+	}
+
+	/// Sets table's __index metamethod to itself
+	void set_self_index()
+	{
+		lua_pushvalue(m_state, -1);
+		lua_setfield(m_state, -2, "__index");
+	}
+
+	/// See LuaStack::begin_metatable()
+	void set_metatable()
+	{
+		lua_setmetatable(m_state, -2);
+	}
+
+	///
+	void get_global(const char* name)
+	{
+		lua_getglobal(m_state, name);
+	}
+
+	///
+	void get_global_metatable(const char* name)
+	{
+		luaL_getmetatable(m_state, name);
+	}
+
 	//-----------------------------------------------------------------------------
 	void push_resource_package(ResourcePackage* package)
 	{
@@ -339,22 +397,6 @@ public:
 		return id;
 	}
 
-	//-----------------------------------------------------------------------------
-	void push_gui_id(GuiId id)
-	{
-		uintptr_t enc = id.encode();
-		lua_pushlightuserdata(m_state, (void*)enc);
-	}
-
-	//-----------------------------------------------------------------------------
-	GuiId get_gui_id(int32_t index)
-	{
-		uint32_t enc = (uintptr_t) lua_touserdata(m_state, index);
-		GuiId id;
-		id.decode(enc);
-		return id;
-	}
-
 	//-----------------------------------------------------------------------------
 	void push_gui(Gui* gui)
 	{
@@ -471,6 +513,48 @@ public:
 		lua_pushlightuserdata(m_state, lua_system::next_quaternion(q));
 	}
 
+	/// Allocates a new Vector3Box (full userdata)
+	Vector3& push_vector3box()
+	{
+		return *(Vector3*) lua_newuserdata(m_state, sizeof(Vector3));
+	}
+
+	/// Retrieves Vector3Box (full userdata)
+	Vector3& get_vector3box(uint32_t index)
+	{
+		CE_ASSERT(lua_isuserdata(m_state, index), "Unable to retrieve 'Vector3Box' (wrong index)");
+		Vector3* ud = (Vector3*) luaL_checkudata(m_state, index, "Vector3Box_i_mt");
+		return *ud;
+	}
+
+	/// Allocates a new QuaternionBox (full userdata)
+	Quaternion& push_quaternionbox()
+	{
+		return *(Quaternion*) lua_newuserdata(m_state, sizeof(Quaternion));
+	}
+
+	/// Retrieves QuaternionBox (full userdata)
+	Quaternion& get_quaternionbox(uint32_t index)
+	{
+		CE_ASSERT(lua_isuserdata(m_state, index), "Unable to retrieve QuaternionBox (wrong index)");
+		Quaternion* ud = (Quaternion*) luaL_checkudata(m_state, index, "QuaternionBox_i_mt");
+		return *ud;
+	}
+
+	/// Allocates a new Matrix4x4Box (full userdata)
+	Matrix4x4& push_matrix4x4box()
+	{
+		return *(Matrix4x4*) lua_newuserdata(m_state, sizeof(Matrix4x4));
+	}
+
+	/// Retrieves QuaternionBox (full userdata)
+	Matrix4x4& get_matrix4x4box(uint32_t index)
+	{
+		CE_ASSERT(lua_isuserdata(m_state, index), "Unable to retrieve Matrix4x4Box (wrong index)");
+		Matrix4x4* ud = (Matrix4x4*) luaL_checkudata(m_state, index, "Matrix4x4Box_i_mt");
+		return *ud;
+	}
+
 private:
 
 	lua_State* m_state;

+ 134 - 95
engine/lua/LuaSystem.cpp

@@ -37,6 +37,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "ResourceManager.h"
 #include "LuaResource.h"
 #include "LuaEnvironment.h"
+#include "LuaStack.h"
 
 namespace crown
 {
@@ -56,6 +57,12 @@ extern int vector3_new(lua_State* L);
 extern int matrix4x4(lua_State* L);
 extern int quaternion_new(lua_State* L);
 
+extern int matrix4x4box(lua_State* L);
+extern int quaternionbox(lua_State* L);
+extern int vector3box(lua_State* L);
+extern int vector3box_get_value(lua_State* L);
+extern int vector3box_set_value(lua_State* L);
+
 //-----------------------------------------------------------------------------
 static int crown_lua_vector2_call(lua_State* L)
 {
@@ -144,6 +151,27 @@ static int crown_lua_lightuserdata_unm(lua_State* L)
 	return vector2_negate(L);
 }
 
+//-----------------------------------------------------------------------------
+static int crown_lua_vector3box_call(lua_State* L)
+{
+	lua_remove(L, 1);
+	return vector3box(L);
+}
+
+//-----------------------------------------------------------------------------
+static int crown_lua_quaternionbox_call(lua_State* L)
+{
+	lua_remove(L, 1);
+	return quaternionbox(L);
+}
+
+//-----------------------------------------------------------------------------
+static int crown_lua_matrix4x4box_call(lua_State* L)
+{
+	lua_remove(L, 1);
+	return matrix4x4box(L);	
+}
+
 //-----------------------------------------------------------------------------
 static int crown_lua_require(lua_State* L)
 {
@@ -175,6 +203,7 @@ namespace lua_system
 	static uint32_t 		s_quat_used = 0;
 	static Quaternion 		s_quat_buffer[CE_MAX_LUA_QUATERNION];
 
+	//-----------------------------------------------------------------------------
 	void init()
 	{
 		s_L = luaL_newstate();
@@ -186,33 +215,34 @@ namespace lua_system
 		// Register crown libraries
 		LuaEnvironment env(s_L);
 
-		load_int_setting(env);
+		load_accelerometer(env);
+		load_actor(env);
+		load_camera(env);
+		load_controller(env);
+		load_debug_line(env);
+		load_device(env);
 		load_float_setting(env);
-		load_string_setting(env);
-		load_vector2(env);
-		load_vector3(env);
-		load_matrix4x4(env);
-		load_quaternion(env);
+		load_gui(env);
+		load_int_setting(env);
+		load_keyboard(env);
 		load_math(env);
-		load_window(env);
+		load_matrix4x4(env);
+		load_mesh(env);
 		load_mouse(env);
-		load_keyboard(env);
-		load_touch(env);
-		load_accelerometer(env);
-		load_device(env);
+		load_physics_world(env);
+		load_quaternion(env);
+		load_raycast(env);
 		load_resource_package(env);
+		load_sound_world(env);
+		load_sprite(env);
+		load_string_setting(env);
+		load_touch(env);
 		load_unit(env);
-		load_camera(env);
+		load_vector2(env);
+		load_vector3(env);
+		load_vector3box(env);
+		load_window(env);
 		load_world(env);
-		load_mesh(env);
-		load_sprite(env);
-		load_actor(env);
-		load_controller(env);
-		load_physics_world(env);
-		load_sound_world(env);
-		load_gui(env);
-		load_debug_line(env);
-		load_raycast(env);
 
 		// Register custom loader
 		lua_getfield(s_L, LUA_GLOBALSINDEX, "package");
@@ -232,103 +262,104 @@ namespace lua_system
 		lua_rawset(s_L, -3);
 		lua_pop(s_L, 1);
 
-		// Create metatable for lightuserdata
-		lua_pushlightuserdata(s_L, (void*)0x0); // Just dummy userdata
-		luaL_newmetatable(s_L, "Lightuserdata_mt");
-		lua_setmetatable(s_L, -2);
-		lua_pop(s_L, -1);
-
-		luaL_newmetatable(s_L, "Lightuserdata_mt");
-
-		lua_pushstring(s_L, "__add");
-		lua_pushcfunction(s_L, crown_lua_lightuserdata_add);
-		lua_settable(s_L, 1);
-
-		lua_pushstring(s_L, "__sub");
-		lua_pushcfunction(s_L, crown_lua_lightuserdata_sub);
-		lua_settable(s_L, 1);
 
-		lua_pushstring(s_L, "__mul");
-		lua_pushcfunction(s_L, crown_lua_lightuserdata_mul);
-		lua_settable(s_L, 1);
+		LuaStack stack(s_L);
 
-		lua_pushstring(s_L, "__div");
-		lua_pushcfunction(s_L, crown_lua_lightuserdata_div);
-		lua_settable(s_L, 1);
-
-		lua_pushstring(s_L, "__unm");
-		lua_pushcfunction(s_L, crown_lua_lightuserdata_unm);
-		lua_settable(s_L, 1);
-
-		//lua_pop(s_L, -1); // pop Lightuserdata_mt
+		// Create metatable for lightuserdata
+		lua_pushlightuserdata(s_L, (void*)0x0); // Just dummy userdata
+		stack.create_metatable("Lightuserdata_mt");
+		stack.set_metatable();
+		lua_pop(s_L, -1); // Pop dummy userdata
 
-		Log::d("Stacksize = %d", lua_gettop(s_L));
+		stack.get_global_metatable("Lightuserdata_mt");
+		stack.set_metatable_function("__add", crown_lua_lightuserdata_add);
+		stack.set_metatable_function("__sub", crown_lua_lightuserdata_sub);
+		stack.set_metatable_function("__mul", crown_lua_lightuserdata_mul);
+		stack.set_metatable_function("__div", crown_lua_lightuserdata_div);
+		stack.set_metatable_function("__unm", crown_lua_lightuserdata_unm);
 
 		// Vector2 metatable
-		luaL_newmetatable(s_L, "Vector2_mt");
-		lua_pushvalue(s_L, -1);
-		lua_setfield(s_L, -2, "__index");
-		lua_pushcfunction(s_L, crown_lua_vector2_call);
-		lua_setfield(s_L, -2, "__call");
-		//lua_pop(s_L, -1); // pop Vector2_mt
-
-		lua_getglobal(s_L, "Vector2");
-		lua_pushvalue(s_L, -2); // Duplicate metatable
-		lua_setmetatable(s_L, -2); // setmetatable(Vector2, Vector2_mt)
-		//lua_pop(s_L, -1); // pop Vector2
+		stack.get_global("Vector2");
+		stack.create_metatable("Vector2_mt");
+		stack.set_self_index();
+		stack.set_metatable_function("__call", crown_lua_vector2_call);
+		stack.set_metatable();
 
 		// Vector3 metatable
-		luaL_newmetatable(s_L, "Vector3_mt");
-		lua_pushvalue(s_L, -1);
-		lua_setfield(s_L, -2, "__index");
-		lua_pushcfunction(s_L, crown_lua_vector3_call);
-		lua_setfield(s_L, -2, "__call");
-		//lua_pop(s_L, -1);
-
-		lua_getglobal(s_L, "Vector3");
-		lua_pushvalue(s_L, -2); // Duplicate metatable
-		lua_setmetatable(s_L, -2); // setmetatable(Vector3, Vector3_mt)
-		//lua_pop(s_L, -1);
+		stack.get_global("Vector3");
+		stack.create_metatable("Vector3_mt");
+		stack.set_self_index();
+		stack.set_metatable_function("__call", crown_lua_vector3_call);
+		stack.set_metatable();
 
 		// Matrix4x4 metatable
-		luaL_newmetatable(s_L, "Matrix4x4_mt");
-		lua_pushvalue(s_L, -1);
-		lua_setfield(s_L, -2, "__index");
-		lua_pushcfunction(s_L, crown_lua_matrix4x4_call);
-		lua_setfield(s_L, -2, "__call");
-		lua_pop(s_L, -1);
-
-		lua_getglobal(s_L, "Matrix4x4");
-		lua_pushvalue(s_L, -2); // Duplicate metatable
-		lua_setmetatable(s_L, -2); // setmetatable(Matrix4x4, Matrix4x4_mt)
-		//lua_pop(s_L, -1);
+		stack.get_global("Matrix4x4");
+		stack.create_metatable("Matrix4x4_mt");
+		stack.set_self_index();
+		stack.set_metatable_function("__call", crown_lua_matrix4x4_call);
+		stack.set_metatable();
 
 		// Quaternion metatable
-		luaL_newmetatable(s_L, "Quaternion_mt");
-		lua_pushvalue(s_L, -1);
-		lua_setfield(s_L, -2, "__index");
-		lua_pushcfunction(s_L, crown_lua_quaternion_call);
-		lua_setfield(s_L, -2, "__call");
-		//lua_pop(s_L, -1);
-
-		lua_getglobal(s_L, "Quaternion");
-		lua_pushvalue(s_L, -2); // Duplicate metatable
-		lua_setmetatable(s_L, -2); // setmetatable(Quaternion, Quaternion_mt)
-		//lua_pop(s_L, -1);
-
-		Log::d("Stacksize = %d", lua_gettop(s_L));
+		stack.get_global("Quaternion");
+		stack.create_metatable("Quaternion_mt");
+		stack.set_self_index();
+		stack.set_metatable_function("__call", crown_lua_quaternion_call);
+		stack.set_metatable();
+
+		// Create and attach metatable to global table Vector3Box
+		stack.get_global("Vector3Box");
+		stack.create_metatable("Vector3Box_g_mt");
+		stack.set_self_index();
+		stack.set_metatable_function("__call", crown_lua_vector3box_call);
+		stack.set_metatable();
+
+		// Create metatable for userdata Vector3Box (instance)
+		// Used for type checking and also provide access facilities to data
+		// e.g: 
+		// inst = Vector3Box(0, 0, 0)
+		// print (inst.x)	<= cannot do it without the following code
+		stack.create_metatable("Vector3Box_i_mt");
+		stack.set_metatable_function("__index", vector3box_get_value);
+		stack.set_metatable_function("__newindex", vector3box_set_value);
+
+		// Create and attach metatable to global table Quaternion
+		stack.get_global("QuaternionBox");
+		stack.create_metatable("QuaternionBox_g_mt");
+		stack.set_self_index();
+		stack.set_metatable_function("__call", crown_lua_quaternionbox_call);
+		stack.set_metatable();
+
+		// Create metatable for userdata QuaternionBox (instance)
+		// Used for type checking
+		stack.create_metatable("QuaternionBox_i_mt");
+
+		// Create and attach metatable to global table Matrix4x4
+		stack.get_global("Matrix4x4");
+		stack.create_metatable("Matrix4x4_g_mt");
+		stack.set_self_index();
+		stack.set_metatable_function("__call", crown_lua_matrix4x4box_call);
+		stack.set_metatable();
+
+		// Create metatable for userdata QuaternionBox (instance)
+		// Used for type checking
+		stack.create_metatable("Matrix4x4_i_mt");
+
+		Log::d("Lua stack size = %d", lua_gettop(s_L));
 	}
 
+	//-----------------------------------------------------------------------------
 	void shutdown()
 	{
 		lua_close(s_L);
 	}
 
+	//-----------------------------------------------------------------------------
 	lua_State* state()
 	{
 		return s_L;
 	}
 
+	//-----------------------------------------------------------------------------
 	Vector2* next_vector2(const Vector2& v)
 	{
 		CE_ASSERT(s_vec2_used < CE_MAX_LUA_VECTOR2, "Maximum number of Vector2 reached");
@@ -336,6 +367,7 @@ namespace lua_system
 		return &(s_vec2_buffer[s_vec2_used++] = v);
 	}
 
+	//-----------------------------------------------------------------------------
 	Vector3* next_vector3(const Vector3& v)
 	{
 		CE_ASSERT(s_vec3_used < CE_MAX_LUA_VECTOR3, "Maximum number of Vector3 reached");
@@ -343,6 +375,7 @@ namespace lua_system
 		return &(s_vec3_buffer[s_vec3_used++] = v);
 	}
 
+	//-----------------------------------------------------------------------------
 	Matrix4x4* next_matrix4x4(const Matrix4x4& m)
 	{
 		CE_ASSERT(s_mat4_used < CE_MAX_LUA_MATRIX4X4, "Maximum number of Matrix4x4 reached");
@@ -350,36 +383,42 @@ namespace lua_system
 		return &(s_mat4_buffer[s_mat4_used++] = m);
 	}
 
+	//-----------------------------------------------------------------------------
 	Quaternion* next_quaternion(const Quaternion& q)
 	{
 		CE_ASSERT(s_quat_used < CE_MAX_LUA_QUATERNION, "Maximum number of Quaternion reached");
 		return &(s_quat_buffer[s_quat_used++] = q);
 	}
 
+	//-----------------------------------------------------------------------------
 	bool is_vector2(int32_t index)
 	{
 		void* type = lua_touserdata(s_L, index);
 		return (type >= &s_vec2_buffer[0] && type <= &s_vec2_buffer[CE_MAX_LUA_VECTOR2 - 1]);
 	}
 
+	//-----------------------------------------------------------------------------
 	bool is_vector3(int32_t index)
 	{
 		void* type = lua_touserdata(s_L, index);
 		return (type >= &s_vec3_buffer[0] && type <= &s_vec3_buffer[CE_MAX_LUA_VECTOR3 - 1]);
 	}
 
+	//-----------------------------------------------------------------------------
 	bool is_matrix4x4(int32_t index)
 	{
 		void* type = lua_touserdata(s_L, index);
 		return (type >= &s_mat4_buffer[0] && type <= &s_mat4_buffer[CE_MAX_LUA_MATRIX4X4 - 1]);
 	}
 
+	//-----------------------------------------------------------------------------
 	bool is_quaternion(int32_t index)
 	{
 		void* type = lua_touserdata(s_L, index);
 		return (type >= &s_quat_buffer[0] && type <= &s_quat_buffer[CE_MAX_LUA_QUATERNION - 1]);
 	}
 
+	//-----------------------------------------------------------------------------
 	void clear_temporaries()
 	{
 		s_vec2_used = 0;

+ 1 - 1
engine/lua/LuaVector3.cpp

@@ -332,4 +332,4 @@ void load_vector3(LuaEnvironment& env)
 	env.load_module_function("Vector3", "angle",			vector3_angle);
 }
 
-} // namespace crown
+} // namespace crown

+ 155 - 0
engine/lua/LuaVector3Box.cpp

@@ -0,0 +1,155 @@
+/*
+Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "LuaEnvironment.h"
+#include "LuaStack.h"
+#include "Vector3.h"
+#include "StringUtils.h"
+
+namespace crown
+{
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int vector3box_get_value(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Vector3& v = stack.get_vector3box(1);
+	const char* s = stack.get_string(2);
+
+	if (string::strcmp(s, "x") == 0)
+	{
+		stack.push_float(v.x);
+		return 1;
+	}
+	else if (string::strcmp(s, "y") == 0)
+	{
+		stack.push_float(v.y);
+		return 1;
+	}
+	else if (string::strcmp(s, "z") == 0)
+	{
+		stack.push_float(v.z);
+		return 1;
+	}
+
+	// Never happens
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int vector3box_set_value(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Vector3& v = stack.get_vector3box(1);
+	const char* s = stack.get_string(2);
+	float value = stack.get_float(3);
+
+	if (string::strcmp(s, "x") == 0)
+	{
+		v.x = value;
+	}
+	else if (string::strcmp(s, "y") == 0)
+	{
+		v.y = value;
+	}
+	else if (string::strcmp(s, "z") == 0)
+	{
+		v.z = value;
+	}
+
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int vector3box(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Vector3& v = stack.push_vector3box();
+
+	// Associates a metatable to userdata
+	stack.get_global_metatable("Vector3Box_i_mt");
+	stack.set_metatable();
+
+	if (stack.num_args() == 2)
+	{
+		Vector3 tv = stack.get_vector3(1);
+
+		v = tv;
+	}
+	else if (stack.num_args() == 4)
+	{
+		v.x = stack.get_float(1);
+		v.y = stack.get_float(2);
+		v.z = stack.get_float(3);
+	}
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int vector3box_store(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Vector3& v = stack.get_vector3box(1);
+	
+	if (stack.num_args() == 2)
+	{
+		Vector3 tv = stack.get_vector3(1);
+
+		v = tv;
+	}
+	else if (stack.num_args() == 4)
+	{
+		v.x = stack.get_float(1);
+		v.y = stack.get_float(2);
+		v.z = stack.get_float(3);
+	}
+	return 0;
+}
+
+//-----------------------------------------------------------------------------
+CE_EXPORT int vector3box_unbox(lua_State* L)
+{
+	LuaStack stack(L);
+
+	Vector3& v = stack.get_vector3box(1);
+
+	stack.push_vector3(v);
+	return 1;
+}
+
+//-----------------------------------------------------------------------------
+void load_vector3box(LuaEnvironment& env)
+{
+	env.load_module_function("Vector3Box", "new", vector3box);
+	env.load_module_function("Vector3Box", "store", vector3box_store);
+	env.load_module_function("Vector3Box", "unbox", vector3box_unbox);
+}
+
+} // namespace crown

+ 7 - 22
engine/os/win/AtomicInt.h

@@ -27,6 +27,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #pragma once
 
 #include "Types.h"
+#include "windows.h"
 
 namespace crown
 {
@@ -38,35 +39,19 @@ struct AtomicInt
 		m_value = value;
 	}
 
-	AtomicInt& operator+=(int32_t value)
+	int load() const
 	{
-		InterlockedAdd(&m_value, value);
-		return *this;
-	}
-
-	AtomicInt& operator++(void)
-	{
-		InterlockedIncrement(&m_value);
-	}
-
-	AtomicInt& operator--(void)
-	{
-		InterlockedDecrement(&m_value);
-	}
-
-	AtomicInt& operator=(int32_t value)
-	{
-		InterlockedExchange(&m_value, value);
+		InterlockedExchangeAdd(&m_value, (int32_t)0);
+		return m_value;
 	}
 
-	operator int32_t()
+	void store(int val)
 	{
-		return m_value;
+		InterlockedExchange(&m_value, val);
 	}
 
 private:
-
-	LONG m_value;
+	mutable LONG m_value;
 };
 
 } // namespace crown

+ 3 - 1
engine/os/win/WinOS.cpp

@@ -141,7 +141,9 @@ bool is_directory(const char* path)
 //-----------------------------------------------------------------------------
 bool is_file(const char* path)
 {
-	return !is_directory(path);
+	DWORD fileAttr;
+	fileAttr = GetFileAttributes(path);
+	return (fileAttr != INVALID_FILE_ATTRIBUTES && (fileAttr & FILE_ATTRIBUTE_DIRECTORY) == 0);
 }
 
 //-----------------------------------------------------------------------------

+ 3 - 3
engine/os/win/main.cpp

@@ -429,7 +429,7 @@ public:
 		OsEvent event;
 		do
 		{
-			m_queue.pop_event(&event);
+			m_queue.pop_event(event);
 
 			if (event.type != OsEvent::NONE)
 			{
@@ -841,7 +841,7 @@ public:
 			DynamicString boot;
 			root.key("boot").to_string(boot);
 
-			string::strncpy(m_boot_file, boot, (boot.length() > MAX_PATH_LENGTH) ? MAX_PATH_LENGTH : boot.length() + 1);
+			string::strncpy(m_boot_file, boot.c_str(), (boot.length() > MAX_PATH_LENGTH) ? MAX_PATH_LENGTH : boot.length() + 1);
 		}
 
 		// Window width
@@ -914,4 +914,4 @@ int main(int argc, char** argv)
 	shutdown();
 
 	return ret;
-}
+}

+ 6 - 3
engine/world/Unit.cpp

@@ -41,10 +41,10 @@ namespace crown
 {
 
 //-----------------------------------------------------------------------------
-Unit::Unit(World& w, const char* name, const UnitResource* ur, const Matrix4x4& pose)
+Unit::Unit(World& w, const ResourceId id, const UnitResource* ur, const Matrix4x4& pose)
 	: m_world(w)
-	, m_unit_name(name)
 	, m_scene_graph(*w.scene_graph_manager()->create_scene_graph())
+	, m_resource_id(id)
 	, m_resource(ur)
 	, m_num_cameras(0)
 	, m_num_meshes(0)
@@ -565,7 +565,10 @@ Material* Unit::material(uint32_t i)
 //-----------------------------------------------------------------------------
 bool Unit::is_a(const char* name)
 {
-	return string::strcmp(name, m_unit_name) == 0;
+	DynamicString unit(name);
+	unit += ".unit";
+
+	return m_resource_id.id == hash::murmur2_64(unit.c_str(), string::strlen(unit.c_str()), 0);
 }
 
 

+ 3 - 3
engine/world/Unit.h

@@ -75,7 +75,7 @@ struct UnitResource;
 
 struct Unit
 {
-						Unit(World& w, const char* name, const UnitResource* ur, const Matrix4x4& pose);
+						Unit(World& w, const ResourceId id, const UnitResource* ur, const Matrix4x4& pose);
 						~Unit();
 
 	void				set_id(const UnitId id);
@@ -136,6 +136,7 @@ struct Unit
 	Controller*			controller();
 
 	bool				is_a(const char* name);
+
 private:
 
 	void				create_objects(const Matrix4x4& pose);
@@ -149,6 +150,7 @@ public:
 
 	World&				m_world;
 	SceneGraph&			m_scene_graph;
+	const ResourceId	m_resource_id;
 	const UnitResource*	m_resource;
 	UnitId				m_id;
 
@@ -168,8 +170,6 @@ public:
 	Component			m_materials[CE_MAX_MATERIAL_COMPONENTS];
 
 	Component			m_controller;
-
-	const char* 		m_unit_name;
 };
 
 } // namespace crown

+ 4 - 3
engine/world/World.cpp

@@ -72,14 +72,15 @@ void World::set_id(WorldId id)
 UnitId World::spawn_unit(const char* name, const Vector3& pos, const Quaternion& rot)
 {
 	UnitResource* ur = (UnitResource*) device()->resource_manager()->lookup(UNIT_EXTENSION, name);
-	return spawn_unit(name, ur, pos, rot);
+	ResourceId id = device()->resource_manager()->resource_id(UNIT_EXTENSION, name);
+	return spawn_unit(id, ur, pos, rot);
 }
 
 //-----------------------------------------------------------------------------
-UnitId World::spawn_unit(const char* name, UnitResource* ur, const Vector3& pos, const Quaternion& rot)
+UnitId World::spawn_unit(const ResourceId id, UnitResource* ur, const Vector3& pos, const Quaternion& rot)
 {
 	// Allocate memory for unit
-	Unit* unit = CE_NEW(m_unit_pool, Unit)(*this, name, ur, Matrix4x4(rot, pos));
+	Unit* unit = CE_NEW(m_unit_pool, Unit)(*this, id, ur, Matrix4x4(rot, pos));
 
 	// Create Id for the unit
 	const UnitId unit_id = m_units.create(unit);

+ 2 - 1
engine/world/World.h

@@ -63,7 +63,8 @@ public:
 	void								set_id(WorldId id);
 
 	UnitId								spawn_unit(const char* name, const Vector3& pos = vector3::ZERO, const Quaternion& rot = quaternion::IDENTITY);
-	UnitId								spawn_unit(const char* name, UnitResource* ur, const Vector3& pos, const Quaternion& rot);
+	UnitId								spawn_unit(const ResourceId id, UnitResource* ur, const Vector3& pos, const Quaternion& rot);
+
 	void								destroy_unit(UnitId id);
 	void								reload_units(UnitResource* old_ur, UnitResource* new_ur);
 

+ 36 - 16
utils/crown-android.rb

@@ -104,7 +104,7 @@ $physx				= "../engine/third/ARMv7/physx"
 #------------------------------------------------------------------------------
 def validate_command_line(args)
 
-	if args.length != 8
+	if args.length < 8
 		return false 
 	end
 	if args[0] != "--build"
@@ -126,7 +126,7 @@ end
 #------------------------------------------------------------------------------
 def parse_command_line(args)
 
-	banner = "Usage: crown-android.rb --build <crown-build> --target <android-target> --name <project-name> --path <project-path>\n"
+	banner = "Usage: crown-android.rb --build BUILD --target TARGET --name NAME --path PATH [--res RES]\n"
 
 	if not validate_command_line(args)
 		print banner
@@ -150,14 +150,14 @@ def parse_command_line(args)
 			options.name = n
 		end
 
-		opts.on("-r", "--res RES", "Android project compiled resources") do |r|
-			options.res = r
-		end
-
 		opts.on("-p", "--path PATH", "Android project path") do |p|
 			options.path = p
 		end
 
+		opts.on("-r", "--res RES", "Android project compiled resources") do |r|
+			options.res = r
+		end
+
 	    opts.on_tail("-h", "--help", "Show this message") do
 	    	puts opts
 	      	exit
@@ -198,29 +198,35 @@ def create_android_project(target, name, path)
 
 	# Creates path if not exists
 	if not Dir.exists?(path)
+		print "Creating directory " + path + "..."
 		FileUtils.mkdir_p(path)
+		print "OK!\n"
 	end
 
-	# Project path is empty
-	if Dir[path + "/*"].empty?
-		# Creates android project
-		system($android_create + " --target " + target + " --name " + name + " --path " + path + 
-				" --activity " + $activity + " --package " + $package)
-	else
-		# Updates android project
-		system($android_update + " --target " + target + " --name " + name + " --path " + path)
+	# Project path is not empty
+	if not Dir["#{path}/."].empty?
+		print "Cleaning directory " + path + "..."
+		FileUtils.rm_rf("#{path}/.", :secure => true)
+		print "OK!\n"
 	end
+
+	# Creates android project
+	print "Creating android project...\n"
+	system($android_create + " --target " + target + " --name " + name + " --path " + path + " --activity " + $activity + " --package " + $package)
+	print "OK!\n"
 	
 	# if jni dir does not exists, create it!
 	if not Dir.exists?(engine_dest)
+		print "Creating directory " + engine_dest + "..."
 		FileUtils.mkdir_p(engine_dest)
-		print "Created directory " + engine_dest + "\n"
+		print "OK!\n"
 	end
 
 	# if assets dir does not exists, create it!
 	if not Dir.exists?(assets_dest)
+		print "Creating directory " + assets_dest + "..."
 		FileUtils.mkdir_p(assets_dest)
-		print "Created directory " + assets_dest + "\n"
+		print "OK!\n"
 	end
 end
 
@@ -231,6 +237,7 @@ def fill_android_project(build, target, res, path)
 	android_dest	= path + "/src/crown/android"
 	resources_dest	= path + "/assets"
 
+	print "Filling Android project..."
 	# Copy Engine files
 	FileUtils.cp_r($engine_src, engine_dest, :remove_destination => true)
 
@@ -267,10 +274,17 @@ def fill_android_project(build, target, res, path)
 
 	# Copy android manifest
 	FileUtils.cp($android_manifest, path)
+
+	if build == "release"
+		FileUtils.cp_r(res + "/.", resources_dest)
+	end
+
+	print "OK!\n"
 end
 
 #------------------------------------------------------------------------------
 def build_android_project(path)
+	print "Building...\n"
 	# Move to root directory of Android project
 	Dir.chdir(path)
 	# Build libraries
@@ -278,10 +292,16 @@ def build_android_project(path)
 		print "Critical error: Unable to build crown libraries"
 		return
 	end
+
 	# Build apk
+	# FIXME: it's convenient to build apk in debug mode because we avoid apk signature.
+	# In a near future, we'll manage the build process in release mode
+	# N.B: you can build crown in release mode and run 'ant debug' for achieving the same result of a final product
 	if not system("ant debug")
 		print "Critical error: Unable to build crown project"
 		return
+	else
+		print "Done!\n"
 	end
 end
 

+ 150 - 0
utils/crown-make.rb

@@ -0,0 +1,150 @@
+# Copyright (c) 2013 Daniele Bartolini, Michele Rossi
+# Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+# 
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+# 
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+require 'optparse'
+require 'ostruct'
+require 'fileutils'
+
+# README
+# LINUX ONLY RIGHT NOW
+
+#------------------------------------------------------------------------------
+def validate_command_line(args)
+
+	# if args.length < 8
+	# 	return false 
+	# end
+	# if args[0] != "--build"
+	# 	return false
+	# end
+	# if args[2] != "--path"
+	# 	return false
+	# end
+
+	# return true
+end
+
+#------------------------------------------------------------------------------
+def parse_command_line(args)
+
+	banner = "Usage: crown-make.rb --build BUILD --path PATH\n"
+
+	# if not validate_command_line(args)
+	# 	print banner
+	# 	exit
+	# end
+
+	options = OpenStruct.new
+
+	OptionParser.new do |opts|
+		opts.banner = banner
+
+		opts.on("-m", "--mode MODE", "Crown build mode(debug, development, release, all)") do |m|
+			options.mode = m
+		end
+
+		opts.on("-e", "--engine-path ENGINE_PATH", "Engine path") do |e|
+			options.engine_path = e
+		end
+
+		opts.on("-b", "--build-path BUILD_PATH", "Build path") do |b|
+			options.build_path = b
+		end
+
+		opts.on("-i", "--install-path PATH", "Install path") do |i|
+			options.install_path = i
+		end
+
+	    opts.on_tail("-h", "--help", "Show this message") do
+	    	puts opts
+	      	exit
+	    end
+	end.parse!(args)
+
+	return options
+end
+
+#------------------------------------------------------------------------------
+def build_linux_debug(engine_path, build_path, install_path)
+	Dir.chdir(build_path)
+	FileUtils.mkdir_p("debug")
+
+	Dir.chdir(build_path + "/debug")
+	if not system("cmake " + engine_path + " -DCMAKE_INSTALL_PREFIX=" + install_path + "/debug" + " -DCROWN_BUILD=linux-debug-64")
+		print ("Unable to run cmake")
+		return
+	end
+	if not system("make install -j 8")
+		print ("Unable to compile")
+		return
+	end
+end
+
+#------------------------------------------------------------------------------
+def build_linux_development(engine_path, build_path, install_path)
+	Dir.chdir(build_path)
+	FileUtils.mkdir_p("development")
+
+	Dir.chdir(build_path + "/development")
+	if not system("cmake " + engine_path + " -DCMAKE_INSTALL_PREFIX=" + install_path + "/development" + " -DCROWN_BUILD=linux-development-64")
+		print ("Unable to run cmake")
+		return
+	end
+	if not system("make install -j 8")
+		print ("Unable to compile")
+		return
+	end
+end
+
+#------------------------------------------------------------------------------
+def build_linux_release(engine_path, build_path, install_path)
+	Dir.chdir(build_path)
+	FileUtils.mkdir_p("release")
+
+	Dir.chdir(build_path + "/release")
+	if not system("cmake " + engine_path + " -DCMAKE_INSTALL_PREFIX=" + install_path + "/release" + " -DCROWN_BUILD=linux-release-64")
+		print ("Unable to run cmake")
+		return
+	end
+	if not system("make install -j 8")
+		print ("Unable to compile")
+		return
+	end
+end
+
+#------------------------------------------------------------------------------
+opts = parse_command_line(ARGV)
+
+case opts.mode
+when "debug"
+	build_linux_debug(opts.engine_path, opts.build_path, opts.install_path)
+when "development"
+	build_linux_development(opts.engine_path, opts.build_path, opts.install_path)
+when "release"
+	build_linux_release(opts.engine_path, opts.build_path, opts.install_path)
+when "all"
+	build_linux_debug(opts.engine_path, opts.build_path, opts.install_path)
+	build_linux_development(opts.engine_path, opts.build_path, opts.install_path)
+	build_linux_release(opts.engine_path, opts.build_path, opts.install_path)
+end