Browse Source

Changed component creation from using PropertySets to specialized containers allowing easier and faster component creation
Changed PropertySet importing; moved it from Scenes/Objects to SceneLoader to detach serialization from SystemObjects
Added ConstructionInfo containers for every component
Added new methods for component creation in each SystemScene (i.e. factories for SystemObjects); removed creation logic from SystemObjects themselves
Added a flag in LoadableGraphicsObject to signify whether an object is to be made active after loading it (because it might need to be set to inactive during the loading)
Added loading in background for components in RendererScene
Added scene importing from PropertySets into ConstructionInfo containers for each component in SceneLoader
Fixed a bug of returning a reference to temporary data in PhysicsMotionState, by setting the data on the spot to a mutable container
Removed unused code

Paul A 3 years ago
parent
commit
9bc012dc14

+ 1 - 0
Praxis3D/Praxis3D.vcxproj

@@ -227,6 +227,7 @@
     <ClInclude Include="Source\CollisionShapeComponent.h" />
     <ClInclude Include="Source\CommandBuffer.h" />
     <ClInclude Include="Source\CommonDefinitions.h" />
+    <ClInclude Include="Source\ComponentConstructorInfo.h" />
     <ClInclude Include="Source\Config.h" />
     <ClInclude Include="Source\ConfigLoader.h" />
     <ClInclude Include="Source\Containers.h" />

+ 3 - 0
Praxis3D/Praxis3D.vcxproj.filters

@@ -809,6 +809,9 @@
     <ClInclude Include="Source\LuminancePass.h">
       <Filter>Renderer\Render Passes\Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Source\ComponentConstructorInfo.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="Data\config.ini" />

+ 8 - 0
Praxis3D/Source/CameraComponent.h

@@ -7,6 +7,14 @@ class CameraComponent : public SystemObject, public LoadableGraphicsObject
 {
 	friend class RendererScene;
 public:
+	struct CameraComponentConstructionInfo : public SystemObject::SystemObjectConstructionInfo
+	{
+		CameraComponentConstructionInfo()
+		{
+
+		}
+	};
+
 	CameraComponent(SystemScene *p_systemScene, std::string p_name, const EntityID p_entityID, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::CameraComponent, p_entityID)
 	{
 

+ 39 - 0
Praxis3D/Source/ComponentConstructorInfo.h

@@ -0,0 +1,39 @@
+#pragma once
+
+#include "CommonDefinitions.h"
+#include "GUIScene.h"
+#include "RendererScene.h"
+#include "PhysicsScene.h"
+#include "ScriptScene.h"
+#include "WorldScene.h"
+
+struct ComponentsConstructionInfo
+{
+	ComponentsConstructionInfo()
+	{
+		m_name = "null";
+		m_id = NULL_ENTITY_ID;
+		m_parent = NULL_ENTITY_ID;
+	}
+
+	void deleteConstructionInfo()
+	{
+		m_graphicsComponents.deleteConstructionInfo();
+		m_guiComponents.deleteConstructionInfo();
+		m_physicsComponents.deleteConstructionInfo();
+		m_scriptComponents.deleteConstructionInfo();
+		m_worldComponents.deleteConstructionInfo();
+	}
+
+	GraphicsComponentsConstructionInfo m_graphicsComponents;
+	GUIComponentsConstructionInfo m_guiComponents;
+	PhysicsComponentsConstructionInfo m_physicsComponents;
+	ScriptComponentsConstructionInfo m_scriptComponents;
+	WorldComponentsConstructionInfo m_worldComponents;
+
+	std::string m_name;
+	EntityID m_id;
+	EntityID m_parent;
+};
+
+typedef std::vector<ComponentsConstructionInfo> EntitiesConstructionInfo;

+ 23 - 81
Praxis3D/Source/GUIScene.cpp

@@ -1,5 +1,6 @@
 
 #include "WorldScene.h"
+#include "ComponentConstructorInfo.h"
 #include "GUIHandlerLocator.h"
 #include "GUIScene.h"
 #include "NullSystemObjects.h"
@@ -93,96 +94,37 @@ void GUIScene::loadInBackground()
 {
 }
 
-SystemObject *GUIScene::createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties)
+std::vector<SystemObject*> GUIScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
+{
+	return createComponents(p_entityID, p_constructionInfo.m_guiComponents);
+}
+
+SystemObject *GUIScene::createComponent(const EntityID p_entityID, const GUISequenceComponent::GUISequenceComponentConstructionInfo &p_constructionInfo)
 {	
 	// If valid type was not specified, or object creation failed, return a null object instead
-	SystemObject *returnObject = g_nullSystemBase.getScene()->createObject(p_properties);
-
-	// Check if property set node is present
-	if(p_properties)
-	{
-		// Get the world scene required for attaching components to the entity
-		WorldScene *worldScene = static_cast<WorldScene*>(m_sceneLoader->getSystemScene(Systems::World));
+	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();
 
-		switch(p_properties.getPropertyID())
-		{
-			case Properties::PropertyID::Sequence:
-			{
-				auto &component = worldScene->addComponent<GUISequenceComponent>(p_entityID, this, p_entityName + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::Sequence), p_entityID);
-
-				// Try to initialize the component
-				auto componentInitError = component.init();
-				if(componentInitError == ErrorCode::Success)
-				{
-					// Try to import the component
-					auto const &componentImportError = component.importObject(p_properties);
-
-					// Remove the component if it failed to import
-					if(componentImportError != ErrorCode::Success)
-					{
-						ErrHandlerLoc().get().log(componentImportError, ErrorSource::Source_GUISequenceComponent, component.getName());
-						worldScene->removeComponent<GUISequenceComponent>(p_entityID);
-					}
-					else
-						returnObject = &component;
-				}
-				else // Remove the component if it failed to initialize
-				{
-					ErrHandlerLoc().get().log(componentInitError, ErrorSource::Source_GUISequenceComponent, component.getName());
-					worldScene->removeComponent<GUISequenceComponent>(p_entityID);
-				}
-			}
-			break;
-		}
-	}
+	// Get the world scene required for attaching components to the entity
+	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
 
-	return returnObject;
-}
+	auto &component = worldScene->addComponent<GUISequenceComponent>(p_entityID, this, p_constructionInfo.m_name, p_entityID);
 
-SystemObject* GUIScene::createObject(const PropertySet& p_properties)
-{
-	// Check if property set node is present
-	if(p_properties)
+	// Try to initialize the component
+	auto componentInitError = component.init();
+	if(componentInitError == ErrorCode::Success)
 	{
-		// Check if the GUI property is present
-		auto &GUIProperty = p_properties.getPropertySetByID(Properties::GUI);
-		if(GUIProperty)
-		{
-			// Get the object name
-			auto &nameProperty = p_properties.getPropertyByID(Properties::Name);
-
-			// Find a place for the new object in the pool
-			auto GUIObjectFromPool = m_GUIObjects.newObject();
-
-			// Check if the pool wasn't full
-			if(GUIObjectFromPool != nullptr)
-			{
-				std::string name;
+		component.m_objectType = Properties::PropertyID::GUISequenceComponent;
+		component.setActive(p_constructionInfo.m_active);
 
-				// If the name property is missing, generate a unique name based on the object's index in the pool
-				if(nameProperty)
-					name = nameProperty.getString() + " (" + GetString(Properties::GUIObject) + ")";
-				else
-					name = GetString(Properties::GUIObject) + Utilities::toString(GUIObjectFromPool->getIndex());
-
-				// Construct the GUIObject
-				GUIObjectFromPool->construct(this, name);
-				auto newGUIObject = GUIObjectFromPool->getObject();
-
-				// Start importing the newly created object in a background thread
-				newGUIObject->importObject(GUIProperty);
-
-				return newGUIObject;
-			}
-			else
-			{
-				ErrHandlerLoc::get().log(ErrorCode::ObjectPool_full, ErrorSource::Source_GUIObject, "Failed to add GUIObject - \'" + nameProperty.getString() + "\'");
-			}
-		}
+		returnObject = &component;
+	}
+	else // Remove the component if it failed to initialize
+	{
+		ErrHandlerLoc().get().log(componentInitError, ErrorSource::Source_GUISequenceComponent, component.getName());
+		worldScene->removeComponent<GUISequenceComponent>(p_entityID);
 	}
 
-	// If valid type was not specified, or object creation failed, return a null object instead
-	return g_nullSystemBase.getScene()->createObject(p_properties);
+	return returnObject;
 }
 
 ErrorCode GUIScene::destroyObject(SystemObject* p_systemObject)

+ 28 - 4
Praxis3D/Source/GUIScene.h

@@ -6,6 +6,23 @@
 #include "System.h"
 
 class GUISystem;
+struct ComponentsConstructionInfo;
+
+struct GUIComponentsConstructionInfo
+{
+	GUIComponentsConstructionInfo()
+	{
+		m_guiSequenceConstructionInfo = nullptr;
+	}
+
+	void deleteConstructionInfo()
+	{
+		if(m_guiSequenceConstructionInfo != nullptr)
+			delete m_guiSequenceConstructionInfo;
+	}
+
+	GUISequenceComponent::GUISequenceComponentConstructionInfo *m_guiSequenceConstructionInfo;
+};
 
 class GUIScene : public SystemScene
 {
@@ -23,11 +40,18 @@ public:
 
 	void loadInBackground();
 
-	// Exports all the data of the scene (including all objects within) as a PropertySet (for example, used for saving to map file)
-	PropertySet exportObject() { return PropertySet(); }
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const GUIComponentsConstructionInfo &p_constructionInfo)
+	{
+		std::vector<SystemObject *> components;
+
+		if(p_constructionInfo.m_guiSequenceConstructionInfo != nullptr)
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_guiSequenceConstructionInfo));
+
+		return components;
+	}
 
-	SystemObject *createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties);
-	SystemObject *createObject(const PropertySet& p_properties);
+	SystemObject *createComponent(const EntityID p_entityID, const GUISequenceComponent::GUISequenceComponentConstructionInfo &p_constructionInfo);
 	ErrorCode destroyObject(SystemObject* p_systemObject);
 
 	void changeOccurred(ObservedSubject* p_subject, BitMask p_changeType) { }

+ 11 - 1
Praxis3D/Source/GUISequenceComponent.h

@@ -7,8 +7,18 @@
 
 class GUISequenceComponent : public SystemObject
 {
-	friend class ScriptScene;
+	friend class GUIScene;
 public:
+	struct GUISequenceComponentConstructionInfo : public SystemObject::SystemObjectConstructionInfo
+	{
+		GUISequenceComponentConstructionInfo()
+		{
+			m_staticSequence = false;
+		}
+
+		bool m_staticSequence;
+	};
+
 	GUISequenceComponent(SystemScene *p_systemScene, std::string p_name, const EntityID p_entityID, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::GUISequenceComponent, p_entityID)//, m_GUIData(*this)
 	{
 		m_staticSequence = false;

+ 5 - 2
Praxis3D/Source/InheritanceObjects.h

@@ -170,11 +170,13 @@ public:
 	{
 		m_loadedToMemory = false;
 		m_loadedToVideoMemory = false;
+		m_setActiveAfterLoading = true;
 	}	
-	LoadableGraphicsObject(bool p_loadedToMemory, bool p_loadedToVideoMemory)
+	LoadableGraphicsObject(bool p_loadedToMemory, bool p_loadedToVideoMemory, bool p_setActiveAfterLoading = true)
 	{
 		m_loadedToMemory = p_loadedToMemory;
 		m_loadedToVideoMemory = p_loadedToVideoMemory;
+		m_setActiveAfterLoading = p_setActiveAfterLoading;
 	}
 	~LoadableGraphicsObject() { }
 
@@ -191,7 +193,8 @@ public:
 
 protected:
 	bool	m_loadedToMemory,
-			m_loadedToVideoMemory;
+			m_loadedToVideoMemory,
+			m_setActiveAfterLoading;
 };
 
 // Functionality for tracking an index of a double buffer

+ 31 - 10
Praxis3D/Source/LightComponent.h

@@ -18,6 +18,26 @@ public:
 		LightComponentType_spot
 	};
 
