Browse Source

Implemented Lua scripting language;
Added ScriptObject and its LuaComponent classes;
Added LuaScript class that's responsible for handling Lua scripts;
Added test.lua script for testing the Lua implementation;
Added script component to GameObject;
Added view matrix calculations for a camera in RendererScene;
Added assignment operator for SpatialDataManager;
Added more errors and error strings;
Renamed Scripting system to Script system;

Paul A 4 years ago
parent
commit
a518de9b76
42 changed files with 1326 additions and 234 deletions
  1. 15 1
      Praxis3D/Data/Maps/componentTest.pmap
  2. 88 0
      Praxis3D/Data/Scripts/test.lua
  3. 3 1
      Praxis3D/Data/error-strings-eng.data
  4. 10 6
      Praxis3D/Praxis3D.vcxproj
  5. 18 6
      Praxis3D/Praxis3D.vcxproj.filters
  6. 1 1
      Praxis3D/Source/BaseScriptObject.h
  7. 6 6
      Praxis3D/Source/CameraScript.h
  8. 9 0
      Praxis3D/Source/Config.cpp
  9. 42 9
      Praxis3D/Source/Config.h
  10. 1 1
      Praxis3D/Source/DebugMoveScript.h
  11. 1 1
      Praxis3D/Source/DebugRotateScript.h
  12. 4 4
      Praxis3D/Source/DebugUIScript.h
  13. 3 1
      Praxis3D/Source/ErrorCodes.h
  14. 4 2
      Praxis3D/Source/ErrorHandler.cpp
  15. 2 2
      Praxis3D/Source/GameLogicObject.h
  16. 39 5
      Praxis3D/Source/GameObject.h
  17. 2 2
      Praxis3D/Source/GraphicsObject.h
  18. 1 0
      Praxis3D/Source/InheritanceObjects.h
  19. 1 1
      Praxis3D/Source/KeyCommand.cpp
  20. 1 1
      Praxis3D/Source/KeyCommand.h
  21. 184 0
      Praxis3D/Source/LuaComponent.h
  22. 8 0
      Praxis3D/Source/LuaScript.cpp
  23. 286 0
      Praxis3D/Source/LuaScript.h
  24. 8 3
      Praxis3D/Source/Math.h
  25. 5 5
      Praxis3D/Source/PlayState.cpp
  26. 1 1
      Praxis3D/Source/RendererBackend.h
  27. 2 1
      Praxis3D/Source/RendererScene.cpp
  28. 1 0
      Praxis3D/Source/RendererScene.h
  29. 228 0
      Praxis3D/Source/ScriptObject.h
  30. 134 67
      Praxis3D/Source/ScriptScene.cpp
  31. 37 8
      Praxis3D/Source/ScriptScene.h
  32. 12 12
      Praxis3D/Source/ScriptSystem.cpp
  33. 6 6
      Praxis3D/Source/ScriptSystem.h
  34. 19 0
      Praxis3D/Source/ScriptTask.cpp
  35. 23 0
      Praxis3D/Source/ScriptTask.h
  36. 0 19
      Praxis3D/Source/ScriptingTask.cpp
  37. 0 23
      Praxis3D/Source/ScriptingTask.h
  38. 1 1
      Praxis3D/Source/SolarTimeScript.h
  39. 94 14
      Praxis3D/Source/SpatialDataManager.h
  40. 12 12
      Praxis3D/Source/WorldEditObject.h
  41. 6 6
      Praxis3D/Source/WorldEditState.cpp
  42. 8 6
      Praxis3D/Source/WorldScene.cpp

+ 15 - 1
Praxis3D/Data/Maps/componentTest.pmap

@@ -90,13 +90,20 @@
 			"Name": "Camera 1",
 			"Parent": "0",
 			"LocalPosition": "0.0f, 0.0f, 0.0f",
-			"LocalRotation": "0.0f, 0.0f, 0.0f",
+			"LocalRotation": "9.0f, 5.0f, 0.0f",
 			"Rendering":
 			{
 				"Camera":
 				{
 
 				}
+			},
+			"Script":
+			{
+				"Lua":
+				{
+					"Filename": "test.lua"
+				}
 			}
 		}
 	],
@@ -110,6 +117,13 @@
 				"ObjectPoolSize": "50"
 			}
 		},
+		"Script":
+		{
+			"Scene":
+			{
+				"ObjectPoolSize": "50"
+			}
+		},
 		"World":
 		{
 			"Scene":

+ 88 - 0
Praxis3D/Data/Scripts/test.lua

@@ -0,0 +1,88 @@
+
+print('before functions call in LUA')
+
+function init ()
+	print('init() function call in LUA')
+	
+	create(Types.SpatialDataManager, 'spatialData');
+	
+	create(Types.InputVariables, 'inputVariables');
+	
+	create(Types.KeyCommand, 'forwardKey')
+	create(Types.KeyCommand, 'backwardKey')
+	create(Types.KeyCommand, 'leftKey')
+	create(Types.KeyCommand, 'rightKey')
+	create(Types.KeyCommand, 'upKey')
+	create(Types.KeyCommand, 'downKey')
+	
+	forwardKey:bind(inputVariables.forward_key)
+	backwardKey:bind(inputVariables.backward_key)
+	leftKey:bind(inputVariables.left_strafe_key)
+	rightKey:bind(inputVariables.right_strafe_key)
+	upKey:bind(inputVariables.up_key)
+	downKey:bind(inputVariables.down_key)
+	
+	x = 0
+	y = 0
+	speed = 100
+	
+	vec1 = Vec3f.new()
+	vec1.x = 5
+	vec1.y = 8
+	
+	vec2 = Vec3f.new()
+	vec2.x = 10
+	vec2.y = 20
+end
+
+function update (p_deltaTime)
+	--print('update() function call in LUA')
+	
+	
+	--test1 = spatialData:getWorldSpaceData
+	
+	--targetVec = test1.m_spatialData.m_rotationEuler
+	
+	--targetVec = Vec3f.new()
+	--targetVec.x = 99
+	--targetVec.y = 99
+	
+	--targetVec = spatialData:getWorldRotation()
+	
+	positionVec = spatialData:getWorldSpaceData().m_spatialData.m_position
+	rotationVec = spatialData:getWorldSpaceData().m_spatialData.m_rotationEuler
+	targetVec = Vec3f.new()
+	targetVec:target(toRadianF(rotationVec.x), toRadianF(rotationVec.y))
+	
+	if forwardKey:isActivated() then
+		positionVec:subVec3f(targetVec:mulF(speed * p_deltaTime))
+		--x = x + (speed * p_deltaTime)
+	end	
+	
+	if backwardKey:isActivated() then
+		positionVec:addVec3f(targetVec:mulF(speed * p_deltaTime))
+		--x = x - (speed * p_deltaTime)
+	end
+	
+	if leftKey:isActivated() then
+		y = y + (speed * p_deltaTime)
+	end	
+	
+	if rightKey:isActivated() then
+		y = y - (speed * p_deltaTime)
+	end
+	
+	--x = vec1.x
+	--y = vec1.y
+	
+	vec1.x = x
+	vec1.y = y
+	
+	spatialData:setWorldPosition(positionVec)
+	
+	
+	--vec1:mulVec3f(vec2)
+	--print(Types.KeyCommand)
+	--print('test')
+	--print(vec1.x .. ' : ' .. vec1.y)
+end

+ 3 - 1
Praxis3D/Data/error-strings-eng.data

@@ -6,6 +6,7 @@
 		"Failure"										: "Failed",
 		"Initialize_success"				: "Has been initialized",
 		"Initialize_failure"				: "Failed to initialized",
+		"File_not_found"						: "File missing",
 		"Destroy_obj_not_found"			: "Destruction: object not found",
 		"Glew_failed"								: "OpenGL Extension Wrangler Library has failed to initialize",
 		"Ifstream_failed"						: "Unable to read input file stream",
@@ -53,6 +54,7 @@
 		"Source_LightComponent"					: "Light Component",
 		"Source_LightObject"						: "Light Object",
 		"Source_LightingPass"						: "Lighting Rendering Pass",
+		"Source_LuaComponent"						: "Lua Component",
 		"Source_ModelComponent"					: "Model Component",
 		"Source_ModelLoader"						: "Model Loader",
 		"Source_ObjectDirectory"				: "Object Directory",
@@ -64,7 +66,7 @@
 		"Source_RendererScene"					: "Renderer Scene",
 		"Source_RendererSystem"					: "Renderer System",
 		"Source_SceneLoader"						: "Scene Loader",
-		"Source_Scripting"							: "Scripting System",
+		"Source_Script"									: "Scripting System",
 		"Source_ScriptObject"						: "Script Object",
 		"Source_ShaderComponent"				: "Shader Component",
 		"Source_ShaderLoader"						: "Shader Loader",

+ 10 - 6
Praxis3D/Praxis3D.vcxproj

@@ -144,6 +144,7 @@
     <ClCompile Include="Source\KeyCommand.cpp" />
     <ClCompile Include="Source\LightComponent.cpp" />
     <ClCompile Include="Source\Loaders.cpp" />
+    <ClCompile Include="Source\LuaScript.cpp" />
     <ClCompile Include="Source\Math.cpp" />
     <ClCompile Include="Source\ModelLoader.cpp" />
     <ClCompile Include="Source\NullObject.cpp" />
@@ -163,9 +164,9 @@
     <ClCompile Include="Source\RenderTask.cpp" />
     <ClCompile Include="Source\Scancodes.cpp" />
     <ClCompile Include="Source\SceneLoader.cpp" />
-    <ClCompile Include="Source\ScriptingScene.cpp" />
-    <ClCompile Include="Source\ScriptingSystem.cpp" />
-    <ClCompile Include="Source\ScriptingTask.cpp" />
+    <ClCompile Include="Source\ScriptScene.cpp" />
+    <ClCompile Include="Source\ScriptSystem.cpp" />
+    <ClCompile Include="Source\ScriptTask.cpp" />
     <ClCompile Include="Source\ShaderLoader.cpp" />
     <ClCompile Include="Source\ShaderUniformUpdater.cpp" />
     <ClCompile Include="Source\SpatialDataChangeManager.cpp" />
@@ -239,6 +240,8 @@
     <ClInclude Include="Source\LightingPass.h" />
     <ClInclude Include="Source\LoaderBase.h" />
     <ClInclude Include="Source\Loaders.h" />
+    <ClInclude Include="Source\LuaComponent.h" />
+    <ClInclude Include="Source\LuaScript.h" />
     <ClInclude Include="Source\Math.h" />
     <ClInclude Include="Source\ModelComponent.h" />
     <ClInclude Include="Source\ModelLoader.h" />
@@ -263,9 +266,10 @@
     <ClInclude Include="Source\RenderTaskBase.h" />
     <ClInclude Include="Source\Scancodes.h" />
     <ClInclude Include="Source\SceneLoader.h" />
-    <ClInclude Include="Source\ScriptingScene.h" />
-    <ClInclude Include="Source\ScriptingSystem.h" />
-    <ClInclude Include="Source\ScriptingTask.h" />
+    <ClInclude Include="Source\ScriptObject.h" />
+    <ClInclude Include="Source\ScriptScene.h" />
+    <ClInclude Include="Source\ScriptSystem.h" />
+    <ClInclude Include="Source\ScriptTask.h" />
     <ClInclude Include="Source\ServiceBase.h" />
     <ClInclude Include="Source\ShaderComponent.h" />
     <ClInclude Include="Source\ShaderGraphicsObjects.h" />

+ 18 - 6
Praxis3D/Praxis3D.vcxproj.filters

@@ -180,13 +180,13 @@
     <ClCompile Include="Source\WindowLocator.cpp">
       <Filter>Service Locators\Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="Source\ScriptingScene.cpp">
+    <ClCompile Include="Source\ScriptScene.cpp">
       <Filter>Scripting\Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="Source\ScriptingSystem.cpp">
+    <ClCompile Include="Source\ScriptSystem.cpp">
       <Filter>Scripting\Source Files</Filter>
     </ClCompile>
-    <ClCompile Include="Source\ScriptingTask.cpp">
+    <ClCompile Include="Source\ScriptTask.cpp">
       <Filter>Scripting\Source Files</Filter>
     </ClCompile>
     <ClCompile Include="Source\DeferredRenderer.cpp">
@@ -297,6 +297,9 @@
     <ClCompile Include="Source\NullObjects.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\LuaScript.cpp">
+      <Filter>Renderer\Objects\Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Source\ErrorCodes.h">
@@ -350,13 +353,13 @@
     <ClInclude Include="Source\WindowLocator.h">
       <Filter>Service Locators\Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="Source\ScriptingScene.h">
+    <ClInclude Include="Source\ScriptScene.h">
       <Filter>Scripting\Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="Source\ScriptingSystem.h">
+    <ClInclude Include="Source\ScriptSystem.h">
       <Filter>Scripting\Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="Source\ScriptingTask.h">
+    <ClInclude Include="Source\ScriptTask.h">
       <Filter>Scripting\Header Files</Filter>
     </ClInclude>
     <ClInclude Include="Source\BaseScriptObject.h">
@@ -629,6 +632,15 @@
     <ClInclude Include="Source\WorldSystem.h">
       <Filter>World\Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Source\ScriptObject.h">
+      <Filter>Scripting\Objects\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\LuaComponent.h">
+      <Filter>Scripting\Objects\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\LuaScript.h">
+      <Filter>Scripting\Objects\Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="Data\config.ini" />

+ 1 - 1
Praxis3D/Source/BaseScriptObject.h

@@ -11,7 +11,7 @@ public:
 
 	}
 	
-	BitMask getSystemType() final { return Systems::Scripting; }
+	BitMask getSystemType() final { return Systems::Script; }
 
 	virtual BitMask getDesiredSystemChanges() { return Systems::Changes::None; }
 

+ 6 - 6
Praxis3D/Source/CameraScript.h

