Procházet zdrojové kódy

Added engine states; AudioScene; data-driven rendering passes

Added MainMenu engine state; moved all system and scene creation form Engine to EngineState, so each state has it's own copy of systems and entity registry
Added an empty Audio system (system, scene, task, component creation info, component importing, PropertyIDs), to be implemented later
Added a way to define rendering passes and their order in map files, so each state can have a different setup
Added more GUI and engine bindings to Lua scripts
Added a mainMenu Lua script that draws windowless buttons and can change the current EngineState
Added a mainMenu map
Added more ErrorCodes and error strings
Removed old unneeded usage of ObjectPools, and rewrote destroyObject methods to be used with entity registry
Fixed a bug of crashing the engine when the entity registry is mostly empty (because creating views of components that have empty pools, create their pools, in effect assigning the same date concurrently and crashing; now the all the pools are created in advance)
Fixed a bug of GUI system crashing the engine if a GUI rendering pass was not added to all the rendering passes
Fixed a bug of returning a reference to temporary data in SpatialDataManager, by calculating the data on the spot to a mutable container
Paul A před 3 roky
rodič
revize
5e70c8d253
44 změnil soubory, kde provedl 1450 přidání a 394 odebrání
  1. 1 0
      .gitignore
  2. binární
      Builds/x64/Debug/Praxis3D.exe
  3. 30 0
      Praxis3D/Data/Maps/componentTest.pmap
  4. 101 0
      Praxis3D/Data/Maps/mainMenu.pmap
  5. 84 0
      Praxis3D/Data/Scripts/MainMenu.lua
  6. 2 1
      Praxis3D/Data/Scripts/Window_controls.lua
  7. 4 0
      Praxis3D/Data/error-strings-eng.data
  8. 8 0
      Praxis3D/Praxis3D.vcxproj
  9. 36 0
      Praxis3D/Praxis3D.vcxproj.filters
  10. 195 0
      Praxis3D/Source/AudioScene.cpp
  11. 69 0
      Praxis3D/Source/AudioScene.h
  12. 66 0
      Praxis3D/Source/AudioSystem.h
  13. 15 0
      Praxis3D/Source/AudioTask.cpp
  14. 22 0
      Praxis3D/Source/AudioTask.h
  15. 7 0
      Praxis3D/Source/CommonDefinitions.h
  16. 5 0
      Praxis3D/Source/ComponentConstructorInfo.h
  17. 10 2
      Praxis3D/Source/Config.cpp
  18. 38 5
      Praxis3D/Source/Config.h
  19. 14 82
      Praxis3D/Source/Engine.cpp
  20. 39 10
      Praxis3D/Source/Engine.h
  21. 172 0
      Praxis3D/Source/EngineState.cpp
  22. 28 4
      Praxis3D/Source/EngineState.h
  23. 4 0
      Praxis3D/Source/ErrorCodes.h
  24. 2 2
      Praxis3D/Source/GUIPass.h
  25. 74 40
      Praxis3D/Source/GUIScene.cpp
  26. 2 30
      Praxis3D/Source/GUIScene.h
  27. 26 2
      Praxis3D/Source/LuaScript.cpp
  28. 29 0
      Praxis3D/Source/LuaScript.h
  29. 42 0
      Praxis3D/Source/MainMenuState.cpp
  30. 20 0
      Praxis3D/Source/MainMenuState.h
  31. 10 1
      Praxis3D/Source/PhysicsScene.cpp
  32. 9 56
      Praxis3D/Source/PlayState.cpp
  33. 3 9
      Praxis3D/Source/PlayState.h
  34. 106 15
      Praxis3D/Source/RendererFrontend.cpp
  35. 8 1
      Praxis3D/Source/RendererFrontend.h
  36. 13 4
      Praxis3D/Source/RendererScene.cpp
  37. 43 0
      Praxis3D/Source/RendererSystem.cpp
  38. 39 1
      Praxis3D/Source/SceneLoader.cpp
  39. 2 0
      Praxis3D/Source/SceneLoader.h
  40. 31 17
      Praxis3D/Source/ScriptScene.cpp
  41. 0 30
      Praxis3D/Source/ScriptScene.h
  42. 4 1
      Praxis3D/Source/SpatialDataManager.h
  43. 26 52
      Praxis3D/Source/WorldScene.cpp
  44. 11 29
      Praxis3D/Source/WorldScene.h

+ 1 - 0
.gitignore

@@ -34,3 +34,4 @@ Builds/x64/Debug/Praxis3D.lib
 Praxis3D/x64/Debug/CodeAnalysisResultManifest.txt
 .vs/
 Builds/x64/Debug/Praxis3D.exe
+Builds/x64/Debug/Praxis3D.exe

binární
Builds/x64/Debug/Praxis3D.exe


+ 30 - 0
Praxis3D/Data/Maps/componentTest.pmap

@@ -419,6 +419,36 @@
 			"Scene":
 			{
 				"ObjectPoolSize": "50"
+			},
+			"System":
+			{
+				"RenderPasses":
+				[
+					{
+						"Type": "GeometryRenderPass"
+					},
+					{
+						"Type": "AtmScatteringRenderPass"
+					},
+					{
+						"Type": "LightingRenderPass"
+					},
+					{
+						"Type": "AtmScatteringRenderPass"
+					},
+					{
+						"Type": "BloomRenderPass"
+					},
+					{
+						"Type": "LuminanceRenderPass"
+					},
+					{
+						"Type": "FinalRenderPass"
+					},
+					{
+						"Type": "GUIRenderPass"
+					}
+				]
 			}
 		},
 		"Script":

+ 101 - 0
Praxis3D/Data/Maps/mainMenu.pmap

@@ -0,0 +1,101 @@
+{
+	"GameObject":
+	[
+		{
+			"Name": "root",
+			"ID": "0",
+			"World":
+			{
+				"SpatialComponent":
+				{
+					"LocalPosition": "0.0f, 0.0f, 0.0f",
+					"LocalRotation": "0.0f, 0.0f, 0.0f",
+					"LocalScale": "1.0f, 1.0f, 1.0f"
+				}
+			},
+			"Script":
+			{
+				"LuaComponent":
+				{
+					"Filename": "Window_controls.lua"
+				}
+			}
+		},
+		{
+			"Name": "GUI",
+			"ID": "1",
+			"Parent": "0",
+			"GUI":
+			{
+				"Sequence":
+				{
+
+				}
+			},
+			"Script":
+			{
+				"LuaComponent":
+				{
+					"Filename": "MainMenu.lua"
+				}
+			}
+		}
+	],
+	"LoadInBackground": "0",
+	"Systems":
+	{
+		"Graphics":
+		{
+			"Scene":
+			{
+				"ObjectPoolSize": "50"
+			},
+			"System":
+			{
+				"RenderPasses":
+				[
+					{
+						"Type": "GeometryRenderPass"
+					},
+					{
+						"Type": "LightingRenderPass"
+					},
+					{
+						"Type": "BloomRenderPass"
+					},
+					{
+						"Type": "LuminanceRenderPass"
+					},
+					{
+						"Type": "FinalRenderPass"
+					},
+					{
+						"Type": "GUIRenderPass"
+					}
+				]
+			}
+		},
+		"Script":
+		{
+			"Scene":
+			{
+				"ObjectPoolSize": "50"
+			}
+		},
+		"Physics":
+		{
+			"Scene":
+			{
+				"ObjectPoolSize": "50",
+				"Gravity": "0.0f, -9.8f, 0.0f"
+			}
+		},
+		"World":
+		{
+			"Scene":
+			{
+				"ObjectPoolSize": "50"
+			}
+		}
+	}
+}

+ 84 - 0
Praxis3D/Data/Scripts/MainMenu.lua

@@ -0,0 +1,84 @@
+
+function init ()
+	-- Create needed variables
+	create(Types.EngineVariables, 'engineVariables');
+	create(Types.GraphicsVariables, 'graphicsVariables');
+	create(Types.InputVariables, 'inputVariables');
+	create(Types.WindowVariables, 'windowVariables');
+	
+	create(Types.Conditional, 'loadButton')
+	create(Types.Conditional, 'playButton')
+	create(Types.Conditional, 'optionsButton')
+	create(Types.Conditional, 'exitButton')
+	create(Types.Conditional, 'checkbox1')
+	
+	buttonSizeX = 100.0
+	buttonSizeY = 25.0
+	
+	buttonHalfSizeX = buttonSizeX / 2
+	buttonHalfSizeY = buttonSizeY / 2
+	
+	buttonOffsetMultX = 1
+	buttonOffsetMultY = 1.75
+	
+	buttonSpacing = 5
+	
+	print('MainMenu.lua script initialized.')
+end
+	
+function update (p_deltaTime)
+	-- Make sure the mouse is released, so the buttons can be pressed
+	setMouseCapture(false)
+	
+	-- Calculate the starting position for the buttons (relative to window size, not absolute, so the buttons are always in the right place)
+	halfScreenSizeX = (graphicsVariables.current_resolution_x / 2.0) * buttonOffsetMultX
+	halfScreenSizeY = (graphicsVariables.current_resolution_y / 2.0) * buttonOffsetMultY
+	
+	-- Draw the EXIT button
+	GUI.SetNextWindowPos(halfScreenSizeX - buttonHalfSizeX, halfScreenSizeY - buttonHalfSizeY)
+	GUI.Begin('EXIT BTN', bitwiseOr(ImGuiWindowFlags.NoDecoration, ImGuiWindowFlags.NoMove, ImGuiWindowFlags.NoSavedSettings, ImGuiWindowFlags.NoBackground))
+	GUI.Button('EXIT', buttonSizeX, buttonSizeY, exitButton)
+	GUI.End()
+	
+	-- Draw the OPTIONS button
+	GUI.SetNextWindowPos(halfScreenSizeX - buttonHalfSizeX, halfScreenSizeY - buttonHalfSizeY - (buttonSpacing + buttonSizeY))
+	GUI.Begin('OPTIONS BTN', bitwiseOr(ImGuiWindowFlags.NoDecoration, ImGuiWindowFlags.NoMove, ImGuiWindowFlags.NoSavedSettings, ImGuiWindowFlags.NoBackground))
+	GUI.Button('OPTIONS', buttonSizeX, buttonSizeY, optionsButton)
+	GUI.End()
+	
+	-- Draw the PLAY button
+	GUI.SetNextWindowPos(halfScreenSizeX - buttonHalfSizeX, halfScreenSizeY - buttonHalfSizeY - ((buttonSpacing + buttonSizeY) * 2))
+	GUI.Begin('PLAY BTN', bitwiseOr(ImGuiWindowFlags.NoDecoration, ImGuiWindowFlags.NoMove, ImGuiWindowFlags.NoSavedSettings, ImGuiWindowFlags.NoBackground))
+	GUI.Button('PLAY', buttonSizeX, buttonSizeY, playButton)
+	GUI.End()
+	
+	-- Draw the LOAD MAP button
+	GUI.SetNextWindowPos(halfScreenSizeX - buttonHalfSizeX, halfScreenSizeY - buttonHalfSizeY - ((buttonSpacing + buttonSizeY) * 3))
+	GUI.Begin('LOAD BTN', bitwiseOr(ImGuiWindowFlags.NoDecoration, ImGuiWindowFlags.NoMove, ImGuiWindowFlags.NoSavedSettings, ImGuiWindowFlags.NoBackground))
+	GUI.Button('LOAD MAP', buttonSizeX, buttonSizeY, loadButton)
+	GUI.End()
+	
+	-- Check if the EXIT button is pressed; close the engine if it is
+	if exitButton:isChecked() then
+		print('Exit called from MainMenu.lua')
+		setEngineRunning(false)
+	end
+	
+	-- Check if the OPTIONS button is pressed
+	if optionsButton:isChecked() then
+		print('OPTIONS')
+	end
+	
+	-- Check if the PLAY button is pressed; change the current engine state to PLAY, if it is
+	if playButton:isChecked() then
+		setEngineState(EngineStateType.Play)
+		setMouseCapture(true)
+	end
+	
+	-- Check if the LOAD button is pressed
+	if loadButton:isChecked() then
+		print('LOAD')
+	end
+	
+	--print('test')
+end

+ 2 - 1
Praxis3D/Data/Scripts/Window_controls.lua

@@ -29,7 +29,8 @@ function update (p_deltaTime)
 		
 	if closeKey:isActivated() then
 		-- Set the engine running state to false, so it is shutdown the next frame
-		setEngineRunning(false)
+		--setEngineRunning(false)
+		setEngineState(EngineStateType.MainMenu)
 	end	
 	
 	if fullscreenKey:isActivated() then

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

@@ -45,6 +45,9 @@
 		"Source_Unknown"									: "Unknown",
 		"Source_General"									: "General",
 		"Source_AtmScatteringPass"				: "Atmosphere Scattering Rendering Pass",
+		"Source_AudioScene"								: "Audio Scene",
+		"Source_AudioSystem"							: "Audio System",
+		"Source_AudioTask"								: "Audio Task",
 		"Source_BloomCompositePass"				: "Bloom Effect Composite Rendering Pass",
 		"Source_BloomPass"								: "Bloom Effect Rendering Pass",
 		"Source_BlurPass"									: "Blur Effect Rendering Pass",
@@ -61,6 +64,7 @@
 		"Source_GraphicsObject"						: "Graphics Object",
 		"Source_GUI"											: "GUI",
 		"Source_GUIObject"								: "GUI Object",
+		"Source_GUIPass"									: "GUI Rendering Pass",
 		"Source_GUISequenceComponent"			: "GUI Sequence Component",
 		"Source_HdrMappingPass"						: "HDR Mapping Rendering Pass",
 		"Source_LensFlareCompositePass"		: "Lens Flare Effect Composite Rendering Pass",

+ 8 - 0
Praxis3D/Praxis3D.vcxproj

@@ -138,6 +138,8 @@
     <ClCompile Include="main.cpp" />
     <ClCompile Include="Source\AtmScatteringModel.cpp" />
     <ClCompile Include="Source\AtmScatteringPass.cpp" />