+	struct LightComponentConstructionInfo : public SystemObject::SystemObjectConstructionInfo
+	{
+		LightComponentConstructionInfo()
+		{
+			m_color = glm::vec3(1.0f);
+			m_intensity = 1.0f;
+			m_cutoffAngle = 1.0f;
+			m_lightComponentType = LightComponentType::LightComponentType_null;
+		}
+
+		glm::vec3 m_color;
+		glm::vec3 m_direction;
+		glm::vec3 m_position;
+
+		float m_intensity;
+		float m_cutoffAngle;
+
+		LightComponentType m_lightComponentType;
+	};
+
 	LightComponent(SystemScene *p_systemScene, std::string p_name, const EntityID p_entityID, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::Lighting, p_entityID)
 	{
 		m_lightComponentType = LightComponentType::LightComponentType_null;
@@ -267,16 +287,6 @@ public:
 	inline SpotLightDataSet *getSpotLightSafe() { return (m_lightComponentType == LightComponentType::LightComponentType_spot) ? &m_lightComponent.m_spot : nullptr; }
 
 private:
-	// Union object that hold any one of the three light types
-	union m_lightComponent
-	{
-		m_lightComponent() { }
-		~m_lightComponent() { }
-
-		DirectionalLightDataSet m_directional;
-		PointLightDataSet m_point;
-		SpotLightDataSet m_spot;
-	} m_lightComponent;
 
 	inline void updateColor(const glm::vec3 &p_color)
 	{
@@ -363,5 +373,16 @@ private:
 		}
 	}
 
+	// Union object that hold any one of the three light types
+	union m_lightComponent
+	{
+		m_lightComponent() { }
+		~m_lightComponent() { }
+
+		DirectionalLightDataSet m_directional;
+		PointLightDataSet m_point;
+		SpotLightDataSet m_spot;
+	} m_lightComponent;
+
 	LightComponentType m_lightComponentType;
 };

+ 14 - 2
Praxis3D/Source/LuaComponent.h