@@ -6,7 +6,7 @@
 
 class Camera : public BaseScriptObject
 {
-	friend class ScriptingScene;
+	friend class ScriptScene;
 public:
 	Camera(SystemScene *p_systemScene, std::string p_name, Properties::PropertyID p_objectType)
 		: BaseScriptObject(p_systemScene, p_name, p_objectType)
@@ -205,7 +205,7 @@ public:
 	inline void setForwardKey(std::string &p_string)
 	{
 		m_forwardKey.unbindAll();
-		m_forwardKey.bind(p_string);
+		m_forwardKey.bindByKeyName(p_string);
 	}
 
 	inline void setBackwardKey(Scancode p_key)
@@ -216,7 +216,7 @@ public:
 	inline void setBackwardKey(std::string &p_string)
 	{
 		m_backwardKey.unbindAll();
-		m_backwardKey.bind(p_string);
+		m_backwardKey.bindByKeyName(p_string);
 	}
 
 	inline void setStrafeLeftKey(Scancode p_key)
@@ -227,7 +227,7 @@ public:
 	inline void setStrafeLeftKey(std::string &p_string)
 	{
 		m_strafeLeftKey.unbindAll();
-		m_strafeLeftKey.bind(p_string);
+		m_strafeLeftKey.bindByKeyName(p_string);
 	}
 
 	inline void setStrafeRightKey(Scancode p_key)
@@ -238,7 +238,7 @@ public:
 	inline void setStrafeRightKey(std::string &p_string)
 	{
 		m_strafeRightKey.unbindAll();
-		m_strafeRightKey.bind(p_string);
+		m_strafeRightKey.bindByKeyName(p_string);
 	}
 
 	inline void setSprintKey(Scancode p_key)
@@ -249,7 +249,7 @@ public:
 	inline void setSprintKey(std::string &p_string)
 	{
 		m_sprintKey.unbindAll();
-		m_sprintKey.bind(p_string);
+		m_sprintKey.bindByKeyName(p_string);
 	}
 
 	inline void setLowerLimit(const float p_limit)

+ 9 - 0
Praxis3D/Source/Config.cpp

@@ -37,6 +37,7 @@ Config::ModelVariables		Config::m_modelVar;
 Config::ObjectPoolVariables	Config::m_objPoolVar;
 Config::PathsVariables		Config::m_filepathVar;
 Config::RendererVariables	Config::m_rendererVar;
+Config::ScriptVariables		Config::m_scriptVar;
 Config::ShaderVariables		Config::m_shaderVar;
 Config::TextureVariables	Config::m_textureVar;
 Config::WindowVariables		Config::m_windowVar;
@@ -52,6 +53,7 @@ void Config::init()
 	// Component Variables
 	AddVariablePredef(m_componentVar, camera_component_name);
 	AddVariablePredef(m_componentVar, light_component_name);
+	AddVariablePredef(m_componentVar, lua_component_name);
 	AddVariablePredef(m_componentVar, model_component_name);
 	AddVariablePredef(m_componentVar, shader_component_name);
 
@@ -214,6 +216,7 @@ void Config::init()
 	AddVariablePredef(m_filepathVar, map_path);
 	AddVariablePredef(m_filepathVar, model_path);
 	AddVariablePredef(m_filepathVar, object_path);
+	AddVariablePredef(m_filepathVar, script_path);
 	AddVariablePredef(m_filepathVar, shader_path);
 	AddVariablePredef(m_filepathVar, sound_path);
 	AddVariablePredef(m_filepathVar, texture_path);
@@ -281,6 +284,12 @@ void Config::init()
 	AddVariablePredef(m_rendererVar, depth_test);
 	AddVariablePredef(m_rendererVar, face_culling);
 
+	// Script variables
+	AddVariablePredef(m_scriptVar, iniFunctionName);
+	AddVariablePredef(m_scriptVar, updateFunctionName);
+	AddVariablePredef(m_scriptVar, createObjectFunctionName);
+	AddVariablePredef(m_scriptVar, userTypeTableName);
+
 	// Shader variables
 	AddVariablePredef(m_shaderVar, atmScatProjMatUniform);
 	AddVariablePredef(m_shaderVar, modelMatUniform);

+ 42 - 9
Praxis3D/Source/Config.h

@@ -27,7 +27,7 @@ namespace Systems
 	#define TYPEID(Code) \
 	Code(Null, = -1) \
 	Code(Graphics,) \
-	Code(Scripting,) \
+	Code(Script,) \
 	Code(World,) \
 	Code(NumberOfSystems,) 
 	DECLARE_ENUM(TypeID, TYPEID)
@@ -35,7 +35,7 @@ namespace Systems
 	const static std::string SystemNames[NumberOfSystems] =
 	{
 		GetString(Graphics),
-		GetString(Scripting),
+		GetString(Script),
 		GetString(World)
 	};
 	
@@ -48,8 +48,8 @@ namespace Systems
 	{
 		static constexpr BitMask None		= (BitMask)1 << 0;
 		static constexpr BitMask Graphics	= (BitMask)1 << 1;
-		static constexpr BitMask Scripting	= (BitMask)1 << 2;
-	}	
+		static constexpr BitMask Script		= (BitMask)1 << 2;
+	}
 	namespace GraphicsObjectComponents
 	{
 		static constexpr BitMask None		= (BitMask)1 << 0;
@@ -58,6 +58,11 @@ namespace Systems
 		static constexpr BitMask Model		= (BitMask)1 << 3;
 		static constexpr BitMask Shader		= (BitMask)1 << 4;
 	}
+	namespace ScriptObjectComponents
+	{
+		static constexpr BitMask None = (BitMask)1 << 0;
+		static constexpr BitMask Lua = (BitMask)1 << 1;
+	}
 	namespace Changes
 	{
 		namespace Common
@@ -91,7 +96,7 @@ namespace Systems
 			static constexpr BitMask Graphics	= (BitMask)1 << 61;
 			static constexpr BitMask Physics	= (BitMask)1 << 60;
 			static constexpr BitMask Audio		= (BitMask)1 << 59;
-			static constexpr BitMask Scripting	= (BitMask)1 << 58;
+			static constexpr BitMask Script		= (BitMask)1 << 58;
 		}
 
 		namespace Generic
@@ -148,7 +153,7 @@ namespace Systems
 		{
 
 		}
-		namespace Scripting
+		namespace Script
 		{
 
 		}
@@ -267,7 +272,7 @@ namespace Properties
 	Code(ObjectLinks,) \
 	Code(Observer,) \
 	Code(Subject,) \
-	/* Scripting */ \
+	/* Script */ \
 	Code(Angle,) \
 	Code(Axis,) \
 	Code(Azimuth,) \
@@ -281,6 +286,8 @@ namespace Properties
 	Code(Latitude,) \
 	Code(Longitude,) \
 	Code(LowerLimit,) \
+	Code(Lua,) \
+	Code(LuaComponent,) \
 	Code(InputScript,) \
 	Code(Hours,) \
 	Code(KeyCode,) \
@@ -288,7 +295,8 @@ namespace Properties
 	Code(Minutes,) \
 	Code(Month,) \
 	Code(Radius,) \
-	Code(Scripting,) \
+	Code(Script,) \
+	Code(ScriptObject,) \
 	Code(Seconds,) \
 	Code(SolarTimeScript,) \
 	Code(Speed,) \
@@ -429,6 +437,8 @@ namespace Properties
 		GetString(Latitude),
 		GetString(Longitude),
 		GetString(LowerLimit),
+		GetString(Lua),
+		GetString(LuaComponent),
 		GetString(InputScript),
 		GetString(Hours),
 		GetString(KeyCode),
@@ -436,7 +446,8 @@ namespace Properties
 		GetString(Minutes),
 		GetString(Month),
 		GetString(Radius),
-		GetString(Scripting),
+		GetString(Script),
+		GetString(ScriptObject),
 		GetString(Seconds),
 		GetString(SolarTimeScript),
 		GetString(Speed),
@@ -517,12 +528,14 @@ public:
 		{
 			camera_component_name = " (Camera Component)";
 			light_component_name = " (Light Component)";
+			lua_component_name = " (Lua Component)";
 			model_component_name = " (Model Component)";
 			shader_component_name = " (Shader Component)";
 		}
 
 		std::string camera_component_name;
 		std::string light_component_name;
+		std::string lua_component_name;
 		std::string model_component_name;
 		std::string shader_component_name;
 	};
@@ -906,6 +919,7 @@ public:
 			map_path = "Data\\Maps\\";
 			model_path = "Data\\Models\\";
 			object_path = "Data\\Objects\\";
+			script_path = "Data\\Scripts\\";
 			shader_path = "Data\\Shaders\\";
 			sound_path = "Data\\Sounds\\";
 			texture_path = "Data\\Materials\\";
@@ -915,6 +929,7 @@ public:
 		std::string map_path;
 		std::string model_path;
 		std::string object_path;
+		std::string script_path;
 		std::string shader_path;
 		std::string sound_path;
 		std::string texture_path;
@@ -1048,6 +1063,21 @@ public:
 		bool depth_test;
 		bool face_culling;
 	};