+    <ClCompile Include="Source\AudioScene.cpp" />
+    <ClCompile Include="Source\AudioTask.cpp" />
     <ClCompile Include="Source\BaseGraphicsComponent.cpp" />
     <ClCompile Include="Source\BaseGraphicsObjects.cpp" />
     <ClCompile Include="Source\ChangeController.cpp" />
@@ -146,6 +148,7 @@
     <ClCompile Include="Source\ConfigLoader.cpp" />
     <ClCompile Include="Source\DeferredRenderer.cpp" />
     <ClCompile Include="Source\Engine.cpp" />
+    <ClCompile Include="Source\EngineState.cpp" />
     <ClCompile Include="Source\ErrorCodes.cpp" />
     <ClCompile Include="Source\ErrorHandler.cpp" />
     <ClCompile Include="Source\ErrorHandlerLocator.cpp" />
@@ -159,6 +162,7 @@
     <ClCompile Include="Source\LightComponent.cpp" />
     <ClCompile Include="Source\Loaders.cpp" />
     <ClCompile Include="Source\LuaScript.cpp" />
+    <ClCompile Include="Source\MainMenuState.cpp" />
     <ClCompile Include="Source\Math.cpp" />
     <ClCompile Include="Source\ModelLoader.cpp" />
     <ClCompile Include="Source\NullObjects.cpp" />
@@ -212,6 +216,9 @@
     <ClInclude Include="Source\AtmScatteringShaderDefinitions.h" />
     <ClInclude Include="Source\AtmScatteringShaderFunctions.h" />
     <ClInclude Include="Source\AtmScatteringShaderPass.h" />
+    <ClInclude Include="Source\AudioScene.h" />
+    <ClInclude Include="Source\AudioSystem.h" />
+    <ClInclude Include="Source\AudioTask.h" />
     <ClInclude Include="Source\BaseGraphicsComponent.h" />
     <ClInclude Include="Source\BaseGraphicsObjects.h" />
     <ClInclude Include="Source\BaseScriptObject.h" />
@@ -278,6 +285,7 @@
     <ClInclude Include="Source\LuaComponent.h" />
     <ClInclude Include="Source\LuaScript.h" />
     <ClInclude Include="Source\LuminancePass.h" />
+    <ClInclude Include="Source\MainMenuState.h" />
     <ClInclude Include="Source\Math.h" />
     <ClInclude Include="Source\ModelComponent.h" />
     <ClInclude Include="Source\ModelLoader.h" />

+ 36 - 0
Praxis3D/Praxis3D.vcxproj.filters

@@ -175,6 +175,18 @@
     <Filter Include="Data Managers">
       <UniqueIdentifier>{1d4c199c-6fd9-492b-9c8d-23af455d408f}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Audio">
+      <UniqueIdentifier>{b0af423c-ca96-4651-8735-d17c9593c49e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Audio\Header Files">
+      <UniqueIdentifier>{fb7679a3-0a75-473e-9935-b7fdf9cf027f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Audio\Source Files">
+      <UniqueIdentifier>{f3cfd48d-1244-403a-abd6-62cda62bf679}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Audio\Components">
+      <UniqueIdentifier>{de63b868-204f-4f5a-9bf7-56e48e541097}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="main.cpp">
@@ -381,6 +393,18 @@
     <ClCompile Include="Source\GUIHandler.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\AudioScene.cpp">
+      <Filter>Audio\Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\AudioTask.cpp">
+      <Filter>Audio\Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\MainMenuState.cpp">
+      <Filter>Engine States\Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\EngineState.cpp">
+      <Filter>Engine States\Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Source\ErrorCodes.h">
@@ -812,6 +836,18 @@
     <ClInclude Include="Source\ComponentConstructorInfo.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Source\AudioScene.h">
+      <Filter>Audio\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\AudioTask.h">
+      <Filter>Audio\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\AudioSystem.h">
+      <Filter>Audio\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Source\MainMenuState.h">
+      <Filter>Engine States\Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="Data\config.ini" />

+ 195 - 0
Praxis3D/Source/AudioScene.cpp

@@ -0,0 +1,195 @@
+
+#include "AudioScene.h"
+#include "ComponentConstructorInfo.h"
+#include "NullSystemObjects.h"
+#include "TaskManagerLocator.h"
+#include "WorldScene.h"
+
+AudioScene::AudioScene(SystemBase *p_system, SceneLoader *p_sceneLoader) : SystemScene(p_system, p_sceneLoader)
+{
+	m_audioTask = nullptr;
+}
+
+AudioScene::~AudioScene()
+{
+}
+
+ErrorCode AudioScene::init()
+{
+	m_audioTask = new AudioTask(this);
+
+	return ErrorCode::Success;
+}
+
+ErrorCode AudioScene::setup(const PropertySet &p_properties)
+{
+	for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
+	{
+		switch(p_properties[i].getPropertyID())
+		{
+		case Properties::ObjectPoolSize:
+
+			break;
+		case Properties::Gravity:
+			//m_dynamicsWorld->setGravity(Math::toBtVector3(p_properties[i].getVec3f()));
+			break;
+		}
+	}
+
+	return ErrorCode::Success;
+}
+
+void AudioScene::update(const float p_deltaTime)
+{
+	//std::cout << "1 Audio update" << std::endl;
+	//printf("1 Audio \n");
+
+	// Get the world scene required for getting the entity registry
+	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+
+	// Get the entity registry 
+	auto &entityRegistry = worldScene->getEntityRegistry();
+
+	// Get the rigid body component view and iterate every entity that contains is
+	/*auto rigidBodyView = worldScene->getEntityRegistry().view<RigidBodyComponent>();
+	for(auto entity : rigidBodyView)
+	{
+		auto &component = rigidBodyView.get<RigidBodyComponent>(entity);
+
+		component.update(p_deltaTime);
+	}*/
+}
+
+ErrorCode AudioScene::preload()
+{
+	return ErrorCode::Success;
+}
+
+void AudioScene::loadInBackground()
+{
+}
+
+std::vector<SystemObject*> AudioScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading)
+{
+	return createComponents(p_entityID, p_constructionInfo.m_audioComponents, p_startLoading);
+}
+
+/*SystemObject *AudioScene::createComponent(const EntityID &p_entityID, const RigidBodyComponent::RigidBodyComponentConstructionInfo &p_constructionInfo, const bool p_startLoading)
+{
+	// If valid type was not specified, or object creation failed, return a null object instead
+	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();
+
+	// Get the world scene required for attaching components to the entity
+	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+
+	auto &component = worldScene->addComponent<RigidBodyComponent>(p_entityID, this, p_constructionInfo.m_name, p_entityID);
+
+	// Try to initialize the camera component
+	auto componentInitError = component.init();
+	if(componentInitError == ErrorCode::Success)
+	{
+		component.m_collisionShapeType = p_constructionInfo.m_collisionShapeType;
+		component.m_kinematic = p_constructionInfo.m_kinematic;
+		component.m_objectType = Properties::PropertyID::RigidBodyComponent;
+		component.setActive(p_constructionInfo.m_active);
+		component.setLoadedToMemory(true);
+		component.setLoadedToVideoMemory(true);
+
+		if(component.m_collisionShapeType != RigidBodyComponent::CollisionShapeType::CollisionShapeType_Null)
+		{
+			switch(component.m_collisionShapeType)
+			{
+			case RigidBodyComponent::CollisionShapeType::CollisionShapeType_Box:
+			{
+				btVector3 boxHalfExtents = Math::toBtVector3(p_constructionInfo.m_collisionShapeSize);
+				component.m_collisionShape.m_boxShape = new btBoxShape(boxHalfExtents);
+			}
+			break;
+
+			case RigidBodyComponent::CollisionShapeType::CollisionShapeType_Sphere:
+			{
+				float radius = p_constructionInfo.m_collisionShapeSize.x;
+				component.m_collisionShape.m_sphereShape = new btSphereShape(radius);
+			}
+			break;
+			}
+
+			// Success on the loaded collision shape
+			ErrHandlerLoc().get().log(ErrorType::Info, ErrorSource::Source_RigidBodyComponent, component.getName() + " - Collision shape loaded");
+
+			// Create the struct that holds all the required information for constructing a rigid body
+			component.m_constructionInfo = new btRigidBody::btRigidBodyConstructionInfo(p_constructionInfo.m_mass, &component.m_motionState, component.getCollisionShape());
+
+			component.m_constructionInfo->m_friction = p_constructionInfo.m_friction;
+			component.m_constructionInfo->m_restitution = p_constructionInfo.m_restitution;
+
+			// If mass is not zero, rigid body is dynamic; in that case, calculate the local inertia 
+			if(component.m_constructionInfo->m_mass != 0.0f)
+			{
+				// Kinematic objects must have a mass of zero
+				if(component.m_kinematic)
+				{
+					component.m_constructionInfo->m_mass = 0.0f;
+					ErrHandlerLoc().get().log(ErrorCode::Kinematic_has_mass, component.getName(), ErrorSource::Source_RigidBodyComponent);
+				}
+				else
+					component.getCollisionShape()->calculateLocalInertia(component.m_constructionInfo->m_mass, component.m_constructionInfo->m_localInertia);
+			}
+
+			// Set the body origin in space to the position in Spatial Component, if the Spatial Component is present
+			auto *spatialComponent = worldScene->getEntityRegistry().try_get<SpatialComponent>(p_entityID);
+			if(spatialComponent != nullptr)
+			{
+				btTransform groundTransform;
+				groundTransform.setIdentity();
+				groundTransform.setOrigin(Math::toBtVector3(spatialComponent->getSpatialDataChangeManager().getLocalSpaceData().m_spatialData.m_position));
+				groundTransform.setRotation(Math::toBtQuaternion(spatialComponent->getSpatialDataChangeManager().getLocalSpaceData().m_spatialData.m_rotationQuat));
+				//groundTransform.setFromOpenGLMatrix(&spatialComponent->getSpatialDataChangeManager().getLocalSpaceData().m_transformMat[0][0]);
+				component.m_motionState.setWorldTransform(groundTransform);
+
+				component.m_motionState.updateMotionStateTrans();
+			}
+
+			// Add the collision shape
+			m_collisionShapes.push_back(component.getCollisionShape());
+
+			// Create the rigid body by passing the rigid body construction info
+			component.m_rigidBody = new btRigidBody(*component.m_constructionInfo);
+
+			if(component.m_kinematic)
+			{
+				component.m_rigidBody->setCollisionFlags(component.m_rigidBody->getCollisionFlags() | btCollisionObject::CollisionFlags::CF_KINEMATIC_OBJECT);
+				component.m_rigidBody->setActivationState(DISABLE_DEACTIVATION);
+			}
+
+			// Set linear velocity if it is not zero
+			if(p_constructionInfo.m_linearVelocity != glm::vec3())
+				component.m_rigidBody->setLinearVelocity(Math::toBtVector3(p_constructionInfo.m_linearVelocity));
+
+			// Add the rigid body to the dynamics world, essentially loading it into the physics system
+			m_dynamicsWorld->addRigidBody(component.m_rigidBody);
+
+			returnObject = &component;
+
+		}
+		else // Remove the component if it didn't have a collision shape
+		{
+			// Missing the collision shape
+			worldScene->removeComponent<RigidBodyComponent>(p_entityID);
+			ErrHandlerLoc().get().log(ErrorCode::Collision_missing, component.getName(), ErrorSource::Source_RigidBodyComponent);
+		}
+	}
+	else // Remove the component if it failed to initialize
+	{
+		worldScene->removeComponent<RigidBodyComponent>(p_entityID);
+		ErrHandlerLoc().get().log(componentInitError, ErrorSource::Source_RigidBodyComponent, component.getName());
+	}
+
+	return returnObject;
+}*/
+
+ErrorCode AudioScene::destroyObject(SystemObject *p_systemObject)
+{
+	// If this point is reached, no object was found, return an appropriate error
+	return ErrorCode::Destroy_obj_not_found;
+}

+ 69 - 0
Praxis3D/Source/AudioScene.h

@@ -0,0 +1,69 @@
+#pragma once
+
+#include "AUdioTask.h"
+#include "System.h"
+
+struct ComponentsConstructionInfo;
+
+struct AudioComponentsConstructionInfo
+{
+	AudioComponentsConstructionInfo()
+	{
+		//m_rigidBodyConstructionInfo = nullptr;
+	}
+
+	// Perform a complete copy, instantiating (with new) every member variable pointer, instead of just assigning the pointer to the same memory
+	void completeCopy(const AudioComponentsConstructionInfo &p_other)
+	{
+		//Utilities::performCopy<RigidBodyComponent::RigidBodyComponentConstructionInfo>(&m_rigidBodyConstructionInfo, &p_other.m_rigidBodyConstructionInfo);
+	}
+
+	void deleteConstructionInfo()
+	{
+		//if(m_rigidBodyConstructionInfo != nullptr)
+		//	delete m_rigidBodyConstructionInfo;
+	}
+
+	//RigidBodyComponent::RigidBodyComponentConstructionInfo *m_rigidBodyConstructionInfo;
+};
+
+class AudioScene : public SystemScene
+{
+public:
+	AudioScene(SystemBase *p_system, SceneLoader *p_sceneLoader);
+	~AudioScene();
+
+	ErrorCode init();
+
+	ErrorCode setup(const PropertySet &p_properties);
+
+	void update(const float p_deltaTime);
+
+	ErrorCode preload();
+
+	void loadInBackground();
+
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const AudioComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true)
+	{
+		std::vector<SystemObject*> components;
+
+		//if(p_constructionInfo.m_rigidBodyConstructionInfo != nullptr)
+		//	components.push_back(createComponent(p_entityID, *p_constructionInfo.m_rigidBodyConstructionInfo, p_startLoading));
+
+		return components;
+	}
+
+	//SystemObject *createComponent(const EntityID &p_entityID, const RigidBodyComponent::RigidBodyComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
+	ErrorCode destroyObject(SystemObject *p_systemObject);
+
+	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) { }
+
+	SystemTask *getSystemTask() { return m_audioTask; };
+	Systems::TypeID getSystemType() { return Systems::TypeID::Audio; };
+	BitMask getDesiredSystemChanges() { return Systems::Changes::Generic::CreateObject || Systems::Changes::Generic::DeleteObject; }
+	BitMask getPotentialSystemChanges() { return Systems::Changes::None; }
+
+private:
+	AudioTask *m_audioTask;
+};

