Browse Source

Added GUIObject and implemented it as a component in GameObject
Added object handling and updating in GUIScene
Added change processing in GameObject for every system and change forwarding to corresponding components
Added GUIData container and GUIDataManager class, designed to store GUI variables and process changes
Added GUIDataManagerObject as an inheritance class, made for sharing GUIDataManager resources between objects and their components
Added GUI functions in LuaScript class, that can be called from a lua script, that get collected as functors to be passed later to GUI system
Added GUISequenceComponent (GUIObject component) that constructs GUI elements from a received Functor of GUI function call sequences
Added getFunctors method to ObserverBase, meant for passing function call sequences
Added dynamic lens flair aspect ration calculation
Added ability to move camera by hold a mouse button, when mouse isn't captured, in the Camera_free.lua script
Added changes bitmask for GUI and Script systems / objects
Added more error codes, sources and strings
Fixed multiple concurrent keyBind calls crashing the engine, by adding a mutex
Fixed not initializing pointer variables in shader passes and Engine
Fixed undefined variables in GeometryBuffer
Fixed not setting spotlight cutoff angle in SpotLightDataSet

Paul A 4 years ago
parent
commit
9bc0d64917
69 changed files with 1235 additions and 343 deletions
  1. 2 0
      .gitignore
  2. BIN
      Builds/x64/Release 64bit/SDL2.dll
  3. 0 0
      Builds/x64/Release/FreeImage.dll
  4. 0 0
      Builds/x64/Release/assimp-vc142-mt.dll
  5. 0 0
      Builds/x64/Release/glew32.dll
  6. 0 0
      Builds/x64/Release/tbb.dll
  7. 0 0
      Builds/x64/Release/zlib.dll
  8. 21 2
      Praxis3D/Data/Maps/componentTest.pmap
  9. 3 1
      Praxis3D/Data/Scripts/Camera_free.lua
  10. 36 0
      Praxis3D/Data/Scripts/GUI_test.lua
  11. 1 1
      Praxis3D/Data/config.ini
  12. 2 0
      Praxis3D/Data/error-strings-eng.data
  13. 6 1
      Praxis3D/Praxis3D.vcxproj
  14. 15 0
      Praxis3D/Praxis3D.vcxproj.filters
  15. 2 2
      Praxis3D/Source/AtmScatteringPass.h
  16. 2 2
      Praxis3D/Source/BloomCompositePass.h
  17. 4 4
      Praxis3D/Source/BlurPass.h
  18. 5 5
      Praxis3D/Source/CameraScript.h
  19. 2 0
      Praxis3D/Source/CommonDefinitions.h
  20. 1 0
      Praxis3D/Source/Config.cpp
  21. 34 11
      Praxis3D/Source/Config.h
  22. 36 2
      Praxis3D/Source/Containers.h
  23. 4 4
      Praxis3D/Source/DebugUIScript.h
  24. 9 0
      Praxis3D/Source/Engine.cpp
  25. 3 1
      Praxis3D/Source/ErrorCodes.h
  26. 2 0
      Praxis3D/Source/ErrorHandler.cpp
  27. 1 1
      Praxis3D/Source/FinalPass.h
  28. 91 0
      Praxis3D/Source/GUIDataManager.h
  29. 27 0
      Praxis3D/Source/GUIHandler.cpp
  30. 15 15
      Praxis3D/Source/GUIHandler.h
  31. 1 0
      Praxis3D/Source/GUIHandlerLocator.h
  32. 176 0
      Praxis3D/Source/GUIObject.h
  33. 1 1
      Praxis3D/Source/GUIPass.h
  34. 131 6
      Praxis3D/Source/GUIScene.cpp
  35. 35 5
      Praxis3D/Source/GUIScene.h
  36. 124 0
      Praxis3D/Source/GUISequenceComponent.h
  37. 9 0
      Praxis3D/Source/GUISystem.h
  38. 47 36
      Praxis3D/Source/GameObject.h
  39. 2 0
      Praxis3D/Source/GeometryBuffer.cpp
  40. 27 10
      Praxis3D/Source/GraphicsDataSets.h
  41. 5 2
      Praxis3D/Source/HdrMappingPass.h
  42. 41 0
      Praxis3D/Source/InheritanceObjects.h
  43. 3 3
      Praxis3D/Source/KeyCommand.cpp
  44. 5 5
      Praxis3D/Source/KeyCommand.h
  45. 2 2
      Praxis3D/Source/LenseFlareCompositePass.h
  46. 33 4
      Praxis3D/Source/LenseFlarePass.h
  47. 1 1
      Praxis3D/Source/LightingPass.h
  48. 25 26
      Praxis3D/Source/LuaComponent.h
  49. 96 34
      Praxis3D/Source/LuaScript.h
  50. 4 0
      Praxis3D/Source/NullObjects.cpp
  51. 8 12
      Praxis3D/Source/NullObjects.h
  52. 12 12
      Praxis3D/Source/ObserverBase.h
  53. 1 1
      Praxis3D/Source/PostProcessPass.h
  54. 19 19
      Praxis3D/Source/RendererFrontend.cpp
  55. 21 30
      Praxis3D/Source/RendererScene.cpp
  56. 8 15
      Praxis3D/Source/RendererScene.h
  57. 0 1
      Praxis3D/Source/RendererSystem.cpp
  58. 0 3
      Praxis3D/Source/RendererSystem.h
  59. 5 4
      Praxis3D/Source/ScriptObject.h
  60. 26 22
      Praxis3D/Source/ScriptScene.cpp
  61. 2 2
      Praxis3D/Source/ScriptScene.h
  62. 1 1
      Praxis3D/Source/SkyPass.h
  63. 1 1
      Praxis3D/Source/SolarTimeScript.h
  64. 1 10
      Praxis3D/Source/SpatialDataManager.h
  65. 10 10
      Praxis3D/Source/Window.cpp
  66. 6 0
      Praxis3D/Source/Window.h
  67. 12 12
      Praxis3D/Source/WorldEditObject.h
  68. 10 1
      Praxis3D/Source/WorldScene.cpp
  69. 0 0
      Praxis3D/x64/Release/Praxis3D.vcxproj.FileListAbsolute.txt

+ 2 - 0
.gitignore

@@ -30,3 +30,5 @@ VC/
 *.pdb
 Builds/x64/Debug/Praxis3D.exp
 Builds/x64/Debug/Praxis3D.lib
+*.sarif
+Praxis3D/x64/Debug/CodeAnalysisResultManifest.txt

BIN
Builds/x64/Release 64bit/SDL2.dll


+ 0 - 0
Builds/x64/Release 64bit/FreeImage.dll → Builds/x64/Release/FreeImage.dll


+ 0 - 0
Builds/x64/Release 64bit/assimp-vc142-mt.dll → Builds/x64/Release/assimp-vc142-mt.dll


+ 0 - 0
Builds/x64/Release 64bit/glew32.dll → Builds/x64/Release/glew32.dll


+ 0 - 0
Builds/x64/Release 64bit/tbb.dll → Builds/x64/Release/tbb.dll


+ 0 - 0
Builds/x64/Release 64bit/zlib.dll → Builds/x64/Release/zlib.dll


+ 21 - 2
Praxis3D/Data/Maps/componentTest.pmap