@@ -13,6 +13,17 @@ class LuaComponent : public SystemObject, public SpatialDataManagerObject, publi
 {
 	friend class ScriptScene;
 public:
+	struct LuaComponentConstructionInfo : public SystemObject::SystemObjectConstructionInfo
+	{
+		LuaComponentConstructionInfo()
+		{
+
+		}
+
+		std::string m_luaScriptFilename;
+		std::vector<std::pair<std::string, Property>> m_variables;
+	};
+
 	LuaComponent(SystemScene *p_systemScene, std::string p_name, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::LuaComponent), m_luaSpatialData(*this), m_GUIData(*this)
 	{
 		m_luaScript = new LuaScript(m_luaSpatialData, m_GUIData);
@@ -26,7 +37,7 @@ public:
 
 	ErrorCode init() final override
 	{
-		// Mark the object as loaded, because there is nothing to be specifically loaded, at least for now
+		// Mark the object as loaded, because there is nothing to be specifically load, at least for now
 		//setLoadedToMemory(true);
 		//setLoadedToVideoMemory(true);
 
@@ -42,7 +53,8 @@ public:
 		else
 			m_luaScriptLoaded = true;
 
-		setActive(true);
+		setLoadedToMemory(true);
+		setActive(m_setActiveAfterLoading);
 	}
 
 	void update(const float p_deltaTime)

+ 6 - 0
Praxis3D/Source/LuaScript.h

@@ -132,6 +132,12 @@ public:
 	// Set the filename of the script that should be loaded
 	inline void setScriptFilename(std::string &p_filename) { m_luaScriptFilename = p_filename; }
 
+	// Set the variables so they can be accessed from inside the lua script
+	inline void setVariables(const std::vector<std::pair<std::string, Property>> &p_variables)
+	{
+		m_variables = p_variables;
+	}
+
 	// Set the variables so they can be accessed from inside the lua script
 	inline void setVariables(const PropertySet &p_properties)
 	{

+ 74 - 63
Praxis3D/Source/ModelComponent.h

@@ -8,6 +8,77 @@ class ModelComponent : public SystemObject, public LoadableGraphicsObject
 {
 	friend class RendererScene;
 public:
+	struct MeshMaterialsProperties
+	{
+		MeshMaterialsProperties()
+		{
+			m_numOfMeshes = 0;
+		}
+
+		void resize(const std::size_t p_size)
+		{
+			if(p_size > m_numOfMeshes)
+			{
+				m_numOfMeshes = p_size;
+
+
+				// Resize mesh materials
+				if(p_size > m_meshMaterials.size())
+				{
+					std::vector<std::string> emptyStrings(MaterialType::MaterialType_NumOfTypes);
+					m_meshMaterials.resize(p_size, emptyStrings);
+					//m_meshMaterials.emplace_back(emptyStrings);
+				}
+
+				// Resize mesh materials scale and initialize each element to 1.0f
+				const auto oldSize = m_meshMaterialsScale.size();
+				if(p_size > oldSize)
+				{
+					std::vector<glm::vec2> emptyVec2(MaterialType::MaterialType_NumOfTypes, glm::vec2(1.0f, 1.0f));
+					m_meshMaterialsScale.resize(p_size, emptyVec2);
+
+					//for(size_t i = oldSize; i < p_size; i++)
+					//	for(unsigned int iMatType = 0; iMatType < MaterialType::MaterialType_NumOfTypes; iMatType++)
+					//		m_meshMaterialsScale[i][iMatType] = glm::vec2(1.0f, 1.0f);
+				}
+
+				// Resize mesh material alpha threshold and initialize each element to 0.0f
+				if(p_size > m_alphaThreshold.size())
+					m_alphaThreshold.resize(p_size, 0.0f);
+
+				// Resize mesh material height scale and initialize each element to 1.0f
+				if(p_size > m_heightScale.size())
+					m_heightScale.resize(p_size, 1.0f);
+
+				// Resize the "mesh is present" array and initialize each element to false
+				if(p_size > m_present.size())
+					m_present.resize(p_size, false);
+			}
+		}
+
+		std::size_t m_numOfMeshes;
+		std::vector<std::vector<std::string>> m_meshMaterials;
+		std::vector< std::vector<glm::vec2>> m_meshMaterialsScale;
+		std::vector<float> m_alphaThreshold;
+		std::vector<float> m_heightScale;
+		std::vector<bool> m_present;
+	};
+	struct ModelsProperties
+	{
+		std::vector<std::string> m_modelNames;
+	};
+
+	struct ModelComponentConstructionInfo : public SystemObject::SystemObjectConstructionInfo
+	{
+		ModelComponentConstructionInfo()
+		{
+
+		}
+
+		ModelsProperties m_modelsProperties;
+		MeshMaterialsProperties m_materialsFromProperties;
+	};
+
 	ModelComponent(SystemScene *p_systemScene, std::string p_name, const EntityID p_entityID, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::Models, p_entityID)
 	{
 		m_materialsFromProperties = nullptr;
@@ -92,6 +163,9 @@ public:
 			}
 		}
 
+		// Set the component as loaded, because the load function was called
+		setLoadedToMemory(true);
+
 		if(m_materialsFromProperties != nullptr)
 		{
 			delete m_materialsFromProperties;
@@ -318,9 +392,6 @@ public:
 				ErrHandlerLoc().get().log(ErrorType::Info, ErrorSource::Source_ModelComponent, m_name + " - missing model data");
 		}
 		
-		// Set the component as loaded, because the load function was called
-		setLoadedToMemory(true);
-
 		return importError;
 	}
 
@@ -371,66 +442,6 @@ public:
 	const inline std::vector<ModelData> &getModelData() const { return m_modelData; }
 
 private:
-	struct MeshMaterialsProperties
-	{
-		MeshMaterialsProperties()
-		{
-			m_numOfMeshes = 0;
-		}
-
-		void resize(const std::size_t p_size)
-		{
-			if(p_size > m_numOfMeshes)
-			{
-				m_numOfMeshes = p_size;
-
-
-				// Resize mesh materials
-				if(p_size > m_meshMaterials.size())
-				{
-					std::vector<std::string> emptyStrings(MaterialType::MaterialType_NumOfTypes);
-					m_meshMaterials.resize(p_size, emptyStrings);
-					//m_meshMaterials.emplace_back(emptyStrings);
-				}
-
-				// Resize mesh materials scale and initialize each element to 1.0f
-				const auto oldSize = m_meshMaterialsScale.size();
-				if(p_size > oldSize)
-				{
-					std::vector<glm::vec2> emptyVec2(MaterialType::MaterialType_NumOfTypes, glm::vec2(1.0f, 1.0f));
-					m_meshMaterialsScale.resize(p_size, emptyVec2);
-
-					//for(size_t i = oldSize; i < p_size; i++)
-					//	for(unsigned int iMatType = 0; iMatType < MaterialType::MaterialType_NumOfTypes; iMatType++)
-					//		m_meshMaterialsScale[i][iMatType] = glm::vec2(1.0f, 1.0f);
-				}
-
-				// Resize mesh material alpha threshold and initialize each element to 0.0f
-				if(p_size > m_alphaThreshold.size())
-					m_alphaThreshold.resize(p_size, 0.0f);
-
-				// Resize mesh material height scale and initialize each element to 1.0f
-				if(p_size > m_heightScale.size())
-					m_heightScale.resize(p_size, 1.0f);
-
-				// Resize the "mesh is present" array and initialize each element to false
-				if(p_size > m_present.size())
-					m_present.resize(p_size, false);
-			}
-		}
-
-		std::size_t m_numOfMeshes;
-		std::vector<std::vector<std::string>> m_meshMaterials;
-		std::vector< std::vector<glm::vec2>> m_meshMaterialsScale;
-		std::vector<float> m_alphaThreshold;
-		std::vector<float> m_heightScale;
-		std::vector<bool> m_present;
-	};
-	struct ModelsProperties
-	{
-		std::vector<std::string> m_modelNames;
-	};
-
 	inline MaterialData loadMaterialData(PropertySet &p_materialProperty, Model::MaterialArrays &p_materialArraysFromModel, MaterialType p_materialType, std::size_t p_meshIndex)
 	{
 		// Declare the material data that is to be returned and a flag showing whether the material data was loaded successfully

+ 5 - 0
Praxis3D/Source/NullSystemObjects.cpp

@@ -24,6 +24,11 @@ SystemObject *NullSystemScene::createObject(const PropertySet &p_properties)
 	return &m_nullSystemObject;
 }
 
+SystemObject *NullSystemScene::getNullObject()
+{
+	return &m_nullSystemObject;
+}
+
 SystemTask *NullSystemScene::getSystemTask()
 {
 	return &m_nullSystemTask;

+ 1 - 0
Praxis3D/Source/NullSystemObjects.h

@@ -51,6 +51,7 @@ public:
 
 	SystemObject *createObject(const PropertySet &p_properties);
 	ErrorCode destroyObject(SystemObject *p_systemObject) { return ErrorCode::Success; }
+	virtual SystemObject *getNullObject();
 
 	SystemTask *getSystemTask();
 	BitMask getDesiredSystemChanges() { return Systems::Changes::None; };

+ 13 - 2
Praxis3D/Source/PhysicsMotionState.h

@@ -39,8 +39,16 @@ public:
 	// Get the world transform in the form of glm::mat4
 	const inline glm::mat4 &getWorldTransform() const { return m_graphicsWorldTrans; }
 
-	const glm::vec3 getPosition()		const { return Math::toGlmVec3(m_centerOfMassWorldTrans.getOrigin());	}
-	const glm::quat getRotation()		const { return Math::toGlmQuat(m_centerOfMassWorldTrans.getRotation()); }
+	const glm::vec3 &getPosition() const
+	{ 
+		m_tempPosition = Math::toGlmVec3(m_centerOfMassWorldTrans.getOrigin());
+		return m_tempPosition;
+	}
+	const glm::quat &getRotation() const
+	{ 
+		m_tempRotation = Math::toGlmQuat(m_centerOfMassWorldTrans.getRotation());
+		return m_tempRotation;
+	}
 
 	void setPosition(const glm::vec3 &p_position)
 	{
@@ -96,6 +104,9 @@ public:
 	const inline void resetMotionStateDirtyFlag() { m_motionStateDirty = false; }
 
 private:
+	// Mutable spatial data used in const getters required by on observer
+	mutable glm::vec3 m_tempPosition;
+	mutable glm::quat m_tempRotation;
 
 	btTransform m_centerOfMassWorldTrans;
 	glm::mat4 m_graphicsWorldTrans;

+ 91 - 110
Praxis3D/Source/PhysicsScene.cpp

@@ -1,3 +1,4 @@
+#include "ComponentConstructorInfo.h"
 #include "NullSystemObjects.h"
 #include "PhysicsScene.h"
 #include "TaskManagerLocator.h"
@@ -139,139 +140,119 @@ void PhysicsScene::loadInBackground()
 {
 }
 
-SystemObject *PhysicsScene::createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties)
-{	
+std::vector<SystemObject*> PhysicsScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
+{
+	return createComponents(p_entityID, p_constructionInfo.m_physicsComponents);
+}
+
+SystemObject *PhysicsScene::createComponent(const EntityID &p_entityID, const RigidBodyComponent::RigidBodyComponentConstructionInfo &p_constructionInfo)
+{
 	// If valid type was not specified, or object creation failed, return a null object instead
-	SystemObject *returnObject = g_nullSystemBase.getScene()->createObject(p_properties);
+	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();
 
-	// Check if property set node is present
-	if(p_properties)
-	{
-		// Get the world scene required for attaching components to the entity
-		WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+	// 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);
 
-		switch(p_properties.getPropertyID())
+	// 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)
 		{
-		case Properties::PropertyID::RigidBodyComponent:
+			switch(component.m_collisionShapeType)
 			{
-				auto &component = worldScene->addComponent<RigidBodyComponent>(p_entityID, this, p_entityName + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::RigidBodyComponent), p_entityID);
-
-				// Try to initialize the camera component
-				auto componentInitError = component.init();
-				if(componentInitError == ErrorCode::Success)
+				case RigidBodyComponent::CollisionShapeType::CollisionShapeType_Box:
 				{
-					// Try to import the component
-					auto const &componentImportError = component.importObject(p_properties);
-
-					// Create the rigid body inside the dynamics world, if it was imported successfully
-					if(componentImportError == ErrorCode::Success)
-					{
-						//btCollisionShape *collisionShape = component.getCollisionShape();
-
-
-						//btVector3 localInertia(0, 0, 0);
-						// If mass is not zero, rigid body is dynamic; in that case, calculate local inertia 
-						//if(component.m_mass != 0.0f)
-						//	collisionShape->calculateLocalInertia(component.m_mass, 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();
-						}
-						
-						// Set the required information for the rigid body constructor and create the rigid body
-						//btRigidBody::btRigidBodyConstructionInfo rigidBodyConstructor(component.m_mass, &component.m_motionState, collisionShape, localInertia);
-
-						// 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);						
-						}
-
-						// 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 failed to import
-					{
-						worldScene->removeComponent<RigidBodyComponent>(p_entityID);
-						ErrHandlerLoc().get().log(componentImportError, ErrorSource::Source_RigidBodyComponent, p_entityName);
-					}
+					btVector3 boxHalfExtents = Math::toBtVector3(p_constructionInfo.m_collisionShapeSize);
+					component.m_collisionShape.m_boxShape = new btBoxShape(boxHalfExtents);
 				}
-				else // Remove the component if it failed to initialize
+				break;
+
+				case RigidBodyComponent::CollisionShapeType::CollisionShapeType_Sphere:
 				{
-					worldScene->removeComponent<RigidBodyComponent>(p_entityID);
-					ErrHandlerLoc().get().log(componentInitError, ErrorSource::Source_RigidBodyComponent, p_entityName);
+					float radius = p_constructionInfo.m_collisionShapeSize.x;
+					component.m_collisionShape.m_sphereShape = new btSphereShape(radius);
 				}
+				break;
 			}
-			break;
 
-		}
-	}
+			// Success on the loaded collision shape
+			ErrHandlerLoc().get().log(ErrorType::Info, ErrorSource::Source_RigidBodyComponent, component.getName() + " - Collision shape loaded");
 
-	return returnObject;
-}
-
-SystemObject *PhysicsScene::createObject(const PropertySet &p_properties)
-{	
-	/*/ Check if property set node is present
-	if(p_properties)
-	{
-		// Check if the Physics property is present
-		auto &physicsProperty = p_properties.getPropertySetByID(Properties::Physics);
-		if(physicsProperty)
-		{
-			// Get the object name
-			auto &nameProperty = p_properties.getPropertyByID(Properties::Name);
+			// 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());
 
-			// Find a place for the new object in the pool
-			auto physicsObjectFromPool = m_physicsObjects.newObject();
+			component.m_constructionInfo->m_friction = p_constructionInfo.m_friction;
+			component.m_constructionInfo->m_restitution = p_constructionInfo.m_restitution;
 
-			// Check if the pool wasn't full
-			if(physicsObjectFromPool != nullptr)
+			// If mass is not zero, rigid body is dynamic; in that case, calculate the local inertia 
+			if(component.m_constructionInfo->m_mass != 0.0f)
 			{
-				std::string name;
-
-				// If the name property is missing, generate a unique name based on the object's index in the pool
-				if(nameProperty)
-					name = nameProperty.getString() + " (" + GetString(Properties::PhysicsObject) + ")";
+				// 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
-					name = GetString(Properties::PhysicsObject) + Utilities::toString(physicsObjectFromPool->getIndex());
+					component.getCollisionShape()->calculateLocalInertia(component.m_constructionInfo->m_mass, component.m_constructionInfo->m_localInertia);
+			}
 
-				// Construct the PhysicsObject
-				physicsObjectFromPool->construct(this, name);
-				auto newGUIObject = physicsObjectFromPool->getObject();
+			// 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();
+			}
 
-				// Start importing the newly created object in a background thread
-				newGUIObject->importObject(physicsProperty);
+			// Add the collision shape
+			m_collisionShapes.push_back(component.getCollisionShape());
 
-				return newGUIObject;
-			}
-			else
+			// Create the rigid body by passing the rigid body construction info
+			component.m_rigidBody = new btRigidBody(*component.m_constructionInfo);
+
+			if(component.m_kinematic)
 			{
-				ErrHandlerLoc::get().log(ErrorCode::ObjectPool_full, ErrorSource::Source_GUIObject, "Failed to add PhysicsObject - \'" + nameProperty.getString() + "\'");
+				component.m_rigidBody->setCollisionFlags(component.m_rigidBody->getCollisionFlags() | btCollisionObject::CollisionFlags::CF_KINEMATIC_OBJECT);
+				component.m_rigidBody->setActivationState(DISABLE_DEACTIVATION);
 			}
+
+			// 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());
+	}
 
-	// If valid type was not specified, or object creation failed, return a null object instead
-	return g_nullSystemBase.getScene()->createObject(p_properties);
+	return returnObject;
 }
 
 ErrorCode PhysicsScene::destroyObject(SystemObject *p_systemObject)

+ 28 - 4
Praxis3D/Source/PhysicsScene.h

@@ -36,6 +36,23 @@
 #include "PhysicsTask.h"
 
 class PhysicsSystem;
+struct ComponentsConstructionInfo;
+
+struct PhysicsComponentsConstructionInfo
+{
+	PhysicsComponentsConstructionInfo()
+	{
+		m_rigidBodyConstructionInfo = nullptr;
+	}
+
+	void deleteConstructionInfo()
+	{
+		if(m_rigidBodyConstructionInfo != nullptr)
+			delete m_rigidBodyConstructionInfo;
+	}
+
+	RigidBodyComponent::RigidBodyComponentConstructionInfo *m_rigidBodyConstructionInfo;
+};
 
 class PhysicsScene : public SystemScene
 {
@@ -53,11 +70,18 @@ public:
 
 	void loadInBackground();
 
-	// Exports all the data of the scene (including all objects within) as a PropertySet (for example, used for saving to map file)
-	PropertySet exportObject() { return PropertySet(); }
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const PhysicsComponentsConstructionInfo &p_constructionInfo)
+	{
+		std::vector<SystemObject*> components;
+
+		if(p_constructionInfo.m_rigidBodyConstructionInfo != nullptr)
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_rigidBodyConstructionInfo));
+
+		return components;
+	}
 
-	SystemObject *createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties);
-	SystemObject *createObject(const PropertySet &p_properties);
+	SystemObject *createComponent(const EntityID &p_entityID, const RigidBodyComponent::RigidBodyComponentConstructionInfo &p_constructionInfo);
 	ErrorCode destroyObject(SystemObject *p_systemObject);
 
 	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) { }

File diff suppressed because it is too large
+ 156 - 770
Praxis3D/Source/RendererScene.cpp


+ 61 - 93
Praxis3D/Source/RendererScene.h

@@ -22,6 +22,39 @@
 
 class RendererSystem;
 
+struct GraphicsComponentsConstructionInfo
+{
+	GraphicsComponentsConstructionInfo()
+	{
+		m_cameraConstructionInfo = nullptr;
+		m_lightConstructionInfo = nullptr;
+		m_modelConstructionInfo = nullptr;
+		m_shaderConstructionInfo = nullptr;
+	}
+
+	void deleteConstructionInfo()
+	{
+		if(m_cameraConstructionInfo != nullptr)
+			delete m_cameraConstructionInfo;
+
+		if(m_lightConstructionInfo != nullptr)
+			delete m_lightConstructionInfo;
+
+		if(m_modelConstructionInfo != nullptr)
+			delete m_modelConstructionInfo;
+
+		if(m_shaderConstructionInfo != nullptr)
+			delete m_shaderConstructionInfo;
+
+		//GraphicsComponentsConstructionInfo();
+	}
+
+	CameraComponent::CameraComponentConstructionInfo *m_cameraConstructionInfo;
+	LightComponent::LightComponentConstructionInfo *m_lightConstructionInfo;
+	ModelComponent::ModelComponentConstructionInfo *m_modelConstructionInfo;
+	ShaderComponent::ShaderComponentConstructionInfo *m_shaderConstructionInfo;
+};
+
 struct LoadableComponentContainer
 {
 	LoadableComponentContainer(ModelComponent &p_model)
@@ -87,14 +120,34 @@ public:
 	// Starts loading all the created objects in background threads
 	void loadInBackground();
 
-	// Exports all the data of the scene (including all objects within) as a PropertySet
-	virtual PropertySet exportObject();
-
 	// Processes all the objects and puts them in the separate vectors
 	void update(const float p_deltaTime);
-	
-	SystemObject *createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties);
-	SystemObject *createObject(const PropertySet &p_properties);
+
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const GraphicsComponentsConstructionInfo &p_constructionInfo)
+	{
+		std::vector<SystemObject *> components;
+
+		if(p_constructionInfo.m_cameraConstructionInfo != nullptr)
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_cameraConstructionInfo));
+
+		if(p_constructionInfo.m_lightConstructionInfo != nullptr)
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_lightConstructionInfo));
+
+		if(p_constructionInfo.m_modelConstructionInfo != nullptr)
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_modelConstructionInfo));
+
+		if(p_constructionInfo.m_shaderConstructionInfo != nullptr)
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_shaderConstructionInfo));
+
+		return components;
+	}
+
+	SystemObject *createComponent(const EntityID &p_entityID, const CameraComponent::CameraComponentConstructionInfo &p_constructionInfo);
+	SystemObject *createComponent(const EntityID &p_entityID, const LightComponent::LightComponentConstructionInfo &p_constructionInfo);
+	SystemObject *createComponent(const EntityID &p_entityID, const ModelComponent::ModelComponentConstructionInfo &p_constructionInfo);
+	SystemObject *createComponent(const EntityID &p_entityID, const ShaderComponent::ShaderComponentConstructionInfo &p_constructionInfo);
+
 	ErrorCode destroyObject(SystemObject *p_systemObject);
 
 	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType);
@@ -108,61 +161,6 @@ public:
 	inline SceneObjects &getSceneObjects() { return m_sceneObjects; }
 	
 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(GraphicsObject &p_object)
-	{
-		// Go over each graphics object
-		for(decltype(m_graphicsObjPool.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_graphicsObjPool.getNumAllocated(),
-			size = m_graphicsObjPool.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
-		{
-			// Check if the graphics object is allocated inside the pool container
-			if(m_graphicsObjPool[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 graphics object pool
-				if(*m_graphicsObjPool[i].getObject() == p_object)
-				{
-					m_graphicsObjPool.remove(m_graphicsObjPool[i].getIndex());
-					return true;
-				}
-			}
-		}
-
-		return false;
-	}
-	
-	/*/ Checks if an object is allocated in an object pool
-	inline bool checkIfAllocated(const LoadableGraphicsObject &p_object)
-	{
-		// Remove object from the pool determined by object's type
-		switch(p_object.getObjectType())
-		{
-		case Properties::ModelObject:
-			
-			// Get a pool object by it's index and check if it's allocated
-			return m_modelObjPool.getObject(p_object.getIndex())->allocated();
-			
-			break;
-		}
-	}*/
-
-	// Finds a match in the currently being loaded object array; returns null pointer if no match is found
-	inline LoadableGraphicsObject *getCurrentlyLoadingObject(SystemObject &p_loadableObject)
-	{
-		// Iterate over currently loading objects
-		for(decltype(m_objectsLoadingToMemory.size()) i = 0, size = m_objectsLoadingToMemory.size(); i < size;)
-		{
-			// Compare pointers, if match is found, return the object
-			if(*m_objectsLoadingToMemory[i] == p_loadableObject)
-				return m_objectsLoadingToMemory[i];
-		}
-
-		// If this point is reached - object wasn't found, return a null pointer
-		return nullptr;
-	}
-
 	inline void calculateCamera(SpatialTransformData &p_viewData)
 	{
 		/*p_viewData.m_spatialData.m_rotationEuler = Math::toRadian(p_viewData.m_spatialData.m_rotationEuler);
@@ -207,39 +205,9 @@ private:
 
 	MaterialData loadMaterialData(PropertySet &p_materialProperty, Model::MaterialArrays &p_materialArraysFromModel, MaterialType p_materialType, std::size_t p_meshIndex);
 
-	// Object component creators (factories)
-	ModelComponent *loadModelComponent(const PropertySet &p_properties);
-	ShaderComponent *loadShaderComponent(const PropertySet &p_properties);
-	LightComponent *loadLightComponent(const PropertySet &p_properties);
-
-	ModelObject *loadModelObject(const PropertySet &p_properties);
-	CameraObject *loadCameraObject(const PropertySet &p_properties);
-	EnvironmentMapObject *loadEnvironmentMap(const PropertySet &p_properties);
-	DirectionalLightObject *loadDirectionalLight(const PropertySet &p_properties);
-	PointLightObject *loadPointLight(const PropertySet &p_properties);
-	SpotLightObject *loadSpotLight(const PropertySet &p_properties);
-		
-	// Object pools
-	// OLD
-	//ObjectPool<ModelObject> m_modelObjPool;
-	//ObjectPool<ModelObject> m_shaderObjPool;
-	//ObjectPool<PointLightObject> m_pointLightPool;
-	//ObjectPool<SpotLightObject> m_spotLightPool;
-	//ObjectPool<EnvironmentMapObject> m_envMapPool;
-
+	// Stores objects that are currently being loaded to memory in a background thread
 	std::list<LoadableComponentContainer> m_componentsLoadingToMemory;
-
-	//NEW
-	ObjectPool<GraphicsObject> m_graphicsObjPool;
-	std::vector<GraphicsObject*> m_objectsLoadingToMemory;
-	std::vector<GraphicsObject*> m_objectsToDestroy;
-
-	ObjectPool<LightComponent> m_lightComponents;
-	std::vector<ModelComponentData> m_modelComponents;
-
-	// Stores objects that are currently being loaded to memory in background thread
-	//std::vector<LoadableGraphicsObject> m_objectsBeingLoaded;
-	
+		
 	EnvironmentMapObject *m_skybox;
 
 	// Only one camera present at a time

+ 20 - 0
Praxis3D/Source/RigidBodyComponent.h

@@ -18,6 +18,26 @@ public:
 		CollisionShapeType_Sphere
 	};
 
+	struct RigidBodyComponentConstructionInfo : public SystemObject::SystemObjectConstructionInfo
+	{
+		RigidBodyComponentConstructionInfo()
+		{
+			m_friction = 0.5f;
+			m_mass = 0.0f;
+			m_restitution = 0.0f;
+			m_kinematic = false;
+			m_collisionShapeType = CollisionShapeType::CollisionShapeType_Null;
+			m_collisionShapeSize = glm::vec3(0.5f);
+		}
+
+		float m_friction;
+		float m_mass;
+		float m_restitution;
+		bool m_kinematic;
+		CollisionShapeType m_collisionShapeType;
+		glm::vec3 m_collisionShapeSize;
+	};
+
 	RigidBodyComponent(SystemScene *p_systemScene, std::string p_name, const EntityID p_entityID, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::RigidBodyComponent, p_entityID)
 	{
 		m_collisionShapeType = CollisionShapeType::CollisionShapeType_Null;

+ 505 - 3
Praxis3D/Source/SceneLoader.cpp

@@ -2,6 +2,7 @@
 #include <utility>
 #include <vector>
 
+#include "ComponentConstructorInfo.h"
 #include "PropertyLoader.h"
 #include "SceneLoader.h"
 
@@ -9,6 +10,8 @@ ErrorCode SceneLoader::loadFromFile(const std::string &p_filename)
 {
 	ErrorCode returnError = ErrorCode::Success;
 
+	EntitiesConstructionInfo constructionInfo;
+
 	// Load properties from file
 	PropertyLoader loadedProperties(Config::filepathVar().map_path + p_filename);
 	returnError = loadedProperties.loadFromFile();
@@ -49,12 +52,25 @@ ErrorCode SceneLoader::loadFromFile(const std::string &p_filename)
 
 		if(gameObjects)
 		{
+			constructionInfo.resize(gameObjects.getNumPropertySets());
+
 			// Iterate over all game object
 			for(decltype(gameObjects.getNumPropertySets()) objIndex = 0, objSize = gameObjects.getNumPropertySets(); objIndex < objSize; objIndex++)
 			{
 				// Create each game object by passing its PropertySet
-				m_systemScenes[Systems::World]->createObject(gameObjects.getPropertySetUnsafe(objIndex));
+				//m_systemScenes[Systems::World]->createObject(gameObjects.getPropertySetUnsafe(objIndex));
+
+				importFromProperties(constructionInfo[objIndex], gameObjects.getPropertySetUnsafe(objIndex));
+			}
+
+			WorldScene *worldScene = static_cast<WorldScene*>(m_systemScenes[Systems::World]);
+
+			for(decltype(constructionInfo.size()) i = 0, size = constructionInfo.size(); i < size; i++)
+			{
+				worldScene->createEntity(constructionInfo[i]);
 			}
+
+			std::cout << "TEST" << std::endl;
 		}
 		else
 		{
@@ -142,8 +158,8 @@ ErrorCode SceneLoader::saveToFile(const std::string p_filename)
 		auto &systems = propertySet.addPropertySet(Properties::Systems);
 
 		// Add each system's properties
-		for(size_t i = 0; i < Systems::NumberOfSystems; i++)
-			systems.addPropertySet(m_systemScenes[i]->exportObject());
+		//for(size_t i = 0; i < Systems::NumberOfSystems; i++)
+		//	systems.addPropertySet(m_systemScenes[i]->exportObject());
 
 		// Add root property set for object links
 		auto &objLinksPropertySet = propertySet.addPropertySet(Properties::ObjectLinks);
@@ -172,3 +188,489 @@ ErrorCode SceneLoader::saveToFile(const std::string p_filename)
 	// TODO ERROR empty filename
 	return ErrorCode::Failure;
 }
+
+void SceneLoader::importFromProperties(ComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties)
+{
+	// Get the object name and ID
+	std::string name = p_properties.getPropertyByID(Properties::Name).getString();
+	EntityID desiredEntityID = (EntityID)p_properties.getPropertyByID(Properties::ID).getInt();
+
+	// If the name property is missing, generate a unique name based on the entity ID
+	if(name.empty())
+		name = GetString(Properties::GameObject) + Utilities::toString(desiredEntityID);
+
+	p_constructionInfo.m_name = name;
+	p_constructionInfo.m_id = desiredEntityID;
+
+	// Load property data
+	for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
+	{
+		switch(p_properties[i].getPropertyID())
+		{
+			case Properties::Parent:
+			{
+				// Get the entity ID if the parent object
+				p_constructionInfo.m_parent = (EntityID)p_properties[i].getInt();
+			}
+			break;
+		}
+	}
+
+	{
+		auto &sceneProperty = p_properties.getPropertySetByID(Properties::Rendering);
+		if(sceneProperty)
+		{
+			for(decltype(sceneProperty.getNumPropertySets()) i = 0, size = sceneProperty.getNumPropertySets(); i < size; i++)
+			{
+				importFromProperties(p_constructionInfo.m_graphicsComponents, sceneProperty.getPropertySet(i), name);
+			}
+		}
+	}
+
+	{
+		auto &sceneProperty = p_properties.getPropertySetByID(Properties::GUI);
+		if(sceneProperty)
+		{
+			for(decltype(sceneProperty.getNumPropertySets()) i = 0, size = sceneProperty.getNumPropertySets(); i < size; i++)
+			{
+				importFromProperties(p_constructionInfo.m_guiComponents, sceneProperty.getPropertySet(i), name);
+			}
+		}
+	}
+
+	{
+		auto &sceneProperty = p_properties.getPropertySetByID(Properties::Physics);
+		if(sceneProperty)
+		{
+			for(decltype(sceneProperty.getNumPropertySets()) i = 0, size = sceneProperty.getNumPropertySets(); i < size; i++)
+			{
+				importFromProperties(p_constructionInfo.m_physicsComponents, sceneProperty.getPropertySet(i), name);
+			}
+		}
+	}
+
+	{
+		auto &sceneProperty = p_properties.getPropertySetByID(Properties::Script);
+		if(sceneProperty)
+		{
+			for(decltype(sceneProperty.getNumPropertySets()) i = 0, size = sceneProperty.getNumPropertySets(); i < size; i++)
+			{
+				importFromProperties(p_constructionInfo.m_scriptComponents, sceneProperty.getPropertySet(i), name);
+			}
+		}
+	}
+
+	{
+		auto &sceneProperty = p_properties.getPropertySetByID(Properties::World);
+		if(sceneProperty)
+		{
+			for(decltype(sceneProperty.getNumPropertySets()) i = 0, size = sceneProperty.getNumPropertySets(); i < size; i++)
+			{
+				importFromProperties(p_constructionInfo.m_worldComponents, sceneProperty.getPropertySet(i), name);
+			}
+		}
+	}
+}
+
+void SceneLoader::importFromProperties(GraphicsComponentsConstructionInfo &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::CameraComponent:
+			{
+				if(p_constructionInfo.m_cameraConstructionInfo == nullptr)
+					p_constructionInfo.m_cameraConstructionInfo = new CameraComponent::CameraComponentConstructionInfo();
+
+				p_constructionInfo.m_cameraConstructionInfo->m_name = p_name + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::CameraComponent);
+			}
+			break;
+
+			case Properties::PropertyID::LightComponent:
+			{
+				if(p_constructionInfo.m_lightConstructionInfo == nullptr)
+					p_constructionInfo.m_lightConstructionInfo = new LightComponent::LightComponentConstructionInfo();
+
+				p_constructionInfo.m_lightConstructionInfo->m_name = p_name + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::LightComponent);
+
+				// Get the light type
+				auto const &type = p_properties.getPropertyByID(Properties::Type).getID();
+
+				// Load values based on the type of light
+				switch(type)
+				{
+				case Properties::DirectionalLight:
+
+					p_constructionInfo.m_lightConstructionInfo->m_lightComponentType = LightComponent::LightComponentType::LightComponentType_directional;
+
+					p_constructionInfo.m_lightConstructionInfo->m_color = p_properties.getPropertyByID(Properties::Color).getVec3f();
+					p_constructionInfo.m_lightConstructionInfo->m_intensity = p_properties.getPropertyByID(Properties::Intensity).getFloat();
+
+					break;
+
+				case Properties::PointLight:
+
+					p_constructionInfo.m_lightConstructionInfo->m_lightComponentType = LightComponent::LightComponentType::LightComponentType_point;
+
+					p_constructionInfo.m_lightConstructionInfo->m_color = p_properties.getPropertyByID(Properties::Color).getVec3f();
+					p_constructionInfo.m_lightConstructionInfo->m_intensity = p_properties.getPropertyByID(Properties::Intensity).getFloat();
+
+					break;
+
+				case Properties::SpotLight:
+
+					p_constructionInfo.m_lightConstructionInfo->m_lightComponentType = LightComponent::LightComponentType::LightComponentType_spot;
+
+					p_constructionInfo.m_lightConstructionInfo->m_color = p_properties.getPropertyByID(Properties::Color).getVec3f();
+					p_constructionInfo.m_lightConstructionInfo->m_cutoffAngle = p_properties.getPropertyByID(Properties::CutoffAngle).getFloat();
+					p_constructionInfo.m_lightConstructionInfo->m_intensity = p_properties.getPropertyByID(Properties::Intensity).getFloat();
+
+					break;
+
+				default:
+
+					ErrHandlerLoc().get().log(ErrorType::Warning, ErrorSource::Source_LightComponent, p_name + " - missing \'Type\' identifier");
+					delete p_constructionInfo.m_lightConstructionInfo;
+					p_constructionInfo.m_lightConstructionInfo = nullptr;
+
+					break;
+				}
+			}
+			break;
+
+			case Properties::PropertyID::ModelComponent:
+			{
+				if(p_constructionInfo.m_modelConstructionInfo == nullptr)
+					p_constructionInfo.m_modelConstructionInfo = new ModelComponent::ModelComponentConstructionInfo();
+
+				p_constructionInfo.m_modelConstructionInfo->m_name = p_name + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::ModelComponent);
+
+				auto &modelsProperty = p_properties.getPropertySetByID(Properties::Models);
+
+				if(modelsProperty)
+				{
+					// Loop over each model entry in the node
+					for(decltype(modelsProperty.getNumPropertySets()) iModel = 0, numModels = modelsProperty.getNumPropertySets(); iModel < numModels; iModel++)
+					{
+						// Get model filename
+						auto modelName = modelsProperty.getPropertySet(iModel).getPropertyByID(Properties::Filename).getString();
+
+						// Add a new model data entry, and get a reference to it
+						p_constructionInfo.m_modelConstructionInfo->m_modelsProperties.m_modelNames.push_back(modelName);
+
+						auto &meshesProperty = modelsProperty.getPropertySet(iModel).getPropertySetByID(Properties::Meshes);
+
+						// Check if the meshes array node is present;
+						// If it is present, only add the meshes included in the meshes node
+						// If it is not present, add all the meshes included in the model
+						if(meshesProperty)
+						{
+							if(meshesProperty.getNumPropertySets() > 0)
+							{
+								// Loop over each mesh entry in the model node
+								for(decltype(meshesProperty.getNumPropertySets()) iMesh = 0, numMeshes = meshesProperty.getNumPropertySets(); iMesh < numMeshes; iMesh++)
+								{
+									// Try to get the mesh index property node and check if it is present
+									auto &meshIndexProperty = meshesProperty.getPropertySet(iMesh).getPropertyByID(Properties::Index);
+									if(meshIndexProperty)
+									{
+										// Get the mesh index, check if it is valid and within the range of mesh array that was loaded from the model
+										const int meshDataIndex = meshIndexProperty.getInt();
+
+										// Make sure the meshMaterials vector can fit the given mesh index
+										if(meshDataIndex >= p_constructionInfo.m_modelConstructionInfo->m_materialsFromProperties.m_meshMaterials.size())
+										{
+											p_constructionInfo.m_modelConstructionInfo->m_materialsFromProperties.resize(meshDataIndex + 1);
+											p_constructionInfo.m_modelConstructionInfo->m_materialsFromProperties.m_present[meshDataIndex] = true;
+										}
+
+										// Get material alpha threshold value, if it is present
+										auto alphaThresholdProperty = meshesProperty.getPropertySet(iMesh).getPropertyByID(Properties::AlphaThreshold);
+										if(alphaThresholdProperty)
+											p_constructionInfo.m_modelConstructionInfo->m_materialsFromProperties.m_alphaThreshold[meshDataIndex] = alphaThresholdProperty.getFloat();
+
+										// Get material height scale value, if it is present
+										auto heightScaleProperty = meshesProperty.getPropertySet(iMesh).getPropertyByID(Properties::HeightScale);
+										if(heightScaleProperty)
+											p_constructionInfo.m_modelConstructionInfo->m_materialsFromProperties.m_heightScale[meshDataIndex] = heightScaleProperty.getFloat();
+
+										// Get material properties
+										auto materialsProperty = meshesProperty.getPropertySet(iMesh).getPropertySetByID(Properties::Materials);
+
+										// Define material data and material properties
+										MaterialData materials[MaterialType::MaterialType_NumOfTypes];
+										PropertySet materialProperties[MaterialType::MaterialType_NumOfTypes] =
+										{
+											materialsProperty.getPropertySetByID(Properties::Diffuse),
+											materialsProperty.getPropertySetByID(Properties::Normal),
+											materialsProperty.getPropertySetByID(Properties::Emissive),
+											materialsProperty.getPropertySetByID(Properties::RMHAO)
+										};
+
+										// Go over each material type
+										for(unsigned int iMatType = 0; iMatType < MaterialType::MaterialType_NumOfTypes; iMatType++)
+										{
+											// Check if an entry for the current material type was present within the properties
+											if(materialProperties[iMatType])
+											{
+												// Get texture filename property, check if it is valid
+												auto filenameProperty = materialProperties[iMatType].getPropertyByID(Properties::Filename);
+												if(filenameProperty.isVariableTypeString())
+												{
+													// Get texture filename string, check if it is valid
+													p_constructionInfo.m_modelConstructionInfo->m_materialsFromProperties.m_meshMaterials[meshDataIndex][iMatType] = filenameProperty.getString();
+												}
+
+												// Get texture scale property, check if it is valid
+												auto scaleProperty = materialProperties[iMatType].getPropertyByID(Properties::TextureScale);
+												if(scaleProperty)
+													p_constructionInfo.m_modelConstructionInfo->m_materialsFromProperties.m_meshMaterialsScale[meshDataIndex][iMatType] = scaleProperty.getVec2f();
+											}
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+
+				if(p_properties.getNumPropertySets() == 0)
+					ErrHandlerLoc().get().log(ErrorType::Info, ErrorSource::Source_ModelComponent, p_name + " - missing model data");
+			}
+			break;
+
+			case Properties::PropertyID::ShaderComponent:
+			{
+				if(p_constructionInfo.m_shaderConstructionInfo == nullptr)
+					p_constructionInfo.m_shaderConstructionInfo = new ShaderComponent::ShaderComponentConstructionInfo();
+
+				p_constructionInfo.m_shaderConstructionInfo->m_name = p_name + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::ShaderComponent);
+
+				// Get nodes for different shader types
+				auto geometryShaderNode = p_properties.getPropertyByID(Properties::GeometryShader);
+				auto vertexShaderNode = p_properties.getPropertyByID(Properties::VertexShader);
+				auto fragmentShaderNode = p_properties.getPropertyByID(Properties::FragmentShader);
+
+				if(geometryShaderNode)
+					p_constructionInfo.m_shaderConstructionInfo->m_geometryShaderFilename = geometryShaderNode.getString();
+
+				if(vertexShaderNode)
+					p_constructionInfo.m_shaderConstructionInfo->m_vetexShaderFilename = vertexShaderNode.getString();
+
+				if(fragmentShaderNode)
+					p_constructionInfo.m_shaderConstructionInfo->m_fragmentShaderFilename = fragmentShaderNode.getString();
+			}
+			break;
+		}
+	}
+}
+
+void SceneLoader::importFromProperties(GUIComponentsConstructionInfo &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::Sequence:
+			{
+				if(p_constructionInfo.m_guiSequenceConstructionInfo == nullptr)
+					p_constructionInfo.m_guiSequenceConstructionInfo = new GUISequenceComponent::GUISequenceComponentConstructionInfo();
+
+				p_constructionInfo.m_guiSequenceConstructionInfo->m_name = p_name + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::GUISequenceComponent);
+
+			}
+			break;
+		}
+	}
+}
+
+void SceneLoader::importFromProperties(PhysicsComponentsConstructionInfo &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::RigidBodyComponent:
+		{
+			if(p_constructionInfo.m_rigidBodyConstructionInfo == nullptr)
+				p_constructionInfo.m_rigidBodyConstructionInfo = new RigidBodyComponent::RigidBodyComponentConstructionInfo();
+
+			p_constructionInfo.m_rigidBodyConstructionInfo->m_name = p_name + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::RigidBodyComponent);
+
+			// --------------------
+			// Load collision shape
+			// --------------------
+			auto const &collisionShapeProperty = p_properties.getPropertySetByID(Properties::CollisionShape);
+			if(collisionShapeProperty)
+			{
+				// Get the type of the collision shape and load the data based on it
+				auto const &typeProperty = collisionShapeProperty.getPropertyByID(Properties::Type);
+				if(typeProperty)
+				{
+					switch(typeProperty.getID())
+					{
+					case Properties::Box:
+					{
+						// Get the size property
+						auto const &sizeProperty = collisionShapeProperty.getPropertyByID(Properties::Size);
+
+						// If the size was not given, leave it to a default 0.5f all around (so it gets to the final 1.0/1.0/1.0 dimension)
+						if(sizeProperty)
+							p_constructionInfo.m_rigidBodyConstructionInfo->m_collisionShapeSize = sizeProperty.getVec3f();
+						else
+							ErrHandlerLoc().get().log(ErrorCode::Property_missing_size, p_name, ErrorSource::Source_RigidBodyComponent);
+
+						p_constructionInfo.m_rigidBodyConstructionInfo->m_collisionShapeType = RigidBodyComponent::CollisionShapeType::CollisionShapeType_Box;
+					}
+					break;
+
+					case Properties::Sphere:
+					{
+						// Get the size property
+						auto const &radiusProperty = collisionShapeProperty.getPropertyByID(Properties::Radius);
+
+						// If the size was not given, leave it to a default radius of 0.5f (which makes the sphere diameter equal to 1.0)
+						if(radiusProperty)
+							p_constructionInfo.m_rigidBodyConstructionInfo->m_collisionShapeSize.x = radiusProperty.getFloat();
+						else
+							ErrHandlerLoc().get().log(ErrorCode::Property_missing_radius, p_name, ErrorSource::Source_RigidBodyComponent);
+
+						p_constructionInfo.m_rigidBodyConstructionInfo->m_collisionShapeType = RigidBodyComponent::CollisionShapeType::CollisionShapeType_Sphere;
+					}
+					break;
+
+					default:
+
+						// If this is reached, the collision shape type was not valid
+						ErrHandlerLoc().get().log(ErrorCode::Collision_invalid, p_name, ErrorSource::Source_RigidBodyComponent);
+						break;
+					}
+				}
+				else
+				{
+					// Missing the Type property entirely
+					ErrHandlerLoc().get().log(ErrorCode::Property_missing_type, p_name, ErrorSource::Source_RigidBodyComponent);
+				}
+			}
+
+			// -----------------------------
+			// Load individual property data
+			// -----------------------------
+			for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
+			{
+				switch(p_properties[i].getPropertyID())
+				{
+				case Properties::Friction:
+					p_constructionInfo.m_rigidBodyConstructionInfo->m_friction = p_properties[i].getFloat();
+					break;
+				case Properties::Kinematic:
+					p_constructionInfo.m_rigidBodyConstructionInfo->m_kinematic = p_properties[i].getBool();
+					break;
+				case Properties::Mass:
+					p_constructionInfo.m_rigidBodyConstructionInfo->m_mass = p_properties[i].getFloat();
+					break;
+				case Properties::Restitution:
+					p_constructionInfo.m_rigidBodyConstructionInfo->m_restitution = p_properties[i].getFloat();
+					break;
+				}
+			}
+		}
+
+		break;
+		}
+	}
+}
+
+void SceneLoader::importFromProperties(ScriptComponentsConstructionInfo &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::LuaComponent:
+			{
+				if(p_constructionInfo.m_luaConstructionInfo == nullptr)
+					p_constructionInfo.m_luaConstructionInfo = new LuaComponent::LuaComponentConstructionInfo();
+
+				p_constructionInfo.m_luaConstructionInfo->m_name = p_name + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::LuaComponent);
+
+				auto const &luaFilenameProperty = p_properties.getPropertyByID(Properties::Filename);
+				auto const &luaVariablesProperty = p_properties.getPropertySetByID(Properties::Variables);
+
+				if(luaFilenameProperty)
+				{
+					std::string luaFilename = luaFilenameProperty.getString();
+					if(!luaFilename.empty())
+					{
+						p_constructionInfo.m_luaConstructionInfo->m_luaScriptFilename = luaFilename;
+
+						if(luaVariablesProperty)
+						{
+							// Loop over each variable entry in the node
+							for(decltype(luaVariablesProperty.getNumPropertySets()) iVariable = 0, numVariables = luaVariablesProperty.getNumPropertySets(); iVariable < numVariables; iVariable++)
+							{
+								// Add the variable
+								p_constructionInfo.m_luaConstructionInfo->m_variables.emplace_back(
+									luaVariablesProperty.getPropertySet(iVariable).getPropertyByID(Properties::Name).getString(),
+									luaVariablesProperty.getPropertySet(iVariable).getPropertyByID(Properties::Value));
+							}
+						}
+					}
+					else
+					{
+						ErrHandlerLoc().get().log(ErrorCode::Property_no_filename, p_name, ErrorSource::Source_SceneLoader);
+					}
+				}
+				else
+				{
+					ErrHandlerLoc().get().log(ErrorCode::Property_no_filename, p_name, ErrorSource::Source_SceneLoader);
+				}
+			}
+			break;
+		}
+	}
+}
+
+void SceneLoader::importFromProperties(WorldComponentsConstructionInfo &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::SpatialComponent:
+			{
+				if(p_constructionInfo.m_spatialConstructionInfo == nullptr)
+					p_constructionInfo.m_spatialConstructionInfo = new SpatialComponent::SpatialComponentConstructionInfo();
+
+				p_constructionInfo.m_spatialConstructionInfo->m_name = p_name + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::SpatialComponent);
+
+				// Load property data
+				for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
+				{
+					switch(p_properties[i].getPropertyID())
+					{
+					case Properties::LocalPosition:
+						p_constructionInfo.m_spatialConstructionInfo->m_localPosition = p_properties[i].getVec3f();
+						break;
+					case Properties::LocalRotation:
+						p_constructionInfo.m_spatialConstructionInfo->m_localRotationEuler = p_properties[i].getVec3f();
+						break;
+					case Properties::LocalRotationQuaternion:
+						p_constructionInfo.m_spatialConstructionInfo->m_localRotationQuaternion = glm::quat(p_properties[i].getVec4f());
+						break;
+					case Properties::LocalScale:
+						p_constructionInfo.m_spatialConstructionInfo->m_localScale = p_properties[i].getVec3f();
+						break;
+					}
+				}
+			}
+			break;
+		}
+	}
+}

+ 15 - 0
Praxis3D/Source/SceneLoader.h

@@ -5,6 +5,13 @@
 #include "PropertySet.h"
 #include "Universal.h"
 
+struct ComponentsConstructionInfo;
+struct GraphicsComponentsConstructionInfo;
+struct GUIComponentsConstructionInfo;
+struct PhysicsComponentsConstructionInfo;
+struct ScriptComponentsConstructionInfo;
+struct WorldComponentsConstructionInfo;
+
 // Loads and links various objects by requesting them from registered scenes.
 // Uses property sets to send data to scenes (about specific objects).
 class SceneLoader
@@ -13,6 +20,7 @@ public:
 	SceneLoader()
 	{
 		m_changeController = nullptr;
+		m_loadInBackground = false;
 
 		for(int i = 0; i < Systems::NumberOfSystems; i++)
 			m_systemScenes[i] = g_nullSystemBase.createScene(this);
@@ -43,6 +51,13 @@ public:
 	ErrorCode saveToFile(const std::string p_filename = "");
 
 private:
+	void importFromProperties(ComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties);
+	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);
+	void importFromProperties(ScriptComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties, const std::string &p_name);
+	void importFromProperties(WorldComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties, const std::string &p_name);
+
 	SystemScene *m_systemScenes[Systems::NumberOfSystems];
 
 	std::vector<std::pair<const std::string&, SystemObject*>> m_createdObjects[Systems::NumberOfSystems];

+ 35 - 139
Praxis3D/Source/ScriptScene.cpp

@@ -1,6 +1,7 @@
 
 #include <functional>
 
+#include "ComponentConstructorInfo.h"
 #include "NullSystemObjects.h"
 #include "ScriptSystem.h"
 #include "ScriptScene.h"
@@ -112,169 +113,64 @@ ErrorCode ScriptScene::preload()
 	}
 
 	return ErrorCode::Success;
-
-	// Load every script object. It still works in parallel, however,
-	// it returns only when all objects have finished loading (simulating sequential call)
-	//TaskManagerLocator::get().parallelFor(size_t(0), m_scriptObjects.getPoolSize(), size_t(1), [=](size_t i)
-	//{
-	//	if(m_scriptObjects[i].allocated())
-	//	{
-	//		m_scriptObjects[i].getObject()->loadToMemory();
-	//	}
-	//});
-
-	//return ErrorCode::Success;
 }
 
-PropertySet ScriptScene::exportObject()
+std::vector<SystemObject*> ScriptScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
 {
-	//// Create the root property set
-	PropertySet propertySet(Properties::Script);
-
-	//// Add root property set for scene values
-	//auto &scene = propertySet.addPropertySet(Properties::Scene);
-
-	//// Add root property set for all the objects
-	//auto &objects = propertySet.addPropertySet(Properties::Objects);
-
-	//// Add script object property sets
-	//for(decltype(m_scriptObjects.size()) i = 0, size = m_scriptObjects.size(); i < size; i++)
-	//	objects.addPropertySet(m_scriptObjects[i]->exportObject());
-
-	return propertySet;
+	return createComponents(p_entityID, p_constructionInfo.m_scriptComponents);
 }
 
-SystemObject *ScriptScene::createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties)
-{
+SystemObject *ScriptScene::createComponent(const EntityID &p_entityID, const LuaComponent::LuaComponentConstructionInfo &p_constructionInfo)
+{	
 	// If valid type was not specified, or object creation failed, return a null object instead
-	SystemObject *returnObject = g_nullSystemBase.getScene()->createObject(p_properties);
-
-	// Check if property set node is present
-	if(p_properties)
-	{
-		// Get the world scene required for attaching components to the entity
-		WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
-
-		switch(p_properties.getPropertyID())
-		{
-		case Properties::PropertyID::LuaComponent:
-		{
-			auto &component = worldScene->addComponent<LuaComponent>(p_entityID, this, p_entityName + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::LuaComponent));
+	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();
 
-			// Try to initialize the lua component
-			auto componentInitError = component.init();
-			if(componentInitError == ErrorCode::Success)
-			{
-				// Try to import the component
-				auto const &componentImportError = component.importObject(p_properties);
-
-				// Remove the component if it failed to import
-				if(componentImportError != ErrorCode::Success)
-				{
-					ErrHandlerLoc().get().log(componentImportError, ErrorSource::Source_LuaComponent, component.getName());
-					worldScene->removeComponent<LuaComponent>(p_entityID);
-				}
-				else
-					returnObject = &component;
-			}
-			else // Remove the component if it failed to initialize
-			{
-				ErrHandlerLoc().get().log(componentInitError, ErrorSource::Source_LuaComponent, component.getName());
-				worldScene->removeComponent<LuaComponent>(p_entityID);
-			}
-		}
-		break;
-		}
-	}
+	// Get the world scene required for attaching components to the entity
+	WorldScene *worldScene = static_cast<WorldScene*>(m_sceneLoader->getSystemScene(Systems::World));
 
-	return returnObject;
-}
+	auto &component = worldScene->addComponent<LuaComponent>(p_entityID, this, p_constructionInfo.m_name, p_entityID);
 
-SystemObject *ScriptScene::createObject(const PropertySet &p_properties)
-{
-	// Check if property set node is present
-	if(p_properties)
+	// Try to initialize the lua component
+	auto componentInitError = component.init();
+	if(componentInitError == ErrorCode::Success)
 	{
-		// Check if the rendering property is present
-		auto &scriptProperty = p_properties.getPropertySetByID(Properties::Script);
-		if(scriptProperty)
+		if(!p_constructionInfo.m_luaScriptFilename.empty())
 		{
-			// Get the object name
-			auto &nameProperty = p_properties.getPropertyByID(Properties::Name);
-
-			// Find a place for the new object in the pool
-			auto scriptObjectFromPool = m_scriptObjects.newObject();
-
-			// Check if the pool wasn't full
-			if(scriptObjectFromPool != nullptr)
+			std::string luaFilename = Config::filepathVar().script_path + p_constructionInfo.m_luaScriptFilename;
+			if(Filesystem::exists(luaFilename))
 			{
-				std::string name;
-
-				// If the name property is missing, generate a unique name based on the object's index in the pool
-				if(nameProperty)
-					name = nameProperty.getString() + " (" + GetString(Properties::ScriptObject) + ")";
-				else
-					name = GetString(Properties::ScriptObject) + Utilities::toString(scriptObjectFromPool->getIndex());
-
-				// Construct the GraphicsObject
-				scriptObjectFromPool->construct(this, name);
-				auto scriptObject = scriptObjectFromPool->getObject();
+				component.m_luaScript->setScriptFilename(luaFilename);
 
-				//graphicsObject->importObject(renderingProperty);
+				if(!p_constructionInfo.m_variables.empty())
+					component.m_luaScript->setVariables(p_constructionInfo.m_variables);
 
-				// Start importing the newly created object in a background thread
-				//TaskManagerLocator::get().startBackgroundThread(std::bind(&ScriptObject::importObject, scriptObject, scriptProperty));
-				scriptObject->importObject(scriptProperty);
+				component.m_objectType = Properties::PropertyID::LuaComponent;
+				component.m_setActiveAfterLoading = p_constructionInfo.m_active;
+				component.setActive(false);
+				component.setLoadedToMemory(false);
 
-				return scriptObject;
+				returnObject = &component;
+				//ErrHandlerLoc().get().log(ErrorType::Info, ErrorSource::Source_LuaComponent, component.getName() + " - Script loaded");
 			}
 			else
 			{
-				ErrHandlerLoc::get().log(ErrorCode::ObjectPool_full, ErrorSource::Source_Script, "Failed to add ScriptObject - \'" + nameProperty.getString() + "\'");
+				ErrHandlerLoc().get().log(ErrorCode::File_not_found, component.getName(), ErrorSource::Source_LuaComponent);
+				worldScene->removeComponent<LuaComponent>(p_entityID);
 			}
 		}
+		else
+		{
+			ErrHandlerLoc().get().log(ErrorCode::Property_no_filename, component.getName(), ErrorSource::Source_LuaComponent);
+			worldScene->removeComponent<LuaComponent>(p_entityID);
+		}
 	}
-
-	// If valid type was not specified, or object creation failed, return a null object instead
-	return g_nullSystemBase.getScene()->createObject(p_properties);
-
-	/*/  Get certain object properties
-	auto const &type = p_properties.getPropertyByID(Properties::Type).getID();
-
-	SystemObject *newObject = nullptr;
-
-	// Create the object by it's type
-	switch(type)
+	else // Remove the component if it failed to initialize
 	{
-	case Properties::FreeCamera:
-		newObject = loadFreeCamera(p_properties);
-		break;
-	case Properties::DebugUIScript:
-		newObject = loadDebugUI(p_properties);
-		break;
-	case Properties::DebugMoveScript:
-		newObject = loadDebugMove(p_properties);
-		break;
-	case Properties::DebugRotateScript:
-		newObject = loadDebugRotate(p_properties);
-		break;
-	case Properties::SolarTimeScript:
-		newObject = loadSolarTime(p_properties);
-		break;
-	case Properties::SunScript:
-		newObject = loadSun(p_properties);
-		break;
-	case Properties::WorldEditScript:
-		newObject = loadWorldEdit(p_properties);
-		break;
+		ErrHandlerLoc().get().log(componentInitError, ErrorSource::Source_LuaComponent, component.getName());
+		worldScene->removeComponent<LuaComponent>(p_entityID);
 	}
 
-	// If the object creation was successful, return the new object
-	if(newObject != nullptr)
-		return newObject;
-
-	// If valid type was not specified, or object creation failed, return a null object instead
-	return g_nullSystemBase.getScene()->createObject(p_properties);*/
+	return returnObject;
 }
 
 ErrorCode ScriptScene::destroyObject(SystemObject *p_systemObject)

+ 28 - 4
Praxis3D/Source/ScriptScene.h

@@ -14,6 +14,23 @@
 #include "WorldEditObject.h"
 
 class ScriptSystem;
+struct ComponentsConstructionInfo;
+
+struct ScriptComponentsConstructionInfo
+{
+	ScriptComponentsConstructionInfo()
+	{
+		m_luaConstructionInfo = nullptr;
+	}
+
+	void deleteConstructionInfo()
+	{
+		if(m_luaConstructionInfo != nullptr)
+			delete m_luaConstructionInfo;
+	}
+
+	LuaComponent::LuaComponentConstructionInfo *m_luaConstructionInfo;
+};
 
 class ScriptScene : public SystemScene
 {
@@ -31,11 +48,18 @@ public:
 
 	ErrorCode preload();
 
-	// Exports all the data of the scene (including all objects within) as a PropertySet
-	virtual PropertySet exportObject();
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ScriptComponentsConstructionInfo &p_constructionInfo)
+	{
+		std::vector<SystemObject*> components;
+
+		if(p_constructionInfo.m_luaConstructionInfo != nullptr)
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_luaConstructionInfo));
+
+		return components;
+	}
 
-	SystemObject *createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties);
-	SystemObject *createObject(const PropertySet &p_properties);
+	SystemObject *createComponent(const EntityID &p_entityID, const LuaComponent::LuaComponentConstructionInfo &p_constructionInfo);
 	ErrorCode destroyObject(SystemObject *p_systemObject);
 
 	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType);