+ 66 - 0
Praxis3D/Source/AudioSystem.h

@@ -0,0 +1,66 @@
+#pragma once
+
+#include "AudioScene.h"
+#include "ErrorHandlerLocator.h"
+#include "System.h"
+
+class AudioSystem : public SystemBase
+{
+public:
+	AudioSystem()
+	{
+		m_audioScene = nullptr;
+		m_systemName = GetString(Systems::Audio);
+	}
+	~AudioSystem() { }
+
+	ErrorCode init()
+	{
+		ErrorCode returnCode = ErrorCode::Success;
+
+		ErrHandlerLoc::get().log(ErrorCode::Initialize_success, ErrorSource::Source_AudioSystem);
+
+		return returnCode;
+	}
+
+	ErrorCode setup(const PropertySet &p_properties)
+	{
+		ErrorCode returnCode = ErrorCode::Success;
+
+		return returnCode;
+	}
+
+	virtual ErrorCode preload()
+	{
+		ErrorCode returnCode = ErrorCode::Success;
+
+		return returnCode;
+	}
+
+	void loadInBackground() { }
+
+	Systems::TypeID getSystemType() { return Systems::Audio; }
+
+	SystemScene *createScene(SceneLoader *p_sceneLoader)
+	{
+		if(m_audioScene == nullptr)
+		{
+			// Create new scene
+			m_audioScene = new AudioScene(this, p_sceneLoader);
+			ErrorCode sceneError = m_audioScene->init();
+
+			// Check if it initialized correctly (cannot continue without the scene)
+			if(sceneError != ErrorCode::Success)
+			{
+				ErrHandlerLoc::get().log(sceneError, ErrorSource::Source_AudioScene);
+			}
+		}
+
+		return m_audioScene;
+	}
+
+	SystemScene *getScene() { return m_audioScene; }
+
+protected:
+	AudioScene *m_audioScene;
+};

+ 15 - 0
Praxis3D/Source/AudioTask.cpp

@@ -0,0 +1,15 @@
+#include "AudioScene.h"
+#include "AudioTask.h"
+
+AudioTask::AudioTask(AudioScene *p_audioScene) : SystemTask(p_audioScene), m_audioScene(p_audioScene)
+{
+}
+
+AudioTask::~AudioTask()
+{
+}
+
+void AudioTask::update(const float p_deltaTime)
+{
+	m_audioScene->update(p_deltaTime);
+}

+ 22 - 0
Praxis3D/Source/AudioTask.h

@@ -0,0 +1,22 @@
+#pragma once
+
+#include "System.h"
+
+class AudioScene;
+
+class AudioTask : public SystemTask
+{
+	friend class GUIScene;
+public:
+	AudioTask(AudioScene *p_audioScene);
+	~AudioTask();
+
+	Systems::TypeID getSystemType() { return Systems::Audio; }
+
+	void update(const float p_deltaTime);
+
+	bool isPrimaryThreadOnly() { return false; }
+
+private:
+	AudioScene *m_audioScene;
+};

+ 7 - 0
Praxis3D/Source/CommonDefinitions.h

@@ -9,6 +9,12 @@ typedef std::vector<std::function<void()>> Functors;
 
 constexpr EntityID NULL_ENTITY_ID = std::numeric_limits<EntityID>::max();
 
+enum EngineStateType : unsigned int
+{
+	EngineStateType_MainMenu = 0,
+	EngineStateType_Play
+};
+
 enum BindCommandType : unsigned int
 {
 	BindCommandType_Texture,
@@ -120,6 +126,7 @@ enum ModelBufferType : unsigned int
 	ModelBuffer_Index = ModelBuffer_NumTypesWithoutIndex,
 	ModelBuffer_NumAllTypes
 };
+
 enum AtmScatteringTextureType : unsigned int
 {
 	AtmScatteringTextureType_Irradiance = MaterialType_NumOfTypes_Extended,

+ 5 - 0
Praxis3D/Source/ComponentConstructorInfo.h

@@ -1,5 +1,6 @@
 #pragma once
 
+#include "AudioScene.h"
 #include "CommonDefinitions.h"
 #include "GUIScene.h"
 #include "RendererScene.h"
@@ -27,6 +28,7 @@ struct ComponentsConstructionInfo
 		m_id = p_other.m_id;
 		m_parent = p_other.m_parent;
 
+		m_audioComponents = p_other.m_audioComponents;
 		m_graphicsComponents = p_other.m_graphicsComponents;
 		m_guiComponents = p_other.m_guiComponents;
 		m_physicsComponents = p_other.m_physicsComponents;
@@ -43,6 +45,7 @@ struct ComponentsConstructionInfo
 		m_id = p_other.m_id;
 		m_parent = p_other.m_parent;
 
+		m_audioComponents.completeCopy(p_other.m_audioComponents);
 		m_graphicsComponents.completeCopy(p_other.m_graphicsComponents);
 		m_guiComponents.completeCopy(p_other.m_guiComponents);
 		m_physicsComponents.completeCopy(p_other.m_physicsComponents);
@@ -52,6 +55,7 @@ struct ComponentsConstructionInfo
 
 	void deleteConstructionInfo()
 	{
+		m_audioComponents.deleteConstructionInfo();
 		m_graphicsComponents.deleteConstructionInfo();
 		m_guiComponents.deleteConstructionInfo();
 		m_physicsComponents.deleteConstructionInfo();
@@ -59,6 +63,7 @@ struct ComponentsConstructionInfo
 		m_worldComponents.deleteConstructionInfo();
 	}
 
+	AudioComponentsConstructionInfo m_audioComponents;
 	GraphicsComponentsConstructionInfo m_graphicsComponents;
 	GUIComponentsConstructionInfo m_guiComponents;
 	PhysicsComponentsConstructionInfo m_physicsComponents;

+ 10 - 2
Praxis3D/Source/Config.cpp

@@ -112,6 +112,8 @@ void Config::init()
 
 	// Game-play variables
 	AddVariablePredef(m_gameplayVar, default_map);
+	AddVariablePredef(m_gameplayVar, main_menu_map);
+	AddVariablePredef(m_gameplayVar, play_map);
 	AddVariablePredef(m_gameplayVar, camera_freelook_speed);
 
 	// Graphics variables
@@ -219,10 +221,16 @@ void Config::init()
 	AddVariablePredef(m_modelVar, optimizeGraph);
 
 	// Object pool variables
+	AddVariablePredef(m_objPoolVar, camera_component_default_pool_size);
+	AddVariablePredef(m_objPoolVar, light_component_default_pool_size);
+	AddVariablePredef(m_objPoolVar, lua_component_default_pool_size);
+	AddVariablePredef(m_objPoolVar, gui_sequence_component_default_pool_size);
+	AddVariablePredef(m_objPoolVar, model_component_default_pool_size);
 	AddVariablePredef(m_objPoolVar, object_pool_size);
-	AddVariablePredef(m_objPoolVar, model_object_pool_size);
 	AddVariablePredef(m_objPoolVar, point_light_pool_size);
-	AddVariablePredef(m_objPoolVar, shader_object_pool_size);
+	AddVariablePredef(m_objPoolVar, regid_body_component_default_pool_size);
+	AddVariablePredef(m_objPoolVar, shader_component_default_pool_size);
+	AddVariablePredef(m_objPoolVar, spatial_component_default_pool_size);
 	AddVariablePredef(m_objPoolVar, spot_light_pool_size);
 
 	// File-path variables

+ 38 - 5
Praxis3D/Source/Config.h

@@ -6,6 +6,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "CommonDefinitions.h"
 #include "ErrorCodes.h"
 #include "EnumFactory.h"
 #include "Utilities.h"
@@ -26,6 +27,7 @@ namespace Systems
 {
 	#define TYPEID(Code) \
 	Code(Null, = -1) \
+	Code(Audio,) \
 	Code(Graphics,) \
 	Code(GUI,) \
 	Code(Physics,) \
@@ -36,6 +38,7 @@ namespace Systems
 
 	const static std::string SystemNames[NumberOfSystems] =
 	{
+		GetString(Audio),
 		GetString(Graphics),
 		GetString(GUI),
 		GetString(Physics),
@@ -149,7 +152,7 @@ namespace Systems
 		}
 		namespace Audio
 		{
-
+			static constexpr BitMask All					= Changes::Type::Audio + Changes::Common::Shared1;
 		}
 		namespace Graphics
 		{
@@ -208,10 +211,13 @@ namespace Properties
 	Code(Objects,) \
 	Code(ObjectPoolSize,) \
 	Code(Scene,) \
+	Code(System,) \
 	Code(Systems,) \
 	Code(Type,) \
 	Code(Value,) \
 	Code(Variables,) \
+	/* Audio */ \
+	Code(Audio,) \
 	/* Geometry */ \
 	Code(OffsetPosition,) \
 	Code(OffsetRotation,) \
@@ -268,6 +274,7 @@ namespace Properties
 	Code(PostProcess,) \
 	Code(Renderer,) \
 	Code(Rendering,) \
+	Code(RenderPasses,) \
 	Code(RMHAO,) \
 	Code(Roughness,) \
 	Code(Shaders,) \
@@ -283,6 +290,14 @@ namespace Properties
 	Code(TextureTilingFactor,) \
 	Code(TextureScale,) \
 	Code(VertexShader,) \
+	/* Graphics rendering passes */ \
+	Code(AtmScatteringRenderPass,) \
+	Code(BloomRenderPass,) \
+	Code(GeometryRenderPass,) \
+	Code(GUIRenderPass,) \
+	Code(LightingRenderPass,) \
+	Code(LuminanceRenderPass,) \
+	Code(FinalRenderPass,) \
 	/* GUI */ \
 	Code(GUI,) \
 	Code(GUIObject,) \
@@ -487,6 +502,7 @@ public:
 			smoothing_tick_samples = 100;
 			running = true;
 			loadingState = true;
+			engineState = EngineStateType::EngineStateType_MainMenu;
 		}
 
 		int change_ctrl_cml_notify_list_reserv;
@@ -502,6 +518,7 @@ public:
 		int smoothing_tick_samples;
 		bool running;
 		bool loadingState;
+		EngineStateType engineState;
 	};
 	struct FramebfrVariables
 	{
@@ -609,10 +626,14 @@ public:
 		GameplayVariables()
 		{
 			default_map = "default.pmap";
+			main_menu_map = "mainMenu.pmap";
+			play_map = "componentTest.pmap";
 			camera_freelook_speed = 10.0f;
 		}
 
 		std::string default_map;
+		std::string main_menu_map;
+		std::string play_map;
 		float camera_freelook_speed;
 	};
 	struct GraphicsVariables
@@ -854,17 +875,29 @@ public:
 	{
 		ObjectPoolVariables()
 		{
+			camera_component_default_pool_size = 5;
+			light_component_default_pool_size = 100;
+			lua_component_default_pool_size = 5;
+			gui_sequence_component_default_pool_size = 5;
+			model_component_default_pool_size = 100;
 			object_pool_size = 50;
-			model_object_pool_size = 20;
 			point_light_pool_size = 50;
-			shader_object_pool_size = 10;
+			regid_body_component_default_pool_size = 100;
+			shader_component_default_pool_size = 5;
+			spatial_component_default_pool_size = 100;
 			spot_light_pool_size = 25;
 		}
 
+		int camera_component_default_pool_size;
+		int light_component_default_pool_size;
+		int lua_component_default_pool_size;
+		int gui_sequence_component_default_pool_size;
+		int model_component_default_pool_size;
 		int object_pool_size;
-		int model_object_pool_size;
 		int point_light_pool_size;
-		int shader_object_pool_size;
+		int regid_body_component_default_pool_size;
+		int shader_component_default_pool_size;
+		int spatial_component_default_pool_size;
 		int spot_light_pool_size;
 	};
 	struct PathsVariables

+ 14 - 82
Praxis3D/Source/Engine.cpp

@@ -4,6 +4,7 @@
 
 #include <iostream>
 
+#include "AudioSystem.h"
 #include "ClockLocator.h"
 #include "Engine.h"
 #include "GUIHandlerLocator.h"
@@ -33,6 +34,8 @@ Engine::Engine()
 	m_changeCtrlScene = nullptr;
 	m_sceneChangeController = nullptr;
 	m_objectChangeController = nullptr;
+	m_currentState = nullptr;
+	m_currentStateType = Config::engineVar().engineState;
 }
 
 Engine::~Engine()
@@ -41,11 +44,6 @@ Engine::~Engine()
 	delete m_taskManager;
 	delete m_errorHandler;
 	delete m_clock;
-
-	// Delete all created systems
-	for(int i = 0; i < Systems::NumberOfSystems; i++)
-		if(m_systems[i]->getSystemType() != Systems::Null)
-			delete m_systems[i];
 }
 
 // Some of the initialization sequences are order sensitive. Do not change the order of calls.
@@ -63,21 +61,15 @@ ErrorCode Engine::init()
 	if(servicesError != ErrorCode::Success)
 		return servicesError;
 
-	// Initialize all engine systems
-	auto systemsError = initSystems();
-	if(systemsError != ErrorCode::Success)
-		return systemsError;
-
 	//  ___________________________________
 	// |								   |
 	// |	ENGINE STATE INITIALIZATION	   |
 	// |___________________________________|