+	struct ScriptVariables
+	{
+		ScriptVariables()
+		{
+			iniFunctionName = "init";
+			updateFunctionName = "update";
+			createObjectFunctionName = "create";
+			userTypeTableName = "Types";
+		}
+
+		std::string iniFunctionName;
+		std::string updateFunctionName;
+		std::string createObjectFunctionName;
+		std::string userTypeTableName;
+	};
 	struct ShaderVariables
 	{
 		ShaderVariables()
@@ -1323,6 +1353,7 @@ public:
 	const inline static ObjectPoolVariables &objectPoolVar()	{ return m_objPoolVar;		}
 	const inline static PathsVariables		&filepathVar()		{ return m_filepathVar;		}
 	const inline static RendererVariables	&rendererVar()		{ return m_rendererVar;		}
+	const inline static ScriptVariables		&scriptVar()		{ return m_scriptVar;		}
 	const inline static ShaderVariables		&shaderVar()		{ return m_shaderVar;		}
 	const inline static TextureVariables	&textureVar()		{ return m_textureVar;		}
 	const inline static WindowVariables		&windowVar()		{ return m_windowVar;		}
@@ -1437,6 +1468,7 @@ private:
 	static ObjectPoolVariables	m_objPoolVar;
 	static PathsVariables		m_filepathVar;
 	static RendererVariables	m_rendererVar;
+	static ScriptVariables		m_scriptVar;
 	static ShaderVariables		m_shaderVar;
 	static TextureVariables		m_textureVar;
 	static WindowVariables		m_windowVar;
@@ -1458,6 +1490,7 @@ private:
 	inline static ModelVariables		&setModelVar()		{ return m_modelVar;		}
 	inline static PathsVariables		&setFilepathVar()	{ return m_filepathVar;		}
 	inline static RendererVariables		&setRendererVar()	{ return m_rendererVar;		}
+	inline static ScriptVariables		&setScriptVar()		{ return m_scriptVar;		}
 	inline static ShaderVariables		&setShaderVar()		{ return m_shaderVar;		}
 	inline static TextureVariables		&setTextureVar()	{ return m_textureVar;		}
 	inline static WindowVariables		&setWindowVar()		{ return m_windowVar;		}

+ 1 - 1
Praxis3D/Source/DebugMoveScript.h

@@ -5,7 +5,7 @@
 // Provides bare object movement functionality for debugging purposes (like making a light move around the scene)
 class DebugMoveScript : public BaseScriptObject
 {
-	friend class ScriptingScene;
+	friend class ScriptScene;
 public:
 	DebugMoveScript(SystemScene *p_systemScene, std::string p_name)
 		: BaseScriptObject(p_systemScene, p_name, Properties::DebugMoveScript)

+ 1 - 1
Praxis3D/Source/DebugRotateScript.h

@@ -5,7 +5,7 @@
 // Provides bare object rotation functionality for debugging purposes (like making a spotlight rotate)
 class DebugRotateScript : public BaseScriptObject
 {
-	friend class ScriptingScene;
+	friend class ScriptScene;
 public:
 	DebugRotateScript(SystemScene *p_systemScene, std::string p_name)
 		: BaseScriptObject(p_systemScene, p_name, Properties::DebugRotateScript)

+ 4 - 4
Praxis3D/Source/DebugUIScript.h

@@ -131,7 +131,7 @@ public:
 	inline void setMouseCaptureKey(std::string &p_string)
 	{
 		m_mouseCaptureCommand.unbindAll();
-		m_mouseCaptureCommand.bind(p_string);
+		m_mouseCaptureCommand.bindByKeyName(p_string);
 	}
 
 	inline void setFullscreenKey(Scancode p_key)
@@ -142,7 +142,7 @@ public:
 	inline void setFullscreenKey(std::string &p_string)
 	{
 		m_fullscreenCommand.unbindAll();
-		m_fullscreenCommand.bind(p_string);
+		m_fullscreenCommand.bindByKeyName(p_string);
 	}
 
 	inline void setVerticalSyncKey(Scancode p_key)
@@ -153,7 +153,7 @@ public:
 	inline void setVerticalSyncKey(std::string &p_string)
 	{
 		m_vertSyncCommand.unbindAll();
-		m_vertSyncCommand.bind(p_string);
+		m_vertSyncCommand.bindByKeyName(p_string);
 	}
 
 	inline void setCloseWindowKey(Scancode p_key)
@@ -164,7 +164,7 @@ public:
 	inline void setCloseWindowKey(std::string &p_string)
 	{
 		m_closeWindowCommand.unbindAll();
-		m_closeWindowCommand.bind(p_string);
+		m_closeWindowCommand.bindByKeyName(p_string);
 	}
 	
 protected:

+ 3 - 1
Praxis3D/Source/ErrorCodes.h

@@ -38,6 +38,7 @@ DECLARE_ENUM(ErrorType, ERROR_TYPES)
     Code(Failure,) \
     Code(Initialize_success,) \
     Code(Initialize_failure,) \
+    Code(File_not_found,) \
 	/* General engine errors */\
     Code(Destroy_obj_not_found,) \
     Code(Glew_failed,) \
@@ -99,6 +100,7 @@ DECLARE_ENUM(ErrorCode, ERROR_CODES)
     Code(Source_LightComponent,) \
     Code(Source_LightObject,) \
     Code(Source_LightingPass,) \
+    Code(Source_LuaComponent,) \
     Code(Source_ModelComponent,) \
     Code(Source_ModelLoader,) \
     Code(Source_ObjectDirectory,) \
@@ -110,7 +112,7 @@ DECLARE_ENUM(ErrorCode, ERROR_CODES)
     Code(Source_RendererScene,) \
     Code(Source_RendererSystem,) \
     Code(Source_SceneLoader,) \
-    Code(Source_Scripting,) \
+    Code(Source_Script,) \
     Code(Source_ScriptObject,) \
     Code(Source_ShaderComponent,) \
     Code(Source_ShaderLoader,) \

+ 4 - 2
Praxis3D/Source/ErrorHandler.cpp

@@ -27,6 +27,7 @@ ErrorHandler::ErrorHandler()
 	AssignErrorType(Failure, Warning);
 	AssignErrorType(Initialize_success, Info);
 	AssignErrorType(Initialize_failure, Info);
+	AssignErrorType(File_not_found, Warning);
 	AssignErrorType(Destroy_obj_not_found, Warning);
 	AssignErrorType(Glew_failed, FatalError);
 	AssignErrorType(Ifstream_failed, Warning);
@@ -72,7 +73,8 @@ ErrorHandler::ErrorHandler()
     m_errHashmap[GetString(Source_LensFlarePass)]				= NumberOfErrorCodes + Source_LensFlarePass;
 	m_errHashmap[GetString(Source_LightComponent)]				= NumberOfErrorCodes + Source_LightComponent;
     m_errHashmap[GetString(Source_LightObject)]					= NumberOfErrorCodes + Source_LightObject;
-    m_errHashmap[GetString(Source_LightingPass)]				= NumberOfErrorCodes + Source_LightingPass;
+	m_errHashmap[GetString(Source_LightingPass)]				= NumberOfErrorCodes + Source_LightingPass;
+	m_errHashmap[GetString(Source_LuaComponent)]				= NumberOfErrorCodes + Source_LuaComponent;
 	m_errHashmap[GetString(Source_ObjectDirectory)]				= NumberOfErrorCodes + Source_ObjectDirectory;
 	m_errHashmap[GetString(Source_ModelComponent)]				= NumberOfErrorCodes + Source_ModelComponent;
     m_errHashmap[GetString(Source_ModelLoader)]					= NumberOfErrorCodes + Source_ModelLoader;
@@ -84,7 +86,7 @@ ErrorHandler::ErrorHandler()
 	m_errHashmap[GetString(Source_RendererScene)]				= NumberOfErrorCodes + Source_RendererScene;
 	m_errHashmap[GetString(Source_RendererSystem)]				= NumberOfErrorCodes + Source_RendererSystem;
     m_errHashmap[GetString(Source_SceneLoader)]					= NumberOfErrorCodes + Source_SceneLoader;
-    m_errHashmap[GetString(Source_Scripting)]					= NumberOfErrorCodes + Source_Scripting;
+    m_errHashmap[GetString(Source_Script)]						= NumberOfErrorCodes + Source_Script;
     m_errHashmap[GetString(Source_ScriptObject)]				= NumberOfErrorCodes + Source_ScriptObject;
 	m_errHashmap[GetString(Source_ShaderComponent)]				= NumberOfErrorCodes + Source_ShaderComponent;
     m_errHashmap[GetString(Source_ShaderLoader)]				= NumberOfErrorCodes + Source_ShaderLoader;

+ 2 - 2
Praxis3D/Source/GameLogicObject.h

@@ -9,7 +9,7 @@ class GameLogicObject : public SystemObject
 {
 public:
 	GameLogicObject(SystemScene *p_systemScene, const std::string &p_name)
-		: SystemObject(p_systemScene, p_name, Properties::Scripting)
+		: SystemObject(p_systemScene, p_name, Properties::Script)
 	{
 
 
@@ -21,7 +21,7 @@ public:
 	}
 
 	// System type is Graphics
-	BitMask getSystemType() { return Systems::Scripting; }
+	BitMask getSystemType() { return Systems::Script; }
 
 	void update(const float p_deltaTime)
 	{

+ 39 - 5
Praxis3D/Source/GameObject.h

@@ -4,6 +4,7 @@
 #include "GraphicsObject.h"
 #include "ObjectRegister.h"
 #include "SceneLoader.h"
+#include "ScriptObject.h"
 #include "SpatialDataManager.h"
 #include "System.h"
 
@@ -17,6 +18,7 @@ public:
 	{
 		m_parent = nullptr;
 		m_graphicsComponent = nullptr;
+		m_scriptComponent = nullptr;
 		m_componentsFlag = 0;
 	}
 	~GameObject()
@@ -55,7 +57,7 @@ public:
 	// Notify this object of the data that has been changed
 	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) override 
 	{
-		assert(p_subject == nullptr);
+		//assert(p_subject == nullptr);
 
 		// Process the spatial changes and record the world-space changes to be passed to the children objects
 		BitMask newChanges = m_spatialData.changeOccurred(*p_subject, p_changeType);
@@ -139,13 +141,13 @@ public:
 	const std::vector<GameObject*> &getChildren() const { return m_children; }
 
 	// Component functions
-	void addComponent(GraphicsObject *p_graphicsComponent) 
+	void addComponent(GraphicsObject *p_component)
 	{ 
 		// Remove the old component if it exists
 		removeComponent(Systems::TypeID::Graphics);
 
 		// Assign the new graphics component
-		m_graphicsComponent = p_graphicsComponent;
+		m_graphicsComponent = p_component;
 
 		// Share the GameObjects spatial data with the component
 		m_graphicsComponent->setSpatialDataManagerReference(m_spatialData);
@@ -155,6 +157,25 @@ public:
 
 		// Set the graphics component as an observer of this game object
 		m_sceneLoader.getChangeController()->createObjectLink(this, m_graphicsComponent);
+	}	
+	void addComponent(ScriptObject *p_component)
+	{
+		// Remove the old component if it exists
+		removeComponent(Systems::TypeID::Script);
+
+		// Assign the new script component
+		m_scriptComponent = p_component;
+
+		// Share the GameObjects spatial data with the component
+		m_scriptComponent->setSpatialDataManagerReference(m_spatialData);
+
+		// Set the flag for the script component, so it is known from the flag that there is one currently present
+		m_componentsFlag |= Systems::GameObjectComponents::Script;
+
+		m_sceneLoader.getChangeController()->createObjectLink(m_scriptComponent->getLuaComponent(), this);
+
+		// Set the script component as an observer of this game object
+		//m_sceneLoader.getChangeController()->createObjectLink(this, m_scriptComponent);
 	}
 	void removeComponent(Systems::TypeID p_componentType) 
 	{
@@ -178,9 +199,22 @@ public:
 				}
 				break;
 			}
-			case Systems::TypeID::Scripting:
+			case Systems::TypeID::Script:
 			{
+				// First check if the component exists
+				if(m_scriptComponent != nullptr)
+				{
+					unlinkComponent(m_scriptComponent);
+
+					// Stop sharing the spatial data with the component
+					m_scriptComponent->removeSpatialDataManagerReference();
 
+					// Assign the component pointer as nullptr to denote that it has been removed
+					m_scriptComponent = nullptr;
+
+					// Remove the bit corresponding to script component from the componentsFlag bitmask
+					m_componentsFlag &= ~Systems::GameObjectComponents::Script;
+				}
 				break;
 			}
 		}
@@ -216,7 +250,7 @@ private:
 
 	//Components
 	GraphicsObject *m_graphicsComponent;
-	SystemObject *m_scriptingComponent;
+	ScriptObject *m_scriptComponent;
 
 	// Stores a separate flag for each component currently present
 	BitMask m_componentsFlag;

+ 2 - 2
Praxis3D/Source/GraphicsObject.h

@@ -26,7 +26,7 @@ class GraphicsObject : public SystemObject, public SpatialDataManagerObject, pub
 {
 public:
 	GraphicsObject(SystemScene *p_systemScene, const std::string &p_name)
-		: SystemObject(p_systemScene, p_name, Properties::Graphics)
+		: SystemObject(p_systemScene, p_name, Properties::GraphicsObject)
 	{
 		m_cameraComponent = nullptr;
 		m_lightComponent = nullptr;
@@ -36,7 +36,7 @@ public:
 		m_componentsFlag = 0;
 
 	}
-	virtual ~GraphicsObject() 
+	~GraphicsObject() 
 	{
 		// Iterate over all component types and delete components if they have been created
 		for(std::size_t i = 0; i < GraphicsComponentType::GraphicsComponentType_NumOfComponents; i++)

+ 1 - 0
Praxis3D/Source/InheritanceObjects.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "CommonDefinitions.h"
+#include "GraphicsDataSets.h"
 #include "NullObjects.h"
 #include "SpatialDataManager.h"
 

+ 1 - 1
Praxis3D/Source/KeyCommand.cpp

@@ -2,7 +2,7 @@
 #include "KeyCommand.h"
 #include "WindowLocator.h"
 
-void KeyCommand::bind(std::string &p_keyName)
+void KeyCommand::bindByKeyName(std::string p_keyName)
 {
 	// Get the scancode by the key name, and call bind
 	bind(WindowLocator::get().getScancode(p_keyName));

+ 1 - 1
Praxis3D/Source/KeyCommand.h

@@ -33,7 +33,7 @@ public:
 		std::vector<Scancode>().swap(m_scancodes);
 	}
 
-	void bind(std::string &p_keyName);
+	void bindByKeyName(std::string p_keyName);
 	void bind(Scancode p_scancode);
 	void unbind(Scancode p_scancode);
 	void unbindAll();

+ 184 - 0
Praxis3D/Source/LuaComponent.h

@@ -0,0 +1,184 @@
+#pragma once
+
+#define SOL_LUAJIT 1
+
+#include "ErrorHandlerLocator.h"
+#include "Filesystem.h"
+#include "InheritanceObjects.h"
+#include "LuaScript.h"
+#include "System.h"
+
+class LuaComponent : public SystemObject, public SpatialDataManagerObject, public LoadableGraphicsObject
+{
+	friend class ScriptScene;
+public:
+	LuaComponent(SystemScene *p_systemScene, std::string p_name, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::LuaComponent), m_luaSpatialData(*this), m_luaScript(m_luaSpatialData)
+	{
+		m_luaScriptLoaded = false;
+		m_luaSpatialData.setTrackLocalChanges(true);
+	}
+	~LuaComponent() { }
+
+	ErrorCode init() final override
+	{
+		// Mark the object as loaded, because there is nothing to be specifically loaded, at least for now
+		//setLoadedToMemory(true);
+		//setLoadedToVideoMemory(true);
+
+		return ErrorCode::Success;
+	}
+
+	void loadToMemory()
+	{
+		auto luaError = m_luaScript.init();
+
+		if(luaError != ErrorCode::Success)
+			ErrHandlerLoc().get().log(luaError, ErrorSource::Source_LuaComponent, m_name);
+		else
+			m_luaScriptLoaded = true;
+
+		setActive(true);
+	}
+
+	void update(const float p_deltaTime)
+	{
+		// Get the current spatial data
+		m_luaSpatialData.setSpatialData(*m_spatialData);
+
+		if(m_luaScriptLoaded)
+			m_luaScript.update(p_deltaTime);
+
+		m_luaSpatialData.update();
+
+		auto changes = m_luaSpatialData.getCurrentChangesAndReset();
+
+		//if(CheckBitmask(changes, Systems::Changes::Spatial::WorldPosition))
+		//	std::cout << "Position changes occurred" << std::endl;
+
+		//if(CheckBitmask(changes, Systems::Changes::Spatial::WorldRotation))
+		//	std::cout << "Rotation changes occurred" << std::endl;
+
+		postChanges(changes);
+
+		std::cout << m_spatialData->getWorldSpaceData().m_spatialData.m_position.x << " : " << m_spatialData->getWorldSpaceData().m_spatialData.m_position.y << " : " << m_spatialData->getWorldSpaceData().m_spatialData.m_position.z << std::endl;
+	}
+
+	ErrorCode importObject(const PropertySet &p_properties) final override
+	{
+		ErrorCode importError = ErrorCode::Failure;
+
+		// Check if PropertySet isn't empty and the component hasn't been loaded already
+		if(p_properties && !isLoadedToMemory())
+		{
+			if(p_properties.getPropertyID() == Properties::Lua)
+			{
+				auto const &luaFilenameProperty = p_properties.getPropertyByID(Properties::Filename);
+
+				if(luaFilenameProperty)
+				{
+					std::string luaFilename = luaFilenameProperty.getString();
+					if(!luaFilename.empty())
+					{
+						luaFilename = Config::filepathVar().script_path + luaFilename;
+						if(Filesystem::exists(luaFilename))
+						{
+							m_luaScript.setScriptFilename(luaFilename);
+
+							importError = ErrorCode::Success;
+							ErrHandlerLoc().get().log(ErrorType::Info, ErrorSource::Source_LuaComponent, m_name + " - Script loaded");
+						}
+						else
+						{
+							importError = ErrorCode::File_not_found;
+							ErrHandlerLoc().get().log(ErrorType::Warning, ErrorSource::Source_LuaComponent, m_name + " - File \'" + luaFilename + "\' not found");
+						}
+					}
+					else
+					{
+						importError = ErrorCode::Property_no_filename;
+						ErrHandlerLoc().get().log(ErrorType::Warning, ErrorSource::Source_LuaComponent, m_name + " - Property \'" + GetString(Properties::Filename) + "\' is empty");
+					}
+				}
+				else
+				{
+					importError = ErrorCode::Property_no_filename;
+					ErrHandlerLoc().get().log(ErrorType::Warning, ErrorSource::Source_LuaComponent, m_name + " - Missing \'" + GetString(Properties::Filename) + "\' property");
+				}
+			}
+
+			if(importError == ErrorCode::Success)
+			{
+				setLoadedToMemory(true);
+				setLoadedToVideoMemory(true);
+			}
+		}
+
+		return importError;
+	}
+
+	PropertySet exportObject() final override
+	{
+		// Create the root Camera property set
+		PropertySet propertySet(Properties::Camera);
+
+		return propertySet;
+	}
+
+	// System type is Graphics
+	BitMask getSystemType() final override { return Systems::Script; }
+
+	BitMask getDesiredSystemChanges() final override { return Systems::Changes::None; }
+	BitMask getPotentialSystemChanges() final override { return Systems::Changes::All; }
+
+	const inline Math::Quaternion &getQuaternion(const Observer *p_observer, BitMask p_changedBits) const
+	{
+		return m_luaSpatialData.getQuaternion(p_observer, p_changedBits);
+	}
+	const inline Math::Vec3f &getVec3(const Observer *p_observer, BitMask p_changedBits) const
+	{
+		if(CheckBitmask(p_changedBits, Systems::Changes::Type::Spatial))
+			return m_luaSpatialData.getVec3(p_observer, p_changedBits);
+
+		return NullObjects::NullVec3f;
+	}
+	const inline Math::Mat4f &getMat4(const Observer *p_observer, BitMask p_changedBits) const
+	{
+		if(CheckBitmask(p_changedBits, Systems::Changes::Type::Spatial))
+			return m_luaSpatialData.getMat4(p_observer, p_changedBits);
+
+		return NullObjects::NullMat4f;
+	}
+	const inline SpatialData &getSpatialData(const Observer *p_observer, BitMask p_changedBits) const
+	{
+		if(CheckBitmask(p_changedBits, Systems::Changes::Type::Spatial))
+			return m_luaSpatialData.getSpatialData(p_observer, p_changedBits);
+
+		return NullObjects::NullSpacialData;
+	}
+	const inline SpatialTransformData &getSpatialTransformData(const Observer *p_observer, BitMask p_changedBits) const
+	{
+		if(CheckBitmask(p_changedBits, Systems::Changes::Type::Spatial))
+			return m_luaSpatialData.getSpatialTransformData(p_observer, p_changedBits);
+
+		return NullObjects::NullSpacialTransformData;
+	}
+
+	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) { }
+
+	void setSpatialDataManagerReference(const SpatialDataManager &p_spatialData) 
+	{ 
+		m_spatialData = &p_spatialData;
+
+		// Copy data from reference spatial data manager to a copy of it that's used for lua script
+		m_luaSpatialData = *m_spatialData;
+
+		// Make sure to track local changes
+		m_luaSpatialData.setTrackLocalChanges(true);
+	}
+
+private:
+	LuaScript m_luaScript;
+	bool m_luaScriptLoaded;
+
+	SpatialDataManager m_luaSpatialData;
+};

+ 8 - 0
Praxis3D/Source/LuaScript.cpp

@@ -0,0 +1,8 @@
+#include "LuaScript.h"
+
+namespace LuaDefinitions
+{
+	DEFINE_ENUM(UserTypes, LUA_USER_TYPES)
+
+	DEFINE_ENUM(SpatialChanges, LUA_SPATIAL_CHANGES)
+}

+ 286 - 0
Praxis3D/Source/LuaScript.h

@@ -0,0 +1,286 @@
+#pragma once
+
+#define SOL_LUAJIT 1
+
+#include "EnumFactory.h"
+#include "ErrorHandlerLocator.h"
+#include "SpatialDataManager.h"
+#include "WindowLocator.h"
+
+#include <sol/sol.hpp>
+
+namespace LuaDefinitions
+{
+#define LUA_USER_TYPES(Code) \
+    Code(MouseInfo,) \
+    Code(KeyCommand,) \
+	Code(InputVariables,) \
+	Code(SpatialDataManager,) \
+	Code(NumOfTypes, )
+	DECLARE_ENUM(UserTypes, LUA_USER_TYPES)
+
+#define LUA_SPATIAL_CHANGES(Code) \
+	Code(LocalPosition,) \
+	Code(LocalRotation,) \
+	Code(LocalScale,) \
+	Code(LocalTransform,) \
+	Code(WorldPosition,) \
+	Code(WorldRotation,) \
+	Code(WorldScale,) \
+	Code(WorldTransform,) \
+	Code(AllLocalNoTransform,) \
+	Code(AllWorldNoTransform,) \
+	Code(AllLocal,) \
+	Code(AllWorld,) \
+	Code(AllSpatial, )
+	DECLARE_ENUM(SpatialChanges, LUA_SPATIAL_CHANGES)
+}
+
+class LuaScript
+{
+public:
+	LuaScript(SpatialDataManager &p_spatialData) : m_spatialData(p_spatialData)
+	{ 
+		m_keyCommands.reserve(10);
+	}
+	LuaScript(SpatialDataManager &p_spatialData, std::string &p_scriptFilename) : m_spatialData(p_spatialData), m_luaScriptFilename(p_scriptFilename)
+	{
+		m_keyCommands.reserve(10);
+	}
+	~LuaScript() 
+	{
+		// Unbind all created key commands
+		for(decltype(m_keyCommands.size()) i = 0; i < m_keyCommands.size(); i++)
+		{
+			if(m_keyCommands[i] != nullptr)
+			{
+				m_keyCommands[i]->unbindAll();
+				delete m_keyCommands[i];
+			}
+		}
+	}
+
+	ErrorCode init()
+	{
+		// Initialize Lua state
+		m_luaState.open_libraries(sol::lib::base);
+
+		// Load script file
+		m_luaState.script_file(m_luaScriptFilename);
+
+		// Set enum definitions and function call-backs, and define C++ user-types in Lua
+		setDefinitions();
+		setFunctions();
+		setUsertypes();
+
+		// Get function references that are inside the Lua script
+		m_luaInit = m_luaState[Config::scriptVar().iniFunctionName];
+		m_luaUpdate = m_luaState[Config::scriptVar().updateFunctionName];
+
+		// Initialize the Lua script
+		m_luaInit();
+
+		return ErrorCode::Success;
+	}
+
+	inline void update(const float p_deltaTime)
+	{
+		m_luaUpdate(p_deltaTime);
+	}
+
+	inline void setScriptFilename(std::string &p_filename) { m_luaScriptFilename = p_filename; }
+
+private:
+	void setDefinitions()
+	{
+		//m_userTypes[sol::update_if_empty]["TEST"] = 25;
+		//m_luaState[sol::update_if_empty]["UserTypes"]["TEST"] = 25;
+		//m_userTypes.create_with("TEST", 25);
+		//m_luaState.create_table_with("TEST", 25);
+		//m_luaState[sol::update_if_empty]["TEST"] = 25;
+
+		// Create a table for user types that are supported by Lua scripts
+		m_userTypes = m_luaState[Config::scriptVar().userTypeTableName].get_or_create<sol::table>();
+
+		// Add each object type to the user type table
+		for(int i = 0; i < LuaDefinitions::UserTypes::NumOfTypes; i++)
+			m_userTypes[sol::update_if_empty][GetString(static_cast<LuaDefinitions::UserTypes>(i))] = i;
+	}
+	void setFunctions()
+	{
+		m_luaState.set_function("toRadianF", sol::resolve<float(const float)>(&Math::toRadian));
+
+		m_luaState.set_function(Config::scriptVar().createObjectFunctionName, &LuaScript::createObjectInLua, this);
+	}
+	void setUsertypes()
+	{
+		m_luaState.new_usertype<Config::InputVariables>("InputVariables",
+			"back_key", &Config::InputVariables::back_key,
+			"backward_editor_key", &Config::InputVariables::backward_editor_key,
+			"backward_key", &Config::InputVariables::backward_key,
+			"center_key", &Config::InputVariables::center_key,
+			"clip_mouse_key", &Config::InputVariables::clip_mouse_key,
+			"close_window_key", &Config::InputVariables::close_window_key,
+			"debug_1_key", &Config::InputVariables::debug_1_key,
+			"debug_2_key", &Config::InputVariables::debug_2_key,
+			"down_editor_key", &Config::InputVariables::down_editor_key,
+			"down_key", &Config::InputVariables::down_key,
+			"escape_key", &Config::InputVariables::escape_key,
+			"forward_editor_key", &Config::InputVariables::forward_editor_key,
+			"forward_key", &Config::InputVariables::forward_key,
+			"fullscreen_key", &Config::InputVariables::fullscreen_key,
+			"jump_key", &Config::InputVariables::jump_key,
+			"left_editor_key", &Config::InputVariables::left_editor_key,
+			"left_strafe_key", &Config::InputVariables::left_strafe_key,
+			"modifier_editor_key", &Config::InputVariables::modifier_editor_key,
+			"next_editor_key", &Config::InputVariables::next_editor_key,
+			"num_preallocated_keybinds", &Config::InputVariables::num_preallocated_keybinds,
+			"previous_editor_key", &Config::InputVariables::previous_editor_key,
+			"right_editor_key", &Config::InputVariables::right_editor_key,
+			"right_strafe_key", &Config::InputVariables::right_strafe_key,
+			"save_editor_key", &Config::InputVariables::save_editor_key,
+			"sprint_key", &Config::InputVariables::sprint_key,
+			"up_editor_key", &Config::InputVariables::up_editor_key,
+			"up_key", &Config::InputVariables::up_key,
+			"vsync_key", &Config::InputVariables::vsync_key,
+			"mouse_filter", &Config::InputVariables::mouse_filter,
+			"cromouse_warp_modess", &Config::InputVariables::mouse_warp_mode,
+			"mouse_jaw", &Config::InputVariables::mouse_jaw,
+			"mouse_pitch", &Config::InputVariables::mouse_pitch,
+			"mouse_pitch_clip", &Config::InputVariables::mouse_pitch_clip,
+			"mouse_sensitivity", &Config::InputVariables::mouse_sensitivity);
+
+		m_luaState.new_usertype<Math::Vec3f>("Vec3f",
+			"x", &Math::Vec3f::x,
+			"y", &Math::Vec3f::y,
+			"z", &Math::Vec3f::z,
+			"cross", &Math::Vec3f::cross,
+			"dot", &Math::Vec3f::dot,
+			"length", &Math::Vec3f::length,
+			"normalize", &Math::Vec3f::normalize,
+			"target", &Math::Vec3f::target,
+			"rotateAngleAxis", sol::resolve<void(float, const Math::Vec3f &)>(&Math::Vec3f::rotate),
+			"rotateVec3f", sol::resolve<void (const Math::Vec3f&)>(&Math::Vec3f::rotate),
+			"addVec3f", &Math::Vec3f::operator+=,
+			"subVec3f", &Math::Vec3f::operator-=,
+			"mulF", sol::resolve<const Math::Vec3f &(const float)>(&Math::Vec3f::operator*=),
+			"mulVec3f", sol::resolve<const Math::Vec3f &(const Math::Vec3f&)>(&Math::Vec3f::operator*=),
+			"divF", sol::resolve<const Math::Vec3f &(const float)>(&Math::Vec3f::operator/=),
+			"divVec3f", sol::resolve<const Math::Vec3f &(const Math::Vec3f &)>(&Math::Vec3f::operator/=));
+
+		m_luaState.new_usertype<SpatialData>("SpatialData",
+			"clear", &SpatialData::clear,
+			"m_position", &SpatialData::m_position,
+			"m_rotationEuler", &SpatialData::m_rotationEuler,
+			"m_scale", &SpatialData::m_scale);
+
+		m_luaState.new_usertype<SpatialTransformData>("SpatialTransformData",
+			"clear", &SpatialTransformData::clear,
+			"m_spatialData", &SpatialTransformData::m_spatialData);
+
+		m_luaState.new_usertype<SpatialDataManager>("SpatialDataManager",
+			"getLocalSpaceData", &SpatialDataManager::getLocalSpaceData,
+			"setLocalPosition", &SpatialDataManager::setLocalPosition,
+			"setLocalRotation", sol::resolve<const void (const Math::Vec3f)>(&SpatialDataManager::setLocalRotation),
+			"setLocalScale", &SpatialDataManager::setLocalScale,
+			"setLocalTransform", &SpatialDataManager::setLocalTransform,
+			"getWorldSpaceData", &SpatialDataManager::getWorldSpaceData,
+			"setWorldPosition", &SpatialDataManager::setWorldPosition,
+			"setWorldRotation", sol::resolve<const void(const Math::Vec3f)>(&SpatialDataManager::setWorldRotation),
+			"setWorldScale", &SpatialDataManager::setWorldScale,
+			"setWorldTransform", &SpatialDataManager::setWorldTransform,
+			"getWorldRotation", &SpatialDataManager::getWorldRotation);
+
+		m_luaState.new_usertype<Window::MouseInfo>("MouseInfo",
+			"m_movementCurrentFrameX", &Window::MouseInfo::m_movementCurrentFrameX,
+			"m_movementCurrentFrameY", &Window::MouseInfo::m_movementCurrentFrameY,
+			"m_movementPrevFrameX", &Window::MouseInfo::m_movementPrevFrameX,
+			"m_movementPrevFrameY", &Window::MouseInfo::m_movementPrevFrameY,
+			"m_wheelX", &Window::MouseInfo::m_wheelX,
+			"m_wheelY", &Window::MouseInfo::m_wheelY,
+			"m_movementX", &Window::MouseInfo::m_movementX,
+			"activm_movementYate", &Window::MouseInfo::m_movementY);
+
+		m_luaState.new_usertype<KeyCommand>("KeyCommand",
+			"activate", &KeyCommand::activate,
+			"deactivate", &KeyCommand::deactivate,
+			"isActivated", &KeyCommand::isActivated,
+			"bind", &KeyCommand::bind,
+			"bindByKeyName", &KeyCommand::bindByKeyName,
+			"unbind", &KeyCommand::unbind,
+			"unbindAll", &KeyCommand::unbindAll);
+	}
+
+	void createObjectInLua(const unsigned int p_objectType, const std::string p_variableName)
+	{
+		// Check if the object type is in a valid range and if the variable name isn't empty
+		if(p_objectType >= 0 && p_objectType < LuaDefinitions::UserTypes::NumOfTypes && !p_variableName.empty())
+		{
+			switch(p_objectType)
+			{
+			case LuaDefinitions::MouseInfo:
+
+				// Set the given variable name in Lua to point to the MouseInfo object
+				m_luaState.set(p_variableName, WindowLocator::get().getMouseInfo());
+
+				break;
+			case LuaDefinitions::KeyCommand:
+			{
+				// Create new key command
+				KeyCommand *keyCommand = new KeyCommand();
+
+				// Set the given variable name in Lua to point to the created key command
+				m_luaState.set(p_variableName, keyCommand);
+
+				// Add key command pointer to an array so it is not lost
+				m_keyCommands.push_back(keyCommand);
+			}
+				break;
+			case LuaDefinitions::InputVariables:
+
+				// Set the given variable name in Lua to point to the MouseInfo object
+				m_luaState.set(p_variableName, Config::inputVar());
+
+				break;
+
+			case LuaDefinitions::SpatialDataManager:
+
+				// Set the given variable name in Lua to point to the Spatial Data Manager object
+				m_luaState.set(p_variableName, &m_spatialData);
+
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	void recordBoolChange(const bool p_change, const unsigned int p_changeType)
+	{
+
+	}
+	void recordIntChange(const int p_change, const unsigned int p_changeType)
+	{
+
+	}
+	void recordFloatChange(const float p_change, const unsigned int p_changeType)
+	{
+
+	}
+	void recordVec3fChange(const Math::Vec3f p_change, const unsigned int p_changeType)
+	{
+
+	}
+
+	SpatialDataManager &m_spatialData;
+
+	std::vector<KeyCommand*> m_keyCommands;
+
+	sol::state m_luaState;
+	std::string m_luaScriptFilename;
+
+	sol::function m_luaInit;
+	sol::function m_luaUpdate;
+
+	sol::table m_userTypes;
+};

+ 8 - 3
Praxis3D/Source/Math.h

@@ -189,6 +189,7 @@ namespace Math
 			x = p_vec.x;	y = p_vec.y;	z = z_arg;
 		}
 		Vec3f(const Vec4f p_vec);
+		~Vec3f() { }
 
 		const inline Vec3f &operator=(const Vec3f& p_vec)
 		{
@@ -260,9 +261,13 @@ namespace Math
 		}
 		const inline Vec3f &target(float verticalAngle_arg, float horizontalAngle_arg)
 		{
-			*this = Vec3f(cosf(verticalAngle_arg) * sinf(horizontalAngle_arg),
-						  sinf(verticalAngle_arg),
-						  cosf(verticalAngle_arg) * cosf(horizontalAngle_arg));
+			//*this = Vec3f(cosf(verticalAngle_arg) * sinf(horizontalAngle_arg),
+			//			  sinf(verticalAngle_arg),
+			//			  cosf(verticalAngle_arg) * cosf(horizontalAngle_arg));
+
+			*this = Vec3f(	cosf(verticalAngle_arg) * cosf(horizontalAngle_arg),
+							cosf(verticalAngle_arg) * sinf(horizontalAngle_arg),
+							sinf(verticalAngle_arg));
 			return *this;
 		}
 		const inline Vec3f &horizontal(float horizontalAngle_arg)

+ 5 - 5
Praxis3D/Source/PlayState.cpp

@@ -2,7 +2,7 @@
 #include "ClockLocator.h"
 #include "PlayState.h"
 #include "PropertySet.h"
-#include "ScriptingSystem.h"
+#include "ScriptSystem.h"
 #include "RendererSystem.h"
 #include "WorldSystem.h"
 
@@ -52,11 +52,11 @@ ErrorCode PlayState::init(TaskManager *p_taskManager)
 	// |  SCRIPTING SYSTEM INITIALIZATION  |
 	// |___________________________________|
 	// Create scripting system and check if it was successful (if not, assign a null system in it's place)
-	m_systems[Systems::Scripting] = new ScriptingSystem();
-	if(m_systems[Systems::Scripting]->init() != ErrorCode::Success)
+	m_systems[Systems::Script] = new ScriptSystem();
+	if(m_systems[Systems::Script]->init() != ErrorCode::Success)
 	{
-		delete m_systems[Systems::Scripting];
-		m_systems[Systems::Scripting] = &g_nullSystemBase;
+		delete m_systems[Systems::Script];
+		m_systems[Systems::Script] = &g_nullSystemBase;
 	}
 
 	//  ___________________________________

+ 1 - 1
Praxis3D/Source/RendererBackend.h

@@ -742,7 +742,7 @@ protected:
 				// Check for linking errors. If an error has occurred, get the error message and throw an exception
 				glGetProgramiv(p_command.m_handle, GL_LINK_STATUS, &shaderLinkingResult);
 
-				// If shader loading was successfull
+				// If shader loading was successful
 				if(shaderLinkingResult)
 				{
 

+ 2 - 1
Praxis3D/Source/RendererScene.cpp

@@ -690,7 +690,8 @@ SystemObject *RendererScene::createObject(const PropertySet &p_properties)
 				//graphicsObject->importObject(renderingProperty);
 
 				// Start importing the newly created object in a background thread
-				TaskManagerLocator::get().startBackgroundThread(std::bind(&GraphicsObject::importObject, graphicsObject, renderingProperty));
+				//TaskManagerLocator::get().startBackgroundThread(std::bind(&GraphicsObject::importObject, graphicsObject, renderingProperty));
+				graphicsObject->importObject(renderingProperty);
 			
 				return graphicsObject;
 			}

+ 1 - 0
Praxis3D/Source/RendererScene.h

@@ -152,6 +152,7 @@ private:
 		p_viewData.m_transformMat.initCamera(p_viewData.m_spatialData.m_position, targetVector + p_viewData.m_spatialData.m_position, upVector);*/
 
 		p_viewData.m_transformMat.identity();
+		p_viewData.m_transformMat.translate(-p_viewData.m_spatialData.m_position);
 		p_viewData.m_transformMat.rotate(p_viewData.m_spatialData.m_rotationEuler);
 	}
 

+ 228 - 0
Praxis3D/Source/ScriptObject.h

@@ -0,0 +1,228 @@
+#pragma once
+
+#include "InheritanceObjects.h"
+#include "LuaComponent.h"
+#include "System.h"
+
+enum ScriptComponentType : std::size_t
+{
+	ScriptComponentType_LUA = 0,
+	ScriptComponentType_NumOfComponents
+};
+
+class ScriptObject : public SystemObject, public SpatialDataManagerObject, public LoadableGraphicsObject
+{
+public:
+	ScriptObject(SystemScene *p_systemScene, const std::string &p_name)
+		: SystemObject(p_systemScene, p_name, Properties::ScriptObject)
+	{
+		m_luaComponent = nullptr;
+	}
+	~ScriptObject()
+	{
+		// Iterate over all component types and delete components if they have been created
+		for(std::size_t i = 0; i < ScriptComponentType::ScriptComponentType_NumOfComponents; i++)
+			removeComponent(static_cast<ScriptComponentType>(i));
+	}
+
+	ErrorCode init() { return ErrorCode::Success; }
+
+	void loadToMemory()
+	{
+		if(luaComponentPresent())
+			m_luaComponent->loadToMemory();
+
+		setActive(true);
+		setLoadedToMemory(true);
+		setLoadedToVideoMemory(true);
+	}
+
+	ErrorCode importObject(const PropertySet &p_properties)
+	{
+		ErrorCode returnError = ErrorCode::Success;
+
+		// Check if the property set is valid and the script object hasn't been loaded already
+		if(p_properties)
+		{
+			if(!isLoadedToMemory())
+			{
+				// Check if there is a property set for camera and load the camera component if there is
+				auto const &luaComponentProperty = p_properties.getPropertySetByID(Properties::Lua);
+				if(luaComponentProperty)
+				{
+					// Create the lua component
+					addComponent(new LuaComponent(m_systemScene, m_name + Config::componentVar().lua_component_name));
+
+					// Try to initialize the lua component
+					auto componentInitError = m_luaComponent->init();
+					if(componentInitError == ErrorCode::Success)
+					{
+						// Try to import the component
+						auto const &componentImportError = m_luaComponent->importObject(luaComponentProperty);
+
+						// Remove the component if it failed to import
+						if(componentImportError != ErrorCode::Success)
+						{
+							removeComponent(ScriptComponentType::ScriptComponentType_LUA);
+							ErrHandlerLoc().get().log(componentImportError, ErrorSource::Source_CameraComponent, m_name);
+						}
+					}
+					else // Remove the component if it failed to initialize
+					{
+						removeComponent(ScriptComponentType::ScriptComponentType_LUA);
+						ErrHandlerLoc().get().log(componentInitError, ErrorSource::Source_CameraComponent, m_name);
+					}
+				}
+			}
+		}
+		else
+		{
+			returnError = ErrorCode::Failure;
+		}
+
+		return returnError;
+	}
+
+	PropertySet exportObject()
+	{
+		// If there are components present, export each one; if there are no components, return an empty propertySet
+		//if(containsComponents())
+		//{
+		//	PropertySet exportPropertySet(Properties::Rendering);
+
+		//	//if(cameraComponentPresent())
+		//	//	exportPropertySet.addPropertySet(m_cameraComponent->exportObject());
+		//	//if(lightComponentPresent())
+		//	//	exportPropertySet.addPropertySet(m_lightComponent->exportObject());
+		//	//if(modelComponentPresent())
+		//	//	exportPropertySet.addPropertySet(m_modelComponent->exportObject());
+		//	//if(shaderComponentPresent())
+		//	//	exportPropertySet.addPropertySet(m_shaderComponent->exportObject());
+
+		//	return exportPropertySet;
+		//}
+		//else
+			return PropertySet();
+	}
+
+	void update(const float p_deltaTime)
+	{
+		if(!isLoadedToVideoMemory())
+		{
+			performCheckIsLoadedToVideoMemory();
+
+			if(!isLoadedToVideoMemory())
+				return;
+		}
+
+		if(luaComponentPresent())
+			m_luaComponent->update(p_deltaTime);
+
+		if(hasSpatialDataUpdated())
+		{
+
+		}
+
+		if(isUpdateNeeded())
+		{
+
+
+			// Calculate model matrix
+			//m_worldSpace.m_transformMat = Math::createTransformMat(m_worldSpace.m_spatialData.m_position, m_worldSpace.m_spatialData.m_rotationEuler, m_worldSpace.m_spatialData.m_scale);
+
+			// Update components
+			//if(modelComponentPresent())
+			//	m_modelComponent->update(p_deltaTime);
+			//if(shaderComponentPresent())
+			//	m_shaderComponent->update(p_deltaTime);
+			//if(lightComponentPresent())
+			//	m_lightComponent->update(p_deltaTime);
+
+			// Mark as updated
+			updatePerformed();
+		}
+	}
+
+	// Assign a pointer to a const SpatialDataChangeManager, so the object can use it for its spatial data
+	// Also assigns the pointer to every component that needs it
+	virtual void setSpatialDataManagerReference(const SpatialDataManager &p_spatialData)
+	{
+		SpatialDataManagerObject::setSpatialDataManagerReference(p_spatialData);
+
+		if(luaComponentPresent())
+			m_luaComponent->setSpatialDataManagerReference(*m_spatialData);
+	}
+
+	// System type is Graphics
+	BitMask getSystemType() { return Systems::Script; }
+
+	virtual BitMask getDesiredSystemChanges() { return Systems::Changes::Graphics::All; }
+	virtual BitMask getPotentialSystemChanges() { return Systems::Changes::Graphics::All; }
+
+	inline LuaComponent *getLuaComponent() { return m_luaComponent; }
+
+	inline const bool luaComponentPresent()	const { return (m_luaComponent == nullptr) ? false : true; }
+
+	virtual void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType)
+	{
+		// Track what data has been modified
+		BitMask newChanges = Systems::Changes::None;
+
+		// If any data has been updated, post the changes to listeners
+		if(newChanges != Systems::Changes::None)
+		{
+			postChanges(newChanges);
+		}
+	}
+
+	void addComponent(LuaComponent *p_component)
+	{
+		// Make sure that this component isn't assigned already
+		removeComponent(ScriptComponentType::ScriptComponentType_LUA);
+		m_luaComponent = p_component;
+
+		// Share the ScriptObjects spatial data with the component
+		m_luaComponent->setSpatialDataManagerReference(*m_spatialData);
+
+		// Set the flag for the lua component, so it is known from the flag that there is one currently present
+		m_componentsFlag |= Systems::ScriptObjectComponents::Lua;
+	}
+	void removeComponent(const ScriptComponentType p_compType)
+	{
+		switch(p_compType)
+		{
+		case ScriptComponentType::ScriptComponentType_LUA:
+		{
+			if(m_luaComponent != nullptr)
+			{
+				// Delete the actual component
+				delete m_luaComponent;
+
+				// Assign the component pointer as nullptr to denote that it has been removed
+				m_luaComponent = nullptr;
+
+				// Remove the bit corresponding to lua component from the componentsFlag bitmask
+				m_componentsFlag &= ~Systems::ScriptObjectComponents::Lua;
+			}
+			break;
+		}
+		}
+	}
+	
+	// Returns true if the graphics object contains any components
+	inline const bool containsComponents()
+	{
+		if(luaComponentPresent())
+			return true;
+
+		return false;
+	}
+
+private:
+	// Components
+	LuaComponent *m_luaComponent;
+
+	// Stores a separate flag for each component currently present
+	BitMask m_componentsFlag;
+};
+

+ 134 - 67
Praxis3D/Source/ScriptingScene.cpp → Praxis3D/Source/ScriptScene.cpp

@@ -2,88 +2,160 @@
 #include <functional>
 
 #include "NullSystemObjects.h"
-#include "ScriptingSystem.h"
-#include "ScriptingScene.h"
+#include "ScriptSystem.h"
+#include "ScriptScene.h"
 #include "TaskManagerLocator.h"
 
-ScriptingScene::ScriptingScene(ScriptingSystem *p_system, SceneLoader *p_sceneLoader) : SystemScene(p_system, p_sceneLoader)
+ScriptScene::ScriptScene(ScriptSystem *p_system, SceneLoader *p_sceneLoader) : SystemScene(p_system, p_sceneLoader)
 {
 	m_scriptingTask = nullptr;
 }
 
-ScriptingScene::~ScriptingScene()
+ScriptScene::~ScriptScene()
 {
 }
 
-ErrorCode ScriptingScene::init()
+ErrorCode ScriptScene::init()
 {
-	m_scriptingTask = new ScriptingTask(this);
+	m_scriptingTask = new ScriptTask(this);
 	return ErrorCode::Success;
 }
 
-ErrorCode ScriptingScene::setup(const PropertySet &p_properties)
+ErrorCode ScriptScene::setup(const PropertySet &p_properties)
 {
-	/*for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
+	// Get default object pool size
+	decltype(m_scriptObjects.getPoolSize()) objectPoolSize = Config::objectPoolVar().object_pool_size;
+
+	for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
 	{
 		switch(p_properties[i].getPropertyID())
 		{
-
+		case Properties::ObjectPoolSize:
+			objectPoolSize = p_properties[i].getInt();
+			break;
 		}
-	}*/
+	}
+
+	// Initialize object pools
+	m_scriptObjects.init(objectPoolSize);
 
 	return ErrorCode::Success;
 }
 
-void ScriptingScene::update(const float p_deltaTime)
+void ScriptScene::update(const float p_deltaTime)
 {
-	for(decltype(m_scriptObjects.size()) i = 0, size = m_scriptObjects.size(); i < size; i++)
+	for(decltype(m_scriptObjects.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_scriptObjects.getNumAllocated(),
+		size = m_scriptObjects.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
 	{
-		m_scriptObjects[i]->update(p_deltaTime);
+		// Check if the script object is allocated inside the pool container
+		if(m_scriptObjects[i].allocated())
+		{
+			auto *scriptObject = m_scriptObjects[i].getObject();
+
+			// Increment the number of allocated objects (early bail mechanism)
+			numAllocObjecs++;
+
+			// Check if the script object is enabled
+			if(scriptObject->isObjectActive())
+			{
+				// Update the object
+				scriptObject->update(p_deltaTime);
+			}
+		}
 	}
 }
 
-void ScriptingScene::loadInBackground()
+void ScriptScene::loadInBackground()
 {
-	// Iterate over script objects and start loading them in background
-	for(decltype(m_scriptObjects.size()) i = 0, size = m_scriptObjects.size(); i < size; i++)
-	{
-		TaskManagerLocator::get().startBackgroundThread(std::bind(&BaseScriptObject::loadToMemory, m_scriptObjects[i]));
-	}
+	//// Iterate over script objects and start loading them in background
+	//for(decltype(m_scriptObjects.size()) i = 0, size = m_scriptObjects.size(); i < size; i++)
+	//{
+	//	TaskManagerLocator::get().startBackgroundThread(std::bind(&BaseScriptObject::loadToMemory, m_scriptObjects[i]));
+	//}
 }
 
-PropertySet ScriptingScene::exportObject()
+PropertySet ScriptScene::exportObject()
 {
-	// Create the root property set
-	PropertySet propertySet(Properties::Scripting);
+	//// Create the root property set
+	PropertySet propertySet(Properties::Script);
 
-	// Add root property set for scene values
-	auto &scene = propertySet.addPropertySet(Properties::Scene);
+	//// Add root property set for scene values
+	//auto &scene = propertySet.addPropertySet(Properties::Scene);
 
-	// Add root property set for all the objects
-	auto &objects = propertySet.addPropertySet(Properties::Objects);
+	//// Add root property set for all the objects
+	//auto &objects = propertySet.addPropertySet(Properties::Objects);
 
-	// Add script object property sets
-	for(decltype(m_scriptObjects.size()) i = 0, size = m_scriptObjects.size(); i < size; i++)
-		objects.addPropertySet(m_scriptObjects[i]->exportObject());
+	//// Add script object property sets
+	//for(decltype(m_scriptObjects.size()) i = 0, size = m_scriptObjects.size(); i < size; i++)
+	//	objects.addPropertySet(m_scriptObjects[i]->exportObject());
 
 	return propertySet;
 }
 
-ErrorCode ScriptingScene::preload()
+ErrorCode ScriptScene::preload()
 {	
 	// Load every script object. It still works in parallel, however,
 	// it returns only when all objects have finished loading (simulating sequential call)
-	TaskManagerLocator::get().parallelFor(size_t(0), m_scriptObjects.size(), size_t(1), [=](size_t i)
+	TaskManagerLocator::get().parallelFor(size_t(0), m_scriptObjects.getPoolSize(), size_t(1), [=](size_t i)
 	{
-		m_scriptObjects[i]->loadToMemory();
+		if(m_scriptObjects[i].allocated())
+		{
+			m_scriptObjects[i].getObject()->loadToMemory();
+		}
 	});
 
 	return ErrorCode::Success;
 }
 
-SystemObject *ScriptingScene::createObject(const PropertySet &p_properties)
+SystemObject *ScriptScene::createObject(const PropertySet &p_properties)
 {
-	//  Get certain object properties
+	// Check if property set node is present
+	if(p_properties)
+	{
+		// Check if the rendering property is present
+		auto &scriptProperty = p_properties.getPropertySetByID(Properties::Script);
+		if(scriptProperty)
+		{
+			// Get the object name
+			auto &nameProperty = p_properties.getPropertyByID(Properties::Name);
+
+			// Find a place for the new object in the pool
+			auto scriptObjectFromPool = m_scriptObjects.newObject();
+
+			// Check if the pool wasn't full
+			if(scriptObjectFromPool != nullptr)
+			{
+				std::string name;
+
+				// If the name property is missing, generate a unique name based on the object's index in the pool
+				if(nameProperty)
+					name = nameProperty.getString();
+				else
+					name = GetString(Properties::GraphicsObject) + Utilities::toString(scriptObjectFromPool->getIndex());
+
+				// Construct the GraphicsObject
+				scriptObjectFromPool->construct(this, name);
+				auto scriptObject = scriptObjectFromPool->getObject();
+
+				//graphicsObject->importObject(renderingProperty);
+
+				// Start importing the newly created object in a background thread
+				//TaskManagerLocator::get().startBackgroundThread(std::bind(&ScriptObject::importObject, scriptObject, scriptProperty));
+				scriptObject->importObject(scriptProperty);
+
+				return scriptObject;
+			}
+			else
+			{
+				ErrHandlerLoc::get().log(ErrorCode::ObjectPool_full, ErrorSource::Source_Script, "Failed to add ScriptObject - \'" + nameProperty.getString() + "\'");
+			}
+		}
+	}
+
+	// If valid type was not specified, or object creation failed, return a null object instead
+	return g_nullSystemBase.getScene()->createObject(p_properties);
+
+	/*/  Get certain object properties
 	auto const &type = p_properties.getPropertyByID(Properties::Type).getID();
 
 	SystemObject *newObject = nullptr;
@@ -119,36 +191,31 @@ SystemObject *ScriptingScene::createObject(const PropertySet &p_properties)
 		return newObject;
 
 	// If valid type was not specified, or object creation failed, return a null object instead
-	return g_nullSystemBase.getScene()->createObject(p_properties);
+	return g_nullSystemBase.getScene()->createObject(p_properties);*/
 }
 
-ErrorCode ScriptingScene::destroyObject(SystemObject *p_systemObject)
+ErrorCode ScriptScene::destroyObject(SystemObject *p_systemObject)
 {
-	if(p_systemObject != nullptr)
+	// Check if object is valid and belongs to graphics system
+	if(p_systemObject != nullptr && p_systemObject->getSystemType() == Systems::Graphics)
 	{
-		// Iterate over all elements and match the pointer address
-		for(decltype(m_scriptObjects.size()) i = 0, size = m_scriptObjects.size(); i < size; i++)
-		{
-			// If pointer addresses match, remove it and return success
-			if(m_scriptObjects[i] == p_systemObject)
-			{
-				std::swap(m_scriptObjects[i], m_scriptObjects.back());
-				m_scriptObjects.pop_back();
+		// Cast the system object to graphics object, as it belongs to the renderer scene
+		ScriptObject *objectToDestroy = static_cast<ScriptObject *>(p_systemObject);
 
-				return ErrorCode::Success;
-			}
-		}
+		// Try to destroy the object; return success if it succeeds
+		if(removeObjectFromPool(*objectToDestroy))
+			return ErrorCode::Success;
 	}
 
 	// If this point is reached, no object was found, return an appropriate error
 	return ErrorCode::Destroy_obj_not_found;
 }
 
-void ScriptingScene::changeOccurred(ObservedSubject *p_subject, BitMask p_changeType)
+void ScriptScene::changeOccurred(ObservedSubject *p_subject, BitMask p_changeType)
 {
 }
 
-FreeCamera *ScriptingScene::loadFreeCamera(const PropertySet & p_properties)
+FreeCamera *ScriptScene::loadFreeCamera(const PropertySet & p_properties)
 {
 	FreeCamera *freeCamera = new FreeCamera(this, p_properties.getPropertyByID(Properties::Name).getString());
 
@@ -224,12 +291,12 @@ FreeCamera *ScriptingScene::loadFreeCamera(const PropertySet & p_properties)
 	freeCamera->setStrafeRightKey(rightStrafeKey);
 	freeCamera->setSprintKey(sprintKey);
 
-	m_scriptObjects.push_back(freeCamera);
+	//m_scriptObjects.push_back(freeCamera);
 
 	return freeCamera;
 }
 
-DebugUIScript *ScriptingScene::loadDebugUI(const PropertySet &p_properties)
+DebugUIScript *ScriptScene::loadDebugUI(const PropertySet &p_properties)
 {
 	DebugUIScript *debugUI = new DebugUIScript(this, p_properties.getPropertyByID(Properties::Name).getString());
 
@@ -273,12 +340,12 @@ DebugUIScript *ScriptingScene::loadDebugUI(const PropertySet &p_properties)
 	debugUI->setMouseCaptureKey(mouseCaptureKey);
 	debugUI->setVerticalSyncKey(verticalSyncKey);
 
-	m_scriptObjects.push_back(debugUI);
+	//m_scriptObjects.push_back(debugUI);
 
 	return debugUI;
 }
 
-DebugMoveScript *ScriptingScene::loadDebugMove(const PropertySet &p_properties)
+DebugMoveScript *ScriptScene::loadDebugMove(const PropertySet &p_properties)
 {
 	DebugMoveScript *debugMove = new DebugMoveScript(this, p_properties.getPropertyByID(Properties::Name).getString());
 
@@ -302,12 +369,12 @@ DebugMoveScript *ScriptingScene::loadDebugMove(const PropertySet &p_properties)
 		}
 	}
 
-	m_scriptObjects.push_back(debugMove);
+	//m_scriptObjects.push_back(debugMove);
 
 	return debugMove;
 }
 
-DebugRotateScript *ScriptingScene::loadDebugRotate(const PropertySet &p_properties)
+DebugRotateScript *ScriptScene::loadDebugRotate(const PropertySet &p_properties)
 {
 	DebugRotateScript *debugRotate = new DebugRotateScript(this, p_properties.getPropertyByID(Properties::Name).getString());
 
@@ -328,12 +395,12 @@ DebugRotateScript *ScriptingScene::loadDebugRotate(const PropertySet &p_properti
 		}
 	}
 
-	m_scriptObjects.push_back(debugRotate);
+	//m_scriptObjects.push_back(debugRotate);
 
 	return debugRotate;
 }
 
-SolarTimeScript *ScriptingScene::loadSolarTime(const PropertySet & p_properties)
+SolarTimeScript *ScriptScene::loadSolarTime(const PropertySet & p_properties)
 {
 	SolarTimeScript *solarTimeScript = new SolarTimeScript(this, p_properties.getPropertyByID(Properties::Name).getString());
 
@@ -378,12 +445,12 @@ SolarTimeScript *ScriptingScene::loadSolarTime(const PropertySet & p_properties)
 		}
 	}
 
-	m_scriptObjects.push_back(solarTimeScript);
+	//m_scriptObjects.push_back(solarTimeScript);
 
 	return solarTimeScript;
 }
 
-SunScript *ScriptingScene::loadSun(const PropertySet & p_properties)
+SunScript *ScriptScene::loadSun(const PropertySet & p_properties)
 {
 	SunScript *sunScript = new SunScript(this, p_properties.getPropertyByID(Properties::Name).getString());
 
@@ -401,12 +468,12 @@ SunScript *ScriptingScene::loadSun(const PropertySet & p_properties)
 		}
 	}
 