+ 12 - 0
Praxis3D/Source/ShaderComponent.h

@@ -8,6 +8,18 @@ class ShaderComponent : public SystemObject, public LoadableGraphicsObject
 {
 	friend class RendererScene;
 public:
+	struct ShaderComponentConstructionInfo : public SystemObject::SystemObjectConstructionInfo
+	{
+		ShaderComponentConstructionInfo()
+		{
+
+		}
+
+		std::string m_geometryShaderFilename;
+		std::string m_vetexShaderFilename;
+		std::string m_fragmentShaderFilename;
+	};
+
 	ShaderComponent(SystemScene *p_systemScene, std::string p_name, const EntityID p_entityID, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::Shaders, p_entityID), m_shaderData(nullptr) { }
 	ShaderComponent(SystemScene *p_systemScene, std::string p_name, ShaderLoader::ShaderProgram &p_shader, const EntityID p_entityID, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::Shaders, p_entityID), m_shaderData(new ShaderData(p_shader)) { }
 	~ShaderComponent() 

+ 13 - 0
Praxis3D/Source/SpatialComponent.h

@@ -9,6 +9,19 @@ class SpatialComponent : public SystemObject
 {
 	friend class WorldScene;
 public:
+	struct SpatialComponentConstructionInfo : public SystemObject::SystemObjectConstructionInfo
+	{
+		SpatialComponentConstructionInfo()
+		{
+			m_localScale = glm::vec3(1.0f);
+		}
+
+		glm::vec3 m_localPosition;
+		glm::vec3 m_localRotationEuler;
+		glm::quat m_localRotationQuaternion;
+		glm::vec3 m_localScale;
+	};
+
 	SpatialComponent(SystemScene *p_systemScene, const std::string &p_name, EntityID p_entityID)
 		: SystemObject(p_systemScene, p_name, Properties::SpatialComponent, p_entityID), m_spatialData(*this) //m_spatialData{*this, *this}
 	{

+ 8 - 2
Praxis3D/Source/System.cpp

@@ -1,3 +1,4 @@
+#include "ComponentConstructorInfo.h"
 #include "NullSystemObjects.h"
 #include "ObjectDirectory.h"
 #include "System.h"
@@ -20,7 +21,12 @@ SystemObject::~SystemObject()
 	ObjectDirectory::unregisterObject(*this);
 }
 
-SystemObject *SystemScene::createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties)
+std::vector<SystemObject*> SystemScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
 {
-	return g_nullSystemBase.getScene()->createObject(p_properties); 
+	return std::vector<SystemObject*>();
+}
+
+SystemObject *SystemScene::getNullObject()
+{
+	return g_nullSystemBase.getScene()->getNullObject();
 }

+ 17 - 4
Praxis3D/Source/System.h

@@ -13,6 +13,7 @@ class SceneLoader;
 class SystemObject;
 class SystemScene;
 class SystemTask;
+struct ComponentsConstructionInfo;
 
 class ImportExportObject
 {
@@ -56,7 +57,7 @@ class SystemScene : public ObservedSubject, public Observer
 	friend SystemBase;
 public:
 	SystemScene(SystemBase *p_system, SceneLoader *p_sceneLoader)
-		: m_initialized(false), m_system(p_system), m_sceneLoader(p_sceneLoader){ }
+		: m_initialized(false), m_system(p_system), m_sceneLoader(p_sceneLoader) { }
 	//~SystemScene();
 
 	SystemBase *getSystem() { return m_system; }
@@ -72,11 +73,11 @@ public:
 	virtual void loadInBackground() = 0;
 
 	// Exports all the data of the scene (including all objects within) as a PropertySet (for example, used for saving to map file)
-	virtual PropertySet exportObject() { return PropertySet(Properties::Null); }
+	//virtual PropertySet exportObject() { return PropertySet(Properties::Null); }
 
-	virtual SystemObject *createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties);
-	virtual SystemObject *createObject(const PropertySet &p_properties) = 0;
+	virtual std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo);
 	virtual ErrorCode destroyObject(SystemObject *p_systemObject) = 0;