-	// Initialize the play state, return failure if it wasn't successful
-	if(m_playstate.init(m_taskManager, m_systems) == ErrorCode::Success)
-		m_currentState = &m_playstate;
-	else
+	// Set and initialize the current engine state
+	setCurrentStateType();
+	if(!m_currentState->isInitialized())
 		return ErrorCode::Failure;
-	
+
 	// If this point is reached, all initializations passed, mark the engine as initialized
 	m_initialized = true;
 
@@ -102,6 +94,13 @@ void Engine::run()
 		// If engine is still running
 		if(Config::engineVar().running == true)
 		{
+			// Load a different engine state, if it has been changed
+			if(m_currentStateType != Config::engineVar().engineState)
+			{
+				m_currentStateType = Config::engineVar().engineState;
+				setCurrentStateType();
+			}
+
 			// Call update on the current engine state
 			m_currentState->update(*this);
 
@@ -300,73 +299,6 @@ ErrorCode Engine::initServices()
 	return returnError;
 }
 
-ErrorCode Engine::initSystems()
-{
-	ErrorCode returnError = ErrorCode::Success;
-
-	//  __________________________________
-	// |								  |
-	// |  RENDERER SYSTEM INITIALIZATION  |
-	// |__________________________________|
-	// Create graphics system and check if it was successful (if not, assign a null system in it's place)
-	m_systems[Systems::Graphics] = new RendererSystem();
-	if(m_systems[Systems::Graphics]->init() != ErrorCode::Success)
-	{
-		delete m_systems[Systems::Graphics];
-		m_systems[Systems::Graphics] = &g_nullSystemBase;
-	}
-
-	//  ___________________________________
-	// |								   |
-	// |	 GUI SYSTEM INITIALIZATION	   |
-	// |___________________________________|
-	// Create GUI system and check if it was successful (if not, assign a null system in it's place)
-	m_systems[Systems::GUI] = new GUISystem();
-	if(m_systems[Systems::GUI]->init() != ErrorCode::Success)
-	{
-		delete m_systems[Systems::GUI];
-		m_systems[Systems::GUI] = &g_nullSystemBase;
-	}
-
-	//  ___________________________________
-	// |								   |
-	// |   PHYSICS SYSTEM INITIALIZATION   |
-	// |___________________________________|
-	// Create scripting system and check if it was successful (if not, assign a null system in it's place)
-	m_systems[Systems::Physics] = new PhysicsSystem();
-	if(m_systems[Systems::Physics]->init() != ErrorCode::Success)
-	{
-		delete m_systems[Systems::Physics];
-		m_systems[Systems::Physics] = &g_nullSystemBase;
-	}
-
-	//  ___________________________________
-	// |								   |
-	// |  SCRIPTING SYSTEM INITIALIZATION  |
-	// |___________________________________|
-	// Create scripting system and check if it was successful (if not, assign a null system in it's place)
-	m_systems[Systems::Script] = new ScriptSystem();
-	if(m_systems[Systems::Script]->init() != ErrorCode::Success)
-	{
-		delete m_systems[Systems::Script];
-		m_systems[Systems::Script] = &g_nullSystemBase;
-	}
-
-	//  ___________________________________
-	// |								   |
-	// |	WORLD SYSTEM INITIALIZATION	   |
-	// |___________________________________|
-	// Create scripting system and check if it was successful (if not, assign a null system in it's place)
-	m_systems[Systems::World] = new WorldSystem();
-	if(m_systems[Systems::World]->init() != ErrorCode::Success)
-	{
-		delete m_systems[Systems::World];
-		m_systems[Systems::World] = &g_nullSystemBase;
-	}
-
-	return returnError;
-}
-
 void Engine::shutdown()
 {
 	// Shutdown engine states

+ 39 - 10
Praxis3D/Source/Engine.h

@@ -1,14 +1,11 @@
 #pragma once
 
-#ifndef NOMINMAX
-#define NOMINMAX
-#endif
-
 #include "Clock.h"
 #include "Config.h"
 #include "ErrorCodes.h"
 #include "ErrorHandlerLocator.h"
 #include "GUIHandlerLocator.h"
+#include "MainMenuState.h"
 #include "PlayState.h"
 #include "TaskManager.h"
 #include "Window.h"
@@ -27,19 +24,54 @@ public:
 	void run();
 
 private:
+	// Sets which engine state is currently active
+	void setCurrentStateType()
+	{
+		EngineState *previousState = m_currentState;
+
+		// Set the current state
+		switch(m_currentStateType)
+		{
+		case EngineStateType_MainMenu:
+			m_currentState = &m_mainMenuState;
+			break;
+
+		case EngineStateType_Play:
+			m_currentState = &m_playstate;
+			break;
+
+		default:
+			m_currentStateType = m_currentState->getEngineStateType();
+			break;
+		}
+
+		if(!m_currentState->isInitialized())
+		{
+			// Initialize the current state
+			ErrorCode stateInitError = m_currentState->init(m_taskManager);
+
+			// If it failed to initialize, return to the previous state and log an error
+			if(stateInitError != ErrorCode::Success)
+			{
+				m_currentState = previousState;
+				m_currentStateType = m_currentState->getEngineStateType();
+				ErrHandlerLoc::get().log(stateInitError, ErrorSource::Source_Engine);
+			}
+		}
+	}
+
 	// Creates and initializes all the services and their locators
 	ErrorCode initServices();
 
-	// Creates and initializes all the engine systems
-	ErrorCode initSystems();
-
 	// Shuts all the systems, etc. down, called before returning from run()
 	void shutdown();
 
 	// Currently being executed state
 	EngineState *m_currentState;
+	EngineStateType m_currentStateType;
 
 	// Different execution states
+	MainMenuState m_mainMenuState;
 	PlayState m_playstate;
 
 	// Various required services
@@ -48,9 +80,6 @@ private:
 	Window *m_window;
 	Clock *m_clock;
 
-	// All engine systems
-	SystemBase *m_systems[Systems::NumberOfSystems];
-
 	// Task manager and scheduler for multi-threading
 	TaskManager *m_taskManager;
 	TaskScheduler *m_scheduler;

+ 172 - 0
Praxis3D/Source/EngineState.cpp

@@ -0,0 +1,172 @@
+
+#include "AudioSystem.h"
+#include "EngineState.h"
+#include "GUISystem.h"
+#include "PhysicsSystem.h"
+#include "RendererSystem.h"
+#include "ScriptSystem.h"
+#include "WorldSystem.h"
+
+EngineState::EngineState() : m_initialized(false)
+{
+	m_sceneChangeController = new ChangeController();
+	m_objectChangeController = new ChangeController();
+
+	m_scheduler = nullptr;
+	m_changeCtrlScene = nullptr;
+
+	for(int i = 0; i < Systems::NumberOfSystems; i++)
+		m_systems[i] = nullptr;
+}
+
+EngineState::~EngineState()
+{
+	shutdown();
+
+	//delete m_sceneChangeController;
+	//delete m_objectChangeController;
+}
+
+ErrorCode EngineState::init(TaskManager *p_taskManager)
+{
+	ErrorCode returnError = ErrorCode::Success;
+
+	// Clear the engine state first, if it has already been initialized
+	if(m_initialized)
+		shutdown();
+
+	// Initialize all engine systems
+	returnError = initSystems();
+	if(returnError == ErrorCode::Success)
+	{
+		// Create new scene change controller
+		m_changeCtrlScene = new UniversalScene(m_sceneChangeController, m_objectChangeController);
+
+		// Create new scheduler for updating (executing) scenes
+		m_scheduler = new TaskScheduler(p_taskManager);
+
+		// Use the created scene change controller in our scene loader
+		m_sceneLoader.registerChangeController(m_changeCtrlScene);
+
+		// Create new scenes from each system to be used by this play state
+		// Register systems with change controller and scenes with scene loader
+		for(int i = 0; i < Systems::NumberOfSystems; i++)
+		{
+			m_sceneLoader.registerSystemScene(m_systems[i]->createScene(&m_sceneLoader));
+			m_changeCtrlScene->extend(m_systems[i]);
+		}
+
+		// Register change control scene with the scheduler
+		m_scheduler->setScene(m_changeCtrlScene);
+
+		// Register task manager with object and scene change controllers
+		m_objectChangeController->setTaskManager(p_taskManager);
+		m_sceneChangeController->setTaskManager(p_taskManager);
+	}
+
+	return returnError;
+}
+
+void EngineState::shutdown()
+{
+	if(m_initialized)
+	{
+		//m_objectChangeController->resetTaskManager();
+		//m_sceneChangeController->resetTaskManager();
+
+		if(m_scheduler != nullptr)
+			delete m_scheduler;
+		if(m_changeCtrlScene != nullptr)
+			delete m_changeCtrlScene;
+		if(m_sceneChangeController != nullptr)
+			delete m_sceneChangeController;
+		if(m_objectChangeController != nullptr)
+			delete m_objectChangeController;
+
+		// Delete all created systems
+		for(int i = 0; i < Systems::NumberOfSystems; i++)
+			if(m_systems[i]->getSystemType() != Systems::Null)
+				delete m_systems[i];
+
+		m_initialized = false;
+	}
+}
+
+ErrorCode EngineState::initSystems()
+{
+	ErrorCode returnError = ErrorCode::Success;
+
+	//  __________________________________
+	// |								  |
+	// |   AUDIO SYSTEM INITIALIZATION	  |
+	// |__________________________________|
+	// Create audio system and check if it was successful (if not, assign a null system in it's place)
+	m_systems[Systems::Audio] = new AudioSystem();
+	if(m_systems[Systems::Audio]->init() != ErrorCode::Success)
+	{
+		delete m_systems[Systems::Audio];
+		m_systems[Systems::Audio] = &g_nullSystemBase;
+	}
+
+	//  __________________________________
+	// |								  |
+	// |  RENDERER SYSTEM INITIALIZATION  |
+	// |__________________________________|
+	// Create graphics system and check if it was successful (if not, assign a null system in it's place)
+	m_systems[Systems::Graphics] = new RendererSystem();
+	if(m_systems[Systems::Graphics]->init() != ErrorCode::Success)
+	{
+		delete m_systems[Systems::Graphics];
+		m_systems[Systems::Graphics] = &g_nullSystemBase;
+	}
+
+	//  ___________________________________
+	// |								   |
+	// |	 GUI SYSTEM INITIALIZATION	   |
+	// |___________________________________|
+	// Create GUI system and check if it was successful (if not, assign a null system in it's place)
+	m_systems[Systems::GUI] = new GUISystem();
+	if(m_systems[Systems::GUI]->init() != ErrorCode::Success)
+	{
+		delete m_systems[Systems::GUI];
+		m_systems[Systems::GUI] = &g_nullSystemBase;
+	}
+
+	//  ___________________________________
+	// |								   |
+	// |   PHYSICS SYSTEM INITIALIZATION   |
+	// |___________________________________|
+	// Create scripting system and check if it was successful (if not, assign a null system in it's place)
+	m_systems[Systems::Physics] = new PhysicsSystem();
+	if(m_systems[Systems::Physics]->init() != ErrorCode::Success)
+	{
+		delete m_systems[Systems::Physics];
+		m_systems[Systems::Physics] = &g_nullSystemBase;
+	}
+
+	//  ___________________________________
+	// |								   |
+	// |  SCRIPTING SYSTEM INITIALIZATION  |
+	// |___________________________________|
+	// Create scripting system and check if it was successful (if not, assign a null system in it's place)
+	m_systems[Systems::Script] = new ScriptSystem();
+	if(m_systems[Systems::Script]->init() != ErrorCode::Success)
+	{
+		delete m_systems[Systems::Script];
+		m_systems[Systems::Script] = &g_nullSystemBase;
+	}
+
+	//  ___________________________________
+	// |								   |
+	// |	WORLD SYSTEM INITIALIZATION	   |
+	// |___________________________________|
+	// Create scripting system and check if it was successful (if not, assign a null system in it's place)
+	m_systems[Systems::World] = new WorldSystem();
+	if(m_systems[Systems::World]->init() != ErrorCode::Success)
+	{
+		delete m_systems[Systems::World];
+		m_systems[Systems::World] = &g_nullSystemBase;
+	}
+
+	return returnError;
+}

+ 28 - 4
Praxis3D/Source/EngineState.h

@@ -2,7 +2,10 @@
 
 #include "Config.h"
 #include "ErrorCodes.h"
+#include "SceneLoader.h"
 #include "TaskManager.h"
+#include "TaskScheduler.h"
+
 
 class Engine;
 class SystemBase;
@@ -10,15 +13,36 @@ class SystemBase;
 class EngineState
 {
 public:
-	EngineState() : m_initialized(false) { }
-	virtual ~EngineState() { }
+	EngineState();
+	virtual ~EngineState();
 
-	virtual ErrorCode init(TaskManager *p_taskManager, SystemBase *p_systems[Systems::NumberOfSystems]) = 0;
+	virtual ErrorCode init(TaskManager *p_taskManager);
 	virtual void update(Engine &p_engine) = 0;
 
-	virtual void shutdown() = 0;
+	virtual void shutdown();
+
+	virtual const EngineStateType getEngineStateType() = 0;
+
+	const inline bool isInitialized() const { return m_initialized; }
 
 protected:
+	// Creates and initializes all the engine systems
+	ErrorCode initSystems();
+
 	bool m_initialized;
+
+	// All engine systems
+	SystemBase *m_systems[Systems::NumberOfSystems];
+
+	// System scenes register
+	SceneLoader m_sceneLoader;
+
+	// Multi-threading task scheduler
+	TaskScheduler *m_scheduler;
+	UniversalScene *m_changeCtrlScene;
+
+	// Subject - observer messaging systems
+	ChangeController *m_sceneChangeController;
+	ChangeController *m_objectChangeController;
 };
 

+ 4 - 0
Praxis3D/Source/ErrorCodes.h

@@ -94,6 +94,9 @@ DECLARE_ENUM(ErrorCode, ERROR_CODES)
     Code(Source_Unknown,) \
     Code(Source_General,) \
     Code(Source_AtmScatteringPass,) \
+    Code(Source_AudioScene,) \
+    Code(Source_AudioSystem,) \
+    Code(Source_AudioTask,) \
     Code(Source_BloomCompositePass,) \
     Code(Source_BloomPass,) \
     Code(Source_BlurPass,) \
@@ -110,6 +113,7 @@ DECLARE_ENUM(ErrorCode, ERROR_CODES)
     Code(Source_GraphicsObject,) \
     Code(Source_GUI,) \
     Code(Source_GUIObject,) \
+    Code(Source_GUIPass,) \
     Code(Source_GUISequenceComponent,) \
     Code(Source_HdrMappingPass,) \
     Code(Source_LensFlareCompositePass,) \

+ 2 - 2
Praxis3D/Source/GUIPass.h

@@ -22,9 +22,9 @@ public:
 
 		// Check for errors and log either a successful or a failed initialization
 		if(returnError == ErrorCode::Success)
-			ErrHandlerLoc::get().log(ErrorCode::Initialize_success, ErrorSource::Source_FinalPass);
+			ErrHandlerLoc::get().log(ErrorCode::Initialize_success, ErrorSource::Source_GUIPass);
 		else
-			ErrHandlerLoc::get().log(ErrorCode::Initialize_failure, ErrorSource::Source_FinalPass);
+			ErrHandlerLoc::get().log(ErrorCode::Initialize_failure, ErrorSource::Source_GUIPass);
 
 		GUIHandlerLocator::get().initRendering();
 

+ 74 - 40
Praxis3D/Source/GUIScene.cpp

@@ -27,7 +27,7 @@ ErrorCode GUIScene::init()
 ErrorCode GUIScene::setup(const PropertySet& p_properties)
 {	
 	// Get default object pool size
-	decltype(m_GUIObjects.getPoolSize()) objectPoolSize = Config::objectPoolVar().object_pool_size;
+	int objectPoolSize = Config::objectPoolVar().object_pool_size;
 
 	for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
 	{
@@ -39,52 +39,82 @@ ErrorCode GUIScene::setup(const PropertySet& p_properties)
 		}
 	}
 
-	// Initialize object pools
-	m_GUIObjects.init(objectPoolSize);
+	// Get the world scene required for reserving the component pools
+	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+
+	// Reserve every component type that belongs to this scene
+	worldScene->reserve<GUISequenceComponent>(Config::objectPoolVar().gui_sequence_component_default_pool_size);
 
 	return ErrorCode::Success;
 }
 
 void GUIScene::update(const float p_deltaTime)
 {
-	// Get the world scene required for getting components
-	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+	if(Config::GUIVar().gui_render)
+	{
+		// Get the world scene required for getting components
+		WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
 
-	// Set the beginning of the GUI frame
-	GUIHandlerLocator::get().beginFrame();
+		// Set the beginning of the GUI frame
+		GUIHandlerLocator::get().beginFrame();
 
-	//	 ____________________________
-	//	|							 |
-	//	|	GUI SEQUENCE COMPONENTS	 |
-	//	|____________________________|
-	//
-	auto sequenceView = worldScene->getEntityRegistry().view<GUISequenceComponent>();
-	for(auto entity : sequenceView)
-	{
-		GUISequenceComponent &sequenceComponent = sequenceView.get<GUISequenceComponent>(entity);
+		//static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoBackground;
+
+		//Config::graphicsVar().current_resolution_x;
+		//Config::graphicsVar().current_resolution_y;
 
-		// Check if the script object is enabled
-		if(sequenceComponent.isObjectActive())
+		//ImVec2 exitButtonSize(100.0f, 25.0f);
+
+		//ImGui::SetNextWindowPos(ImVec2((Config::graphicsVar().current_resolution_x / 2.0f) - (exitButtonSize.x / 2.0f), (Config::graphicsVar().current_resolution_y / 2.0f) - (exitButtonSize.y / 2.0f)));
+		//ImGui::Begin("Example: Fullscreen window", 0, flags);
+
+		//ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.0f, 255.0f, 0.0f, 255.0f));
+		//ImGui::Text("Hello, world %d", 123);
+		//ImGui::Button("Exit", exitButtonSize);
+		//ImGui::PopStyleColor();
+
+		//ImGui::End();
+
+		//	 ____________________________
+		//	|							 |
+		//	|	GUI SEQUENCE COMPONENTS	 |
+		//	|____________________________|
+		//
+		auto sequenceView = worldScene->getEntityRegistry().view<GUISequenceComponent>();
+		for(auto entity : sequenceView)
 		{
-			// Update the object
-			sequenceComponent.update(p_deltaTime);
+			GUISequenceComponent &sequenceComponent = sequenceView.get<GUISequenceComponent>(entity);
+
+			// Check if the script object is enabled
+			if(sequenceComponent.isObjectActive())
+			{
+				// Update the object
+				sequenceComponent.update(p_deltaTime);
+			}
 		}
-	}
 
-	// Set the end of the GUI frame
-	GUIHandlerLocator::get().endFrame();
+		// Set the end of the GUI frame
+		GUIHandlerLocator::get().endFrame();
+	}
 }
 
 ErrorCode GUIScene::preload()
 {
-	// Load every GUI object. It still works in parallel, however,
+	// Get the entity registry 
+	auto &entityRegistry = static_cast<WorldScene*>(m_sceneLoader->getSystemScene(Systems::World))->getEntityRegistry();
+	auto sequenceView = entityRegistry.view<GUISequenceComponent>();
+
+	std::vector<SystemObject*> componentsToLoad;
+	for(auto entity : sequenceView)
+	{
+		componentsToLoad.push_back(&sequenceView.get<GUISequenceComponent>(entity));
+	}
+
+	// Load every object to memory. 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)
+	TaskManagerLocator::get().parallelFor(size_t(0), componentsToLoad.size(), size_t(1), [=](size_t i)
 		{
-			if(m_GUIObjects[i].allocated())
-			{
-				m_GUIObjects[i].getObject()->loadToMemory();
-			}
+			componentsToLoad[i]->loadToMemory();
 		});
 
 	return ErrorCode::Success;
@@ -127,19 +157,23 @@ SystemObject *GUIScene::createComponent(const EntityID p_entityID, const GUISequ
 	return returnObject;
 }
 
-ErrorCode GUIScene::destroyObject(SystemObject* p_systemObject)
+ErrorCode GUIScene::destroyObject(SystemObject *p_systemObject)
 {	
-	// 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 GUI object, as it belongs to the renderer scene
-		GUIObject *objectToDestroy = static_cast<GUIObject *>(p_systemObject);
+	ErrorCode returnError = ErrorCode::Success;
 
-		// Try to destroy the object; return success if it succeeds
-		if(removeObjectFromPool(*objectToDestroy))
-			return ErrorCode::Success;
+	switch(p_systemObject->getObjectType())
+	{
+	case Properties::PropertyID::GUISequenceComponent:
+		//m_sceneLoader->getChangeController()->removeObjectLink(p_systemObject);
+		static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World))->removeComponent<GUISequenceComponent>(p_systemObject->getEntityID());
+		break;
+
+	default:
+		// No object was found, return an appropriate error
+		returnError = ErrorCode::Destroy_obj_not_found;
+		break;
 	}
 