@@ -37,7 +37,26 @@
 			}
 		},
 		{
+			"Name": "GUI",
 			"ID": "1",
+			"Parent": "0",
+			"GUI":
+			{
+				"Sequence":
+				{
+
+				}
+			},
+			"Script":
+			{
+				"Lua":
+				{
+					"Filename": "GUI_test.lua"
+				}
+			}
+		},
+		{
+			"ID": "2",
 			"LocalPosition": "0.0f, 0.5f, 0.0f",
 			"LocalRotation": "0.0f, 45.0f, 0.0f",
 			"LocalScale": "1.0f, 1.0f, 1.0f",
@@ -90,7 +109,7 @@
 			}
 		},
 		{
-			"ID": "2",
+			"ID": "3",
 			"LocalPosition": "0.0f, 5.0f, 0.0f",
 			"LocalRotation": "0.0f, 45.0f, 0.0f",
 			"LocalScale": "2.0f, 2.0f, 2.0f",
@@ -138,7 +157,7 @@
 			}
 		},
 		{
-			"ID": "3",
+			"ID": "4",
 			"LocalPosition": "15.0f, 5.0f, 0.0f",
 			"LocalRotation": "0.0f, 45.0f, 0.0f",
 			"LocalScale": "4.0f, 4.0f, 4.0f",

+ 3 - 1
Praxis3D/Data/Scripts/Camera_free.lua

@@ -12,6 +12,7 @@ function init ()
 	create(Types.KeyCommand, 'rightKey')
 	create(Types.KeyCommand, 'upKey')
 	create(Types.KeyCommand, 'downKey')
+	create(Types.KeyCommand, 'mouseLeftKey')
 	
 	-- Bind keys to their corresponding buttons on the keyboard
 	forwardKey:bind(inputVariables.forward_key)
@@ -20,6 +21,7 @@ function init ()
 	rightKey:bind(inputVariables.right_strafe_key)
 	upKey:bind(inputVariables.up_key)
 	downKey:bind(inputVariables.down_key)
+	mouseLeftKey:bindByName('Mouse_left')
 	
 	-- Get the camera movement speed
 	movementSpeedF = gameplayVariables.camera_freelook_speed
@@ -44,7 +46,7 @@ function update (p_deltaTime)
 		
 	-- Rotate the camera matrix by the view angles
 	-- Perform rotations only if the mouse is captured inside the game window
-	if mouseCaptured() then
+	if mouseCaptured() or mouseLeftKey:isActivated() then
 		-- Rotate camera up/down based on the X direction (left/right) of the view matrix (camera's inverse matrix)
 		localTransformMat4 = localTransformMat4:rotate(toRadianF(verticalAngleF), localTransformInverseMat4:getRotXVec3())
 		-- Rotate camera left/right on a fixed Y direction (up/down) to not introduce any roll

+ 36 - 0
Praxis3D/Data/Scripts/GUI_test.lua

@@ -0,0 +1,36 @@
+
+function init ()
+	-- Create needed variables
+	create(Types.EngineVariables, 'engineVariables');
+	create(Types.InputVariables, 'inputVariables');
+	create(Types.WindowVariables, 'windowVariables');
+	
+	-- Create key commands, used to track pressed keys
+	create(Types.KeyCommand, 'closeKey')
+	create(Types.KeyCommand, 'fullscreenKey')
+	create(Types.KeyCommand, 'mouseCaptureKey')
+	create(Types.KeyCommand, 'vsyncKey')
+	
+	-- Bind keys to their corresponding buttons on the keyboard
+	closeKey:bind(inputVariables.close_window_key)
+	fullscreenKey:bind(inputVariables.fullscreen_key)
+	mouseCaptureKey:bind(inputVariables.clip_mouse_key)
+	vsyncKey:bind(inputVariables.vsync_key)
+		
+	print('GUI_test.lua script initialized.')
+end
+
+function update (p_deltaTime)
+	
+	GUI.Begin('Test window')
+	
+	GUI.Text('SAMPLE TEXT M8', 10.0)
+	
+	GUI.End()
+	
+	--print('test')
+	
+	--postChanges(Changes.GUI.Sequence)
+	
+	--print('test')
+end

+ 1 - 1
Praxis3D/Data/config.ini

@@ -1,4 +1,4 @@
-window_position_x 250
+window_position_x 450
 window_position_y 60
 window_size_windowed_x 1920
 window_size_windowed_y 1080

+ 2 - 0
Praxis3D/Data/error-strings-eng.data

@@ -51,6 +51,8 @@
 		"Source_GeometryPass"						: "Geometry Rendering Pass",
 		"Source_GraphicsObject"					: "Graphics Object",
 		"Source_GUI"										: "GUI",
+		"Source_GUIObject"							: "GUI Object",
+		"Source_GUISequenceComponent"		: "GUI Sequence Component",
 		"Source_HdrMappingPass"					: "HDR Mapping Rendering Pass",
 		"Source_LensFlareCompositePass"	: "Lens Flare Effect Composite Rendering Pass",
 		"Source_LensFlarePass"					: "Lens Flare Effect Rendering Pass",

+ 6 - 1
Praxis3D/Praxis3D.vcxproj

@@ -109,7 +109,7 @@
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <ClCompile>
-      <LanguageStandard>stdcpp17</LanguageStandard>
+      <LanguageStandard>stdcpp20</LanguageStandard>
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
       <WarningLevel>Level3</WarningLevel>
       <SDLCheck>true</SDLCheck>
@@ -148,6 +148,7 @@
     <ClCompile Include="Source\ErrorHandler.cpp" />
     <ClCompile Include="Source\ErrorHandlerLocator.cpp" />
     <ClCompile Include="Source\GeometryBuffer.cpp" />
+    <ClCompile Include="Source\GUIHandler.cpp" />
     <ClCompile Include="Source\GUIHandlerLocator.cpp" />
     <ClCompile Include="Source\GUIScene.cpp" />
     <ClCompile Include="Source\GUITask.cpp" />
@@ -246,10 +247,14 @@
     <ClInclude Include="Source\GeometryPass.h" />
     <ClInclude Include="Source\GraphicsDataSets.h" />
     <ClInclude Include="Source\GraphicsObject.h" />
+    <ClInclude Include="Source\GUICommandBuffer.h" />
+    <ClInclude Include="Source\GUIDataManager.h" />
     <ClInclude Include="Source\GUIHandler.h" />
     <ClInclude Include="Source\GUIHandlerLocator.h" />
+    <ClInclude Include="Source\GUIObject.h" />
     <ClInclude Include="Source\GUIPass.h" />
     <ClInclude Include="Source\GUIScene.h" />
+    <ClInclude Include="Source\GUISequenceComponent.h" />
     <ClInclude Include="Source\GUISystem.h" />
     <ClInclude Include="Source\GUITask.h" />
     <ClInclude Include="Source\HdrMappingPass.h" />

+ 15 - 0
Praxis3D/Praxis3D.vcxproj.filters

@@ -375,6 +375,9 @@
     <ClCompile Include="..\Dependencies\include\imgui\backends\imgui_impl_sdl.cpp">
       <Filter>iImgui\Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\GUIHandler.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Source\ErrorCodes.h">
@@ -761,6 +764,18 @@
     <ClInclude Include="Source\GUIPass.h">
       <Filter>Renderer\Render Passes\Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Source\GUICommandBuffer.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\GUIObject.h">
+      <Filter>GUI\Objects\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\GUISequenceComponent.h">
+      <Filter>GUI\Objects\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\GUIDataManager.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="Data\config.ini" />

+ 2 - 2
Praxis3D/Source/AtmScatteringPass.h

@@ -155,7 +155,7 @@ public:
 			//m_renderer.passUpdateCommandsToBackend();
 
 			// Perform various visual effects in the post process shader
-			m_renderer.queueForDrawing(m_skyShader->getShaderHandle(), m_skyShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+			m_renderer.queueForDrawing(m_skyShader->getShaderHandle(), m_skyShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 			
 		}
 		else
@@ -199,7 +199,7 @@ public:
 			//m_renderer.passUpdateCommandsToBackend();
 
 			// Perform various visual effects in the post process shader
-			m_renderer.queueForDrawing(m_groundShader->getShaderHandle(), m_groundShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+			m_renderer.queueForDrawing(m_groundShader->getShaderHandle(), m_groundShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 		
 		}
 		

+ 2 - 2
Praxis3D/Source/BloomCompositePass.h

@@ -9,7 +9,7 @@ public:
 	BloomCompositePass(RendererFrontend &p_renderer) :
 		RenderPass(p_renderer)
 	{
-
+		m_bloomCompositeShader = nullptr;
 	}
 
 	~BloomCompositePass() { }
@@ -52,7 +52,7 @@ public:
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getColorOutputMap());
 
 		// Perform various visual effects in the post process shader
-		m_renderer.queueForDrawing(m_bloomCompositeShader->getShaderHandle(), m_bloomCompositeShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+		m_renderer.queueForDrawing(m_bloomCompositeShader->getShaderHandle(), m_bloomCompositeShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 
 		p_renderPassData.swapColorInputOutputMaps();

+ 4 - 4
Praxis3D/Source/BlurPass.h

@@ -73,7 +73,7 @@ public:
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getIntermediateMap());
 
 		// Perform verical blur. Queue and render a full screen quad using a vertical blur shader
-		m_renderer.queueForDrawing(m_blurVerticalShader->getShaderHandle(), m_blurVerticalShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+		m_renderer.queueForDrawing(m_blurVerticalShader->getShaderHandle(), m_blurVerticalShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 
 		for(decltype(p_renderPassData.m_numOfBlurPasses) i = 0; i < p_renderPassData.m_numOfBlurPasses; i++)
@@ -85,7 +85,7 @@ public:
 			m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getBlurInputMap());
 
 			// Perform horizontal blur. Queue and render a full screen quad using a horizontal blur shader
-			m_renderer.queueForDrawing(m_blurHorizontalShader->getShaderHandle(), m_blurHorizontalShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+			m_renderer.queueForDrawing(m_blurHorizontalShader->getShaderHandle(), m_blurHorizontalShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 			m_renderer.passScreenSpaceDrawCommandsToBackend();
 
 			// Bind emissive texture for reading so it can be accessed in the shaders
@@ -95,7 +95,7 @@ public:
 			m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getIntermediateMap());
 
 			// Perform verical blur. Queue and render a full screen quad using a vertical blur shader
-			m_renderer.queueForDrawing(m_blurVerticalShader->getShaderHandle(), m_blurVerticalShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+			m_renderer.queueForDrawing(m_blurVerticalShader->getShaderHandle(), m_blurVerticalShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 			m_renderer.passScreenSpaceDrawCommandsToBackend();
 		}
 
@@ -113,7 +113,7 @@ public:
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getBlurOutputMap());
 
 		// Perform horizontal blur. Queue and render a full screen quad using a horizontal blur shader
-		m_renderer.queueForDrawing(m_blurHorizontalShader->getShaderHandle(), m_blurHorizontalShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+		m_renderer.queueForDrawing(m_blurHorizontalShader->getShaderHandle(), m_blurHorizontalShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 
 		// If blending should be enabled

+ 5 - 5
Praxis3D/Source/CameraScript.h

@@ -205,7 +205,7 @@ public:
 	inline void setForwardKey(std::string &p_string)
 	{
 		m_forwardKey.unbindAll();
-		m_forwardKey.bindByKeyName(p_string);
+		m_forwardKey.bind(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.bindByKeyName(p_string);
+		m_backwardKey.bind(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.bindByKeyName(p_string);
+		m_strafeLeftKey.bind(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.bindByKeyName(p_string);
+		m_strafeRightKey.bind(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.bindByKeyName(p_string);
+		m_sprintKey.bind(p_string);
 	}
 
 	inline void setLowerLimit(const float p_limit)

+ 2 - 0
Praxis3D/Source/CommonDefinitions.h

@@ -1,8 +1,10 @@
 #pragma once
 
 #include <GL\glew.h>
+#include <functional>
 
 typedef unsigned int UpdateCount;
+typedef std::vector<std::function<void()>> Functors;
 
 enum BindCommandType : unsigned int
 {

+ 1 - 0
Praxis3D/Source/Config.cpp

@@ -160,6 +160,7 @@ void Config::init()
 	// GUI variables
 	AddVariablePredef(m_GUIVar, gui_render);
 	AddVariablePredef(m_GUIVar, gui_dark_style);
+	AddVariablePredef(m_GUIVar, gui_sequence_array_reserve_size);
 
 	// Input variables
 	AddVariablePredef(m_inputVar, back_key);

+ 34 - 11
Praxis3D/Source/Config.h

@@ -52,7 +52,8 @@ namespace Systems
 	{
 		static constexpr BitMask None		= (BitMask)1 << 0;
 		static constexpr BitMask Graphics	= (BitMask)1 << 1;
-		static constexpr BitMask Script		= (BitMask)1 << 2;
+		static constexpr BitMask GUI		= (BitMask)1 << 2;
+		static constexpr BitMask Script		= (BitMask)1 << 3;
 	}
 	namespace GraphicsObjectComponents
 	{
@@ -62,6 +63,11 @@ namespace Systems
 		static constexpr BitMask Model		= (BitMask)1 << 3;
 		static constexpr BitMask Shader		= (BitMask)1 << 4;
 	}
+	namespace GUIObjectComponents
+	{
+		static constexpr BitMask None		= (BitMask)1 << 0;
+		static constexpr BitMask Sequence	= (BitMask)1 << 1;
+	}
 	namespace ScriptObjectComponents
 	{
 		static constexpr BitMask None = (BitMask)1 << 0;
@@ -97,10 +103,11 @@ namespace Systems
 		{
 			static constexpr BitMask Generic	= (BitMask)1 << 63;
 			static constexpr BitMask Spatial	= (BitMask)1 << 62;
-			static constexpr BitMask Graphics	= (BitMask)1 << 61;
-			static constexpr BitMask Physics	= (BitMask)1 << 60;
-			static constexpr BitMask Audio		= (BitMask)1 << 59;
-			static constexpr BitMask Script		= (BitMask)1 << 58;
+			static constexpr BitMask Audio		= (BitMask)1 << 61;
+			static constexpr BitMask Graphics	= (BitMask)1 << 60;
+			static constexpr BitMask GUI		= (BitMask)1 << 59;
+			static constexpr BitMask Physics	= (BitMask)1 << 58;
+			static constexpr BitMask Script		= (BitMask)1 << 57;
 		}
 
 		namespace Generic
@@ -130,6 +137,10 @@ namespace Systems
 			static constexpr BitMask AllLocal				= AllLocalNoTransform | LocalTransform;
 			static constexpr BitMask AllWorld				= AllWorldNoTransform | WorldTransform;
 			static constexpr BitMask All					= AllLocal | AllWorld;
+		}
+		namespace Audio
+		{
+
 		}
 		namespace Graphics
 		{
@@ -149,21 +160,22 @@ namespace Systems
 
 			static constexpr BitMask All					= AllCamera | AllLighting;
 		}
-		namespace Physics
+		namespace GUI
 		{
-
+			static constexpr BitMask Sequence				= Changes::Type::GUI + Changes::Common::Shared1;
+			static constexpr BitMask Placholder				= Changes::Type::GUI + Changes::Common::Shared2;
+			static constexpr BitMask All					= Sequence | Placholder;
 		}
-		namespace Audio
+		namespace Physics
 		{
 
 		}
 		namespace Script
 		{
-
+			static constexpr BitMask Placholder				= Changes::Type::GUI + Changes::Common::Shared1;
+			static constexpr BitMask All					= Placholder;
 		}
 
-		//static constexpr BitMask Link = (BitMask)1 << 29;
-
 		static constexpr BitMask None = 0;
 		static constexpr BitMask All = static_cast<BitMask>(-1);
 	}
@@ -253,6 +265,11 @@ namespace Properties
 	Code(TextureTilingFactor,) \
 	Code(TextureScale,) \
 	Code(VertexShader,) \
+	/* GUI */ \
+	Code(GUI,) \
+	Code(GUIObject,) \
+	Code(GUISequenceComponent,) \
+	Code(Sequence,) \
 	/* Key binds */ \
 	Code(BackwardKey,) \
 	Code(CenterKey,) \
@@ -407,6 +424,10 @@ namespace Properties
 		GetString(TextureTilingFactor),
 		GetString(TextureScale),
 		GetString(VertexShader),
+		GetString(GUI),
+		GetString(GUIObject),
+		GetString(GUISequenceComponent),
+		GetString(Sequence),
 		GetString(BackwardKey),
 		GetString(CenterKey),
 		GetString(CloseKey),
@@ -805,9 +826,11 @@ public:
 		{
 			gui_render = true;
 			gui_dark_style = true;
+			gui_sequence_array_reserve_size = 50;
 		}
 		bool gui_render;
 		bool gui_dark_style;
+		int gui_sequence_array_reserve_size;
 	};
 	struct InputVariables
 	{

+ 36 - 2
Praxis3D/Source/Containers.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include "CommonDefinitions.h"
 #include "Math.h"
 
 // Stores all spatial data (position, rotation, scale)
@@ -28,7 +29,7 @@ struct SpatialData
 							m_rotationQuat * p_data.m_rotationQuat);
 	}
 
-	// Set all data to default
+	// Set all the data to default
 	void clear()
 	{
 		m_position = glm::vec3(0.0f);
@@ -61,7 +62,7 @@ struct SpatialTransformData
 		return SpatialTransformData(m_spatialData + p_data.m_spatialData, m_transformMat * p_data.m_transformMat);
 	}
 
-	// Set all data to default
+	// Set all the data to default
 	void clear()
 	{
 		m_spatialData.clear();
@@ -70,4 +71,37 @@ struct SpatialTransformData
 
 	SpatialData m_spatialData;
 	glm::mat4 m_transformMat;
+};
+
+struct GUIData
+{
+	GUIData()
+	{
+		clear();
+	}	
+
+	// Set all the data to default
+	void clear()
+	{
+		m_functors.clear();
+	}
+
+	Functors m_functors;
+};
+
+// Packs a single unsigned 64bit int into two unsigned 32bit ints
+struct Int64Packer
+{
+	Int64Packer() : x(0), y(0) { }
+	Int64Packer(unsigned __int64 p_int) { set(p_int); }
+
+	inline void set(const unsigned __int64 p_int)
+	{
+		x = (unsigned __int32)(p_int >> 32);
+		y = (unsigned __int32)p_int;
+	}
+
+	inline unsigned __int64 get() const { return ((unsigned __int64)x) << 32 | y; }
+
+	unsigned __int32 x, y;
 };

+ 4 - 4
Praxis3D/Source/DebugUIScript.h

@@ -131,7 +131,7 @@ public:
 	inline void setMouseCaptureKey(std::string &p_string)
 	{
 		m_mouseCaptureCommand.unbindAll();
-		m_mouseCaptureCommand.bindByKeyName(p_string);
+		m_mouseCaptureCommand.bind(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.bindByKeyName(p_string);
+		m_fullscreenCommand.bind(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.bindByKeyName(p_string);
+		m_vertSyncCommand.bind(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.bindByKeyName(p_string);
+		m_closeWindowCommand.bind(p_string);
 	}
 	
 protected:

+ 9 - 0
Praxis3D/Source/Engine.cpp

@@ -24,6 +24,15 @@ Engine::Engine()
 {
 	m_instances++;
 	m_initialized = false;
+	m_errorHandler = nullptr;
+	m_GUIHandler = nullptr;
+	m_window = nullptr;
+	m_clock = nullptr;
+	m_taskManager = nullptr;
+	m_scheduler = nullptr;
+	m_changeCtrlScene = nullptr;
+	m_sceneChangeController = nullptr;
+	m_objectChangeController = nullptr;
 }
 
 Engine::~Engine()

+ 3 - 1
Praxis3D/Source/ErrorCodes.h

@@ -98,6 +98,8 @@ DECLARE_ENUM(ErrorCode, ERROR_CODES)
     Code(Source_GeometryPass,) \
     Code(Source_GraphicsObject,) \
     Code(Source_GUI,) \
+    Code(Source_GUIObject,) \
+    Code(Source_GUISequenceComponent,) \
     Code(Source_HdrMappingPass,) \
     Code(Source_LensFlareCompositePass,) \
     Code(Source_LensFlarePass,) \
@@ -134,7 +136,7 @@ DECLARE_ENUM(ErrorSource, ERROR_SOURCE)
 struct ErrorMessage
 {
 	ErrorMessage() : m_errorCode(Success), m_errorSource(Source_Unknown) { }
-	ErrorMessage(const ErrorCode p_errorCode) : m_errorCode(p_errorCode) { }
+	ErrorMessage(const ErrorCode p_errorCode) : m_errorCode(p_errorCode), m_errorSource(ErrorSource::Source_Unknown) { }
 	ErrorMessage(const ErrorCode p_errorCode, const ErrorSource p_errorsource)
 		: m_errorCode(p_errorCode), m_errorSource(p_errorsource) { }
 	ErrorMessage(const ErrorCode p_errorCode, const ErrorSource p_errorsource, const std::string &p_errorMessage)

+ 2 - 0
Praxis3D/Source/ErrorHandler.cpp

@@ -71,6 +71,8 @@ ErrorHandler::ErrorHandler()
     m_errHashmap[GetString(Source_GeometryPass)]				= NumberOfErrorCodes + Source_GeometryPass;
     m_errHashmap[GetString(Source_GraphicsObject)]				= NumberOfErrorCodes + Source_GraphicsObject;
     m_errHashmap[GetString(Source_GUI)]							= NumberOfErrorCodes + Source_GUI;
+	m_errHashmap[GetString(Source_GUIObject)]					= NumberOfErrorCodes + Source_GUIObject;
+	m_errHashmap[GetString(Source_GUISequenceComponent)]		= NumberOfErrorCodes + Source_GUISequenceComponent;
     m_errHashmap[GetString(Source_HdrMappingPass)]				= NumberOfErrorCodes + Source_HdrMappingPass;
     m_errHashmap[GetString(Source_LensFlareCompositePass)]		= NumberOfErrorCodes + Source_LensFlareCompositePass;
     m_errHashmap[GetString(Source_LensFlarePass)]				= NumberOfErrorCodes + Source_LensFlarePass;

+ 1 - 1
Praxis3D/Source/FinalPass.h

@@ -78,7 +78,7 @@ public:
 		m_renderer.m_backend.getGeometryBuffer()->bindFramebufferForWriting(GeometryBuffer::FramebufferDefault);
 
 		// Queue and render a full screen quad using a final pass shader
-		m_renderer.queueForDrawing(m_shaderFinalPass->getShaderHandle(), m_shaderFinalPass->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+		m_renderer.queueForDrawing(m_shaderFinalPass->getShaderHandle(), m_shaderFinalPass->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 
 #endif // SETTING_USE_BLIT_FRAMEBUFFER

+ 91 - 0
Praxis3D/Source/GUIDataManager.h

@@ -0,0 +1,91 @@
+#pragma once
+
+#include "Containers.h"
+#include "ObserverBase.h"
+
+// Manages GUI data updates
+class GUIDataManager
+{
+public:
+	GUIDataManager(const Observer &p_parent) : m_parent(p_parent)
+	{
+		m_updateCount = 0;
+		m_changes = Systems::Changes::None;
+	}
+	~GUIDataManager()
+	{
+
+	}
+
+	void update()
+	{
+		if(m_changes != Systems::Changes::None)
+			incrementUpdateCount();
+	}
+
+	// Process GUI data changes from the given subject and change type
+	// Returns the changes that have been made
+	BitMask changeOccurred(const ObservedSubject *p_subject, const BitMask p_changeType)
+	{
+		if(CheckBitmask(p_changeType, Systems::Changes::GUI::Sequence))
+		{
+			// Update functors
+			m_GUIData.m_functors = p_subject->getFunctors(&m_parent, Systems::Changes::GUI::Sequence);
+			m_changes |= Systems::Changes::GUI::Sequence;
+		}
+
+		return m_changes;
+	}
+
+	template<typename Functor>
+	inline void addFunctor(Functor p_functor)
+	{
+		m_GUIData.m_functors.push_back(p_functor);
+		m_changes |= Systems::Changes::GUI::Sequence;
+	}
+
+	inline void clearFunctors() { m_GUIData.m_functors.clear(); }
+
+	inline const GUIData &getGUIData() { return m_GUIData; }
+
+	const Functors &getFunctors(const Observer *p_observer, BitMask p_changedBits) const
+	{
+		if(CheckBitmask(p_changedBits, Systems::Changes::GUI::Sequence))
+			return m_GUIData.m_functors;
+
+		return NullObjects::NullFunctors;
+	}
+
+	// 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; }
+
+private:
+	// Increments the update count; should be called after any data has been changed
+	inline void incrementUpdateCount() { m_updateCount++; }
+
+	// GUI data
+	GUIData m_GUIData;
+
+	// 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;
+
+	// 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;
+};

+ 27 - 0
Praxis3D/Source/GUIHandler.cpp

@@ -0,0 +1,27 @@
+
+#include "GUIHandler.h"
+
+void GUIHandler::render()
+{
+	//ImGui::ShowDemoWindow(&m_showDemoWindow);
+	
+	//ImGui::SetNextWindowSize(ImVec2(600.0f, 900.0f));
+	// Create a window called "My First Tool", with a menu bar.
+	//ImGui::Begin("My First Tool", &m_window1Open, ImGuiWindowFlags_MenuBar);
+
+	//ImGui::Text("Hello, world %d", 123);
+
+	//ImGui::End();
+
+	//ImGui::Begin("My First Tool");
+	//ImGui::Text("Hello, world");
+	//ImGui::End();
+
+	//ImGui::Render();
+	//glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
+	//glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+	//glClear(GL_COLOR_BUFFER_BIT);
+	//ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+
+	m_frameReady = false;
+}

+ 15 - 15
Praxis3D/Source/GUIHandler.h

@@ -15,12 +15,17 @@ class GUIHandlerBase
 	friend class GUISystem;
 	friend class GUITask;
 public:
-	GUIHandlerBase() : m_initialized(false) { }
+	GUIHandlerBase() : m_initialized(false), m_frameReady(false) { }
 
+	// Let the GUI process an SDL even so it can be registered
 	virtual void processSDLEvent(const SDL_Event &p_SDLEvent) { }
 
+	// Has the GUI Handle been initialized
 	const inline bool isInitialized() const { return m_initialized; }
 
+	// Is the GUI frame ready to be rendered
+	const inline bool isFrameReady() const { return m_frameReady; }
+
 protected:
 	virtual ErrorCode init() { return ErrorCode::Success; }
 
@@ -29,6 +34,7 @@ protected:
 	virtual void endFrame() { }
 
 	bool m_initialized;
+	std::atomic_bool m_frameReady;
 };
 
 class GUIHandlerNull : public GUIHandlerBase
@@ -51,7 +57,8 @@ class GUIHandler : public GUIHandlerBase
 public:
 	GUIHandler() : GUIHandlerBase()
 	{
-		m_showDemoWindow = true;
+		m_showDemoWindow = false;
+		m_window1Open = false;
 		m_io = nullptr;
 	}
 	~GUIHandler() 
@@ -112,27 +119,20 @@ protected:
 
 	void beginFrame() 
 	{
-		ImGui_ImplOpenGL3_NewFrame();
-		ImGui_ImplSDL2_NewFrame();
-		ImGui::NewFrame();
+		//ImGui_ImplOpenGL3_NewFrame();
+		//ImGui_ImplSDL2_NewFrame();
+		//ImGui::NewFrame();
 	}
 
-	void render() 
-	{
-		ImGui::ShowDemoWindow(&m_showDemoWindow);
-		ImGui::Render();
-		//glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
-		//glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
-		//glClear(GL_COLOR_BUFFER_BIT);
-		ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
-	}
+	void render();
 
 	void endFrame() 
 	{
-
+		m_frameReady = true;
 	}
 
 private:
 	bool m_showDemoWindow;
+	bool m_window1Open;
 	ImGuiIO *m_io;
 };

+ 1 - 0
Praxis3D/Source/GUIHandlerLocator.h

@@ -9,6 +9,7 @@ class GUIHandlerLocator
 {
 	friend class Engine;
 	friend class GUIPass;
+	friend class GUIScene;
 private:
 
 	// Get the services

+ 176 - 0
Praxis3D/Source/GUIObject.h

@@ -0,0 +1,176 @@
+#pragma once
+
+#include "InheritanceObjects.h"
+#include "GUIDataManager.h"
+#include "GUISequenceComponent.h"
+#include "System.h"
+
+enum GUIComponentType : std::size_t
+{
+	GUIComponentType_Sequence = 0,
+	GUIComponentType_NumOfComponents
+};
+
+class GUIObject : public SystemObject, public LoadableGraphicsObject
+{
+public:
+	GUIObject(SystemScene *p_systemScene, const std::string &p_name)
+		: SystemObject(p_systemScene, p_name, Properties::GUIObject), m_GUIData(*this)
+	{
+		m_GUISequenceComponent = nullptr;
+		m_componentsFlag = 0;
+	}
+	~GUIObject()
+	{
+		// 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()
+	{
+
+		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 sequence and load the GUI sequence component if there is
+				auto const &sequenceComponentProperty = p_properties.getPropertySetByID(Properties::Sequence);
+				if(sequenceComponentProperty)
+				{
+					// Create the GUI sequence component
+					addComponent(new GUISequenceComponent(m_systemScene, m_name + Config::componentVar().lua_component_name));
+
+					// Try to initialize the lua component
+					auto componentInitError = m_GUISequenceComponent->init();
+					if(componentInitError == ErrorCode::Success)
+					{
+						// Try to import the component
+						auto const &componentImportError = m_GUISequenceComponent->importObject(sequenceComponentProperty);
+
+						// Remove the component if it failed to import
+						if(componentImportError != ErrorCode::Success)
+						{
+							removeComponent(GUIComponentType::GUIComponentType_Sequence);
+							ErrHandlerLoc().get().log(componentImportError, ErrorSource::Source_GUISequenceComponent, m_name);
+						}
+					}
+					else // Remove the component if it failed to initialize
+					{
+						removeComponent(GUIComponentType::GUIComponentType_Sequence);
+						ErrHandlerLoc().get().log(componentInitError, ErrorSource::Source_GUISequenceComponent, m_name);
+					}
+				}
+			}
+		}
+		else
+		{
+			returnError = ErrorCode::Failure;
+		}
+
+		return returnError;
+	}
+
+	PropertySet exportObject()
+	{
+		return PropertySet();
+	}
+
+	void update(const float p_deltaTime)
+	{
+		if(GUISequenceComponentPresent())
+			m_GUISequenceComponent->update(p_deltaTime);
+	}
+
+	// System type is Graphics
+	BitMask getSystemType() { return Systems::Script; }
+
+	BitMask getDesiredSystemChanges() { return Systems::Changes::Graphics::All; }
+	BitMask getPotentialSystemChanges() { return Systems::Changes::Graphics::All; }
+
+	inline GUISequenceComponent *getGUISequenceComponent() { return m_GUISequenceComponent; }
+
+	inline const bool GUISequenceComponentPresent()	const { return (m_GUISequenceComponent == nullptr) ? false : true; }
+
+	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType)
+	{
+		// Track what data has been modified
+		BitMask newChanges = Systems::Changes::None;
+
+		// If the change type is GUI, send the change to the GUI Data Manager
+		if(CheckBitmask(p_changeType, Systems::Changes::Type::GUI))
+			m_GUIData.changeOccurred(p_subject, p_changeType);
+
+		// If any data has been updated, post the changes to listeners
+		if(newChanges != Systems::Changes::None)
+		{
+			postChanges(newChanges);
+		}
+	}
+
+	void addComponent(GUISequenceComponent *p_component)
+	{
+		// Make sure that this component isn't assigned already
+		removeComponent(GUIComponentType::GUIComponentType_Sequence);
+		m_GUISequenceComponent = p_component;
+
+		// Share the GUIObjects GUI data with the component
+		p_component->setGUIDataManagerReference(m_GUIData);
+
+		// Set the flag for the GUI sequence component, so it is known from the flag that there is one currently present
+		m_componentsFlag |= Systems::GUIObjectComponents::Sequence;
+	}
+	void removeComponent(const GUIComponentType p_compType)
+	{
+		switch(p_compType)
+		{
+		case GUIComponentType::GUIComponentType_Sequence:
+		{
+			if(m_GUISequenceComponent != nullptr)
+			{
+				// Delete the actual component
+				delete m_GUISequenceComponent;
+
+				// Assign the component pointer as nullptr to denote that it has been removed
+				m_GUISequenceComponent = nullptr;
+
+				// Remove the bit corresponding to lua component from the componentsFlag bitmask
+				m_componentsFlag &= ~Systems::GUIObjectComponents::Sequence;
+			}
+			break;
+		}
+		}
+	}
+
+	// Returns true if the graphics object contains any components
+	inline const bool containsComponents()
+	{
+		if(GUISequenceComponentPresent())
+			return true;
+
+		return false;
+	}
+
+private:
+	// Components
+	GUISequenceComponent *m_GUISequenceComponent;
+
+	// GUI data
+	GUIDataManager m_GUIData;
+
+	// Stores a separate flag for each component currently present
+	BitMask m_componentsFlag;
+};
+

+ 1 - 1
Praxis3D/Source/GUIPass.h

@@ -31,7 +31,7 @@ public:
 
 	void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime)
 	{
-		GUIHandlerLocator::get().beginFrame();
+		// Render the GUI
 		GUIHandlerLocator::get().render();
 	}
 

+ 131 - 6
Praxis3D/Source/GUIScene.cpp

@@ -1,31 +1,156 @@
+#include "GUIHandlerLocator.h"
 #include "GUIScene.h"
+#include "NullSystemObjects.h"
+#include "TaskManagerLocator.h"
 
 GUIScene::GUIScene(SystemBase *p_system, SceneLoader *p_sceneLoader) : SystemScene(p_system, p_sceneLoader)
 {
-	m_GUITask = new GUITask(this);
+	 m_GUITask = nullptr;
+}
+
+GUIScene::~GUIScene()
+{
+	if(m_GUITask != nullptr)
+		delete m_GUITask;
 }
 
 ErrorCode GUIScene::init()
 {
+	m_GUITask = new GUITask(this);
 
 	return ErrorCode::Success;
 }
 
 ErrorCode GUIScene::setup(const PropertySet& p_properties)
-{
-	return ErrorCode();
+{	
+	// Get default object pool size
+	decltype(m_GUIObjects.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_GUIObjects.init(objectPoolSize);
+
+	return ErrorCode::Success;
 }
 
 void GUIScene::update(const float p_deltaTime)
+{
+	// Set the beginning of the GUI frame
+	GUIHandlerLocator::get().beginFrame();
+
+	for(decltype(m_GUIObjects.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_GUIObjects.getNumAllocated(),
+		size = m_GUIObjects.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
+	{
+		// Check if the GUI object is allocated inside the pool container
+		if(m_GUIObjects[i].allocated())
+		{
+			auto *currentGUIObject = m_GUIObjects[i].getObject();
+
+			// Increment the number of allocated objects (early bail mechanism)
+			numAllocObjecs++;
+
+			// Check if the GUI object is enabled
+			if(currentGUIObject->isObjectActive())
+			{
+				// Update the object
+				currentGUIObject->update(p_deltaTime);
+			}
+		}
+	}
+
+	// Set the end of the GUI frame
+	GUIHandlerLocator::get().endFrame();
+}
+
+ErrorCode GUIScene::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_GUIObjects.getPoolSize(), size_t(1), [=](size_t i)
+		{
+			if(m_GUIObjects[i].allocated())
+			{
+				m_GUIObjects[i].getObject()->loadToMemory();
+			}
+		});
+
+	return ErrorCode::Success;
+}
+
+void GUIScene::loadInBackground()
 {
 }
 
 SystemObject* GUIScene::createObject(const PropertySet& p_properties)
 {
-	return nullptr;
+	// Check if property set node is present
+	if(p_properties)
+	{
+		// Check if the GUI property is present
+		auto &GUIProperty = p_properties.getPropertySetByID(Properties::GUI);
+		if(GUIProperty)
+		{
+			// Get the object name
+			auto &nameProperty = p_properties.getPropertyByID(Properties::Name);
+
+			// Find a place for the new object in the pool
+			auto GUIObjectFromPool = m_GUIObjects.newObject();
+
+			// Check if the pool wasn't full
+			if(GUIObjectFromPool != 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() + " (" + GetString(Properties::GUIObject) + ")";
+				else
+					name = GetString(Properties::GUIObject) + Utilities::toString(GUIObjectFromPool->getIndex());
+
+				// Construct the GUIObject
+				GUIObjectFromPool->construct(this, name);
+				auto newGUIObject = GUIObjectFromPool->getObject();
+
+				//graphicsObject->importObject(renderingProperty);
+
+				// Start importing the newly created object in a background thread
+				newGUIObject->importObject(GUIProperty);
+
+				return newGUIObject;
+			}
+			else
+			{
+				ErrHandlerLoc::get().log(ErrorCode::ObjectPool_full, ErrorSource::Source_GUIObject, "Failed to add GUIObject - \'" + nameProperty.getString() + "\'");
+			}
+		}
+	}
+
+	// If valid type was not specified, or object creation failed, return a null object instead
+	return g_nullSystemBase.getScene()->createObject(p_properties);
 }
 
 ErrorCode GUIScene::destroyObject(SystemObject* p_systemObject)
-{
-	return ErrorCode();
+{	
+	// Check if object is valid and belongs to the GUI system
+	if(p_systemObject != nullptr && p_systemObject->getSystemType() == Systems::GUI)
+	{
+		// Cast the system object to graphics object, as it belongs to the renderer scene
+		GUIObject *objectToDestroy = static_cast<GUIObject *>(p_systemObject);
+
+		// 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;
 }

+ 35 - 5
Praxis3D/Source/GUIScene.h

@@ -1,6 +1,8 @@
 #pragma once
 
+#include "GUIObject.h"
 #include "GUITask.h"
+#include "ObjectPool.h"
 #include "System.h"
 
 class GUISystem;
@@ -9,6 +11,7 @@ class GUIScene : public SystemScene
 {
 public:
 	GUIScene(SystemBase* p_system, SceneLoader* p_sceneLoader);
+	~GUIScene();
 
 	ErrorCode init();
 
@@ -16,23 +19,50 @@ public:
 
 	void update(const float p_deltaTime);
 
-	ErrorCode preload() { return ErrorCode::Success; }
+	ErrorCode preload();
 
-	void loadInBackground() { }
+	void loadInBackground();
 
 	// Exports all the data of the scene (including all objects within) as a PropertySet (for example, used for saving to map file)
 	PropertySet exportObject() { return PropertySet(); }
 
-	SystemObject* createObject(const PropertySet& p_properties);
+	SystemObject *createObject(const PropertySet& p_properties);
 	ErrorCode destroyObject(SystemObject* p_systemObject);
 
 	void changeOccurred(ObservedSubject* p_subject, BitMask p_changeType) { }
 
-	SystemTask* getSystemTask() { return m_GUITask; };
+	SystemTask *getSystemTask() { return m_GUITask; };
 	Systems::TypeID getSystemType() { return Systems::TypeID::GUI; };
 	BitMask getDesiredSystemChanges() { return Systems::Changes::Generic::CreateObject || Systems::Changes::Generic::DeleteObject; }
 	BitMask getPotentialSystemChanges() { return Systems::Changes::None; }
 
-private:
+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(GUIObject &p_object)
+	{
+		// Go over each graphics object
+		for(decltype(m_GUIObjects.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_GUIObjects.getNumAllocated(),
+			size = m_GUIObjects.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
+		{
+			// Check if the script object is allocated inside the pool container
+			if(m_GUIObjects[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_GUIObjects[i].getObject() == p_object)
+				{
+					m_GUIObjects.remove(m_GUIObjects[i].getIndex());
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
 	GUITask *m_GUITask;
+
+	// Object pools
+	ObjectPool<GUIObject> m_GUIObjects;
 };

+ 124 - 0
Praxis3D/Source/GUISequenceComponent.h

@@ -0,0 +1,124 @@
+#pragma once
+
+#include "ErrorHandlerLocator.h"
+#include "GUIHandler.h"
+#include "InheritanceObjects.h"
+#include "System.h"
+
+class GUISequenceComponent : public SystemObject, public GUIDataManagerObject, public LoadableGraphicsObject
+{
+	friend class ScriptScene;
+public:
+	GUISequenceComponent(SystemScene *p_systemScene, std::string p_name, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::GUISequenceComponent)
+	{
+		m_staticSequence = false;
+	}
+	~GUISequenceComponent() { }
+
+	ErrorCode init() final override
+	{
+		if(Config::GUIVar().gui_sequence_array_reserve_size > 0)
+			m_guiSequence.reserve(Config::GUIVar().gui_sequence_array_reserve_size);
+
+		return ErrorCode::Success;
+	}
+
+	void loadToMemory()
+	{
+	}
+
+	void update(const float p_deltaTime)
+	{
+		for(decltype(m_guiSequence.size()) i = 0, size = m_guiSequence.size(); i < size; i++)
+			m_guiSequence[i]();
+
+		if(!m_staticSequence)
+			m_guiSequence.clear();
+	}
+
+	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::Sequence)
+			{
+				importError = ErrorCode::Success;
+	/*			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);
+				setActive(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::GUI; }
+
+	BitMask getDesiredSystemChanges() final override { return Systems::Changes::None; }
+	BitMask getPotentialSystemChanges() final override { return Systems::Changes::GUI::All; }
+
+	const Functors &getFunctors(const Observer *p_observer, BitMask p_changedBits)
+	{
+		if(CheckBitmask(p_changedBits, Systems::Changes::Type::GUI))
+				return m_guiSequence;
+	}
+
+	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) 
+	{
+		if(CheckBitmask(p_changeType, Systems::Changes::GUI::Sequence))
+			m_guiSequence = p_subject->getFunctors(this, Systems::Changes::GUI::Sequence);
+	}
+
+private:
+	Functors m_guiSequence;
+
+	bool m_staticSequence;
+};

+ 9 - 0
Praxis3D/Source/GUISystem.h

@@ -10,6 +10,7 @@ public:
 	GUISystem()
 	{
 		m_GUIScene = nullptr;
+		//m_guiHandler = nullptr;
 		m_systemName = GetString(Systems::GUI);
 	}
 	~GUISystem() { }
@@ -63,6 +64,14 @@ public:
 
 	SystemScene* getScene() { return m_GUIScene; }
 
+	// Set the GUI Handler, so it can be used to draw GUI to the framebuffer at the end of the frame
+	//inline void setGUIHanlder(GUIHandler *p_guiHandler) { m_guiHandler = p_guiHandler; }
+
+	// Get the GUI Handler; returns nullptr if the GUI Handler is not set
+	//inline GUIHandler *getGUIHanlder() { return m_guiHandler; }
+
 protected:
 	GUIScene* m_GUIScene;
+
+	//GUIHandler *m_guiHandler;
 };

+ 47 - 36
Praxis3D/Source/GameObject.h

@@ -2,6 +2,8 @@
 
 #include "Containers.h"
 #include "GraphicsObject.h"
+#include "GUIDataManager.h"
+#include "GUIObject.h"
 #include "ObjectRegister.h"
 #include "SceneLoader.h"
 #include "ScriptObject.h"
@@ -18,6 +20,7 @@ public:
 	{
 		m_parent = nullptr;
 		m_graphicsComponent = nullptr;
+		m_GUIComponent = nullptr;
 		m_scriptComponent = nullptr;
 		m_componentsFlag = 0;
 	}
@@ -55,7 +58,7 @@ public:
 	}
 
 	// Get the data change types that this object is interested in
-	BitMask getDesiredSystemChanges() override { return Systems::Changes::Spatial::All; }
+	BitMask getDesiredSystemChanges() override { return Systems::Changes::All; }
 
 	// Get the data change types that this object might modify
 	BitMask getPotentialSystemChanges() override { return Systems::Changes::Spatial::All; }
@@ -64,54 +67,44 @@ public:
 	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) override 
 	{
 		//assert(p_subject == nullptr);
+		BitMask newChanges = Systems::Changes::None;
 
 		// 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);
-
-		//if(CheckBitmask(p_changeType, Systems::Changes::Type::Spatial))
-		//	newChanges |= m_spatialData.changeOccurred(*p_subject, p_changeType);
-		
-		//if(CheckBitmask(p_changeType, Systems::Changes::Type::Graphics) && CheckBitmask(m_componentsFlag, Systems::GameObjectComponents::Graphics))
-		//	m_graphicsComponent->changeOccurred(p_subject, p_changeType);
-
-		// Post the world-space changes
-		if(newChanges != Systems::Changes::None)
-			postChanges(newChanges);
-
-		/*if(p_changeType & Systems::Changes::Spatial::LocalRotation)
+		if(CheckBitmask(p_changeType, Systems::Changes::Type::Spatial))
 		{
-			const auto &newLocalRotation = p_subject->getVec3(this, Systems::Changes::Spatial::LocalRotation);
-
-			// If the world rotation isn't being changed, adjust it accordingly, so it has the latest rotation
-			if(!(p_changeType & Systems::Changes::Spatial::WorldRotation))
-			{
-				m_spatialData.m_worldRotationEuler -= m_spatialData.m_localRotationEuler;
-				m_spatialData.m_worldRotationEuler += newLocalRotation;
-				newChanges = newChanges | Systems::Changes::Spatial::WorldRotation;
-			}
-
-			m_spatialData.m_localRotationEuler = newLocalRotation;
+			newChanges = m_spatialData.changeOccurred(*p_subject, p_changeType & Systems::Changes::Spatial::All);
 		}
 
-		if(p_changeType & Systems::Changes::Spatial::WorldRotation)
+		// Process the graphics changes
+		if(CheckBitmask(p_changeType, Systems::Changes::Type::Graphics))
 		{
-			m_spatialData.m_worldRotationEuler = p_subject->getVec3(this, Systems::Changes::Spatial::WorldRotation) + m_spatialData.m_localRotationEuler;
+			if(graphicsComponentPresent())
+				m_graphicsComponent->changeOccurred(p_subject, p_changeType & Systems::Changes::Graphics::All);
 		}
 
-		if(p_changeType & Systems::Changes::Spatial::WorldPosition)
+		// Process the GUI changes
+		if(CheckBitmask(p_changeType, Systems::Changes::Type::GUI))
 		{
-			m_spatialData.m_worldMat.setPosition(p_subject->getVec3(this, Systems::Changes::Spatial::WorldPosition) + m_spatialData.m_localMat.getPosition());
+			if(GUIComponentPresent())
+				m_GUIComponent->changeOccurred(p_subject, p_changeType & Systems::Changes::GUI::All);
 		}
 
-		if(p_changeType & Systems::Changes::Spatial::WorldScale)
+		// Process the script changes
+		if(CheckBitmask(p_changeType, Systems::Changes::Type::Script))
 		{
-			m_spatialData.m_worldMat.setScale(p_subject->getVec3(this, Systems::Changes::Spatial::WorldScale) * m_spatialData.m_localMat.getScale());
+			if(scriptComponentPresent())
+				m_scriptComponent->changeOccurred(p_subject, p_changeType & Systems::Changes::Script::All);
 		}
 
-		if(p_changeType & Systems::Changes::Spatial::WorldModelMatrix)
-		{
-			m_spatialData.m_worldMat = p_subject->getMat4(this, Systems::Changes::Spatial::WorldModelMatrix);
-		}*/
+		//if(CheckBitmask(p_changeType, Systems::Changes::Type::Spatial))
+		//	newChanges |= m_spatialData.changeOccurred(*p_subject, p_changeType);
+		
+		//if(CheckBitmask(p_changeType, Systems::Changes::Type::Graphics) && CheckBitmask(m_componentsFlag, Systems::GameObjectComponents::Graphics))
+		//	m_graphicsComponent->changeOccurred(p_subject, p_changeType);
+
+		// Post the world-space changes
+		if(newChanges != Systems::Changes::None)
+			postChanges(newChanges);
 	}
 
 	// Set the parent of this object. The object can have only one parent, thus if the parent was set already, it will be overridden
@@ -163,7 +156,21 @@ public:
 
 		// Set the graphics component as an observer of this game object
 		m_sceneLoader.getChangeController()->createObjectLink(this, m_graphicsComponent);
-	}	
+	}
+	void addComponent(GUIObject *p_component)
+	{
+		// Remove the old component if it exists
+		removeComponent(Systems::TypeID::GUI);
+
+		// Assign the new graphics component
+		m_GUIComponent = p_component;
+
+		// Set the flag for the graphics component, so it is known from the flag that there is one currently present
+		m_componentsFlag |= Systems::GameObjectComponents::GUI;
+
+		// Set the graphics component as an observer of this game object
+		m_sceneLoader.getChangeController()->createObjectLink(this, m_GUIComponent);
+	}
 	void addComponent(ScriptObject *p_component)
 	{
 		// Remove the old component if it exists
@@ -225,6 +232,9 @@ public:
 			}
 		}
 	}
+	inline const bool graphicsComponentPresent()	const { return (m_graphicsComponent == nullptr) ? false : true; }
+	inline const bool GUIComponentPresent()			const { return (m_GUIComponent == nullptr) ? false : true; }
+	inline const bool scriptComponentPresent()		const { return (m_scriptComponent == nullptr) ? false : true; }
 
 	const SpatialDataManager &getSpatialDataChangeManager() const { return m_spatialData; }
 	const glm::quat &getQuaternion(const Observer *p_observer, BitMask p_changedBits)						const override { return m_spatialData.getQuaternion(p_observer, p_changedBits); }
@@ -256,6 +266,7 @@ private:
 
 	//Components
 	GraphicsObject *m_graphicsComponent;
+	GUIObject *m_GUIComponent;
 	ScriptObject *m_scriptComponent;
 
 	// Stores a separate flag for each component currently present

+ 2 - 0
Praxis3D/Source/GeometryBuffer.cpp

@@ -18,6 +18,8 @@ GeometryBuffer::GeometryBuffer(unsigned int p_bufferWidth, unsigned int p_buffer
 
 		m_GBTextures[i] = 0;
 		m_internalFormats[i] = 0;
+		m_textureFormats[i] = 0;
+		m_textureTypes[i] = 0;
 	}
 }
 

+ 27 - 10
Praxis3D/Source/GraphicsDataSets.h

@@ -94,7 +94,7 @@ struct ShaderData
 // Contains data of a camera, needed for view transformation
 struct CameraData
 {
-	SpatialTransformData m_viewData;
+	SpatialTransformData m_spatialData;
 };
 
 // All graphics objects contain an instance of this struct, which holds the necessary spacial and other data
@@ -249,8 +249,12 @@ struct RenderableMeshData
 
 struct DirectionalLightDataSet
 {
-	DirectionalLightDataSet(glm::vec3 p_color = glm::vec3(1.0f), glm::vec3 p_direction = glm::vec3(0.0f, 1.0f, 0.0f),
-							float p_intensity = 1.0f) : m_color(p_color), m_direction(p_direction), m_intensity(p_intensity) { }
+	DirectionalLightDataSet(glm::vec3 p_color = glm::vec3(1.0f), 
+		glm::vec3 p_direction = glm::vec3(0.0f, 1.0f, 0.0f),
+		float p_intensity = 1.0f) :
+		m_color(p_color), 
+		m_direction(p_direction), 
+		m_intensity(p_intensity) { }
 
 	void clear()
 	{
@@ -265,9 +269,14 @@ struct DirectionalLightDataSet
 
 struct PointLightDataSet
 {
-	PointLightDataSet(glm::vec3 p_color = glm::vec3(1.0f), glm::vec3 p_position = glm::vec3(0.0f), 
-					  glm::vec3 p_attenuation = glm::vec3(0.0f, 0.0f, 1.0f), float p_intensity = 1.0f)
-					: m_color(p_color), m_position(p_position), m_attenuation(p_attenuation), m_intensity(p_intensity) { }
+	PointLightDataSet(glm::vec3 p_color = glm::vec3(1.0f), 
+		glm::vec3 p_position = glm::vec3(0.0f), 
+		glm::vec3 p_attenuation = glm::vec3(0.0f, 0.0f, 1.0f), 
+		float p_intensity = 1.0f) : 
+		m_color(p_color), 
+		m_position(p_position), 
+		m_attenuation(p_attenuation), 
+		m_intensity(p_intensity) { }
 
 	glm::vec3 m_color;
 	float m_padding1;	// Unused variable, declared for padding
@@ -279,10 +288,18 @@ struct PointLightDataSet
 
 struct SpotLightDataSet
 {
-	SpotLightDataSet(glm::vec3 p_color = glm::vec3(1.0f), glm::vec3 p_position = glm::vec3(0.0f),
-					 glm::vec3 p_direction = glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3 p_attenuation = glm::vec3(0.0f, 0.0f, 1.0f),
-					 float p_intensity = 1.0f)
-		: m_color(p_color), m_position(p_position), m_direction(p_direction), m_attenuation(p_attenuation), m_intensity(p_intensity) { }
+	SpotLightDataSet(glm::vec3 p_color = glm::vec3(1.0f), 
+		glm::vec3 p_position = glm::vec3(0.0f),
+		glm::vec3 p_direction = glm::vec3(0.0f, 1.0f, 0.0f), 
+		glm::vec3 p_attenuation = glm::vec3(0.0f, 0.0f, 1.0f),
+		float p_intensity = 1.0f,
+		float p_cutoffAngle = 1.0f) : 
+		m_color(p_color), 
+		m_position(p_position), 
+		m_direction(p_direction),
+		m_attenuation(p_attenuation), 
+		m_intensity(p_intensity),
+		m_cutoffAngle(p_cutoffAngle) { }
 	
 	glm::vec3 m_color;
 	float m_padding1;	// Unused variable, declared for padding

+ 5 - 2
Praxis3D/Source/HdrMappingPass.h

@@ -8,7 +8,10 @@ class HdrMappingPass : public RenderPass
 public:
 	HdrMappingPass(RendererFrontend &p_renderer) :
 		RenderPass(p_renderer),
-		m_HDRSSBuffer(BufferType_ShaderStorage, BufferUsageHint_DynamicCopy) { }
+		m_HDRSSBuffer(BufferType_ShaderStorage, BufferUsageHint_DynamicCopy) 
+	{
+		m_hdrMappingShader = nullptr;
+	}
 
 	~HdrMappingPass() { }
 
@@ -93,7 +96,7 @@ public:
 		m_renderer.m_backend.getGeometryBuffer()->bindBuffersForWriting(m_emissiveAndOutputBuffers);
 
 		// Perform HDR mapping. Queue and render a full screen quad using an HDR pass shader
-		m_renderer.queueForDrawing(m_hdrMappingShader->getShaderHandle(), m_hdrMappingShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+		m_renderer.queueForDrawing(m_hdrMappingShader->getShaderHandle(), m_hdrMappingShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 		
 		p_renderPassData.setBlurInputMap(p_renderPassData.getEmissiveInputMap());

+ 41 - 0
Praxis3D/Source/InheritanceObjects.h

@@ -2,6 +2,7 @@
 
 #include "CommonDefinitions.h"
 #include "GraphicsDataSets.h"
+#include "GUIDataManager.h"
 #include "NullObjects.h"
 #include "SpatialDataManager.h"
 
@@ -69,6 +70,46 @@ protected:
 	const SpatialData *m_spatialData;
 };
 
+class GUIDataManagerObject
+{
+public:
+	GUIDataManagerObject() : m_GUIData(&NullObjects::NullGUIDataManager)
+	{
+		m_updateCount = 0;
+	}
+	~GUIDataManagerObject() { }
+
+	// Assign a pointer to a const GUIDataManager, so the object can use it for its GUI data
+	virtual void setGUIDataManagerReference(const GUIDataManager &p_GUIData) { m_GUIData = &p_GUIData; }
+
+	const GUIDataManager &getGUIDataManagerReference() { return *m_GUIData; }
+
+	// Replaces the pointer to the GUIDataManager with an empty one, so that this object cannot use the GUI data from the current pointer anymore
+	void removeGUIDataManagerReference() { m_GUIData = &NullObjects::NullGUIDataManager; }
+
+protected:
+	// Returns true if the GUIDataManager data has changed since the last check; resets the update counter, so the function will not return true until the GUI data changes again
+	inline bool hasSpatialDataUpdated()
+	{
+		auto GUIDataUpdateCount = m_GUIData->getUpdateCount();
+
+		if(GUIDataUpdateCount != m_updateCount)
+		{
+			m_updateCount = GUIDataUpdateCount;
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	const GUIDataManager *m_GUIData;
+
+private:
+	UpdateCount m_updateCount;
+};
+
 // Contains flags denoting whether the object has been loaded to memory and video memory
 // Sets the flags to false if the default constructor is called
 class LoadableGraphicsObject

+ 3 - 3
Praxis3D/Source/KeyCommand.cpp

@@ -2,13 +2,13 @@
 #include "KeyCommand.h"
 #include "WindowLocator.h"
 
-void KeyCommand::bindByKeyName(std::string p_keyName)
+void KeyCommand::bind(const std::string &p_keyName)
 {
 	// Get the scancode by the key name, and call bind
 	bind(WindowLocator::get().getScancode(p_keyName));
 }
 
-void KeyCommand::bind(Scancode p_scancode)
+void KeyCommand::bind(const Scancode p_scancode)
 {
 	// If the scancode is valid, bind this key command to it
 	if(p_scancode != Scancode::Key_Invalid)
@@ -17,7 +17,7 @@ void KeyCommand::bind(Scancode p_scancode)
 	}
 }
 
-void KeyCommand::unbind(Scancode p_scancode)
+void KeyCommand::unbind(const Scancode p_scancode)
 {
 	// Iterate over all scancodes, if they match, unbind the command and remove the scancode
 	for(decltype(m_scancodes.size()) i = 0, size = m_scancodes.size(); i < size; i++)

+ 5 - 5
Praxis3D/Source/KeyCommand.h

@@ -15,8 +15,8 @@ public:
 	inline void deactivate() { m_active = false; }
 	const inline bool isActivated() const { return m_active; }
 
-	inline void addScancode(Scancode p_scancode) { m_scancodes.push_back(p_scancode); }
-	inline void removeScancode(Scancode p_scancode)
+	inline void addScancode(const Scancode p_scancode) { m_scancodes.push_back(p_scancode); }
+	inline void removeScancode(const Scancode p_scancode)
 	{
 		for(decltype(m_scancodes.size()) i = 0, size = m_scancodes.size(); i < size; i++)
 		{
@@ -33,9 +33,9 @@ public:
 		std::vector<Scancode>().swap(m_scancodes);
 	}
 
-	void bindByKeyName(std::string p_keyName);
-	void bind(Scancode p_scancode);
-	void unbind(Scancode p_scancode);
+	void bind(const std::string &p_keyName);
+	void bind(const Scancode p_scancode);
+	void unbind(const Scancode p_scancode);
 	void unbindAll();
 
 	inline size_t getNumBindings() const { return m_scancodes.size(); }

+ 2 - 2
Praxis3D/Source/LenseFlareCompositePass.h

@@ -11,7 +11,7 @@ public:
 		m_lensFlareDirt(Loaders::texture2D().load(Config::rendererVar().lens_flare_dirt_texture)),
 		m_lenseFlareStarburst(Loaders::texture2D().load(Config::rendererVar().lens_flare_starburst_texture))
 	{
-		
+		m_lenseFlareShader = nullptr;
 	}
 
 	~LenseFlareCompositePass() { }
@@ -84,7 +84,7 @@ public:
 		glBindTexture(GL_TEXTURE_2D, m_lenseFlareStarburst.getHandle());
 
 		// Perform various visual effects in the post process shader
-		m_renderer.queueForDrawing(m_lenseFlareShader->getShaderHandle(), m_lenseFlareShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+		m_renderer.queueForDrawing(m_lenseFlareShader->getShaderHandle(), m_lenseFlareShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 		
 		p_renderPassData.swapColorInputOutputMaps();

+ 33 - 4
Praxis3D/Source/LenseFlarePass.h

@@ -19,8 +19,19 @@ public:
 		m_lensFlareParam.m_haloRadius = Config::graphicsVar().lens_flare_halo_radius;
 		m_lensFlareParam.m_haloThickness = Config::graphicsVar().lens_flare_halo_thickness;
 		m_lensFlareParam.m_haloThreshold = Config::graphicsVar().lens_flare_halo_threshold;
-		//TODO: dynamic aspect ratio
-		m_lensFlareParam.m_haloAspectRatio = 1600.0f / 900.0f;// Config::graphicsVar().lens_flare_aspect_ratio;
+
+		if(Config::windowVar().fullscreen)
+		{
+			m_currentScreenRes.x = Config::windowVar().window_size_fullscreen_x;
+			m_currentScreenRes.y = Config::windowVar().window_size_fullscreen_y;
+		}
+		else
+		{
+			m_currentScreenRes.x = Config::windowVar().window_size_windowed_x;
+			m_currentScreenRes.y = Config::windowVar().window_size_windowed_y;
+		}
+
+		m_lenseFlareShader = nullptr;
 	}
 
 	~LenseFlarePass() { }
@@ -82,7 +93,23 @@ public:
 	void update(RenderPassData &p_renderPassData, const SceneObjects &p_sceneObjects, const float p_deltaTime)
 	{
 		glDisable(GL_DEPTH_TEST);
-		
+
+		// Calculate the apsect ratio for the halo
+
+
+		if(m_currentScreenRes.x != Config::graphicsVar().current_resolution_x || m_currentScreenRes.y != Config::graphicsVar().current_resolution_y)
+		{
+			m_currentScreenRes.x = Config::graphicsVar().current_resolution_x;
+			m_currentScreenRes.y = Config::graphicsVar().current_resolution_y;
+
+			// Set lens flare parameters buffer size and data
+			m_lensFlareParamBuffer.m_size = sizeof(LensFlareParameters);
+			m_lensFlareParamBuffer.m_data = (void *)(&m_lensFlareParam);
+
+			// Queue lens flare parameters buffer to be created
+			m_renderer.queueForLoading(m_lensFlareParamBuffer);
+		}
+
 		// Set the output buffer
 		m_diffuseAndOutputBuffers[1] = m_renderer.m_backend.getGeometryBuffer()->getBufferLocation(p_renderPassData.getColorOutputMap());
 
@@ -99,7 +126,7 @@ public:
 		glBindTexture(GL_TEXTURE_2D, m_lensFlareGhostGradient.getHandle());
 
 		// Perform various visual effects in the post process shader
-		//m_renderer.queueForDrawing(m_lenseFlareShader->getShaderHandle(), m_lenseFlareShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+		//m_renderer.queueForDrawing(m_lenseFlareShader->getShaderHandle(), m_lenseFlareShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 		//m_renderer.passScreenSpaceDrawCommandsToBackend();
 
 		p_renderPassData.setBlurInputMap(GeometryBuffer::GBufferDiffuse);
@@ -120,4 +147,6 @@ private:
 	LensFlareParameters m_lensFlareParam;
 
 	TextureLoader2D::Texture2DHandle m_lensFlareGhostGradient;
+
+	glm::ivec2 m_currentScreenRes;
 };

+ 1 - 1
Praxis3D/Source/LightingPass.h

@@ -94,7 +94,7 @@ public:
 		m_renderer.passUpdateCommandsToBackend();
 
 		// Queue the screen space triangle, using lighting shader, to be drawn
-		m_renderer.queueForDrawing(m_shaderLightPass->getShaderHandle(), m_shaderLightPass->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+		m_renderer.queueForDrawing(m_shaderLightPass->getShaderHandle(), m_shaderLightPass->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 
 		// Pass the draw command so it is executed
 		m_renderer.passScreenSpaceDrawCommandsToBackend();

+ 25 - 26
Praxis3D/Source/LuaComponent.h

@@ -12,7 +12,7 @@ class LuaComponent : public SystemObject, public SpatialDataManagerObject, publi
 {
 	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)
+	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_GUIData(*this), m_luaScript(m_luaSpatialData, m_GUIData)
 	{
 		m_luaScriptLoaded = false;
 		m_luaSpatialData.setTrackLocalChanges(true);
@@ -42,30 +42,21 @@ public:
 
 	void update(const float p_deltaTime)
 	{
-		// Get the current spatial data
-		m_luaSpatialData.setSpatialData(*m_spatialData);
-
+		// Perform updates only the if the script is loaded
 		if(m_luaScriptLoaded)
-			m_luaScript.update(p_deltaTime);
-
-		//m_luaSpatialData.update();
-
-		auto changes = m_luaSpatialData.getCurrentChangesAndReset();
-
-		//changes &= Systems::Changes::Spatial::AllLocal;
-
-		//if(CheckBitmask(changes, Systems::Changes::Spatial::LocalPosition))
-		//	std::cout << "Position changes occurred" << std::endl;
-
-		//if(CheckBitmask(changes, Systems::Changes::Spatial::LocalTransform))
-		//	std::cout << "Transform changes occurred" << std::endl;
+		{
+			// Get the current spatial data
+			m_luaSpatialData.setSpatialData(*m_spatialData);
 
-		//if(CheckBitmask(changes, Systems::Changes::Spatial::LocalRotation))
-		//	std::cout << "Rotation changes occurred" << std::endl;
+			// Update the lua script
+			m_luaScript.update(p_deltaTime);
 
-		postChanges(changes);
+			// Get the changes from the lua script
+			auto changes = m_luaScript.getChanges();
 
-		//std::cout << m_spatialData->getWorldTransform()[3].x << " : " << m_spatialData->getWorldTransform()[3].y << " : " << m_spatialData->getWorldTransform()[3].z << std::endl;
+			// Post the new changes
+			postChanges(changes);
+		}
 	}
 
 	ErrorCode importObject(const PropertySet &p_properties) final override
@@ -135,38 +126,45 @@ public:
 	BitMask getDesiredSystemChanges() final override { return Systems::Changes::None; }
 	BitMask getPotentialSystemChanges() final override { return Systems::Changes::All; }
 
-	const inline glm::quat &getQuaternion(const Observer *p_observer, BitMask p_changedBits) const
+	const glm::quat &getQuaternion(const Observer *p_observer, BitMask p_changedBits) const
 	{
 		return m_luaSpatialData.getQuaternion(p_observer, p_changedBits);
 	}
-	const inline glm::vec3 &getVec3(const Observer *p_observer, BitMask p_changedBits) const
+	const glm::vec3 &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 glm::mat4 &getMat4(const Observer *p_observer, BitMask p_changedBits) const
+	const glm::mat4 &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
+	const 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
+	const 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;
 	}
+	const Functors &getFunctors(const Observer *p_observer, BitMask p_changedBits) const
+	{
+		if(CheckBitmask(p_changedBits, Systems::Changes::Type::GUI))
+				return m_GUIData.getFunctors(p_observer, p_changedBits);
+
+		return NullObjects::NullFunctors;
+	}
 
 	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) { }
 
@@ -186,4 +184,5 @@ private:
 	bool m_luaScriptLoaded;
 
 	SpatialDataManager m_luaSpatialData;
+	GUIDataManager m_GUIData;
 };

+ 96 - 34
Praxis3D/Source/LuaScript.h

@@ -4,9 +4,12 @@
 
 #include "EnumFactory.h"
 #include "ErrorHandlerLocator.h"
+#include "GUIDataManager.h"
+#include "GUIHandler.h"
 #include "SpatialDataManager.h"
 #include "WindowLocator.h"
 
+#include <functional>
 #include <sol/sol.hpp>
 
 namespace LuaDefinitions
@@ -42,13 +45,15 @@ namespace LuaDefinitions
 class LuaScript
 {
 public:
-	LuaScript(SpatialDataManager &p_spatialData) : m_spatialData(p_spatialData)
+	LuaScript(SpatialDataManager &p_spatialData, GUIDataManager &p_GUIData) : m_spatialData(p_spatialData), m_GUIData(p_GUIData)
 	{ 
 		m_keyCommands.reserve(10);
+		m_currentChanges = Systems::Changes::None;
 	}
-	LuaScript(SpatialDataManager &p_spatialData, std::string &p_scriptFilename) : m_spatialData(p_spatialData), m_luaScriptFilename(p_scriptFilename)
+	LuaScript(SpatialDataManager &p_spatialData, GUIDataManager &p_GUIData, std::string &p_scriptFilename) : m_spatialData(p_spatialData), m_GUIData(p_GUIData), m_luaScriptFilename(p_scriptFilename)
 	{
 		m_keyCommands.reserve(10);
+		m_currentChanges = Systems::Changes::None;
 	}
 	~LuaScript() 
 	{
@@ -88,55 +93,101 @@ public:
 
 	inline void update(const float p_deltaTime)
 	{
+		// Clear changes from the last update
+		clearChanges();
+
+		// Clear all the GUI functors from the last update
+		m_GUIData.clearFunctors();
+
+		// Call update function in the lua script
 		m_luaUpdate(p_deltaTime);
+
+		// Add spatial changes to the current changes, because they are tracked separately
+		m_currentChanges += m_spatialData.getCurrentChanges();
+
+		// Add GUI changes to the current changes, because they are tracked separately
+		m_currentChanges += m_GUIData.getCurrentChanges();
 	}
 
+	// Clears the currently registered changes. They are also cleared at the beginning of each update call
+	inline void clearChanges() { m_currentChanges = Systems::Changes::None; }
+
+	// Set the filename of the script that should be loaded
 	inline void setScriptFilename(std::string &p_filename) { m_luaScriptFilename = p_filename; }
 
+	// Get sequences of function calls so that they can be passed to other objects and executed later
+	// They are also cleared at the beginning of each update call, so a copy must be made if there are intentions to store them for later
+	inline const Functors &getFunctors() { return m_GUIData.getGUIData().m_functors; }
+
+	// Get changes since the last update (or the last clearChanges call)
+	inline BitMask getChanges() const { return m_currentChanges; }
+	inline BitMask getChangesAndClear() 
+	{ 
+		return m_currentChanges; 
+		clearChanges();
+	}
+
 private:
+	// Sets lua tables with various definitions and values
 	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>();
+		m_userTypesTable = 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;
+			m_userTypesTable[sol::update_if_empty][GetString(static_cast<LuaDefinitions::UserTypes>(i))] = i;
+
+		// Create a table for different types of changes
+		m_changeTypesTable = m_luaState["Changes"].get_or_create<sol::table>();
+
+		// Create entries for GUI changes
+		m_changeTypesTable[sol::update_if_empty]["GUI"]["Sequence"] = Int64Packer(Systems::Changes::GUI::Sequence);
 	}
+	// Binds functions, so that they can be called from the lua script
 	void setFunctions()
 	{
-		//m_luaState.set_function("toRadianF", sol::resolve<float(const float)>(&Math::toRadian));
-
+		// Math functions
 		m_luaState.set_function("toRadianF", sol::resolve<float(const float)>(&glm::radians));
 		m_luaState.set_function("toRadianVec3", sol::resolve<glm::vec3(const glm::vec3 &)>(&glm::radians));
 		m_luaState.set_function("toRadianVec4", sol::resolve<glm::vec4(const glm::vec4 &)>(&glm::radians));
-
 		m_luaState.set_function("toDegreesF", sol::resolve<float(const float)>(&glm::degrees));
 		m_luaState.set_function("toDegreesVec3", sol::resolve<glm::vec3(const glm::vec3 &)>(&glm::degrees));
 		m_luaState.set_function("toDegreesVec4", sol::resolve<glm::vec4(const glm::vec4 &)>(&glm::degrees));
-
 		m_luaState.set_function("angleAxisQuat", sol::resolve<glm::quat(const float &, const glm::vec3 &)>(&glm::angleAxis));
 
+		// Input / Window functions
 		m_luaState.set_function("getMouseInfo", []() -> const Window::MouseInfo { return WindowLocator::get().getMouseInfo(); });
 		m_luaState.set_function("mouseCaptured", []() -> const bool { return Config::windowVar().mouse_captured; });
-
 		m_luaState.set_function("setFullscreen", [](const bool p_v1) -> const void { WindowLocator::get().setFullscreen(p_v1); });
 		m_luaState.set_function("setMouseCapture", [](const bool p_v1) -> const void { WindowLocator::get().setMouseCapture(p_v1); });
 		m_luaState.set_function("setVerticalSync", [](const bool p_v1) -> const void { WindowLocator::get().setVerticalSync(p_v1); });
 		m_luaState.set_function("setWindowTitle", [](const std::string &p_v1) -> const void { WindowLocator::get().setWindowTitle(p_v1); });
 
+		// Engine functions
 		m_luaState.set_function("setEngineRunning", [](const bool p_v1) -> const void {Config::m_engineVar.running = p_v1; });
 
+		// GUI functions
+		auto GUITable = m_luaState.create_table("GUI");
+		GUITable.set_function("Begin", [this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::Begin(p_v1.c_str()); }); });
+		GUITable.set_function("End", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::End(); }); });
+		GUITable.set_function("SameLine", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::SameLine(); }); });
+		GUITable.set_function("Text", sol::overload([this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::Text(p_v1.c_str()); }); },
+			[this](const std::string &p_v1, const float p_v2) -> const void { m_GUIData.addFunctor([=] { ImGui::Text(p_v1.c_str(), p_v2); }); },
+			[this](const std::string &p_v1, const float p_v2, const float p_v3) -> const void { m_GUIData.addFunctor([=] { ImGui::Text(p_v1.c_str(), p_v2, p_v3); }); }));
+		GUITable.set_function("Checkbox", [this](const std::string &p_v1, bool *p_v2) -> const void { m_GUIData.addFunctor([=] { ImGui::Checkbox(p_v1.c_str(), p_v2); }); });
+		GUITable.set_function("SliderFloat", [this](const std::string &p_v1, float *p_v2, const float p_v3, const float p_v4) -> const void { m_GUIData.addFunctor([=] { ImGui::SliderFloat(p_v1.c_str(), p_v2, p_v3, p_v4); }); });
+		GUITable.set_function("ColorEdit3", [this](const std::string &p_v1, const float p_v2, const float p_v3, const float p_v4) -> const void { m_GUIData.addFunctor([=] { float color[3] = { p_v2, p_v3, p_v4 }; ImGui::ColorEdit3(p_v1.c_str(), color); }); });
+		GUITable.set_function("Button", [this](const std::string &p_v1, bool *p_v2) -> const void { m_GUIData.addFunctor([=] { ImGui::Checkbox(p_v1.c_str(), p_v2); }); });
+
+		// LuaScript callbacks
+		m_luaState.set_function("postChanges", &LuaScript::registerChange, this);
 		m_luaState.set_function(Config::scriptVar().createObjectFunctionName, &LuaScript::createObjectInLua, this);
 	}
+	// Defines usertypes, so that they can be used in the lua script
 	void setUsertypes()
 	{
+		// Config variables
 		m_luaState.new_usertype<Config::EngineVariables>("EngineVariables",
 			"change_ctrl_cml_notify_list_reserv", &Config::EngineVariables::change_ctrl_cml_notify_list_reserv,
 			"change_ctrl_grain_size", &Config::EngineVariables::change_ctrl_grain_size,
@@ -206,6 +257,9 @@ private:
 			"vertical_sync", &Config::WindowVariables::vertical_sync,
 			"window_in_focus", &Config::WindowVariables::window_in_focus);
 
+		// Math types
+		m_luaState.new_usertype<Int64Packer>("Int64");
+
 		m_luaState.new_usertype<glm::vec3>("Vec3",
 			sol::constructors<glm::vec3(), glm::vec3(float), glm::vec3(float, float, float), glm::vec3(glm::vec4)>(),
 			"x", &glm::vec3::x,
@@ -311,6 +365,7 @@ private:
 			"setParentTransform", &SpatialDataManager::setParentTransform,
 			"setWorldTransform", &SpatialDataManager::setWorldTransform);
 
+		// Input types
 		m_luaState.new_usertype<Window::MouseInfo>("MouseInfo",
 			"m_movementCurrentFrameX", &Window::MouseInfo::m_movementCurrentFrameX,
 			"m_movementCurrentFrameY", &Window::MouseInfo::m_movementCurrentFrameY,
@@ -325,12 +380,14 @@ private:
 			"activate", &KeyCommand::activate,
 			"deactivate", &KeyCommand::deactivate,
 			"isActivated", &KeyCommand::isActivated,
-			"bind", &KeyCommand::bind,
-			"bindByKeyName", &KeyCommand::bindByKeyName,
+			"bind", sol::resolve<void(const Scancode)>(&KeyCommand::bind),
+			"bindByName", sol::resolve<void(const std::string&)>(&KeyCommand::bind),
 			"unbind", &KeyCommand::unbind,
 			"unbindAll", &KeyCommand::unbindAll);
 	}
 
+	// Creates and assigns objects to be used in the lua script
+	// Should only be called from the lua script
 	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
@@ -397,32 +454,37 @@ private:
 		}
 	}
 
-	void recordBoolChange(const bool p_change, const unsigned int p_changeType)
+	// Registers a change in some data
+	// Should only be called from the lua script
+	void registerChange(const Int64Packer &p_packer)
 	{
-
+		m_currentChanges += p_packer.get();
 	}
-	void recordIntChange(const int p_change, const unsigned int p_changeType)
-	{
 
-	}
-	void recordFloatChange(const float p_change, const unsigned int p_changeType)
-	{
+	// Lua state for the loaded script
+	sol::state m_luaState;
+	std::string m_luaScriptFilename;
 
-	}
-	void recordVec3fChange(const glm::vec3 p_change, const unsigned int p_changeType)
-	{
+	// Function binds that call functions inside the lua script
+	sol::function m_luaInit;
+	sol::function m_luaUpdate;
 
-	}
+	// Tables for variable definitions
+	sol::table m_userTypesTable;
+	sol::table m_changeTypesTable;
 
+	// Contains all spatial data
 	SpatialDataManager &m_spatialData;
 
-	std::vector<KeyCommand*> m_keyCommands;
+	// Contains all GUI data
+	GUIDataManager &m_GUIData;
 
-	sol::state m_luaState;
-	std::string m_luaScriptFilename;
+	// Keeps all created key commands, so they can be unbound and deleted when cleaning up
+	std::vector<KeyCommand*> m_keyCommands;
 
-	sol::function m_luaInit;
-	sol::function m_luaUpdate;
+	// Contains sequences of function calls that can be passed to other SystemObjects
+	//Functors m_functors;
 
-	sol::table m_userTypes;
+	// Stores the changes made to the data since the last update
+	BitMask m_currentChanges;
 };

+ 4 - 0
Praxis3D/Source/NullObjects.cpp

@@ -1,4 +1,6 @@
 
+#include "CommonDefinitions.h"
+#include "GUIDataManager.h"
 #include "NullObjects.h"
 #include "Math.h"
 #include "ObserverBase.h"
@@ -25,3 +27,5 @@ const std::string			NullObjects::NullString;
 const SpatialData			NullObjects::NullSpacialData;
 const SpatialTransformData	NullObjects::NullSpacialTransformData;
 const SpatialDataManager	NullObjects::NullSpatialDataManager = SpatialDataManager(nullObserver);
+const GUIDataManager		NullObjects::NullGUIDataManager = GUIDataManager(nullObserver);
+const Functors				NullObjects::NullFunctors;

+ 8 - 12
Praxis3D/Source/NullObjects.h

@@ -2,26 +2,20 @@
 
 #include <string>
 
+#include "CommonDefinitions.h"
 #include "Math.h"
 
-/*namespace Math
-{
-	struct Quaternion;
-	struct Vec3f;
-	struct Vec4f;
-	class Mat4f;
-}*/
-
 struct SpatialData;
 struct SpatialTransformData;
 class SpatialDataManager;
+class GUIDataManager;
 
 namespace NullObjects
 {
-	const extern glm::quat		NullQuaterion;
-	const extern glm::vec3			NullVec3f;
-	const extern glm::vec4			NullVec4f;
-	const extern glm::mat4			NullMat4f;
+	const extern glm::quat				NullQuaterion;
+	const extern glm::vec3				NullVec3f;
+	const extern glm::vec4				NullVec4f;
+	const extern glm::mat4				NullMat4f;
 	const extern bool					NullBool;
 	const extern int					NullInt;
 	const extern float					NullFloat;
@@ -30,4 +24,6 @@ namespace NullObjects
 	const extern SpatialData			NullSpacialData;
 	const extern SpatialTransformData	NullSpacialTransformData;
 	const extern SpatialDataManager		NullSpatialDataManager;
+	const extern GUIDataManager			NullGUIDataManager;
+	const extern Functors				NullFunctors;
 }

+ 12 - 12
Praxis3D/Source/ObserverBase.h

@@ -61,18 +61,18 @@ public:
 
 	const static SystemObjectID g_invalidID = static_cast<unsigned int>(-1);
 
-	const virtual glm::quat				&getQuaternion(const Observer *p_observer, BitMask p_changedBits)	const { return NullObjects::NullQuaterion;	}
-	const virtual glm::vec3				&getVec3(const Observer *p_observer, BitMask p_changedBits)			const { return NullObjects::NullVec3f;		}
-	const virtual glm::vec4				&getVec4(const Observer *p_observer, BitMask p_changedBits)			const { return NullObjects::NullVec4f;		}
-	const virtual glm::mat4				&getMat4(const Observer *p_observer, BitMask p_changedBits)			const { return NullObjects::NullMat4f;		}
-
-	const virtual bool					getBool(const Observer *p_observer, BitMask p_changedBits) const					{ return NullObjects::NullBool;					}
-	const virtual int					getInt(const Observer *p_observer, BitMask p_changedBits) const						{ return NullObjects::NullInt;					}
-	const virtual float					getFloat(const Observer *p_observer, BitMask p_changedBits) const					{ return NullObjects::NullFloat;				}
-	const virtual double				&getDouble(const Observer *p_observer, BitMask p_changedBits) const					{ return NullObjects::NullDouble;				}
-	const virtual std::string			&getString(const Observer *p_observer, BitMask p_changedBits) const					{ return NullObjects::NullString;				}
-	const virtual SpatialData			&getSpatialData(const Observer *p_observer, BitMask p_changedBits) const			{ return NullObjects::NullSpacialData;			}
-	const virtual SpatialTransformData	&getSpatialTransformData(const Observer *p_observer, BitMask p_changedBits) const	{ return NullObjects::NullSpacialTransformData;	}
+	const virtual glm::quat				&getQuaternion(const Observer *p_observer, BitMask p_changedBits)			const { return NullObjects::NullQuaterion;				}
+	const virtual glm::vec3				&getVec3(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullVec3f;					}
+	const virtual glm::vec4				&getVec4(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullVec4f;					}
+	const virtual glm::mat4				&getMat4(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullMat4f;					}
+	const virtual bool					getBool(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullBool;					}
+	const virtual int					getInt(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullInt;					}
+	const virtual float					getFloat(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullFloat;					}
+	const virtual double				&getDouble(const Observer *p_observer, BitMask p_changedBits)				const { return NullObjects::NullDouble;					}
+	const virtual std::string			&getString(const Observer *p_observer, BitMask p_changedBits)				const { return NullObjects::NullString;					}
+	const virtual SpatialData			&getSpatialData(const Observer *p_observer, BitMask p_changedBits)			const { return NullObjects::NullSpacialData;			}
+	const virtual SpatialTransformData	&getSpatialTransformData(const Observer *p_observer, BitMask p_changedBits) const { return NullObjects::NullSpacialTransformData;	}
+	const virtual Functors				&getFunctors(const Observer *p_observer, BitMask p_changedBits)				const { return NullObjects::NullFunctors;				}
 
 	// Stores observer information required for postChanges messages
 	struct ObserverData

+ 1 - 1
Praxis3D/Source/PostProcessPass.h

@@ -99,7 +99,7 @@ public:
 		glBindTexture(GL_TEXTURE_2D, m_lensFlareGhostGradient.getHandle());
 
 		// Perform various visual effects in the post process shader
-		m_renderer.queueForDrawing(m_postProcessShader->getShaderHandle(), m_postProcessShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+		m_renderer.queueForDrawing(m_postProcessShader->getShaderHandle(), m_postProcessShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 		m_renderer.passScreenSpaceDrawCommandsToBackend();
 
 		p_renderPassData.swapColorInputOutputMaps();

+ 19 - 19
Praxis3D/Source/RendererFrontend.cpp

@@ -215,46 +215,46 @@ void RendererFrontend::renderFrame(SceneObjects &p_sceneObjects, const float p_d
 		}
 	}
 
-	glm::quat qPitch = glm::angleAxis(glm::radians(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.x), glm::vec3(1, 0, 0));
-	glm::quat qYaw = glm::angleAxis(glm::radians(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.y), glm::vec3(0, 1, 0));
-	glm::quat qRoll = glm::angleAxis(glm::radians(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.z), glm::vec3(0, 0, 1));
+	glm::quat qPitch = glm::angleAxis(glm::radians(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.x), glm::vec3(1, 0, 0));
+	glm::quat qYaw = glm::angleAxis(glm::radians(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.y), glm::vec3(0, 1, 0));
+	glm::quat qRoll = glm::angleAxis(glm::radians(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.z), glm::vec3(0, 0, 1));
 	glm::quat orientation = qPitch * qYaw * qRoll;
 	
-	orientation = glm::toQuat(p_sceneObjects.m_camera.m_viewData.m_transformMat);
+	orientation = glm::toQuat(p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 
 	//glm::quat orientation = qPitch * qYaw * qRoll; 
-	//glm::quat orientation(glm::radians(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler));
+	//glm::quat orientation(glm::radians(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler));
 	orientation = glm::normalize(orientation);
 	glm::mat4 rotate = glm::mat4_cast(orientation);
 	glm::mat4 translate = glm::mat4(1.0f);
-	//translate = glm::translate(translate, -p_sceneObjects.m_camera.m_viewData.m_spatialData.m_position);
-	translate = glm::translate(translate, -glm::vec3(p_sceneObjects.m_camera.m_viewData.m_transformMat[3]));
+	//translate = glm::translate(translate, -p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_position);
+	translate = glm::translate(translate, -glm::vec3(p_sceneObjects.m_camera.m_spatialData.m_transformMat[3]));
 
 	m_frameData.m_viewMatrix = rotate * translate;
 
-	glm::mat4 rotationOnly = p_sceneObjects.m_camera.m_viewData.m_transformMat;
+	glm::mat4 rotationOnly = p_sceneObjects.m_camera.m_spatialData.m_transformMat;
 	rotationOnly[3] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
 
 	//m_frameData.m_viewMatrix = rotationOnly * translate;
 
 
-	//glm::vec3 direction = glm::rotate(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationQuat, glm::vec3(0.0f, 0.0f, -1.0f));
+	//glm::vec3 direction = glm::rotate(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationQuat, glm::vec3(0.0f, 0.0f, -1.0f));
 	glm::vec3 direction = glm::normalize(glm::rotate(orientation, glm::vec3(0.0f, 0.0f, -1.0f)));
 	//direction = glm::normalize(direction);
-	glm::vec3 up = glm::normalize(glm::rotate(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationQuat, glm::vec3(0.0f, 1.0f, 0.0f)));
+	glm::vec3 up = glm::normalize(glm::rotate(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationQuat, glm::vec3(0.0f, 1.0f, 0.0f)));
 
-	//glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.0f), -p_sceneObjects.m_camera.m_viewData.m_spatialData.m_position);
-	//glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, glm::radians(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.x), glm::vec3(1.0f, 0.0f, 0.0f));
-	//glm::mat4 View = glm::rotate(ViewRotateX, glm::radians(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.y), glm::vec3(0.0f, 1.0f, 0.0f));
+	//glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.0f), -p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_position);
+	//glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, glm::radians(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.x), glm::vec3(1.0f, 0.0f, 0.0f));
+	//glm::mat4 View = glm::rotate(ViewRotateX, glm::radians(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.y), glm::vec3(0.0f, 1.0f, 0.0f));
 
 	//m_frameData.m_viewMatrix = View;
 
-	//m_frameData.m_viewMatrix = glm::lookAt(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_position, direction, up);
-	//m_frameData.m_viewMatrix = glm::lookAt(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_position, direction, up);
-	//m_frameData.m_viewMatrix = glm::lookAt(p_sceneObjects.m_camera.m_viewData.m_spatialData.m_position, glm::vec3(0.0f, 0.0, -1.0f), glm::vec3(0.0f, 1.0, 0.0f));
+	//m_frameData.m_viewMatrix = glm::lookAt(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_position, direction, up);
+	//m_frameData.m_viewMatrix = glm::lookAt(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_position, direction, up);
+	//m_frameData.m_viewMatrix = glm::lookAt(p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_position, glm::vec3(0.0f, 0.0, -1.0f), glm::vec3(0.0f, 1.0, 0.0f));
 
 	// Calculate view and view-projection matrix here, so it is only done once, since it only changes between frames
-	//m_frameData.m_viewMatrix = p_sceneObjects.m_camera.m_viewData.m_transformMat;
+	//m_frameData.m_viewMatrix = p_sceneObjects.m_camera.m_spatialData.m_transformMat;
 	m_frameData.m_viewProjMatrix = m_frameData.m_projMatrix * m_frameData.m_viewMatrix;
 	
 	// Convert the view matrix to row major for the atmospheric scattering shaders
@@ -286,10 +286,10 @@ void RendererFrontend::renderFrame(SceneObjects &p_sceneObjects, const float p_d
 	std::cout << m_frameData.m_viewMatrix.m[12] << " : " << m_frameData.m_viewMatrix.m[13] << " : " << m_frameData.m_viewMatrix.m[14] << " : " << m_frameData.m_viewMatrix.m[15] << std::endl;
 	*/
 	// Set the camera position
-	m_frameData.m_cameraPosition = p_sceneObjects.m_camera.m_viewData.m_transformMat[3]; //p_sceneObjects.m_camera.m_viewData.m_spatialData.m_position;
+	m_frameData.m_cameraPosition = p_sceneObjects.m_camera.m_spatialData.m_transformMat[3]; //p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_position;
 	
 	// Set the camera target vector
-	m_frameData.m_cameraTarget = p_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler;
+	m_frameData.m_cameraTarget = p_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler;
 
 	// Assign directional light values and also normalize its direction, so it's not necessary to do it in a shader
 	m_frameData.m_dirLightColor = p_sceneObjects.m_directionalLight->m_color;

+ 21 - 30
Praxis3D/Source/RendererScene.cpp

@@ -226,7 +226,7 @@ PropertySet RendererScene::exportObject()
 void RendererScene::update(const float p_deltaTime)
 {
 	// Clear variables
-	m_sceneObjects.m_staticSkybox = nullptr;
+	//m_sceneObjects.m_staticSkybox = nullptr;
 	//m_sceneObjects.m_directionalLight = nullptr;
 	m_sceneObjects.m_directionalLight = &m_directionalLight->getLightDataSet();
 
@@ -388,7 +388,7 @@ void RendererScene::update(const float p_deltaTime)
 					// Check if the graphics object contains a camera component
 					if(graphicsObject->cameraComponentPresent())
 					{
-						m_sceneObjects.m_camera.m_viewData.m_transformMat = graphicsObject->getSpatialDataManagerReference().getWorldTransform();
+						m_sceneObjects.m_camera.m_spatialData.m_transformMat = graphicsObject->getSpatialDataManagerReference().getWorldTransform();
 
 						/*glm::vec3 m_positionVec(0.0f, 0.0f, 0.0f);
 						glm::vec3 m_targetVec(0.0f, 0.0f, 0.0f);
@@ -404,18 +404,18 @@ void RendererScene::update(const float p_deltaTime)
 
 						// Calculate camera's position based on the pressed movement keys
 						m_upVector = Math::cross(m_horizontalVec, m_targetVec);
-						m_sceneObjects.m_camera.m_viewData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
+						m_sceneObjects.m_camera.m_spatialData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
 
 						// Set the target vector variable, so it can be retrieved later by listeners
 						m_targetVec = glm::vec3(0.0f);
 						m_targetVec.y = m_verticalAngle;
 						m_targetVec.z = m_horizontalAngle;
 
-						m_sceneObjects.m_camera.m_viewData.m_spatialData.m_position = m_positionVec;
-						m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler = m_targetVec;*/
+						m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_position = m_positionVec;
+						m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler = m_targetVec;*/
 
-						//m_sceneObjects.m_camera.m_viewData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
-						//m_sceneObjects.m_camera.m_viewData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
+						//m_sceneObjects.m_camera.m_spatialData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
+						//m_sceneObjects.m_camera.m_spatialData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
 					}
 				}
 			}
@@ -581,19 +581,19 @@ void RendererScene::update(const float p_deltaTime)
 
 
 	// Update camera spatial data
-	calculateCamera(m_sceneObjects.m_camera.m_viewData);
+	calculateCamera(m_sceneObjects.m_camera.m_spatialData);
 
 	//std::cout << GetString(static_cast<Properties::PropertyID>(10)) << std::endl;
 	
 
 	//m_sceneObjects.m_camera.m_spatialData.m_rotationEuler = Math::toRadian(p_viewData.m_spatialData.m_rotationEuler);
-	/*m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.y = 0.5f;
-	m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.z = 3.14f;
+	/*m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.y = 0.5f;
+	m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.z = 3.14f;
 
-	//const glm::vec3 upVector = Math::cross(m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.z, m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.y);
-	//const glm::vec3 targetVector(0.0f, m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.y, m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler.z);
+	//const glm::vec3 upVector = Math::cross(m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.z, m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.y);
+	//const glm::vec3 targetVector(0.0f, m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.y, m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler.z);
 
-	//m_sceneObjects.m_camera.m_viewData.m_transformMat.initCamera(m_sceneObjects.m_camera.m_viewData.m_spatialData.m_position, targetVector + m_sceneObjects.m_camera.m_viewData.m_spatialData.m_position, upVector);
+	//m_sceneObjects.m_camera.m_spatialData.m_transformMat.initCamera(m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_position, targetVector + m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_position, upVector);
 
 	glm::vec3 m_positionVec(0.0f, 0.0f, 0.0f);
 	glm::vec3 m_targetVec(0.0f, 0.0f, 0.0f);
@@ -609,19 +609,19 @@ void RendererScene::update(const float p_deltaTime)
 
 	// Calculate camera's position based on the pressed movement keys
 	m_upVector = Math::cross(m_horizontalVec, m_targetVec);
-	m_sceneObjects.m_camera.m_viewData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
+	m_sceneObjects.m_camera.m_spatialData.m_transformMat.initCamera(m_positionVec, m_targetVec + m_positionVec, m_upVector);
 
 	// Set the target vector variable, so it can be retrieved later by listeners
 	m_targetVec = glm::vec3(0.0f);
 	m_targetVec.y = m_verticalAngle;
 	m_targetVec.z = m_horizontalAngle;
 
-	m_sceneObjects.m_camera.m_viewData.m_spatialData.m_position = m_positionVec;
-	m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler = m_targetVec;
+	m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_position = m_positionVec;
+	m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler = m_targetVec;
 
-	m_sceneObjects.m_camera.m_viewData.m_spatialData.m_rotationEuler = glm::vec3(0.0f);
+	m_sceneObjects.m_camera.m_spatialData.m_spatialData.m_rotationEuler = glm::vec3(0.0f);
 
-	m_sceneObjects.m_camera.m_viewData.m_transformMat = Math::createTransformMat(
+	m_sceneObjects.m_camera.m_spatialData.m_transformMat = Math::createTransformMat(
 		glm::vec3(0.0f),
 		glm::vec3(0.0f, 0.0f, 45.0f),
 		glm::vec3(1.0f));
@@ -652,9 +652,9 @@ void RendererScene::update(const float p_deltaTime)
 	mat.m[9] = sinY * sinR + cosR * cosY * sinP;
 	mat.m[10] = cosP * cosY;
 
-	m_sceneObjects.m_camera.m_viewData.m_transformMat = mat * glm::mat4();*/
+	m_sceneObjects.m_camera.m_spatialData.m_transformMat = mat * glm::mat4();*/
 
-	m_sceneObjects.m_staticSkybox = m_skybox;
+	//m_sceneObjects.m_staticSkybox = m_skybox;
 }
 
 SystemObject *RendererScene::createObject(const PropertySet &p_properties)
@@ -679,7 +679,7 @@ SystemObject *RendererScene::createObject(const PropertySet &p_properties)
 
 				// If the name property is missing, generate a unique name based on the object's index in the pool
 				if(nameProperty)
-					name = nameProperty.getString();
+					name = nameProperty.getString() + " (" + GetString(Properties::GraphicsObject) + ")";
 				else
 					name = GetString(Properties::GraphicsObject) + Utilities::toString(graphicsObjectFromPool->getIndex());
 				
@@ -740,15 +740,6 @@ void RendererScene::changeOccurred(ObservedSubject *p_subject, BitMask p_changeT
 	//std::cout << "change occurred" << std::endl;
 }
 
-BitMask RendererScene::getDesiredSystemChanges()
-{
-	return Systems::Changes::Generic::All;
-}
-BitMask RendererScene::getPotentialSystemChanges()
-{
-	return Systems::Changes::None;
-}
-
 MaterialData RendererScene::loadMaterialData(PropertySet &p_materialProperty, Model::MaterialArrays &p_materialArraysFromModel, MaterialType p_materialType, std::size_t p_meshIndex)
 {
 	// Declare the material data that is to be returned and a flag showing whether the material data was loaded successfully

+ 8 - 15
Praxis3D/Source/RendererScene.h

@@ -22,30 +22,23 @@ class RendererSystem;
 // Used to store processed objects, so they can be sent to the renderer
 struct SceneObjects
 {
-	SceneObjects() : m_staticSkybox(nullptr), m_directionalLight(nullptr) { }
+	SceneObjects() : /*m_staticSkybox(nullptr),*/ m_directionalLight(nullptr) { }
 
+	// Camera
 	CameraData m_camera;
-	EnvironmentMapObject *m_staticSkybox;
+	//EnvironmentMapObject *m_staticSkybox;
 
+	// Lights
 	const DirectionalLightDataSet *m_directionalLight;
 	std::vector<PointLightDataSet> m_pointLights;
 	std::vector<SpotLightDataSet> m_spotLights;
 
+	// Models
 	std::vector<ModelAndSpatialData> m_modelData;
 	std::vector<ModelShaderSpatialData> m_modelDataWithShaders;
 
+	// Objects that need to be loaded to VRAM
 	std::vector<LoadableObjectsContainer> m_loadToVideoMemory;
-
-	//std::vector<const RenderableMeshData> m_meshObjects;
-	//std::vector<RenderableObjectData*> m_modelObjects;
-	//std::vector<RenderableObjectData*> m_tessellatedObjects;
-	//std::vector<RenderableObjectData*> m_customShaderObjects;
-	//std::vector<RenderableObjectData*> m_postLightingObjects;
-
-	//std::vector<RenderableObjectData*> m_objectsToLoad;
-
-	//EnvironmentMapObject *m_staticSkyboxToLoad;
-
 };
 
 class RendererScene : public SystemScene
@@ -76,8 +69,8 @@ public:
 
 	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType);
 
-	BitMask getDesiredSystemChanges();
-	BitMask getPotentialSystemChanges();
+	BitMask getDesiredSystemChanges() { return Systems::Changes::Generic::All; }
+	BitMask getPotentialSystemChanges() { return Systems::Changes::None; }
 
 	// Getters
 	SystemTask *getSystemTask() { return m_renderTask; }

+ 0 - 1
Praxis3D/Source/RendererSystem.cpp

@@ -6,7 +6,6 @@
 RendererSystem::RendererSystem()
 {
 	m_rendererScene = nullptr;
-	m_guiHandler = nullptr;
 	m_systemName = GetString(Systems::Graphics);
 }
 

+ 0 - 3
Praxis3D/Source/RendererSystem.h

@@ -30,11 +30,8 @@ public:
 
 	RendererFrontend &getRenderer() { return m_renderer; }
 
-	void registerGUIHanlder(GUIHandler *p_guiHandler) { m_guiHandler = p_guiHandler; }
-
 protected:
 	RendererFrontend m_renderer;
 	RendererScene *m_rendererScene;
-	GUIHandler *m_guiHandler;
 };
 

+ 5 - 4
Praxis3D/Source/ScriptObject.h

@@ -17,6 +17,7 @@ public:
 		: SystemObject(p_systemScene, p_name, Properties::ScriptObject)
 	{
 		m_luaComponent = nullptr;
+		m_componentsFlag = 0;
 	}
 	~ScriptObject()
 	{
@@ -145,7 +146,7 @@ public:
 
 	// 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)
+	void setSpatialDataManagerReference(const SpatialDataManager &p_spatialData)
 	{
 		SpatialDataManagerObject::setSpatialDataManagerReference(p_spatialData);
 
@@ -156,14 +157,14 @@ public:
 	// 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; }
+	BitMask getDesiredSystemChanges() { return Systems::Changes::Graphics::All; }
+	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)
+	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType)
 	{
 		// Track what data has been modified
 		BitMask newChanges = Systems::Changes::None;

+ 26 - 22
Praxis3D/Source/ScriptScene.cpp

@@ -13,11 +13,14 @@ ScriptScene::ScriptScene(ScriptSystem *p_system, SceneLoader *p_sceneLoader) : S
 
 ScriptScene::~ScriptScene()
 {
+	if(m_scriptingTask != nullptr)
+		delete m_scriptingTask;
 }
 
 ErrorCode ScriptScene::init()
 {
 	m_scriptingTask = new ScriptTask(this);
+
 	return ErrorCode::Success;
 }
 
@@ -67,11 +70,27 @@ void ScriptScene::update(const float p_deltaTime)
 
 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.getPoolSize()) i = 0, size = m_scriptObjects.getPoolSize(); i < size; i++)
+	{
+		// TODO: load in background implementation
+		//TaskManagerLocator::get().startBackgroundThread(std::bind(&ScriptObject::loadToMemory, m_scriptObjects[i]));
+	}
+}
+
+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.getPoolSize(), size_t(1), [=](size_t i)
+	{
+		if(m_scriptObjects[i].allocated())
+		{
+			m_scriptObjects[i].getObject()->loadToMemory();
+		}
+	});
+
+	return ErrorCode::Success;
 }
 
 PropertySet ScriptScene::exportObject()
@@ -92,21 +111,6 @@ PropertySet ScriptScene::exportObject()
 	return propertySet;
 }
 
-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.getPoolSize(), size_t(1), [=](size_t i)
-	{
-		if(m_scriptObjects[i].allocated())
-		{
-			m_scriptObjects[i].getObject()->loadToMemory();
-		}
-	});
-
-	return ErrorCode::Success;
-}
-
 SystemObject *ScriptScene::createObject(const PropertySet &p_properties)
 {
 	// Check if property set node is present
@@ -129,9 +133,9 @@ SystemObject *ScriptScene::createObject(const PropertySet &p_properties)
 
 				// If the name property is missing, generate a unique name based on the object's index in the pool
 				if(nameProperty)
-					name = nameProperty.getString();
+					name = nameProperty.getString() + " (" + GetString(Properties::ScriptObject) + ")";
 				else
-					name = GetString(Properties::GraphicsObject) + Utilities::toString(scriptObjectFromPool->getIndex());
+					name = GetString(Properties::ScriptObject) + Utilities::toString(scriptObjectFromPool->getIndex());
 
 				// Construct the GraphicsObject
 				scriptObjectFromPool->construct(this, name);

+ 2 - 2
Praxis3D/Source/ScriptScene.h

@@ -29,10 +29,10 @@ public:
 
 	void loadInBackground();
 
+	ErrorCode preload();
+
 	// Exports all the data of the scene (including all objects within) as a PropertySet
 	virtual PropertySet exportObject();
-	
-	ErrorCode preload();
 
 	SystemObject *createObject(const PropertySet &p_properties);
 	ErrorCode destroyObject(SystemObject *p_systemObject);

+ 1 - 1
Praxis3D/Source/SkyPass.h

@@ -58,7 +58,7 @@ public:
 		m_renderer.m_backend.getGeometryBuffer()->bindBufferForWriting(p_renderPassData.getColorOutputMap());
 
 		// Perform various visual effects in the post process shader
-		m_renderer.queueForDrawing(m_skyPassShader->getShaderHandle(), m_skyPassShader->getUniformUpdater(), p_sceneObjects.m_camera.m_viewData.m_transformMat);
+		m_renderer.queueForDrawing(m_skyPassShader->getShaderHandle(), m_skyPassShader->getUniformUpdater(), p_sceneObjects.m_camera.m_spatialData.m_transformMat);
 		
 		// Pass the draw command so it is executed
 		m_renderer.passScreenSpaceDrawCommandsToBackend();

+ 1 - 1
Praxis3D/Source/SolarTimeScript.h

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

+ 1 - 10
Praxis3D/Source/SpatialDataManager.h

@@ -27,16 +27,7 @@ public:
 		m_localTransformUpToDate = true;
 		m_worldTransformUpToDate = true;
 
-		//worldSpaceNeedsUpdate = false;
-		//localTransformNeedsUpdate = false;
-		//parentTransformNeedsUpdate = false;
-		//worldTransformNeedsUpdate = false;
-
-		//localEulerUpToDate = true;
-		//localQuaternionUpToDate = true;
-
-		//worldEulerUpToDate = true;
-		//worldQuaternionUpToDate = true;
+		m_changes = Systems::Changes::None;
 	}
 	~SpatialDataManager()
 	{

+ 10 - 10
Praxis3D/Source/Window.cpp

@@ -303,19 +303,19 @@ void Window::handleSDLEvent(const SDL_Event &p_SDLEvent)
 		switch(p_SDLEvent.button.button)
 		{
 		case(SDL_BUTTON_LEFT) :
-			m_binds[MouseBindingIndex::Mouse_left_index].activate();
+			m_binds[Scancode::Mouse_left].activate();
 			break;
 		case(SDL_BUTTON_RIGHT) :
-			m_binds[MouseBindingIndex::Mouse_right_index].activate();
+			m_binds[Scancode::Mouse_right].activate();
 			break;
 		case(SDL_BUTTON_MIDDLE) :
-			m_binds[MouseBindingIndex::Mouse_middle_index].activate();
+			m_binds[Scancode::Mouse_middle].activate();
 			break;
 		case(SDL_BUTTON_X1) :
-			m_binds[MouseBindingIndex::Mouse_x1_index].activate();
+			m_binds[Scancode::Mouse_x1].activate();
 			break;
 		case(SDL_BUTTON_X2) :
-			m_binds[MouseBindingIndex::Mouse_x2_index].activate();
+			m_binds[Scancode::Mouse_x2].activate();
 			break;
 		}
 		break;
@@ -326,19 +326,19 @@ void Window::handleSDLEvent(const SDL_Event &p_SDLEvent)
 		switch(p_SDLEvent.button.button)
 		{
 		case(SDL_BUTTON_LEFT) :
-			m_binds[MouseBindingIndex::Mouse_left_index].deactivate();
+			m_binds[Scancode::Mouse_left].deactivate();
 			break;
 		case(SDL_BUTTON_RIGHT) :
-			m_binds[MouseBindingIndex::Mouse_right_index].deactivate();
+			m_binds[Scancode::Mouse_right].deactivate();
 			break;
 		case(SDL_BUTTON_MIDDLE) :
-			m_binds[MouseBindingIndex::Mouse_middle_index].deactivate();
+			m_binds[Scancode::Mouse_middle].deactivate();
 			break;
 		case(SDL_BUTTON_X1) :
-			m_binds[MouseBindingIndex::Mouse_x1_index].deactivate();
+			m_binds[Scancode::Mouse_x1].deactivate();
 			break;
 		case(SDL_BUTTON_X2) :
-			m_binds[MouseBindingIndex::Mouse_x2_index].deactivate();
+			m_binds[Scancode::Mouse_x2].deactivate();
 			break;
 		}
 		break;

+ 6 - 0
Praxis3D/Source/Window.h

@@ -84,6 +84,9 @@ public:
 	}
 	inline void bindCommand(const Scancode p_scancode, KeyCommand *p_command)
 	{
+		// Block calls from other threads
+		SpinWait::Lock lock(m_spinMutex);
+
 		// Bind the command by directly accessing the array
 		m_binds[p_scancode].bind(p_command);
 	}
@@ -532,4 +535,7 @@ private:
 
 	// Ties scancodes and their names together, so we could match a key by it's name
 	std::unordered_map<std::string, Scancode> m_scancodeNames;
+
+	// Mutex used for multithreaded calls
+	SpinWait m_spinMutex;
 };

+ 12 - 12
Praxis3D/Source/WorldEditObject.h

@@ -247,7 +247,7 @@ public:
 	inline void setForwardKey(std::string &p_string)
 	{
 		m_forwardKey.unbindAll();
-		m_forwardKey.bindByKeyName(p_string);
+		m_forwardKey.bind(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.bindByKeyName(p_string);
+		m_backwardKey.bind(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.bindByKeyName(p_string);
+		m_upKey.bind(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.bindByKeyName(p_string);
+		m_downKey.bind(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.bindByKeyName(p_string);
+		m_leftKey.bind(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.bindByKeyName(p_string);
+		m_rightKey.bind(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.bindByKeyName(p_string);
+		m_nextKey.bind(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.bindByKeyName(p_string);
+		m_previousKey.bind(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.bindByKeyName(p_string);
+		m_fasterMovementKey.bind(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.bindByKeyName(p_string);
+		m_centerKey.bind(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.bindByKeyName(p_string);
+		m_saveKey.bind(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.bindByKeyName(p_string);
+		m_modifierKey.bind(p_string);
 	}
 
 private:

+ 10 - 1
Praxis3D/Source/WorldScene.cpp

@@ -176,7 +176,16 @@ SystemObject *WorldScene::createObject(const PropertySet &p_properties)
 		{
 			auto graphicsObject = m_sceneLoader->getSystemScene(Systems::Graphics)->createObject(p_properties);
 			if(graphicsObject != nullptr && graphicsObject->getSystemType() != Systems::Null)
-				newGameObject->addComponent(static_cast<GraphicsObject*>(graphicsObject));
+				newGameObject->addComponent(static_cast<GraphicsObject *>(graphicsObject));
+		}
+
+		// Add a GUIObject as a component if the Rendering property is present
+		auto &guiProperty = p_properties.getPropertySetByID(Properties::GUI);
+		if(guiProperty)
+		{
+			auto guiProperty = m_sceneLoader->getSystemScene(Systems::GUI)->createObject(p_properties);
+			if(guiProperty != nullptr && guiProperty->getSystemType() != Systems::Null)
+				newGameObject->addComponent(static_cast<GUIObject *>(guiProperty));
 		}
 
 		// Add a ScriptObject as a component if the Script property is present

+ 0 - 0
Praxis3D/x64/Release/Praxis3D.vcxproj.FileListAbsolute.txt