+	virtual SystemObject *getNullObject();
 
 	virtual void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) { }
 
@@ -95,6 +96,18 @@ class SystemObject : public ObservedSubject, public Observer, public ImportExpor
 	friend SystemBase;
 	friend SystemScene;
 public:
+	struct SystemObjectConstructionInfo
+	{
+		SystemObjectConstructionInfo()
+		{
+			m_active = true;
+			m_name = "null";
+		}
+
+		bool m_active;
+		std::string m_name;
+	};
+
 	SystemObject();
 	SystemObject(SystemScene *p_systemScene, const std::string &p_name, Properties::PropertyID p_objectType, EntityID p_entityID = NULL_ENTITY_ID);
 	~SystemObject();

+ 3 - 2
Praxis3D/Source/Universal.cpp

@@ -240,7 +240,7 @@ UniversalObject::~UniversalObject()
 
 SystemObject *UniversalObject::extend(SystemScene *p_systemScene, PropertySet &p_properties)
 {
-	// TODO ASSERT ERROR
+	/*/ TODO ASSERT ERROR
 	_ASSERT(p_systemScene != nullptr);
 	_ASSERT(m_objectExtensions.find(p_systemScene->getSystemType()) == m_objectExtensions.end());
 
@@ -249,7 +249,8 @@ SystemObject *UniversalObject::extend(SystemScene *p_systemScene, PropertySet &p
 
 	extend(systemObject);
 
-	return systemObject;
+	return systemObject;*/
+	return nullptr;
 }
 
 bool UniversalObject::extend(SystemObject *p_systemObject)