-	// If this point is reached, no object was found, return an appropriate error
-	return ErrorCode::Destroy_obj_not_found;
+	// If this point is reached, 
+	return returnError;
 }

+ 2 - 30
Praxis3D/Source/GUIScene.h

@@ -58,7 +58,7 @@ public:
 	}
 
 	SystemObject *createComponent(const EntityID p_entityID, const GUISequenceComponent::GUISequenceComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
-	ErrorCode destroyObject(SystemObject* p_systemObject);
+	ErrorCode destroyObject(SystemObject *p_systemObject);
 
 	void changeOccurred(ObservedSubject* p_subject, BitMask p_changeType) { }
 
@@ -67,34 +67,6 @@ public:
 	BitMask getDesiredSystemChanges() { return Systems::Changes::Generic::CreateObject || Systems::Changes::Generic::DeleteObject; }
 	BitMask getPotentialSystemChanges() { return Systems::Changes::None; }
 
-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 GUI 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 GUI 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 GUI object pool
-				if(*m_GUIObjects[i].getObject() == p_object)
-				{
-					m_GUIObjects.remove(m_GUIObjects[i].getIndex());
-					return true;
-				}
-			}
-		}
-
-		return false;
-	}
-
+private:
 	GUITask *m_GUITask;
-
-	// Object pools
-	ObjectPool<GUIObject> m_GUIObjects;
 };

+ 26 - 2
Praxis3D/Source/LuaScript.cpp

@@ -19,6 +19,9 @@ void LuaScript::setFunctions()
 	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));
+	m_luaState.set_function("bitwiseOr", sol::overload([this](const int p_v1, const int p_v2) -> const int { return p_v1 | p_v2; },
+		[this](const int p_v1, const int p_v2, const int p_v3) -> const int { return p_v1 | p_v2 | p_v3; },
+		[this](const int p_v1, const int p_v2, const int p_v3, const int p_v4) -> const int { return p_v1 | p_v2 | p_v3 | p_v4; }));
 
 	// Input / Window functions
 	m_luaState.set_function("getMouseInfo", []() -> const Window::MouseInfo { return WindowLocator::get().getMouseInfo(); });
@@ -34,13 +37,17 @@ void LuaScript::setFunctions()
 
 	// Engine functions
 	m_luaState.set_function("setEngineRunning", [](const bool p_v1) -> const void {Config::m_engineVar.running = p_v1; });
+	m_luaState.set_function("setEngineState", [](const EngineStateType p_v1) -> const void {Config::m_engineVar.engineState = 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("Begin", sol::overload([this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::Begin(p_v1.c_str()); }); },
+		[this](const std::string &p_v1, const int p_v2) -> const void { m_GUIData.addFunctor([=] { ImGui::Begin(p_v1.c_str(), 0, p_v2); }); },
+		[this](const std::string &p_v1, Conditional *p_v2, const int p_v3) -> const void { m_GUIData.addFunctor([=] { ImGui::Begin(p_v1.c_str(), &p_v2->m_flag, p_v3); }); }));
 	GUITable.set_function("BeginChild", [this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::BeginChild(p_v1.c_str()); }); });
 	GUITable.set_function("BeginMenu", [this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::BeginMenu(p_v1.c_str()); }); });
-	GUITable.set_function("Button", [this](const std::string &p_v1, Conditional *p_v2) -> void { m_GUIData.addFunctor([=] { p_v2->m_flag = ImGui::Button(p_v1.c_str()); }); });
+	GUITable.set_function("Button", sol::overload([this](const std::string &p_v1, Conditional *p_v2) -> void { m_GUIData.addFunctor([=] { p_v2->m_flag = ImGui::Button(p_v1.c_str()); }); },
+		[this](const std::string &p_v1, const float p_v2, const float p_v3, Conditional *p_v4) -> void { m_GUIData.addFunctor([=] { p_v4->m_flag = ImGui::Button(p_v1.c_str(), ImVec2(p_v2, p_v3)); }); }));
 	GUITable.set_function("Checkbox", [this](const std::string &p_v1, Conditional *p_v2) -> void { m_GUIData.addFunctor([=] { ImGui::Checkbox(p_v1.c_str(), &p_v2->m_flag); }); });
 	GUITable.set_function("ColorEdit3", [this](const std::string &p_v1, glm::vec3 *p_v2) -> void { m_GUIData.addFunctor([=] { ImGui::ColorEdit3(p_v1.c_str(), &(p_v2->x)); }); });
 	GUITable.set_function("ColorEdit4", [this](const std::string &p_v1, glm::vec4 *p_v2) -> void { m_GUIData.addFunctor([=] { ImGui::ColorEdit4(p_v1.c_str(), &(p_v2->x)); }); });
@@ -50,6 +57,7 @@ void LuaScript::setFunctions()
 	GUITable.set_function("EndMenuBar", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::EndMenuBar(); }); });
 	GUITable.set_function("MenuItem", [this](const std::string &p_v1, const std::string &p_v2, Conditional *p_v3) -> void { m_GUIData.addFunctor([=] { p_v3->m_flag = ImGui::MenuItem(p_v1.c_str(), p_v2.c_str()); }); });
 	GUITable.set_function("PlotLines", [this](const std::string &p_v1, const float *p_v2, int p_v3) -> const void { m_GUIData.addFunctor([=] { ImGui::PlotLines(p_v1.c_str(), p_v2, p_v3); }); });