-	m_scriptObjects.push_back(sunScript);
+	//m_scriptObjects.push_back(sunScript);
 
 	return sunScript;
 }
 
-WorldEditScript *ScriptingScene::loadWorldEdit(const PropertySet & p_properties)
+WorldEditScript *ScriptScene::loadWorldEdit(const PropertySet & p_properties)
 {
 	WorldEditScript *worldEditor = new WorldEditScript(this, p_properties.getPropertyByID(Properties::Name).getString(), m_sceneLoader);
 
@@ -501,11 +568,11 @@ WorldEditScript *ScriptingScene::loadWorldEdit(const PropertySet & p_properties)
 	}
 
 	// Check if the movement speeds were set
-	if(worldEditor->m_movementSpeed == 0.0f)
-		worldEditor->setSpeed(Config::gameplayVar().camera_freelook_speed);
+	//if(worldEditor->m_movementSpeed == 0.0f)
+	//	worldEditor->setSpeed(Config::gameplayVar().camera_freelook_speed);
 
-	if(worldEditor->m_fasterMovementSpeed == 0.0f)
-		worldEditor->setFasterSpeed(worldEditor->m_movementSpeed * 10.0f);
+	//if(worldEditor->m_fasterMovementSpeed == 0.0f)
+	//	worldEditor->setFasterSpeed(worldEditor->m_movementSpeed * 10.0f);
 
 	// Set the keys of the object
 	worldEditor->setUpKey(upKey);