+ 31 - 366
Praxis3D/Source/WorldScene.cpp

@@ -1,4 +1,5 @@
 
+#include "ComponentConstructorInfo.h"
 #include "GameObjectComponent.h"
 #include "NullSystemObjects.h"
 #include "SceneLoader.h"
@@ -87,164 +88,40 @@ void WorldScene::update(const float p_deltaTime)
 
 }
 
-EntityID WorldScene::createEntity(const PropertySet &p_properties)
+EntityID WorldScene::createEntity(const ComponentsConstructionInfo &p_constructionInfo)
 {
-	return EntityID();
-}
-
-SystemObject *WorldScene::createObject(const PropertySet &p_properties)
-{
-	GameObjectComponent *newGameObject = nullptr;
-		
-	// Get the object name and ID
-	std::string name = p_properties.getPropertyByID(Properties::Name).getString();
-	EntityID desiredEntityID = (EntityID)p_properties.getPropertyByID(Properties::ID).getInt();
-
 	// Add entity to the registry and assign its entity ID
-	EntityID newEntity = addEntity(desiredEntityID);
+	EntityID newEntity = addEntity(p_constructionInfo.m_id);
 
 	// Log an error if the desired ID couldn't be assigned
-	if(desiredEntityID != newEntity)
-		ErrHandlerLoc::get().log(ErrorCode::Duplicate_object_id, ErrorSource::Source_WorldScene, name + " - Entity ID \'" + Utilities::toString(desiredEntityID) + "\' is already taken. Replaced with: \'" + Utilities::toString(newEntity) + "\'");
-
-	// If the name property is missing, generate a unique name based on the entity ID
-	if(name.empty())
-		name = GetString(Properties::GameObject) + Utilities::toString(newEntity);
-
-	// Construct the new GameObject
-	newGameObject = &addComponent<GameObjectComponent>(newEntity, this, name, newEntity);
-
-	// Load property data
-	for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
-	{
-		switch(p_properties[i].getPropertyID())
-		{
-		case Properties::Parent:
-		{
-			// Get the entity ID if the parent object
-			EntityID parentID = (EntityID)p_properties[i].getInt();
-
-			if(m_entityRegistry.all_of<GameObjectComponent>(parentID))
-			{
-				GameObjectComponent &parentGameObject = m_entityRegistry.get<GameObjectComponent>(parentID);
-
-				// Add the game object component (child) to the observer list of the parent
-				m_sceneLoader->getChangeController()->createObjectLink(&parentGameObject, newGameObject);
+	if(p_constructionInfo.m_id != newEntity)
+		ErrHandlerLoc::get().log(ErrorCode::Duplicate_object_id, ErrorSource::Source_WorldScene, p_constructionInfo.m_name + " - Entity ID \'" + Utilities::toString(p_constructionInfo.m_id) + "\' is already taken. Replaced with: \'" + Utilities::toString(newEntity) + "\'");
 
-				newGameObject->setParent(parentID);
-				parentGameObject.addChild(newEntity);
 
-			}
-		}
-		break;
-		}
-	}
+	// Add WORLD components
+	std::vector<SystemObject*> worldComponents = createComponents(newEntity, p_constructionInfo.m_worldComponents);
 
-	SpatialComponent *spatialComponent = nullptr;
+	SystemObject *spatialComponent = nullptr;
 
-	// Add WORLD components
-	auto &worldProperty = p_properties.getPropertySetByID(Properties::World);
-	if(worldProperty)
-	{
-		// Add SPATIAL COMPONENT
-		auto &spatialComponentProperty = worldProperty.getPropertySetByID(Properties::SpatialComponent);
-		if(spatialComponentProperty)
+	// Find a spatial component within the world components array
+	for(decltype(worldComponents.size()) i = 0, size = worldComponents.size(); i < size; i++)
+		if(worldComponents[i]->getObjectType() == Properties::SpatialComponent)
 		{
-			//auto spatial = m_entityRegistry.emplace<SpatialComponent>(newEntity, this, name);
-			SpatialComponent &newSpatialComponent = addComponent<SpatialComponent>(newEntity, this, name + Config::componentVar().component_name_separator + GetString(Properties::SpatialComponent), newEntity);
-
-			// Load property data
-			for(decltype(spatialComponentProperty.getNumProperties()) i = 0, size = spatialComponentProperty.getNumProperties(); i < size; i++)
-			{
-				switch(spatialComponentProperty[i].getPropertyID())
-				{
-				case Properties::LocalPosition:
-					newSpatialComponent.m_spatialData.setLocalPosition(spatialComponentProperty[i].getVec3f());
-					break;
-				case Properties::LocalRotation:
-					newSpatialComponent.m_spatialData.setLocalRotation(spatialComponentProperty[i].getVec3f());
-					break;
-				case Properties::LocalRotationQuaternion:
-					newSpatialComponent.m_spatialData.setLocalRotation(glm::quat(spatialComponentProperty[i].getVec4f()));
-					break;
-				case Properties::LocalScale:
-					newSpatialComponent.m_spatialData.setLocalScale(spatialComponentProperty[i].getVec3f());
-					break;
-				}
-			}
-
-			// Perform a spatial data update, so that all the transform matrices are calculated
-			newSpatialComponent.m_spatialData.update();
-
-			spatialComponent = &newSpatialComponent;
+			spatialComponent = worldComponents[i];
+			break;
 		}
-	}
 
 	// Add RENDERING components
-	std::vector<SystemObject*> renderingComponents;
-	{
-		auto &sceneProperty = p_properties.getPropertySetByID(Properties::Rendering);
-		if(sceneProperty)
-		{
-			SystemScene *scene = m_sceneLoader->getSystemScene(Systems::Graphics);
-			for(decltype(sceneProperty.getNumPropertySets()) i = 0, size = sceneProperty.getNumPropertySets(); i < size; i++)
-			{
-				renderingComponents.push_back(scene->createComponent(newEntity, name, sceneProperty.getPropertySet(i)));
-			}
-		}
-	}
+	std::vector<SystemObject*> renderingComponents = m_sceneLoader->getSystemScene(Systems::Graphics)->createComponents(newEntity, p_constructionInfo);
 
 	// Add GUI components
-	std::vector<SystemObject*> guiComponents;
-	{
-		auto &sceneProperty = p_properties.getPropertySetByID(Properties::GUI);
-		if(sceneProperty)
-		{
-			SystemScene *scene = m_sceneLoader->getSystemScene(Systems::GUI);
-			for(decltype(sceneProperty.getNumPropertySets()) i = 0, size = sceneProperty.getNumPropertySets(); i < size; i++)
-			{
-				guiComponents.push_back(scene->createComponent(newEntity, name, sceneProperty.getPropertySet(i)));
-			}
-		}
-	}	
-	
+	std::vector<SystemObject*> guiComponents = m_sceneLoader->getSystemScene(Systems::GUI)->createComponents(newEntity, p_constructionInfo);
+
 	// Add PHYSICS components
-	std::vector<SystemObject*> physicsComponents;
-	{
-		auto &sceneProperty = p_properties.getPropertySetByID(Properties::Physics);
-		if(sceneProperty)
-		{
-			SystemScene *scene = m_sceneLoader->getSystemScene(Systems::Physics);
-			for(decltype(sceneProperty.getNumPropertySets()) i = 0, size = sceneProperty.getNumPropertySets(); i < size; i++)
-			{
-				physicsComponents.push_back(scene->createComponent(newEntity, name, sceneProperty.getPropertySet(i)));
-			}
-		}
-	}
+	std::vector<SystemObject*> physicsComponents = m_sceneLoader->getSystemScene(Systems::Physics)->createComponents(newEntity, p_constructionInfo);
 
 	// Add SCRIPTING components
-	std::vector<SystemObject*> scriptingComponents;
-	{
-		auto &sceneProperty = p_properties.getPropertySetByID(Properties::Script);
-		if(sceneProperty)
-		{
-			SystemScene *scene = m_sceneLoader->getSystemScene(Systems::Script);
-			for(decltype(sceneProperty.getNumPropertySets()) i = 0, size = sceneProperty.getNumPropertySets(); i < size; i++)
-			{
-				auto *component = scene->createComponent(newEntity, name, sceneProperty.getPropertySet(i));
-
-				//auto *spatialComponent = m_entityRegistry.try_get<SpatialComponent>(newEntity);
-				//if(spatialComponent != nullptr)
-				//	m_sceneLoader->getChangeController()->createObjectLink(component, spatialComponent);
-
-				// Create subject-observer object links between scripting components (subject) and GUI components (observers)
-				//for(decltype(guiComponents.size()) size = guiComponents.size(), i = 0; i < size; i++)
-				//	m_sceneLoader->getChangeController()->createObjectLink(component, guiComponents[i]);
-
-				scriptingComponents.push_back(component);
-			}
-		}
-	}
+	std::vector<SystemObject*> scriptingComponents = m_sceneLoader->getSystemScene(Systems::Script)->createComponents(newEntity, p_constructionInfo);
 
 	// Link subjects and observers of different components
 
@@ -273,7 +150,7 @@ SystemObject *WorldScene::createObject(const PropertySet &p_properties)
 			for(decltype(physicsComponents.size()) physicsIndex = 0, physicsSize = physicsComponents.size(); physicsIndex < physicsSize; physicsIndex++)
 				m_sceneLoader->getChangeController()->createObjectLink(scriptingComponents[scriptingIndex], physicsComponents[physicsIndex]);
 		}