+	GUITable.set_function("SetNextWindowPos", [this](const float p_v1, const float p_v2) -> const void { m_GUIData.addFunctor([=] { ImGui::SetNextWindowPos(ImVec2(p_v1, 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("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()); }); },
@@ -66,6 +74,11 @@ void LuaScript::setFunctions()
 
 void LuaScript::setUsertypes()
 {
+	// Enums
+	m_luaState.new_enum("EngineStateType",
+		"MainMenu", EngineStateType::EngineStateType_MainMenu,
+		"Play", EngineStateType::EngineStateType_Play);
+
 	// Config variables
 	m_luaState.new_usertype<Config::EngineVariables>("EngineVariables",
 		"change_ctrl_cml_notify_list_reserv", &Config::EngineVariables::change_ctrl_cml_notify_list_reserv,
@@ -83,6 +96,10 @@ void LuaScript::setUsertypes()
 	m_luaState.new_usertype<Config::GameplayVariables>("GameplayVariables",
 		"camera_freelook_speed", &Config::GameplayVariables::camera_freelook_speed);
 
+	m_luaState.new_usertype<Config::GraphicsVariables>("GraphicsVariables",
+		"current_resolution_x", &Config::GraphicsVariables::current_resolution_x,
+		"current_resolution_y", &Config::GraphicsVariables::current_resolution_y);
+
 	m_luaState.new_usertype<Config::InputVariables>("InputVariables",
 		"back_key", &Config::InputVariables::back_key,
 		"backward_editor_key", &Config::InputVariables::backward_editor_key,
@@ -409,6 +426,13 @@ void LuaScript::createObjectInLua(const unsigned int p_objectType, const std::st
 
 			break;
 
+		case LuaDefinitions::GraphicsVariables:
+
+			// Set the given variable name in Lua to point to the GraphicsVariables object
+			m_luaState.set(p_variableName, Config::graphicsVar());
+
+			break;
+
 		case LuaDefinitions::InputVariables:
 
 			// Set the given variable name in Lua to point to the InputVariables object

+ 29 - 0
Praxis3D/Source/LuaScript.h

@@ -19,6 +19,7 @@ namespace LuaDefinitions
 	Code(Conditional, ) \
 	Code(EngineVariables, ) \
 	Code(GameplayVariables,) \
+	Code(GraphicsVariables,) \
 	Code(InputVariables,) \
     Code(KeyCommand,) \
     Code(MouseInfo,) \
@@ -181,6 +182,34 @@ private:
 		// Create a table for user types that are supported by Lua scripts
 		m_userTypesTable = m_luaState[Config::scriptVar().userTypeTableName].get_or_create<sol::table>();
 
+		// Create a table for ImGUI window flags
+		sol::table imGuiWindowFlag = m_luaState["ImGuiWindowFlags"].get_or_create<sol::table>();
+
+		imGuiWindowFlag[sol::update_if_empty]["None"] = ImGuiWindowFlags_::ImGuiWindowFlags_None;
+		imGuiWindowFlag[sol::update_if_empty]["NoTitleBar"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoTitleBar;
+		imGuiWindowFlag[sol::update_if_empty]["NoResize"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoResize;
+		imGuiWindowFlag[sol::update_if_empty]["NoMove"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoMove;
+		imGuiWindowFlag[sol::update_if_empty]["NoScrollbar"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoScrollbar;
+		imGuiWindowFlag[sol::update_if_empty]["NoScrollWithMouse"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoScrollWithMouse;
+		imGuiWindowFlag[sol::update_if_empty]["NoCollapse"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoCollapse;
+		imGuiWindowFlag[sol::update_if_empty]["AlwaysAutoResize"] = ImGuiWindowFlags_::ImGuiWindowFlags_AlwaysAutoResize;
+		imGuiWindowFlag[sol::update_if_empty]["NoBackground"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoBackground;
+		imGuiWindowFlag[sol::update_if_empty]["NoSavedSettings"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoSavedSettings;
+		imGuiWindowFlag[sol::update_if_empty]["NoMouseInputs"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoMouseInputs;
+		imGuiWindowFlag[sol::update_if_empty]["MenuBar"] = ImGuiWindowFlags_::ImGuiWindowFlags_MenuBar;
+		imGuiWindowFlag[sol::update_if_empty]["HorizontalScrollbar"] = ImGuiWindowFlags_::ImGuiWindowFlags_HorizontalScrollbar;
+		imGuiWindowFlag[sol::update_if_empty]["NoFocusOnAppearing"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoFocusOnAppearing;
+		imGuiWindowFlag[sol::update_if_empty]["NoBringToFrontOnFocus"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoBringToFrontOnFocus;
+		imGuiWindowFlag[sol::update_if_empty]["AlwaysVerticalScrollbar"] = ImGuiWindowFlags_::ImGuiWindowFlags_AlwaysVerticalScrollbar;
+		imGuiWindowFlag[sol::update_if_empty]["AlwaysHorizontalScrollbar"] = ImGuiWindowFlags_::ImGuiWindowFlags_AlwaysHorizontalScrollbar;
+		imGuiWindowFlag[sol::update_if_empty]["AlwaysUseWindowPadding"] = ImGuiWindowFlags_::ImGuiWindowFlags_AlwaysUseWindowPadding;
+		imGuiWindowFlag[sol::update_if_empty]["NoNavInputs"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoNavInputs;
+		imGuiWindowFlag[sol::update_if_empty]["NoNavFocus"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoNavFocus;
+		imGuiWindowFlag[sol::update_if_empty]["UnsavedDocument"] = ImGuiWindowFlags_::ImGuiWindowFlags_UnsavedDocument;
+		imGuiWindowFlag[sol::update_if_empty]["NoNav"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoNav;
+		imGuiWindowFlag[sol::update_if_empty]["NoDecoration"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoDecoration;
+		imGuiWindowFlag[sol::update_if_empty]["NoInputs"] = ImGuiWindowFlags_::ImGuiWindowFlags_NoInputs;
+
 		// Add each object type to the user type table
 		for(int i = 0; i < LuaDefinitions::UserTypes::NumOfTypes; i++)
 			m_userTypesTable[sol::update_if_empty][GetString(static_cast<LuaDefinitions::UserTypes>(i))] = i;

+ 42 - 0
Praxis3D/Source/MainMenuState.cpp

@@ -0,0 +1,42 @@
+
+#include "ClockLocator.h"
+#include "GUISystem.h"
+#include "MainMenuState.h"
+#include "PhysicsSystem.h"
+#include "PropertySet.h"
+#include "ScriptSystem.h"
+#include "RendererSystem.h"
+#include "WorldSystem.h"
+
+MainMenuState::MainMenuState() : EngineState()
+{
+}
+
+MainMenuState::~MainMenuState()
+{
+}
+
+ErrorCode MainMenuState::init(TaskManager *p_taskManager)
+{
+	ErrorCode returnError = EngineState::init(p_taskManager);
+
+	if(returnError == ErrorCode::Success)
+	{
+		// Load the default map, and log an error if it wasn't successful
+		returnError = m_sceneLoader.loadFromFile(Config::gameplayVar().main_menu_map);
+		if(returnError != ErrorCode::Success)
+			ErrHandlerLoc::get().log(returnError, ErrorSource::Source_SceneLoader);
+
+		m_initialized = true;
+	}
+
+	return returnError;
+}
+
+void MainMenuState::update(Engine &p_engine)
+{
+	m_scheduler->execute(ClockLocator::get().getDeltaSecondsF());
+
+	m_objectChangeController->distributeChanges();
+	m_sceneChangeController->distributeChanges();
+}

+ 20 - 0
Praxis3D/Source/MainMenuState.h

@@ -0,0 +1,20 @@
+#pragma once
+
+#include "SceneLoader.h"
+#include "EngineState.h"
+#include "TaskManager.h"
+#include "TaskScheduler.h"
+
+class MainMenuState : public EngineState
+{
+public:
+	MainMenuState();
+	~MainMenuState();
+
+	ErrorCode init(TaskManager *p_taskManager);
+	void update(Engine &p_engine);
+
+	const EngineStateType getEngineStateType() final { return EngineStateType::EngineStateType_MainMenu; }
+
+private:
+};

+ 10 - 1
Praxis3D/Source/PhysicsScene.cpp

@@ -97,16 +97,25 @@ ErrorCode PhysicsScene::setup(const PropertySet &p_properties)
 		}
 	}
 
+	// Get the world scene required for reserving the component pools
+	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+
+	// Reserve every component type that belongs to this scene
+	worldScene->reserve<RigidBodyComponent>(Config::objectPoolVar().regid_body_component_default_pool_size);
+
 	return ErrorCode::Success;
 }
 
 void PhysicsScene::update(const float p_deltaTime)
 {
+	//std::cout << "4 Physics update" << std::endl;
+	//printf("4 Physics \n");
+
 	// Perform the physics simulation for the time step of the last frame
 	m_dynamicsWorld->stepSimulation(p_deltaTime);
 
 	// Get the world scene required for getting the entity registry
-	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+	WorldScene *worldScene = static_cast<WorldScene*>(m_sceneLoader->getSystemScene(Systems::World));
 
 	// Get the entity registry 
 	auto &entityRegistry = worldScene->getEntityRegistry();

+ 9 - 56
Praxis3D/Source/PlayState.cpp

@@ -10,55 +10,25 @@
 
 PlayState::PlayState() : EngineState()
 {
-	m_sceneChangeController = new ChangeController();
-	m_objectChangeController = new ChangeController();
-
-	m_scheduler = nullptr;
-	m_changeCtrlScene = nullptr;
 }
 
 PlayState::~PlayState()
 {
 }
 
-ErrorCode PlayState::init(TaskManager *p_taskManager, SystemBase *p_systems[Systems::NumberOfSystems])
+ErrorCode PlayState::init(TaskManager *p_taskManager)
 {
-	ErrorCode returnError = ErrorCode::Success;
-
-	// Clear the engine state first, if it has already been initialized
-	if(m_initialized)
-		shutdown();
-
-	// Create new scene change controller
-	m_changeCtrlScene = new UniversalScene(m_sceneChangeController, m_objectChangeController);
-
-	// Create new scheduler for updating (executing) scenes
-	m_scheduler = new TaskScheduler(p_taskManager);
-
-	// Use the created scene change controller in our scene loader
-	m_sceneLoader.registerChangeController(m_changeCtrlScene);
+	ErrorCode returnError = EngineState::init(p_taskManager);
 	
-	// Create new scenes from each system to be used by this play state
-	// Register systems with change controller and scenes with scene loader
-	for(int i = 0; i < Systems::NumberOfSystems; i++)
+	if(returnError == ErrorCode::Success)
 	{
-		m_sceneLoader.registerSystemScene(p_systems[i]->createScene(&m_sceneLoader));
-		m_changeCtrlScene->extend(p_systems[i]);
-	}
+		// Load the default map, and log an error if it wasn't successful
+		returnError = m_sceneLoader.loadFromFile(Config::gameplayVar().default_map);
+		if(returnError != ErrorCode::Success)
+			ErrHandlerLoc::get().log(returnError, ErrorSource::Source_SceneLoader);
 
-	// Register change control scene with the scheduler
-	m_scheduler->setScene(m_changeCtrlScene);
-
-	// Register task manager with object and scene change controllers
-	m_objectChangeController->setTaskManager(p_taskManager);
-	m_sceneChangeController->setTaskManager(p_taskManager);
-	
-	// Load the default map, and log an error if it wasn't successful
-	ErrorCode sceneLoaderError = m_sceneLoader.loadFromFile(Config::gameplayVar().default_map);
-	if(sceneLoaderError != ErrorCode::Success)
-		ErrHandlerLoc::get().log(sceneLoaderError, ErrorSource::Source_SceneLoader);
-
-	m_initialized = true;
+		m_initialized = true;
+	}
 
 	return returnError;
 }
@@ -70,20 +40,3 @@ void PlayState::update(Engine &p_engine)
 	m_objectChangeController->distributeChanges();
 	m_sceneChangeController->distributeChanges();
 }
-
-void PlayState::shutdown()
-{
-	//m_objectChangeController->resetTaskManager();
-	//m_sceneChangeController->resetTaskManager();
-
-	if(m_scheduler != nullptr)
-		delete m_scheduler;
-	if(m_changeCtrlScene != nullptr)
-		delete m_changeCtrlScene;
-	if(m_sceneChangeController != nullptr)
-		delete m_sceneChangeController;
-	if(m_objectChangeController != nullptr)
-		delete m_objectChangeController;
-
-	m_initialized = false;
-}

+ 3 - 9
Praxis3D/Source/PlayState.h

@@ -11,16 +11,10 @@ public:
 	PlayState();
 	~PlayState();
 
-	ErrorCode init(TaskManager *p_taskManager, SystemBase *p_systems[Systems::NumberOfSystems]);
+	ErrorCode init(TaskManager *p_taskManager);
 	void update(Engine &p_engine);
 
-	void shutdown();
-private:
-	SceneLoader m_sceneLoader;
-
-	TaskScheduler *m_scheduler;
-	UniversalScene *m_changeCtrlScene;
+	const EngineStateType getEngineStateType() final { return EngineStateType::EngineStateType_Play; }
 
-	ChangeController *m_sceneChangeController;
-	ChangeController *m_objectChangeController;
+private:
 };

+ 106 - 15
Praxis3D/Source/RendererFrontend.cpp

@@ -18,7 +18,15 @@
 
 RendererFrontend::RendererFrontend() : m_renderPassData(nullptr)
 {
-	// Set up the order of the rendering passes
+	// Disable GUI rendering until GUI render pass is set (as calling GUI functions from GUI components will crash without GUI rendering pass)
+	m_guiRenderWasEnabled = Config::GUIVar().gui_render;
+	Config::m_GUIVar.gui_render = false;
+
+	m_renderingPassesSet = false;
+	for(unsigned int i = 0; i < RenderPassType::RenderPassType_NumOfTypes; i++)
+		m_initializedRenderingPasses[i] = nullptr;
+
+	/*/ Set up the order of the rendering passes
 	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Geometry);
 	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_AtmScattering);
 	m_renderingPassesTypes.push_back(RenderPassType::RenderPassType_Lighting);
@@ -92,7 +100,7 @@ RendererFrontend::RendererFrontend() : m_renderPassData(nullptr)
 				m_initializedRenderingPasses[RenderPassType_GUI] = new GUIPass(*this);
 			break;
 		}
-	}
+	}*/
 }
 
 RendererFrontend::~RendererFrontend()
@@ -131,6 +139,97 @@ ErrorCode RendererFrontend::init()
 	if(!ErrHandlerLoc::get().ifSuccessful(m_backend.init(m_frameData), returnCode))
 		return returnCode;
 
+	// Create the render pass data struct
+	m_renderPassData = new RenderPassData();
+
+	updateProjectionMatrix();
+
+	passLoadCommandsToBackend();
+
+	glViewport(0, 0, m_frameData.m_screenSize.x, m_frameData.m_screenSize.y);
+
+	return returnCode;
+}
+
+void RendererFrontend::setRenderingPasses(const RenderingPasses &p_renderingPasses)
+{
+	m_renderingPassesSet = true;
+
+	// Make sure the entries of the rendering passes are set to nullptr
+	for(unsigned int i = 0; i < RenderPassType::RenderPassType_NumOfTypes; i++)
+	{
+		if(m_initializedRenderingPasses[i] != nullptr)
+			delete m_initializedRenderingPasses[i];
+
+		m_initializedRenderingPasses[i] = nullptr;
+	}
+
+	bool guiRenderPassSet = false;
+
+	// Create rendering passes
+	for(decltype(p_renderingPasses.size()) i = 0, size = p_renderingPasses.size(); i < size; i++)
+	{
+		switch(p_renderingPasses[i])
+		{
+		case RenderPassType_Geometry:
+			if(m_initializedRenderingPasses[RenderPassType_Geometry] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_Geometry] = new GeometryPass(*this);
+			break;
+		case RenderPassType_Lighting:
+			if(m_initializedRenderingPasses[RenderPassType_Lighting] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_Lighting] = new LightingPass(*this);
+			break;
+		case RenderPassType_AtmScattering:
+			if(m_initializedRenderingPasses[RenderPassType_AtmScattering] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_AtmScattering] = new AtmScatteringPass(*this);
+			break;
+		case RenderPassType_HdrMapping:
+			if(m_initializedRenderingPasses[RenderPassType_HdrMapping] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_HdrMapping] = new HdrMappingPass(*this);
+			break;
+		case RenderPassType_Blur:
+			if(m_initializedRenderingPasses[RenderPassType_Blur] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_Blur] = new BlurPass(*this);
+			break;
+		case RenderPassType_Bloom:
+			if(m_initializedRenderingPasses[RenderPassType_Bloom] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_Bloom] = new BloomPass(*this);
+			break;
+		case RenderPassType_BloomComposite:
+			if(m_initializedRenderingPasses[RenderPassType_BloomComposite] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_BloomComposite] = new BloomCompositePass(*this);
+			break;
+		case RenderPassType_LenseFlare:
+			if(m_initializedRenderingPasses[RenderPassType_LenseFlare] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_LenseFlare] = new LenseFlarePass(*this);
+			break;
+		case RenderPassType_LenseFlareComposite:
+			if(m_initializedRenderingPasses[RenderPassType_LenseFlareComposite] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_LenseFlareComposite] = new LenseFlareCompositePass(*this);
+			break;
+		case RenderPassType_Luminance:
+			if(m_initializedRenderingPasses[RenderPassType_Luminance] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_Luminance] = new LuminancePass(*this);
+			break;
+		case RenderPassType_Final:
+			if(m_initializedRenderingPasses[RenderPassType_Final] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_Final] = new FinalPass(*this);
+			break;
+		case RenderPassType_GUI:
+			if(m_initializedRenderingPasses[RenderPassType_GUI] == nullptr)
+				m_initializedRenderingPasses[RenderPassType_GUI] = new GUIPass(*this);
+			guiRenderPassSet = true;
+			break;
+		}
+	}
+
+	// Disable GUI rendering if the GUI render pass wasn't set; re-enable GUI rendering if GUI pass was set and if it GUI rendering was enabled before
+	if(!guiRenderPassSet)
+		Config::m_GUIVar.gui_render = false;
+	else
+		if(m_guiRenderWasEnabled)
+			Config::m_GUIVar.gui_render = true;
+
 	// Initialize rendering passes
 	for(unsigned int i = 0; i < RenderPassType::RenderPassType_NumOfTypes; i++)
 	{
@@ -148,26 +247,18 @@ ErrorCode RendererFrontend::init()
 		}
 	}
 
-	// Create the render pass data struct
-	m_renderPassData = new RenderPassData();
-
 	// Reserve the required space for rendering passes array
-	m_renderingPasses.reserve(m_renderingPassesTypes.size());
+	m_renderingPasses.reserve(p_renderingPasses.size());
 
 	// Add required rendering passes to the main array
-	for(decltype(m_renderingPassesTypes.size()) i = 0, size = m_renderingPassesTypes.size(); i < size; i++)
+	for(decltype(p_renderingPasses.size()) i = 0, size = p_renderingPasses.size(); i < size; i++)
 	{
-		if(m_initializedRenderingPasses[m_renderingPassesTypes[i]] != nullptr)
-			m_renderingPasses.push_back(m_initializedRenderingPasses[m_renderingPassesTypes[i]]);
+		if(m_initializedRenderingPasses[p_renderingPasses[i]] != nullptr)
+			m_renderingPasses.push_back(m_initializedRenderingPasses[p_renderingPasses[i]]);
 	}
 
-	updateProjectionMatrix();
-
-	passLoadCommandsToBackend();
-
+	//passLoadCommandsToBackend();
 	glViewport(0, 0, m_frameData.m_screenSize.x, m_frameData.m_screenSize.y);
-
-	return returnCode;
 }
 
 void RendererFrontend::renderFrame(SceneObjects &p_sceneObjects, const float p_deltaTime)

+ 8 - 1
Praxis3D/Source/RendererFrontend.h

@@ -5,6 +5,8 @@
 #include "RendererBackend.h"
 #include "RendererScene.h"
 
+typedef std::vector<RenderPassType> RenderingPasses;
+
 class RenderPass;
 struct RenderPassData;
 
@@ -56,6 +58,8 @@ public:
 
 	ErrorCode init();
 
+	void setRenderingPasses(const RenderingPasses &p_renderingPasses);
+
 	// Renders a complete frame
 	void renderFrame(SceneObjects &p_sceneObjects, const float p_deltaTime);
 	
@@ -306,6 +310,9 @@ protected:
 		//													m_frameData.m_screenSize.y);
 	}
 
+	bool m_renderingPassesSet;
+	bool m_guiRenderWasEnabled;
+
 	// Renderer backend, serves as an interface layer to GPU
 	RendererBackend m_backend;
 	
@@ -328,7 +335,7 @@ protected:
 	// An array of all active rendering passes
 	std::vector<RenderPass*> m_renderingPasses;
 
-	std::vector<RenderPassType> m_renderingPassesTypes;
+	//RenderingPasses m_renderingPassesTypes;
 	RenderPass *m_initializedRenderingPasses[RenderPassType::RenderPassType_NumOfTypes];
 	//bool m_renderPassBeingUsed[RenderPassType::RenderPassType_NumOfTypes];
 };

+ 13 - 4
Praxis3D/Source/RendererScene.cpp

@@ -22,10 +22,7 @@ RendererScene::~RendererScene()
 ErrorCode RendererScene::init()
 {
 	ErrorCode returnError = ErrorCode::Success;
-	
-	if(!entt::basic_component_traits::in_place_delete)
-		ErrHandlerLoc().get().log(ErrorType::Error, ErrorSource::Source_WorldScene, "entt::basic_component_traits::in_place_delete is switched off, disabling pointer stability upon component deletion");
-		
+			
 	// Create a default camera, in case it is not created upon loading a scene
 	m_camera = new CameraObject(this, "Default Camera");
 
@@ -40,6 +37,15 @@ ErrorCode RendererScene::init()
 
 ErrorCode RendererScene::setup(const PropertySet &p_properties)
 {
+	// Get the world scene required for reserving the component pools
+	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+	
+	// Reserve every component type that belongs to this scene
+	worldScene->reserve<CameraComponent>(Config::objectPoolVar().camera_component_default_pool_size);
+	worldScene->reserve<LightComponent>(Config::objectPoolVar().light_component_default_pool_size);
+	worldScene->reserve<ModelComponent>(Config::objectPoolVar().model_component_default_pool_size);
+	worldScene->reserve<ShaderComponent>(Config::objectPoolVar().shader_component_default_pool_size);
+
 	return ErrorCode::Success;
 }
 
@@ -104,6 +110,9 @@ void RendererScene::loadInBackground()
 
 void RendererScene::update(const float p_deltaTime)
 {
+	//std::cout << "2 Graphics update" << std::endl;
+	//printf("2 Graphics \n");
+
 	// Clear variables from previous frame
 	m_sceneObjects.m_directionalLight = &m_directionalLight->getLightDataSet();
 

+ 43 - 0
Praxis3D/Source/RendererSystem.cpp

@@ -31,6 +31,49 @@ ErrorCode RendererSystem::init()
 }
 ErrorCode RendererSystem::setup(const PropertySet &p_properties)
 {
+	RenderingPasses renderingPasses;
+
+	// Load the rendering passes
+	auto &renderPassesProperty = p_properties.getPropertySetByID(Properties::RenderPasses);
+	if(renderPassesProperty)
+	{
+		// Iterate over the property array
+		for(decltype(renderPassesProperty.getNumPropertySets()) objIndex = 0, objSize = renderPassesProperty.getNumPropertySets(); objIndex < objSize; objIndex++)
+		{
+			auto &typeProperty = renderPassesProperty.getPropertySetUnsafe(objIndex).getPropertyByID(Properties::Type);
+			if(typeProperty)
+			{
+				switch(typeProperty.getID())
+				{
+				case Properties::AtmScatteringRenderPass:
+					renderingPasses.push_back(RenderPassType::RenderPassType_AtmScattering);
+					break;
+				case Properties::BloomRenderPass:
+					renderingPasses.push_back(RenderPassType::RenderPassType_Bloom);
+					break;
+				case Properties::GeometryRenderPass:
+					renderingPasses.push_back(RenderPassType::RenderPassType_Geometry);
+					break;
+				case Properties::GUIRenderPass:
+					renderingPasses.push_back(RenderPassType::RenderPassType_GUI);
+					break;
+				case Properties::LightingRenderPass:
+					renderingPasses.push_back(RenderPassType::RenderPassType_Lighting);
+					break;
+				case Properties::LuminanceRenderPass:
+					renderingPasses.push_back(RenderPassType::RenderPassType_Luminance);
+					break;
+				case Properties::FinalRenderPass:
+					renderingPasses.push_back(RenderPassType::RenderPassType_Final);
+					break;
+				}
+			}
+		}
+	}
+
+	// Pass the loaded rendering passes to the renderer
+	m_renderer.setRenderingPasses(renderingPasses);
+
 	return ErrorCode::Success;
 }
 

+ 39 - 1
Praxis3D/Source/SceneLoader.cpp

@@ -46,17 +46,22 @@ ErrorCode SceneLoader::loadFromFile(const std::string &p_filename)
 		{
 			// Create an empty property set, in case there is none in the loaded file, because a system scene setup must be called either way
 			PropertySet scenePropertySet;
+			PropertySet systemropertySet;
 
 			// Iterate over each system property set
 			for(decltype(systemProperties.getNumPropertySets()) propIndex = 0, propSize = systemProperties.getNumPropertySets(); propIndex < propSize; propIndex++)
 			{
 				// If the system scene property matches in the loaded file, retrieve it so it can be passed to the corresponding scene
 				if(Systems::SystemNames[m_systemScenes[sysIndex]->getSystemType()] == GetString(systemProperties.getPropertySetUnsafe(propIndex).getPropertyID()))
+				{
 					scenePropertySet = systemProperties.getPropertySetUnsafe(propIndex).getPropertySetByID(Properties::Scene);
+					systemropertySet = systemProperties.getPropertySetUnsafe(propIndex).getPropertySetByID(Properties::System);
+				}
 			}
 
-			// Pass the scene propertySet parameters
+			// Pass the scene and system propertySet parameters
 			m_systemScenes[sysIndex]->setup(scenePropertySet);
+			m_systemScenes[sysIndex]->getSystem()->setup(systemropertySet);
 		}
 
 		// Get Game Objects
@@ -305,6 +310,19 @@ void SceneLoader::importFromProperties(ComponentsConstructionInfo &p_constructio
 		}
 	}
 
+	// Load audio components
+	{
+		auto &sceneProperty = p_properties.getPropertySetByID(Properties::Audio);
+		if(sceneProperty)
+		{
+			for(decltype(sceneProperty.getNumPropertySets()) i = 0, size = sceneProperty.getNumPropertySets(); i < size; i++)
+			{
+				importFromProperties(p_constructionInfo.m_audioComponents, sceneProperty.getPropertySet(i), name);
+			}
+		}
+	}
+
+	// Load graphics components
 	{
 		auto &sceneProperty = p_properties.getPropertySetByID(Properties::Rendering);
 		if(sceneProperty)
@@ -316,6 +334,7 @@ void SceneLoader::importFromProperties(ComponentsConstructionInfo &p_constructio
 		}
 	}
 
+	// Load GUI components
 	{
 		auto &sceneProperty = p_properties.getPropertySetByID(Properties::GUI);
 		if(sceneProperty)
@@ -327,6 +346,7 @@ void SceneLoader::importFromProperties(ComponentsConstructionInfo &p_constructio
 		}
 	}
 
+	// Load physics components
 	{
 		auto &sceneProperty = p_properties.getPropertySetByID(Properties::Physics);
 		if(sceneProperty)
@@ -338,6 +358,7 @@ void SceneLoader::importFromProperties(ComponentsConstructionInfo &p_constructio
 		}
 	}
 
+	// Load script components
 	{
 		auto &sceneProperty = p_properties.getPropertySetByID(Properties::Script);
 		if(sceneProperty)
@@ -349,6 +370,7 @@ void SceneLoader::importFromProperties(ComponentsConstructionInfo &p_constructio
 		}
 	}
 
+	// Load world components
 	{
 		auto &sceneProperty = p_properties.getPropertySetByID(Properties::World);
 		if(sceneProperty)
@@ -361,6 +383,22 @@ void SceneLoader::importFromProperties(ComponentsConstructionInfo &p_constructio
 	}
 }
 
+void SceneLoader::importFromProperties(AudioComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties, const std::string &p_name)
+{
+	// Check if property set node is present
+	if(p_properties)
+	{
+		switch(p_properties.getPropertyID())
+		{
+		case Properties::PropertyID::Audio:
+		{
+			
+		}
+		break;
+		}
+	}
+}
+
 void SceneLoader::importFromProperties(GraphicsComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties, const std::string &p_name)
 {
 	// Check if property set node is present

+ 2 - 0
Praxis3D/Source/SceneLoader.h

@@ -6,6 +6,7 @@
 #include "Universal.h"
 
 struct ComponentsConstructionInfo;
+struct AudioComponentsConstructionInfo;
 struct GraphicsComponentsConstructionInfo;
 struct GUIComponentsConstructionInfo;
 struct PhysicsComponentsConstructionInfo;
@@ -43,6 +44,7 @@ public:
 private:
 	ErrorCode importFromFile(ComponentsConstructionInfo &p_constructionInfo, const std::string &p_filename);
 	void importFromProperties(ComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties);
+	void importFromProperties(AudioComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties, const std::string &p_name);
 	void importFromProperties(GraphicsComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties, const std::string &p_name);
 	void importFromProperties(GUIComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties, const std::string &p_name);
 	void importFromProperties(PhysicsComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties, const std::string &p_name);

+ 31 - 17
Praxis3D/Source/ScriptScene.cpp

@@ -29,7 +29,7 @@ ErrorCode ScriptScene::init()
 ErrorCode ScriptScene::setup(const PropertySet &p_properties)
 {
 	// Get default object pool size
-	decltype(m_scriptObjects.getPoolSize()) objectPoolSize = Config::objectPoolVar().object_pool_size;
+	int objectPoolSize = Config::objectPoolVar().object_pool_size;
 
 	for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
 	{
@@ -41,8 +41,11 @@ ErrorCode ScriptScene::setup(const PropertySet &p_properties)
 		}
 	}
 
-	// Initialize object pools
-	m_scriptObjects.init(objectPoolSize);
+	// Get the world scene required for reserving the component pools
+	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+
+	// Reserve every component type that belongs to this scene
+	worldScene->reserve<LuaComponent>(Config::objectPoolVar().lua_component_default_pool_size);
 
 	return ErrorCode::Success;
 }
@@ -92,11 +95,18 @@ void ScriptScene::update(const float p_deltaTime)
 
 void ScriptScene::loadInBackground()
 {
-	// Iterate over script objects and start loading them in background
-	for(decltype(m_scriptObjects.getPoolSize()) i = 0, size = m_scriptObjects.getPoolSize(); i < size; i++)
+	// Get the world scene required for getting the entity registry
+	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+
+	// Get the entity registry 
+	auto &entityRegistry = worldScene->getEntityRegistry();
+
+	auto luaView = worldScene->getEntityRegistry().view<LuaComponent>();
+	for(auto entity : luaView)
 	{
-		// TODO: load in background implementation
-		//TaskManagerLocator::get().startBackgroundThread(std::bind(&ScriptObject::loadToMemory, m_scriptObjects[i]));
+		auto &component = luaView.get<LuaComponent>(entity);
+
+		TaskManagerLocator::get().startBackgroundThread(std::bind(&LuaComponent::loadToMemory, &component));
 	}
 }
 
@@ -175,19 +185,23 @@ SystemObject *ScriptScene::createComponent(const EntityID &p_entityID, const Lua
 
 ErrorCode ScriptScene::destroyObject(SystemObject *p_systemObject)
 {
-	// Check if object is valid and belongs to graphics system
-	if(p_systemObject != nullptr && p_systemObject->getSystemType() == Systems::Graphics)
-	{
-		// Cast the system object to graphics object, as it belongs to the renderer scene
-		ScriptObject *objectToDestroy = static_cast<ScriptObject *>(p_systemObject);
+	ErrorCode returnError = ErrorCode::Success;
 
-		// Try to destroy the object; return success if it succeeds
-		if(removeObjectFromPool(*objectToDestroy))
-			return ErrorCode::Success;
+	switch(p_systemObject->getObjectType())
+	{
+	case Properties::PropertyID::LuaComponent:
+		//m_sceneLoader->getChangeController()->removeObjectLink(p_systemObject);
+		static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World))->removeComponent<LuaComponent>(p_systemObject->getEntityID());
+		break;
+
+	default:
+		// No object was found, return an appropriate error
+		returnError = ErrorCode::Destroy_obj_not_found;
+		break;
 	}
 
-	// If this point is reached, no object was found, return an appropriate error
-	return ErrorCode::Destroy_obj_not_found;
+	// If this point is reached, 
+	return returnError;
 }
 
 void ScriptScene::changeOccurred(ObservedSubject *p_subject, BitMask p_changeType)

+ 0 - 30
Praxis3D/Source/ScriptScene.h

@@ -84,31 +84,6 @@ public:
 	Systems::TypeID getSystemType() { return Systems::Script; }
 
 private:
-	// Removes an object from a pool, by iterating checking each pool for matched index; returns true if the object was found and removed
-	inline bool removeObjectFromPool(ScriptObject &p_object)
-	{
-		// Go over each graphics object
-		for(decltype(m_scriptObjects.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_scriptObjects.getNumAllocated(),
-			size = m_scriptObjects.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
-		{
-			// Check if the script object is allocated inside the pool container
-			if(m_scriptObjects[i].allocated())
-			{
-				// Increment the number of allocated objects (early bail mechanism)
-				numAllocObjecs++;
-
-				// If the object matches with the one we are looking for, remove it from the script object pool
-				if(*m_scriptObjects[i].getObject() == p_object)
-				{
-					m_scriptObjects.remove(m_scriptObjects[i].getIndex());
-					return true;
-				}
-			}
-		}
-
-		return false;
-	}
-
 	FreeCamera *loadFreeCamera(const PropertySet &p_properties);
 	DebugUIScript *loadDebugUI(const PropertySet &p_properties);
 	DebugMoveScript *loadDebugMove(const PropertySet &p_properties);
@@ -118,9 +93,4 @@ private:
 	WorldEditScript *loadWorldEdit(const PropertySet &p_properties);
 
 	ScriptTask *m_scriptingTask;
-
-	//std::vector<BaseScriptObject*> m_scriptObjects;
-
-	// Object pools
-	ObjectPool<ScriptObject> m_scriptObjects;
 };

+ 4 - 1
Praxis3D/Source/SpatialDataManager.h

@@ -266,9 +266,10 @@ public:
 
 		// Construct a local transform matrix without scaling it
 		case Systems::Changes::Spatial::LocalTransformNoScale:
-			return Math::createTransformMat(
+			m_localTransformNoScale = Math::createTransformMat(
 				m_localSpace.m_spatialData.m_position,
 				m_localSpace.m_spatialData.m_rotationQuat);
+			return m_localTransformNoScale;
 		
 		case Systems::Changes::Spatial::WorldTransform:
 			return m_worldTransform;
@@ -508,6 +509,8 @@ private:
 	glm::mat4 m_parentTransform;
 	// Transform data in world space (local and parent space added together), final transform data used for rendering
 	glm::mat4 m_worldTransform;
+	// A local transform matrix constructed without scaling it
+	mutable glm::mat4 m_localTransformNoScale;
 
 	// Used for update tracking; each time data is change, update count is incremented
 	UpdateCount m_updateCount;

+ 26 - 52
Praxis3D/Source/WorldScene.cpp

@@ -11,10 +11,19 @@ WorldScene::WorldScene(SystemBase *p_system, SceneLoader *p_sceneLoader) : Syste
 	m_worldTask = new WorldTask(this);
 }
 
+ErrorCode WorldScene::init() 
+{
+	// Since this flag is modified by hand in the Entt code, check to see if it is still correct, because updating the Entt library will revert the flag back to default (false)
+	if(!entt::basic_component_traits::in_place_delete)
+		ErrHandlerLoc().get().log(ErrorType::Error, ErrorSource::Source_WorldScene, "entt::basic_component_traits::in_place_delete is switched off, disabling pointer stability upon component deletion");
+
+	return ErrorCode::Success; 
+}
+
 ErrorCode WorldScene::setup(const PropertySet &p_properties)
 {
 	// Get default object pool size
-	decltype(m_gameObjects.getPoolSize()) objectPoolSize = Config::objectPoolVar().object_pool_size;
+	int objectPoolSize = Config::objectPoolVar().object_pool_size;
 
 	for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
 	{
@@ -26,53 +35,14 @@ ErrorCode WorldScene::setup(const PropertySet &p_properties)
 		}
 	}
 
-	// Initialize object pools
-	m_gameObjects.init(objectPoolSize);
+	// Reserve every component type that belongs to this scene
+	reserve<SpatialComponent>(Config::objectPoolVar().spatial_component_default_pool_size);
 
 	return ErrorCode::Success;
 }
 
 void WorldScene::update(const float p_deltaTime)
 {
-	//std::cout << "World update:" << std::endl;
-
-	//std::vector<EntityID> entities;
-
-	//m_entityRegistry.each([&entities](auto entity)
-	//	{
-	//		entities.push_back(entity);
-	//	});
-
-	//for(size_t i = 0; i < entities.size(); i++)
-	//{
-	//	std::cout << entities[i];
-	//	if(m_entityRegistry.all_of<CameraComponent>(entities[i]))
-	//		std::cout << " cam ";
-	//	if(m_entityRegistry.all_of<LightComponent>(entities[i]))
-	//		std::cout << " lht ";
-	//	if(m_entityRegistry.all_of<ModelComponent>(entities[i]))
-	//		std::cout << " mdl ";
-	//	std::cout << std::endl;
-	//}
-
-	//std::cout << std::endl;
-
-	// Go over each game object
-	//for(decltype(m_gameObjects.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_gameObjects.getNumAllocated(),
-	//	size = m_gameObjects.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
-	//{
-	//	// Check if the game object is allocated inside the pool container
-	//	if(m_gameObjects[i].allocated())
-	//	{
-	//		// Increment the number of allocated objects (early bail mechanism)
-	//		numAllocObjecs++;
-
-	//		// Update the game object
-	//		m_gameObjects[i].getObject()->update(p_deltaTime);
-	//	}
-	//}
-	
-
 	//	 ___________________________
 	//	|							|
 	//	|	  SPATIAL COMPONENT		|
@@ -184,17 +154,21 @@ std::vector<SystemObject*> WorldScene::createComponents(const EntityID p_entityI
 
 ErrorCode WorldScene::destroyObject(SystemObject *p_systemObject)
 {
-	// Check if object is valid and belongs to world system
-	if(p_systemObject != nullptr && p_systemObject->getSystemType() == Systems::World)
-	{
-		// Cast the system object to game object, as it belongs to the renderer scene
-		GameObject *objectToDestroy = static_cast<GameObject*>(p_systemObject);
+	ErrorCode returnError = ErrorCode::Success;
 
-		// Try to destroy the object; return success if it succeeds
-		if(removeObjectFromPool(*objectToDestroy))
-			return ErrorCode::Success;
+	switch(p_systemObject->getObjectType())
+	{
+	case Properties::PropertyID::SpatialComponent:
+		//m_sceneLoader->getChangeController()->removeObjectLink(p_systemObject);
+		removeComponent<SpatialComponent>(p_systemObject->getEntityID());
+		break;
+
+	default:
+		// No object was found, return an appropriate error
+		returnError = ErrorCode::Destroy_obj_not_found;
+		break;
 	}
 
-	// If this point is reached, no object was found, return an appropriate error
-	return ErrorCode::Destroy_obj_not_found;
+	// If this point is reached, 
+	return returnError;
 }

+ 11 - 29
Praxis3D/Source/WorldScene.h

@@ -37,7 +37,7 @@ class WorldScene : public SystemScene
 public:
 	WorldScene(SystemBase *p_system, SceneLoader *p_sceneLoader);
 
-	ErrorCode init() { return ErrorCode::Success; }
+	ErrorCode init();
 
 	ErrorCode setup(const PropertySet &p_properties);
 
@@ -57,7 +57,6 @@ public:
 	{
 		SpatialComponent *spatialComponent = nullptr;
 
-		//auto spatial = m_entityRegistry.emplace<SpatialComponent>(newEntity, this, name);
 		spatialComponent = &addComponent<SpatialComponent>(p_entityID, this, p_constructionInfo.m_name, p_entityID);
 
 		spatialComponent->m_spatialData.setLocalPosition(p_constructionInfo.m_localPosition);
@@ -71,7 +70,6 @@ public:
 
 		// Perform a spatial data update, so that all the transform matrices are calculated
 		spatialComponent->m_spatialData.update();
-
 		return spatialComponent;
 	}
 
@@ -96,6 +94,16 @@ public:
 		m_entityRegistry.remove<T_Component>(p_entity);
 	}
 
+	// Increases the size of the pool for a given component type
+	// When multi-threading is enabled, creating views concurrently on a mostly empty registry can sometimes trigger an access violation error,
+	// because a view of a non-existent component creates an empty pool for that component, hence creating views for the first time is not thread-safe.
+	// As a solution, reserve must be called for every component type, to create its pool ahead of time
+	template <class T_Component>
+	void reserve(const size_t p_capacity)
+	{
+		m_entityRegistry.storage<T_Component>().reserve(p_capacity);
+	}
+
 	inline entt::basic_registry<EntityID> &getEntityRegistry() { return m_entityRegistry; }
 
 private:
@@ -130,31 +138,6 @@ private:
 		std::vector<decltype(GameObject::m_GameObjectID)> m_children;
 	};
 
-	// 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(GameObject &p_object)
-	{
-		// Go over each game object
-		for(decltype(m_gameObjects.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_gameObjects.getNumAllocated(),
-			size = m_gameObjects.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
-		{
-			// Check if the game object is allocated inside the pool container
-			if(m_gameObjects[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 game object pool
-				if(*m_gameObjects[i].getObject() == p_object)
-				{
-					m_gameObjects.remove(m_gameObjects[i].getIndex());
-					return true;
-				}
-			}
-		}
-
-		return false;
-	}
-
 	inline EntityID addEntity()
 	{
 		return m_entityRegistry.create();
@@ -169,7 +152,6 @@ private:
 	std::vector<GameObjectAndParent> m_unassignedParents;
 	std::vector<GameObjectAndChildren> m_unassignedChildren;
 
-	ObjectPool<GameObject> m_gameObjects;
 	WorldTask *m_worldTask;
 
 	ObjectRegisterConcurrent<GameObject*> m_objectRegister;