@@ -521,7 +588,7 @@ WorldEditScript *ScriptingScene::loadWorldEdit(const PropertySet & p_properties)
 	worldEditor->setSaveKey(saveKey);
 	worldEditor->setModifierKey(modifierKey);
 
-	m_scriptObjects.push_back(worldEditor);
+	//m_scriptObjects.push_back(worldEditor);
 
 	return worldEditor;
 }

+ 37 - 8
Praxis3D/Source/ScriptingScene.h → Praxis3D/Source/ScriptScene.h

@@ -6,19 +6,20 @@
 #include "DebugMoveScript.h"
 #include "DebugRotateScript.h"
 #include "NullSystemObjects.h"
-#include "ScriptingTask.h"
+#include "ScriptObject.h"
+#include "ScriptTask.h"
 #include "SolarTimeScript.h"
 #include "System.h"
 #include "SunScript.h"
 #include "WorldEditObject.h"
 
-class ScriptingSystem;
+class ScriptSystem;
 
-class ScriptingScene : public SystemScene
+class ScriptScene : public SystemScene
 {
 public:
-	ScriptingScene(ScriptingSystem *p_system, SceneLoader *p_sceneLoader);
-	~ScriptingScene();
+	ScriptScene(ScriptSystem *p_system, SceneLoader *p_sceneLoader);
+	~ScriptScene();
 
 	ErrorCode init();
 
@@ -49,9 +50,34 @@ public:
 
 		return g_nullSystemBase.getScene()->getSystemTask();
 	}