-			
+
 		// Link SCRIPTING -> GUI
 		for(decltype(guiComponents.size()) guiIndex = 0, guiSize = guiComponents.size(); guiIndex < guiSize; guiIndex++)
 		{
@@ -281,234 +158,22 @@ SystemObject *WorldScene::createObject(const PropertySet &p_properties)
 		}
 	}
 
+	return newEntity;
+}
 
-	return newGameObject;
-
-
-
-
-
-	ErrorCode objPoolError = ErrorCode::Failure;
-	GameObject *newGameObject2 = nullptr;
-
-	// Find a place for the new object in the pool
-	auto gameObjectFromPool = m_gameObjects.newObject();
-
-	// Check if the pool wasn't full
-	if(gameObjectFromPool != nullptr)
-	{
-		auto &nameProperty = p_properties.getPropertyByID(Properties::Name);
-
-		std::string name;
-
-		// If the name property is missing, generate a unique name based on the object's index in the pool
-		if(nameProperty)
-			name = nameProperty.getString();
-		else
-			name = GetString(Properties::GameObject) + Utilities::toString(gameObjectFromPool->getIndex());
-
-		// Construct the new GameObject
-		gameObjectFromPool->construct(this, name, *m_sceneLoader);
-		newGameObject2 = gameObjectFromPool->getObject();
-						
-		// Load property data
-		for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
-		{
-			switch(p_properties[i].getPropertyID())
-			{
-			case Properties::ID:
-				{
-					// Get the game object ID
-					auto objectIDdesired = static_cast<EntityID>(p_properties.getPropertyByID(Properties::ID).getInt());
-
-					// Create an entity
-					auto entityID = m_entityRegistry.create(objectIDdesired);
-
-					// If the enity wasn't registered with the given game object ID, log an error
-					if(objectIDdesired != entityID)
-					{
-						// If an enity already exists at the given game object ID, log a duplicate ID error, otherwise log an invalid ID error
-						if(m_entityRegistry.valid(objectIDdesired))
-							ErrHandlerLoc::get().log(ErrorCode::Duplicate_object_id, ErrorSource::Source_World, newGameObject2->getName());
-						else
-							ErrHandlerLoc::get().log(ErrorCode::Invalid_object_id, ErrorSource::Source_World, newGameObject2->getName());
-					}
-
-					// Set the game object ID to the created entity ID in the registry
-					newGameObject2->m_GameObjectID = entityID;
-
-					// Try to register the object with the given game object ID
-					auto objectIDactual = m_objectRegister.registerObject(newGameObject2, objectIDdesired);
-
-					// If the object wasn't registered with the given game object ID, log an error
-					if(objectIDdesired != objectIDactual)
-					{
-						// If an object already exists at the given game object ID, log a duplicate ID error, otherwise log an invalid ID error
-						if(m_objectRegister.getObject(objectIDdesired) != nullptr)
-							ErrHandlerLoc::get().log(ErrorCode::Duplicate_object_id, ErrorSource::Source_World, newGameObject2->getName());
-						else
-							ErrHandlerLoc::get().log(ErrorCode::Invalid_object_id, ErrorSource::Source_World, newGameObject2->getName());
-					}
-				}
-				break;
-			case Properties::Parent:
-				{
-					// Get the ID if the parent object
-					decltype(GameObject::m_GameObjectID) parentID = p_properties[i].getInt();
-
-					// Try to get the parent game object, from the object register, by its ID
-					auto parentObject = m_objectRegister.getObject(parentID);
-
-					// Check if the retrieved parent game object is valid
-					if(parentObject != nullptr)
-					{
-						// If it is valid, set it as the parent
-						newGameObject2->setParent(*parentObject);
-					}
-					else
-					{
-						// If it is not valid, add it to the unassigned parent list, to be set later
-						// The game object with the parent ID probably hasn't been loaded yet
-						m_unassignedParents.emplace_back(newGameObject2, parentID);
-					}
-				}
-				break;
-			case Properties::LocalPosition:
-				newGameObject2->m_spatialData.setLocalPosition(p_properties[i].getVec3f());
-				break;
-			case Properties::LocalRotation:
-				newGameObject2->m_spatialData.setLocalRotation(p_properties[i].getVec3f());
-				break;
-			case Properties::LocalRotationQuaternion:
-				newGameObject2->m_spatialData.setLocalRotation(glm::quat(p_properties[i].getVec4f()));
-				break;
-			case Properties::LocalScale:
-				newGameObject2->m_spatialData.setLocalScale(p_properties[i].getVec3f());
-				break;
-			}
-		}
-
-		// Spatial data manager should be updated after setting all the spatial data
-		newGameObject2->m_spatialData.update();
-		newGameObject2->m_spatialData.resetChanges();
-
-		// Declare data struct for children whose IDs haven't been registered yet
-		GameObjectAndChildren unassignedChildren(newGameObject2);
-
-		// Get the children property set array
-		auto &children = p_properties.getPropertySetByID(Properties::Children);
-
-		// Iterate over every child entry
-		for(decltype(children.getNumPropertySets()) i = 0, size = children.getNumPropertySets(); i < size; i++)
-		{
-			decltype(GameObject::m_GameObjectID) childID = children.getPropertySet(i).getPropertyByID(Properties::ID).getInt();
-								
-			// Try to get the child game object, from the object register, by its ID
-			auto childObject = m_objectRegister.getObject(childID);
-
-			// Check if the retrieved child game object is valid
-			if(childObject != nullptr)
-			{
-				// If it is valid, set it as the parent
-				newGameObject2->addChild(**childObject);
-			}
-			else
-			{
-				// If it is not valid, add it to the unassigned children list, to be set later
-				// The game object with the child ID probably hasn't been loaded yet
-				unassignedChildren.m_children.push_back(childID);
-			}
-		}
-
-		// If there were any children added to the unassigned children list, add the struct to the main unassigned children list
-		if(!unassignedChildren.m_children.empty())
-			m_unassignedChildren.emplace_back(unassignedChildren);
-
-		std::vector<std::pair<const EntityID, const PropertySet&>> componentProperties[Systems::NumberOfSystems];
-
-		// Get component entries
-		auto &components = p_properties.getPropertySetByID(Properties::Components);
-		if(components)
-		{
-			// Loop over each model entry in the node
-			for(decltype(components.getNumPropertySets()) i = 0, size = p_properties.getNumPropertySets(); i < size; i++)
-			{
-				auto &singleComponent = components.getPropertySet(i);
-				switch(singleComponent.getPropertyID())
-				{
-				case Properties::CameraComponent:
-				{
-					//componentProperties[Systems::Graphics].push_back()
-				}
-				break;
-
-				case Properties::ModelComponent:
-				{
-
-				}
-				break;
-
-				case Properties::ShaderComponent:
-				{
-
-				}
-				break;
-
-				default:
-					break;
-				}
-
-				// Get component type
-				auto &componentType = p_properties.getPropertySet(i).getPropertyByID(Properties::Filename).getString();
-			}
-		}
-
-
-		// Add a GraphicsObject as a component if the Rendering property is present
-		auto &rendering = p_properties.getPropertySetByID(Properties::Rendering);
-		if(rendering)
-		{
-			auto graphicsObject = m_sceneLoader->getSystemScene(Systems::Graphics)->createObject(p_properties);
-			if(graphicsObject != nullptr && graphicsObject->getSystemType() != Systems::Null)
-				newGameObject2->addComponent(static_cast<GraphicsObject *>(graphicsObject));
-		}
-
-		// Add a GUIObject as a component if the Rendering property is present
-		auto &guiProperty = p_properties.getPropertySetByID(Properties::GUI);
-		if(guiProperty)
-		{
-			auto guiProperty = m_sceneLoader->getSystemScene(Systems::GUI)->createObject(p_properties);
-			if(guiProperty != nullptr && guiProperty->getSystemType() != Systems::Null)
-				newGameObject2->addComponent(static_cast<GUIObject *>(guiProperty));
-		}
-
-		// Add a PhysicsObject as a component if the Script property is present
-		auto &physicsProperty = p_properties.getPropertySetByID(Properties::Physics);
-		if(physicsProperty)
-		{
-			auto physicsObject = m_sceneLoader->getSystemScene(Systems::Physics)->createObject(p_properties);
-			if(physicsObject != nullptr && physicsObject->getSystemType() != Systems::Null)
-				newGameObject2->addComponent(static_cast<PhysicsObject *>(physicsObject));
-		}
+std::vector<SystemObject*> WorldScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
+{
+	return createComponents(p_entityID, p_constructionInfo.m_worldComponents);
+}
 
-		// Add a ScriptObject as a component if the Script property is present
-		auto &scripting = p_properties.getPropertySetByID(Properties::Script);
-		if(scripting)
-		{
-			auto scriptObject = m_sceneLoader->getSystemScene(Systems::Script)->createObject(p_properties);
-			if(scriptObject != nullptr && scriptObject->getSystemType() != Systems::Null)
-				newGameObject2->addComponent(static_cast<ScriptObject *>(scriptObject));
-		}
+std::vector<SystemObject*> WorldScene::createComponents(const EntityID p_entityID, const WorldComponentsConstructionInfo &p_constructionInfo)
+{
+	std::vector<SystemObject*> components;
 
-	}
-	else
-	{
-		// If valid type was not specified, or object creation failed, assign a null object instead
-		//newGameObject2 = g_nullSystemBase.getScene()->createObject(p_properties);
-		//ErrHandlerLoc::get().log(ErrorCode::ObjectPool_full, ErrorSource::Source_WorldScene, "Failed to add GameObject - \'" + nameProperty.getString() + "\'");
-	}
+	if(p_constructionInfo.m_spatialConstructionInfo != nullptr)
+		components.push_back(createComponent(p_entityID, *p_constructionInfo.m_spatialConstructionInfo));
 
-    return newGameObject2;
+	return components;
 }
 
 ErrorCode WorldScene::destroyObject(SystemObject *p_systemObject)