-	Systems::TypeID getSystemType() { return Systems::Scripting; }
+	Systems::TypeID getSystemType() { return Systems::Script; }
 
 private:
+	// Removes an object from a pool, by iterating checking each pool for matched index; returns true if the object was found and removed
+	inline bool removeObjectFromPool(ScriptObject &p_object)
+	{
+		// Go over each graphics object
+		for(decltype(m_scriptObjects.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_scriptObjects.getNumAllocated(),
+			size = m_scriptObjects.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
+		{
+			// Check if the script object is allocated inside the pool container
+			if(m_scriptObjects[i].allocated())
+			{
+				// Increment the number of allocated objects (early bail mechanism)
+				numAllocObjecs++;
+
+				// If the object matches with the one we are looking for, remove it from the script object pool
+				if(*m_scriptObjects[i].getObject() == p_object)
+				{
+					m_scriptObjects.remove(m_scriptObjects[i].getIndex());
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+
 	FreeCamera *loadFreeCamera(const PropertySet &p_properties);
 	DebugUIScript *loadDebugUI(const PropertySet &p_properties);
 	DebugMoveScript *loadDebugMove(const PropertySet &p_properties);
@@ -60,7 +86,10 @@ private:
 	SunScript *loadSun(const PropertySet &p_properties);
 	WorldEditScript *loadWorldEdit(const PropertySet &p_properties);
 
-	ScriptingTask *m_scriptingTask;
+	ScriptTask *m_scriptingTask;
+
+	//std::vector<BaseScriptObject*> m_scriptObjects;
 
-	std::vector<BaseScriptObject*> m_scriptObjects;
+	// Object pools
+	ObjectPool<ScriptObject> m_scriptObjects;
 };

+ 12 - 12
Praxis3D/Source/ScriptingSystem.cpp → Praxis3D/Source/ScriptSystem.cpp

@@ -1,30 +1,30 @@
 
 #include "ErrorHandlerLocator.h"
 #include "NullSystemObjects.h"
-#include "ScriptingScene.h"
-#include "ScriptingSystem.h"
+#include "ScriptScene.h"
+#include "ScriptSystem.h"
 
-ScriptingSystem::ScriptingSystem()
+ScriptSystem::ScriptSystem()
 {
 	m_scriptingScene = nullptr;
-	m_systemName = GetString(Systems::Scripting);
+	m_systemName = GetString(Systems::Script);
 }
 
-ScriptingSystem::~ScriptingSystem()
+ScriptSystem::~ScriptSystem()
 {
 
 }
 
-ErrorCode ScriptingSystem::init()
+ErrorCode ScriptSystem::init()
 {
 	ErrorCode returnCode = ErrorCode::Success;
 	
-	ErrHandlerLoc::get().log(ErrorType::Info, ErrorSource::Source_Scripting, "Scripting system has been initialized");
+	ErrHandlerLoc::get().log(ErrorType::Info, ErrorSource::Source_Script, "Script system has been initialized");
 	
 	return returnCode;
 }
 
-ErrorCode ScriptingSystem::setup(const PropertySet &p_properties)
+ErrorCode ScriptSystem::setup(const PropertySet &p_properties)
 {
 	/*for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
 	{
@@ -37,16 +37,16 @@ ErrorCode ScriptingSystem::setup(const PropertySet &p_properties)
 	return ErrorCode::Success;
 }
 
-void ScriptingSystem::loadInBackground()
+void ScriptSystem::loadInBackground()
 {
 }
 
-SystemScene *ScriptingSystem::createScene(SceneLoader *p_sceneLoader)
+SystemScene *ScriptSystem::createScene(SceneLoader *p_sceneLoader)
 {
 	if(m_scriptingScene == nullptr)
 	{
 		// Create new scene
-		m_scriptingScene = new ScriptingScene(this, p_sceneLoader);
+		m_scriptingScene = new ScriptScene(this, p_sceneLoader);
 		ErrorCode sceneError = m_scriptingScene->init();
 
 		// Check if it initialized correctly (cannot continue without the scene)
@@ -59,7 +59,7 @@ SystemScene *ScriptingSystem::createScene(SceneLoader *p_sceneLoader)
 	return m_scriptingScene;
 }
 
-SystemScene *ScriptingSystem::getScene()
+SystemScene *ScriptSystem::getScene()
 {
 	return m_scriptingScene;
 }

+ 6 - 6
Praxis3D/Source/ScriptingSystem.h → Praxis3D/Source/ScriptSystem.h

@@ -2,13 +2,13 @@
 
 #include "System.h"
 
-class ScriptingScene;
+class ScriptScene;
 
-class ScriptingSystem : public SystemBase
+class ScriptSystem : public SystemBase
 {
 public:
-	ScriptingSystem();
-	virtual ~ScriptingSystem();
+	ScriptSystem();
+	virtual ~ScriptSystem();
 
 	virtual ErrorCode init();
 
@@ -18,13 +18,13 @@ public:
 
 	void loadInBackground();
 
-	Systems::TypeID getSystemType() { return Systems::Scripting; }
+	Systems::TypeID getSystemType() { return Systems::Script; }
 
 	virtual SystemScene *createScene(SceneLoader *p_sceneLoader);
 
 	virtual SystemScene *getScene();
 	
 protected:
-	ScriptingScene *m_scriptingScene;
+	ScriptScene *m_scriptingScene;
 };
 

+ 19 - 0
Praxis3D/Source/ScriptTask.cpp

@@ -0,0 +1,19 @@
+
+#include "ScriptScene.h"
+#include "ScriptTask.h"
+
+ScriptTask::ScriptTask(ScriptScene *p_scriptingScene)
+	: SystemTask(p_scriptingScene), m_scriptingScene(p_scriptingScene)
+{
+
+}
+
+ScriptTask::~ScriptTask()
+{
+
+}
+
+void ScriptTask::update(const float p_deltaTime)
+{
+	m_scriptingScene->update(p_deltaTime);
+}

+ 23 - 0
Praxis3D/Source/ScriptTask.h

@@ -0,0 +1,23 @@
+#pragma once
+
+#include "System.h"
+
+class ScriptScene;
+
+class ScriptTask : public SystemTask
+{
+	friend class ScriptScene;
+public:
+	ScriptTask(ScriptScene *p_scriptingScene);
+	~ScriptTask();
+
+	Systems::TypeID getSystemType() { return Systems::Script; }
+
+	void update(const float p_deltaTime);
+
+	bool isPrimaryThreadOnly() { return false; }
+
+protected:
+	ScriptScene *m_scriptingScene;
+};
+

+ 0 - 19
Praxis3D/Source/ScriptingTask.cpp

@@ -1,19 +0,0 @@
-
-#include "ScriptingScene.h"
-#include "ScriptingTask.h"
-
-ScriptingTask::ScriptingTask(ScriptingScene *p_scriptingScene)
-	: SystemTask(p_scriptingScene), m_scriptingScene(p_scriptingScene)
-{
-
-}
-
-ScriptingTask::~ScriptingTask()
-{
-
-}
-
-void ScriptingTask::update(const float p_deltaTime)
-{
-	m_scriptingScene->update(p_deltaTime);
-}

+ 0 - 23
Praxis3D/Source/ScriptingTask.h

@@ -1,23 +0,0 @@
-#pragma once
-
-#include "System.h"
-
-class ScriptingScene;
-
-class ScriptingTask : public SystemTask
-{
-	friend class ScriptingScene;
-public:
-	ScriptingTask(ScriptingScene *p_scriptingScene);
-	~ScriptingTask();
-
-	Systems::TypeID getSystemType() { return Systems::Scripting; }
-
-	void update(const float p_deltaTime);
-
-	bool isPrimaryThreadOnly() { return false; }
-
-protected:
-	ScriptingScene *m_scriptingScene;
-};
-

+ 1 - 1
Praxis3D/Source/SolarTimeScript.h

@@ -267,7 +267,7 @@ public:
 	inline void setForwardKey(std::string &p_string)
 	{
 		m_forwardKey.unbindAll();
-		m_forwardKey.bind(p_string);
+		m_forwardKey.bindByKeyName(p_string);
 	}
 	
 	// PSA Sun position algorithm

+ 94 - 14
Praxis3D/Source/SpatialDataManager.h

@@ -17,6 +17,7 @@ public:
 	SpatialDataManager(const Observer &p_parent) : m_parent(p_parent)
 	{
 		m_updateCount = 0;
+		m_trackLocalChanges = false;
 		worldSpaceNeedsUpdate = false;
 		localTransformNeedsUpdate = false;
 		parentTransformNeedsUpdate = false;
@@ -27,6 +28,22 @@ public:
 
 	}
 
+	SpatialDataManager &operator=(const SpatialDataManager &p_spatialDataManager)
+	{
+		m_trackLocalChanges = p_spatialDataManager.m_trackLocalChanges;
+		worldSpaceNeedsUpdate = p_spatialDataManager.worldSpaceNeedsUpdate;
+		localTransformNeedsUpdate = p_spatialDataManager.localTransformNeedsUpdate;
+		parentTransformNeedsUpdate = p_spatialDataManager.parentTransformNeedsUpdate;
+		worldTransformNeedsUpdate = p_spatialDataManager.worldTransformNeedsUpdate;
+		m_localSpace = p_spatialDataManager.m_localSpace;
+		m_parentSpace = p_spatialDataManager.m_parentSpace;
+		m_worldSpace = p_spatialDataManager.m_worldSpace;
+		m_updateCount = p_spatialDataManager.m_updateCount;
+		m_changes = p_spatialDataManager.m_changes;
+
+		return *this;
+	}
+
 	void update()
 	{	
 		// Calculate the needed transform matrices
@@ -34,6 +51,8 @@ public:
 		{
 			updateTransformMatrix(m_localSpace);
 			localTransformNeedsUpdate = false;
+			if(m_trackLocalChanges)
+				m_changes |= Systems::Changes::Spatial::LocalTransform;
 		}
 		if(parentTransformNeedsUpdate)
 		{
@@ -51,15 +70,14 @@ public:
 		{
 			updateWorldSpace();
 			incrementUpdateCount();
+			m_changes |= Systems::Changes::Spatial::WorldTransform;
 		}
 	}
 
 	// Process spatial changes from the given subject and change type
-	// Returns the changes that have been made; RETURNS ONLY WORLD-SPACE CHANGES!
+	// Returns the changes that have been made; RETURNS ONLY WORLD-SPACE CHANGES BY DEFAULT!
 	BitMask changeOccurred(const ObservedSubject &p_subject, const BitMask p_changeType)
 	{
-		BitMask newChanges = Systems::Changes::None;
-
 		// Process the "All" changes first, as their bitmask is a combination of multiple changes, so it's faster to process the changes all at once, instead of individually
 		// Checks are laid out in hierarchical sequence, starting with combinations of multiple changes and ending with each individual change
 		if(CheckBitmask(p_changeType, Systems::Changes::Spatial::All))
@@ -67,7 +85,7 @@ public:
 			// Update both the local-space and parent world-space data
 			updateLocalSpatialTransformData(p_subject.getSpatialTransformData(&m_parent, Systems::Changes::Spatial::AllLocal));
 			updateParentSpatialTransformData(p_subject.getSpatialTransformData(&m_parent, Systems::Changes::Spatial::AllWorld));
-			newChanges |= Systems::Changes::Spatial::AllWorld;
+			m_changes |= Systems::Changes::Spatial::AllWorld;
 		}
 		else // If the "All" flag wasn't set, check each local and world (parent) change
 		{
@@ -111,7 +129,7 @@ public:
 			if(CheckBitmask(p_changeType, Systems::Changes::Spatial::AllWorld))
 			{
 				updateParentSpatialTransformData(p_subject.getSpatialTransformData(&m_parent, Systems::Changes::Spatial::AllWorld));
-				newChanges |= Systems::Changes::Spatial::AllWorld;
+				m_changes |= Systems::Changes::Spatial::AllWorld;
 			}
 			else
 			{
@@ -119,32 +137,32 @@ public:
 				if(CheckBitmask(p_changeType, Systems::Changes::Spatial::AllWorldNoTransform))
 				{
 					updateParentSpatialData(p_subject.getSpatialData(&m_parent, Systems::Changes::Spatial::AllWorldNoTransform));
-					newChanges |= Systems::Changes::Spatial::AllWorldNoTransform;
+					m_changes |= Systems::Changes::Spatial::AllWorldNoTransform;
 				}
 				else // If this is reached, check each individual piece of data has changed
 				{
 					if(CheckBitmask(p_changeType, Systems::Changes::Spatial::WorldPosition))
 					{
 						updateParentPosition(p_subject.getVec3(&m_parent, Systems::Changes::Spatial::WorldPosition));
-						newChanges |= Systems::Changes::Spatial::WorldPosition;
+						m_changes |= Systems::Changes::Spatial::WorldPosition;
 					}
 
 					if(CheckBitmask(p_changeType, Systems::Changes::Spatial::WorldRotation))
 					{
 						updateParentRotation(p_subject.getVec3(&m_parent, Systems::Changes::Spatial::WorldRotation));
-						newChanges |= Systems::Changes::Spatial::WorldRotation;
+						m_changes |= Systems::Changes::Spatial::WorldRotation;
 					}
 
 					if(CheckBitmask(p_changeType, Systems::Changes::Spatial::WorldScale))
 					{
 						updateParentScale(p_subject.getVec3(&m_parent, Systems::Changes::Spatial::WorldScale));
-						newChanges |= Systems::Changes::Spatial::WorldScale;
+						m_changes |= Systems::Changes::Spatial::WorldScale;
 					}
 
 					if(CheckBitmask(p_changeType, Systems::Changes::Spatial::WorldTransform))
 					{
 						updateParentTransform(p_subject.getMat4(&m_parent, Systems::Changes::Spatial::WorldTransform));
-						newChanges |= Systems::Changes::Spatial::WorldTransform;
+						m_changes |= Systems::Changes::Spatial::WorldTransform;
 					}
 				}
 			}
@@ -154,11 +172,11 @@ public:
 		if(worldSpaceNeedsUpdate)
 		{
 			updateWorldSpace();
-			newChanges |= Systems::Changes::Spatial::WorldTransform;
 			incrementUpdateCount();
+			m_changes |= Systems::Changes::Spatial::WorldTransform;
 		}
 
-		return newChanges;
+		return m_changes;
 	}
 
 	// Get local-space spatial data
@@ -245,9 +263,37 @@ public:
 		return NullObjects::NullSpacialTransformData;
 	}
 
+	const inline Math::Vec3f &getWorldPosition() const { return m_worldSpace.m_spatialData.m_position; }
+	const inline Math::Vec3f &getWorldRotation() const { return m_worldSpace.m_spatialData.m_rotationEuler; }
+
 	// Returns the current update count; each time data is changed, update count is incremented
 	const inline UpdateCount getUpdateCount() const { return m_updateCount; }
 
+	// Returns all the changes made since the last reset of changes
+	const inline BitMask getCurrentChanges() const { return m_changes; }
+
+	// Returns all the changes made since the last reset of changes; and resets the changes
+	const inline BitMask getCurrentChangesAndReset() 
+	{ 
+		auto returnChanges = m_changes;
+		resetChanges();
+		return returnChanges;
+	}
+	
+	// Reset the tracking of changes
+	inline void resetChanges() { m_changes = Systems::Changes::None; }
+
+	// Should the local changes be tracked and returned when getting current changes
+	inline void setTrackLocalChanges(const bool p_trackLocalChanges) { m_trackLocalChanges = p_trackLocalChanges; }
+
+	// Set only the local, parent and world spatial data
+	inline void setSpatialData(const SpatialDataManager &p_spatialDataManager)
+	{
+		m_localSpace = p_spatialDataManager.m_localSpace;
+		m_parentSpace = p_spatialDataManager.m_parentSpace;
+		m_worldSpace = p_spatialDataManager.m_worldSpace;
+	}
+
 	const inline void setLocalPosition(const Math::Vec3f p_position)		{ updateLocalPosition(p_position);		}
 	const inline void setLocalRotation(const Math::Vec3f p_rotation)		{ updateLocalRotation(p_rotation);		}
 	const inline void setLocalRotation(const Math::Quaternion p_rotation)	{ updateLocalRotation(p_rotation);		}
@@ -264,36 +310,50 @@ public:
 	{ 
 		m_worldSpace.m_spatialData.m_position = p_position; 
 		worldTransformNeedsUpdate = true;
+		m_changes |= Systems::Changes::Spatial::WorldPosition;
 	}
 	const inline void setWorldRotation(const Math::Vec3f p_rotation)		
 	{ 
 		m_worldSpace.m_spatialData.m_rotationEuler = p_rotation;
 		worldTransformNeedsUpdate = true;
+		m_changes |= Systems::Changes::Spatial::WorldRotation;
 	}
 	const inline void setWorldRotation(const Math::Quaternion p_rotation)	
 	{ 
 		m_worldSpace.m_spatialData.m_rotationQuat = p_rotation;
 		worldTransformNeedsUpdate = true;
+		m_changes |= Systems::Changes::Spatial::WorldRotation;
 	}
 	const inline void setWorldScale(const Math::Vec3f p_scale)				
 	{ 
 		m_worldSpace.m_spatialData.m_scale = p_scale;
 		worldTransformNeedsUpdate = true;
+		m_changes |= Systems::Changes::Spatial::WorldScale;
 	}
 	const inline void setWorldTransform(const Math::Mat4f p_transform)		
 	{ 
 		m_worldSpace.m_transformMat = p_transform;
 		worldTransformNeedsUpdate = false;
+		m_changes |= Systems::Changes::Spatial::WorldTransform;
 	}
 
-	const inline void calculateLocalTransform() { updateTransformMatrix(m_localSpace); }
-	const inline void calculateWorldTransform() { updateTransformMatrix(m_worldSpace); }
+	const inline void calculateLocalTransform() 
+	{ 
+		updateTransformMatrix(m_localSpace); 
+	}
+	const inline void calculateWorldTransform() 
+	{ 
+		updateTransformMatrix(m_worldSpace);
+		m_changes |= Systems::Changes::Spatial::WorldRotation;
+	}
 
 	// Make up the world-space data from local and parent data
 	void updateWorldSpace()
 	{
 		m_worldSpace = m_parentSpace + m_localSpace;
 		worldSpaceNeedsUpdate = false;
+		if(m_trackLocalChanges)
+			m_changes |= Systems::Changes::Spatial::LocalTransform;
 	}
 
 private:
@@ -311,6 +371,8 @@ private:
 		m_localSpace = p_spatialTransformData;
 		worldSpaceNeedsUpdate = true;
 		localTransformNeedsUpdate = false;
+		if(m_trackLocalChanges)
+			m_changes |= Systems::Changes::Spatial::AllLocal;
 	}
 	void updateLocalSpatialData(const SpatialData &p_spatialData)
 	{
@@ -318,12 +380,16 @@ private:
 		//updateTransformMatrix(m_localSpace);
 		worldSpaceNeedsUpdate = true;
 		localTransformNeedsUpdate = false;
+		if(m_trackLocalChanges)
+			m_changes |= Systems::Changes::Spatial::AllLocalNoTransform;
 	}
 	void updateLocalTransform(const Math::Mat4f &p_transform)
 	{
 		m_localSpace.m_transformMat = p_transform;
 		worldSpaceNeedsUpdate = true;
 		localTransformNeedsUpdate = false;
+		if(m_trackLocalChanges)
+			m_changes |= Systems::Changes::Spatial::LocalTransform;
 	}
 	void updateLocalPosition(const Math::Vec3f &p_position)
 	{
@@ -331,6 +397,8 @@ private:
 		//updateTransformMatrix(m_localSpace);
 		worldSpaceNeedsUpdate = true;
 		localTransformNeedsUpdate = true;
+		if(m_trackLocalChanges)
+			m_changes |= Systems::Changes::Spatial::LocalPosition;
 	}
 	void updateLocalRotation(const Math::Vec3f &p_rotation)
 	{
@@ -338,6 +406,8 @@ private:
 		//updateTransformMatrix(m_localSpace);
 		worldSpaceNeedsUpdate = true;
 		localTransformNeedsUpdate = true;
+		if(m_trackLocalChanges)
+			m_changes |= Systems::Changes::Spatial::LocalRotation;
 	}	
 	void updateLocalRotation(const Math::Quaternion &p_rotation)
 	{
@@ -345,6 +415,8 @@ private:
 		//updateTransformMatrix(m_localSpace);
 		worldSpaceNeedsUpdate = true;
 		localTransformNeedsUpdate = true;
+		if(m_trackLocalChanges)
+			m_changes |= Systems::Changes::Spatial::LocalRotation;
 	}
 	void updateLocalScale(const Math::Vec3f &p_scale)
 	{
@@ -352,6 +424,8 @@ private:
 		//updateTransformMatrix(m_localSpace);
 		worldSpaceNeedsUpdate = true;
 		localTransformNeedsUpdate = true;
+		if(m_trackLocalChanges)
+			m_changes |= Systems::Changes::Spatial::LocalScale;
 	}
 
 	// Functions of world spatial data of the parent object
@@ -409,6 +483,9 @@ private:
 	// A reference to the parent (which is the observer of all the received changes); required to retrieve the changed data from the observed subject
 	const Observer &m_parent;
 
+	// Should the local changes be tracked
+	bool m_trackLocalChanges;
+
 	// A flag to determine if the world space needs to be updated
 	bool worldSpaceNeedsUpdate;
 	bool localTransformNeedsUpdate;
@@ -424,4 +501,7 @@ private:
 
 	// Used for update tracking; each time data is change, update count is incremented
 	UpdateCount m_updateCount;
+
+	// Holds a bit-mask of all recent changes
+	BitMask m_changes;
 };

+ 12 - 12
Praxis3D/Source/WorldEditObject.h

@@ -247,7 +247,7 @@ public:
 	inline void setForwardKey(std::string &p_string)
 	{
 		m_forwardKey.unbindAll();
-		m_forwardKey.bind(p_string);
+		m_forwardKey.bindByKeyName(p_string);
 	}
 
 	inline void setBackwardKey(Scancode p_key)
@@ -258,7 +258,7 @@ public:
 	inline void setBackwardKey(std::string &p_string)
 	{
 		m_backwardKey.unbindAll();
-		m_backwardKey.bind(p_string);
+		m_backwardKey.bindByKeyName(p_string);
 	}
 
 	inline void setUpKey(Scancode p_key)
@@ -269,7 +269,7 @@ public:
 	inline void setUpKey(std::string &p_string)
 	{
 		m_upKey.unbindAll();
-		m_upKey.bind(p_string);
+		m_upKey.bindByKeyName(p_string);
 	}
 
 	inline void setDownKey(Scancode p_key)
@@ -280,7 +280,7 @@ public:
 	inline void setDownKey(std::string &p_string)
 	{
 		m_downKey.unbindAll();
-		m_downKey.bind(p_string);
+		m_downKey.bindByKeyName(p_string);
 	}
 
 	inline void setLeftKey(Scancode p_key)
@@ -291,7 +291,7 @@ public:
 	inline void setLeftKey(std::string &p_string)
 	{
 		m_leftKey.unbindAll();
-		m_leftKey.bind(p_string);
+		m_leftKey.bindByKeyName(p_string);
 	}
 
 	inline void setRightKey(Scancode p_key)
@@ -302,7 +302,7 @@ public:
 	inline void setRightKey(std::string &p_string)
 	{
 		m_rightKey.unbindAll();
-		m_rightKey.bind(p_string);
+		m_rightKey.bindByKeyName(p_string);
 	}
 
 	inline void setNextKey(Scancode p_key)
@@ -313,7 +313,7 @@ public:
 	inline void setNextKey(std::string &p_string)
 	{
 		m_nextKey.unbindAll();
-		m_nextKey.bind(p_string);
+		m_nextKey.bindByKeyName(p_string);
 	}
 
 	inline void setPreviousKey(Scancode p_key)
@@ -324,7 +324,7 @@ public:
 	inline void setPreviousKey(std::string &p_string)
 	{
 		m_previousKey.unbindAll();
-		m_previousKey.bind(p_string);
+		m_previousKey.bindByKeyName(p_string);
 	}
 
 	inline void setFasterMovementKey(Scancode p_key)
@@ -335,7 +335,7 @@ public:
 	inline void setFasterMovementKey(std::string &p_string)
 	{
 		m_fasterMovementKey.unbindAll();
-		m_fasterMovementKey.bind(p_string);
+		m_fasterMovementKey.bindByKeyName(p_string);
 	}
 
 	inline void setCenterKey(Scancode p_key)
@@ -346,7 +346,7 @@ public:
 	inline void setCenterKey(std::string &p_string)
 	{
 		m_centerKey.unbindAll();
-		m_centerKey.bind(p_string);
+		m_centerKey.bindByKeyName(p_string);
 	}
 
 	inline void setSaveKey(Scancode p_key)
@@ -357,7 +357,7 @@ public:
 	inline void setSaveKey(std::string &p_string)
 	{
 		m_saveKey.unbindAll();
-		m_saveKey.bind(p_string);
+		m_saveKey.bindByKeyName(p_string);
 	}
 
 	inline void setModifierKey(Scancode p_key)
@@ -368,7 +368,7 @@ public:
 	inline void setModifierKey(std::string &p_string)
 	{
 		m_modifierKey.unbindAll();
-		m_modifierKey.bind(p_string);
+		m_modifierKey.bindByKeyName(p_string);
 	}
 
 private:

+ 6 - 6
Praxis3D/Source/WorldEditState.cpp

@@ -1,7 +1,7 @@
 
 #include "ClockLocator.h"
 #include "PropertySet.h"
-#include "ScriptingSystem.h"
+#include "ScriptSystem.h"
 #include "RendererSystem.h"
 #include "WorldEditState.h"
 
@@ -47,14 +47,14 @@ ErrorCode WorldEditState::init(TaskManager *p_taskManager)
 
 	//  ___________________________________
 	// |								   |
-	// |  SCRIPTING SYSTEM INITIALIZATION  |
+	// |   SCRIPT SYSTEM INITIALIZATION    |
 	// |___________________________________|
 	// Create scripting system and check if it was successful (if not, assign a null system in it's place)
-	m_systems[Systems::Scripting] = new ScriptingSystem();
-	if(m_systems[Systems::Scripting]->init() != ErrorCode::Success)
+	m_systems[Systems::Script] = new ScriptSystem();
+	if(m_systems[Systems::Script]->init() != ErrorCode::Success)
 	{
-		delete m_systems[Systems::Scripting];
-		m_systems[Systems::Scripting] = &g_nullSystemBase;
+		delete m_systems[Systems::Script];
+		m_systems[Systems::Script] = &g_nullSystemBase;
 	}
 
 	// Register systems with change controller and scenes with scene loader

+ 8 - 6
Praxis3D/Source/WorldScene.cpp

@@ -151,20 +151,22 @@ SystemObject *WorldScene::createObject(const PropertySet &p_properties)
 		if(!unassignedChildren.m_children.empty())
 			m_unassignedChildren.emplace_back(unassignedChildren);
 
+		// Add a GraphicsObject as a component if the Rendering property is present
 		auto &rendering = p_properties.getPropertySetByID(Properties::Rendering);
 		if(rendering)
 		{
 			auto graphicsObject = m_sceneLoader->getSystemScene(Systems::Graphics)->createObject(p_properties);
-			if(graphicsObject != nullptr)
+			if(graphicsObject != nullptr && graphicsObject->getSystemType() != Systems::Null)
 				newGameObject->addComponent(static_cast<GraphicsObject*>(graphicsObject));
 		}
-		
-		auto &scripting = p_properties.getPropertySetByID(Properties::Scripting);
+
+		// Add a ScriptObject as a component if the Script property is present
+		auto &scripting = p_properties.getPropertySetByID(Properties::Script);
 		if(scripting)
 		{
-			//auto scriptingObject = m_sceneLoader->getSystemScene(Systems::Scripting)->createObject(p_properties);
-			//if(scriptingObject != nullptr)
-			//	newGameObject->addComponent(static_cast<ScriptingObject *>(scriptingObject));
+			auto scriptObject = m_sceneLoader->getSystemScene(Systems::Script)->createObject(p_properties);
+			if(scriptObject != nullptr && scriptObject->getSystemType() != Systems::Null)
+				newGameObject->addComponent(static_cast<ScriptObject *>(scriptObject));
 		}
 
 	}