+ 42 - 5
Praxis3D/Source/WorldScene.h

@@ -8,6 +8,23 @@
 #include "WorldTask.h"
 
 class WorldSystem;
+struct ComponentsConstructionInfo;
+
+struct WorldComponentsConstructionInfo
+{
+	WorldComponentsConstructionInfo()
+	{
+		m_spatialConstructionInfo = nullptr;
+	}
+
+	void deleteConstructionInfo()
+	{
+		if(m_spatialConstructionInfo != nullptr)
+			delete m_spatialConstructionInfo;
+	}
+
+	SpatialComponent::SpatialComponentConstructionInfo *m_spatialConstructionInfo;
+};
 
 class WorldScene : public SystemScene
 {
@@ -24,14 +41,34 @@ public:
 
 	void loadInBackground() { }
 
-	// Exports all the data of the scene (including all objects within) as a PropertySet (for example, used for saving to map file)
-	PropertySet exportObject() { return PropertySet(); }
-
-	EntityID createEntity(const PropertySet &p_properties);
+	EntityID createEntity(const ComponentsConstructionInfo &p_constructionInfo);
 
-	SystemObject *createObject(const PropertySet &p_properties);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const WorldComponentsConstructionInfo &p_constructionInfo);
 	ErrorCode destroyObject(SystemObject *p_systemObject);
 
+	SystemObject *createComponent(const EntityID p_entityID, const SpatialComponent::SpatialComponentConstructionInfo &p_constructionInfo)
+	{
+		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);
+		spatialComponent->m_spatialData.setLocalScale(p_constructionInfo.m_localScale);
+
+		// If the rotation quaternion is empty, use the Euler angle rotation
+		if(p_constructionInfo.m_localRotationQuaternion == glm::quat())
+			spatialComponent->m_spatialData.setLocalRotation(p_constructionInfo.m_localRotationEuler);
+		else
+			spatialComponent->m_spatialData.setLocalRotation(p_constructionInfo.m_localRotationQuaternion);
+
+		// Perform a spatial data update, so that all the transform matrices are calculated
+		spatialComponent->m_spatialData.update();
+
+		return spatialComponent;
+	}
+
 	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) { }
 
 	SystemTask *getSystemTask() { return m_worldTask; };

Some files were not shown because too many files changed in this diff