Parcourir la source

Added prefab support

Added prefab support, so that common objects can be made into prefabs and new prefabs can be specified in map files. Any parameter in a map file overrides the same parameter in a prefab.
Added Lua bind functions for prefab loading and component functionality (create entities, modify component parameters)
Added copy methods for ConstructionInfo structs for all components
Added support for linear velocity in RigidBodyComponentConstructionInfo
Modified the default map file to use prefabs
Fixed an issue when a model component is created directly (after scene loading) is not loaded properly
Paul A il y a 3 ans
Parent
commit
3769a22f07
39 fichiers modifiés avec 1140 ajouts et 562 suppressions
  1. 1 0
      .gitignore
  2. 14 120
      Praxis3D/Data/Maps/componentTest.pmap
  3. 60 0
      Praxis3D/Data/Prefabs/cube1.prefab
  4. 70 0
      Praxis3D/Data/Prefabs/cubeMetalPaintedChips.prefab
  5. 140 0
      Praxis3D/Data/Scripts/Camera_free_object_spawn.lua
  6. 4 2
      Praxis3D/Data/Scripts/Kinematic_test.lua
  7. 3 0
      Praxis3D/Data/Shaders/geometryPass.frag
  8. 16 0
      Praxis3D/Data/Shaders/test.comp
  9. 2 2
      Praxis3D/Data/config.ini
  10. 1 0
      Praxis3D/Data/error-strings-eng.data
  11. 3 1
      Praxis3D/Source/CameraComponent.h
  12. 35 1
      Praxis3D/Source/ComponentConstructorInfo.h
  13. 4 0
      Praxis3D/Source/Config.h
  14. 1 0
      Praxis3D/Source/ErrorCodes.h
  15. 3 2
      Praxis3D/Source/ErrorHandler.cpp
  16. 3 3
      Praxis3D/Source/GUIScene.cpp
  17. 10 4
      Praxis3D/Source/GUIScene.h
  18. 0 1
      Praxis3D/Source/GeometryBuffer.cpp
  19. 1 1
      Praxis3D/Source/LuaComponent.h
  20. 513 1
      Praxis3D/Source/LuaScript.cpp
  21. 14 339
      Praxis3D/Source/LuaScript.h
  22. 2 0
      Praxis3D/Source/ModelComponent.h
  23. 7 3
      Praxis3D/Source/PhysicsScene.cpp
  24. 10 4
      Praxis3D/Source/PhysicsScene.h
  25. 1 1
      Praxis3D/Source/PropertyLoader.cpp
  26. 1 2
      Praxis3D/Source/RendererFrontend.cpp
  27. 28 14
      Praxis3D/Source/RendererScene.cpp
  28. 19 10
      Praxis3D/Source/RendererScene.h
  29. 1 0
      Praxis3D/Source/RigidBodyComponent.h
  30. 96 4
      Praxis3D/Source/SceneLoader.cpp
  31. 16 16
      Praxis3D/Source/SceneLoader.h
  32. 3 3
      Praxis3D/Source/ScriptScene.cpp
  33. 10 4
      Praxis3D/Source/ScriptScene.h
  34. 1 1
      Praxis3D/Source/System.cpp
  35. 3 2
      Praxis3D/Source/System.h
  36. 11 0
      Praxis3D/Source/Utilities.h
  37. 2 2
      Praxis3D/Source/WorldEditObject.h
  38. 21 15
      Praxis3D/Source/WorldScene.cpp
  39. 10 4
      Praxis3D/Source/WorldScene.h

+ 1 - 0
.gitignore

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

+ 14 - 120
Praxis3D/Data/Maps/componentTest.pmap

@@ -81,7 +81,7 @@
 					"CollisionShape":
 					{
 						"Type": "Box",
-						"Size": "100.01f, 0.25f, 100.01f"
+						"Size": "100.0f, 0.0f, 100.0f"
 					},
 					"Mass": "0.0f"
 				}
@@ -104,23 +104,23 @@
 									{
 										"Diffuse":
 										{
-											"Filename": "Metal_CleanPaintedWithChips_2k_alb.tga",
-											"TextureScale": "100.0f, 100.0f"
+											"Filename": "Ground_SmoothRocks_2k_alb.tga",
+											"TextureScale": "10.0f, 10.0f"
 										},
 										"Normal":
 										{
-											"Filename": "Metal_CleanPaintedWithChips_2k_n.tga",
-											"TextureScale": "100.0f, 100.0f"
+											"Filename": "Ground_SmoothRocks_2k_n.tga",
+											"TextureScale": "10.0f, 10.0f"
 										},
 										"Emissive":
 										{
 											"Filename": "default_emissive.png",
-											"TextureScale": "100.0f, 100.0f"
+											"TextureScale": "1.0f, 1.0f"
 										},
 										"RMHAO":
 										{
-											"Filename": "Metal_CleanPaintedWithChips_RMHAO3.tga",
-											"TextureScale": "100.0f, 100.0f"
+											"Filename": "Ground_SmoothRocks_RMHAO.tga",
+											"TextureScale": "10.0f, 10.0f"
 										}
 									}
 								}
@@ -134,70 +134,13 @@
 			"ID": "3",
 			"Name": "Cube 1",
 			"Parent": "0",
+			"Prefab": "cubeMetalPaintedChips.prefab",
 			"World":
 			{
 				"SpatialComponent":
 				{
 					"LocalPosition": "0.0f, 30.0f, 0.0f",
-					"LocalRotation": "0.0f, 40.0f, 0.0f",
-					"LocalScale": "2.0f, 2.0f, 2.0f"
-				}
-			},
-			"Rendering":
-			{
-				"ModelComponent":
-				{
-					"Models":
-					[
-						{
-							"Filename": "cube.obj",
-							"Meshes":
-							[
-								{
-									"Index": "0",
-									"AlphaThreshold": "0.0f",
-									"HeightScale": "0.0f",
-									"Materials":
-									{
-										"Diffuse":
-										{
-											"Filename": "Metal_CleanPaintedWithChips_2k_alb.tga",
-											"TextureScale": "2.0f, 2.0f"
-										},
-										"Normal":
-										{
-											"Filename": "Metal_CleanPaintedWithChips_2k_n.tga",
-											"TextureScale": "1.0f, 1.0f"
-										},
-										"Emissive":
-										{
-											"Filename": "default_emissive.png",
-											"TextureScale": "1.0f, 1.0f"
-										},
-										"RMHAO":
-										{
-											"Filename": "Metal_CleanPaintedWithChips_RMHAO3.tga",
-											"TextureScale": "1.0f, 1.0f"
-										}
-									}
-								}
-							]
-						}
-					]
-				}
-			},
-			"Physics":
-			{
-				"RigidBodyComponent":
-				{
-					"Mass": "10.0f",
-					"Restitution": "0.5f",
-					"Friction": "0.5f",
-					"CollisionShape":
-					{
-						"Type": "Box",
-						"Size": "2.0f, 2.0f, 2.0f"
-					}
+					"LocalRotation": "0.0f, 40.0f, 0.0f"
 				}
 			}
 		},
@@ -205,56 +148,13 @@
 			"ID": "33",
 			"Name": "Cube 2",
 			"Parent": "0",
+			"Prefab": "cubeMetalPaintedChips.prefab",
 			"World":
 			{
 				"SpatialComponent":
 				{
 					"LocalPosition": "3.0f, 3.0f, 0.0f",
-					"LocalRotation": "0.0f, 0.0f, 0.0f",
-					"LocalScale": "2.0f, 2.0f, 2.0f"
-				}
-			},
-			"Rendering":
-			{
-				"ModelComponent":
-				{
-					"Models":
-					[
-						{
-							"Filename": "cube.obj",
-							"Meshes":
-							[
-								{
-									"Index": "0",
-									"AlphaThreshold": "0.0f",
-									"HeightScale": "0.0f",
-									"Materials":
-									{
-										"Diffuse":
-										{
-											"Filename": "Metal_CleanPaintedWithChips_2k_alb.tga",
-											"TextureScale": "2.0f, 2.0f"
-										},
-										"Normal":
-										{
-											"Filename": "Metal_CleanPaintedWithChips_2k_n.tga",
-											"TextureScale": "1.0f, 1.0f"
-										},
-										"Emissive":
-										{
-											"Filename": "default_emissive.png",
-											"TextureScale": "1.0f, 1.0f"
-										},
-										"RMHAO":
-										{
-											"Filename": "Metal_CleanPaintedWithChips_RMHAO3.tga",
-											"TextureScale": "1.0f, 1.0f"
-										}
-									}
-								}
-							]
-						}
-					]
+					"LocalRotation": "0.0f, 0.0f, 0.0f"
 				}
 			},
 			"Physics":
@@ -262,13 +162,7 @@
 				"RigidBodyComponent":
 				{
 					"Mass": "0.0f",
-					"Kinematic": "true",
-					"Restitution": "0.1f",
-					"CollisionShape":
-					{
-						"Type": "Box",
-						"Size": "2.0f"
-					}
+					"Kinematic": "true"
 				}
 			},
 			"Script":
@@ -396,7 +290,7 @@
 			{
 				"LuaComponent":
 				{
-					"Filename": "Camera_free.lua",
+					"Filename": "Camera_free_object_spawn.lua",
 					"Variables":
 					[
 						{

+ 60 - 0
Praxis3D/Data/Prefabs/cube1.prefab

@@ -0,0 +1,60 @@
+{
+	"Name": "Cube",
+	"Rendering":
+	{
+		"ModelComponent":
+		{
+			"Models":
+			[
+				{
+					"Filename": "cube.obj",
+					"Meshes":
+					[
+						{
+							"Index": "0",
+							"AlphaThreshold": "0.0f",
+							"HeightScale": "0.0f",
+							"Materials":
+							{
+								"Diffuse":
+								{
+									"Filename": "badlands-boulders_albedo.png",
+									"TextureScale": "2.0f, 2.0f"
+								},
+								"Normal":
+								{
+									"Filename": "badlands-boulders_normal-ogl.png",
+									"TextureScale": "2.0f, 2.0f"
+								},
+								"Emissive":
+								{
+									"Filename": "default_emissive.png",
+									"TextureScale": "1.0f, 1.0f"
+								},
+								"RMHAO":
+								{
+									"Filename": "badlands-boulders_RMHAO.png",
+									"TextureScale": "2.0f, 2.0f"
+								}
+							}
+						}
+					]
+				}
+			]
+		}
+	},
+	"Physics":
+	{
+		"RigidBodyComponent":
+		{
+			"Mass": "10.0f",
+			"Restitution": "0.5f",
+			"Friction": "0.5f",
+			"CollisionShape":
+			{
+				"Type": "Box",
+				"Size": "1.0f, 1.0f, 1.0f"
+			}
+		}
+	}
+}

+ 70 - 0
Praxis3D/Data/Prefabs/cubeMetalPaintedChips.prefab

@@ -0,0 +1,70 @@
+{
+	"Name": "Cube",
+	"Parent": "0",
+	"World":
+	{
+		"SpatialComponent":
+		{
+			"LocalPosition": "0.0f, 0.0f, 0.0f",
+			"LocalRotation": "0.0f, 0.0f, 0.0f",
+			"LocalScale": "2.0f, 2.0f, 2.0f"
+		}
+	},
+	"Rendering":
+	{
+		"ModelComponent":
+		{
+			"Models":
+			[
+				{
+					"Filename": "cube.obj",
+					"Meshes":
+					[
+						{
+							"Index": "0",
+							"AlphaThreshold": "0.0f",
+							"HeightScale": "0.0f",
+							"Materials":
+							{
+								"Diffuse":
+								{
+									"Filename": "Metal_CleanPaintedWithChips_2k_alb.tga",
+									"TextureScale": "2.0f, 2.0f"
+								},
+								"Normal":
+								{
+									"Filename": "Metal_CleanPaintedWithChips_2k_n.tga",
+									"TextureScale": "2.0f, 2.0f"
+								},
+								"Emissive":
+								{
+									"Filename": "default_emissive.png",
+									"TextureScale": "1.0f, 1.0f"
+								},
+								"RMHAO":
+								{
+									"Filename": "Metal_CleanPaintedWithChips_RMHAO3.tga",
+									"TextureScale": "2.0f, 2.0f"
+								}
+							}
+						}
+					]
+				}
+			]
+		}
+	},
+	"Physics":
+	{
+		"RigidBodyComponent":
+		{
+			"Mass": "10.0f",
+			"Restitution": "0.5f",
+			"Friction": "0.5f",
+			"CollisionShape":
+			{
+				"Type": "Box",
+				"Size": "2.0f, 2.0f, 2.0f"
+			}
+		}
+	}
+}

+ 140 - 0
Praxis3D/Data/Scripts/Camera_free_object_spawn.lua

@@ -0,0 +1,140 @@
+
+function init ()
+	-- Create needed variables
+	create(Types.GameplayVariables, 'gameplayVariables');
+	create(Types.InputVariables, 'inputVariables');
+	create(Types.SpatialDataManager, 'spatialData');
+	
+	-- Create key commands, used to track pressed keys
+	create(Types.KeyCommand, 'forwardKey')
+	create(Types.KeyCommand, 'backwardKey')
+	create(Types.KeyCommand, 'leftKey')
+	create(Types.KeyCommand, 'rightKey')
+	create(Types.KeyCommand, 'upKey')
+	create(Types.KeyCommand, 'downKey')
+	create(Types.KeyCommand, 'sprintKey')
+	create(Types.KeyCommand, 'mouseLeftKey')
+	create(Types.KeyCommand, 'mouseRightKey')
+	
+	-- Bind keys to their corresponding buttons on the keyboard
+	forwardKey:bind(inputVariables.forward_key)
+	backwardKey:bind(inputVariables.backward_key)
+	leftKey:bind(inputVariables.left_strafe_key)
+	rightKey:bind(inputVariables.right_strafe_key)
+	upKey:bind(inputVariables.up_key)
+	downKey:bind(inputVariables.down_key)
+	sprintKey:bind(inputVariables.sprint_key)
+	mouseLeftKey:bindByName('Mouse_left')
+	mouseRightKey:bindByName('Mouse_right')
+	
+	-- Get the camera movement speed
+	if cameraSpeed then 
+		movementSpeedF = cameraSpeed
+	else
+		movementSpeedF = gameplayVariables.camera_freelook_speed
+	end
+	
+	-- Get the camera movement speed multiplier
+	if cameraSpeedMultiplier then 
+		movementSpeedMultF = cameraSpeedMultiplier
+	else
+		movementSpeedMultF = 1.0
+	end
+	
+	create(Types.ComponentsInfo, 'spawnObject')
+	importPrefab(spawnObject, 'cube1.prefab')
+		
+	if not spawnObject.m_worldComponents:spatialPresent() then
+		spawnObject.m_worldComponents:createSpatial()
+	end
+	
+	
+	
+	print('Camera_free.lua script initialized.')
+end
+
+function update (p_deltaTime)
+	-- Get current mouse data
+	mouseData = getMouseInfo()
+	
+	-- Get current spatial data and its inverse
+	localTransformMat4 = spatialData:getLocalTransform()
+	localTransformInverseMat4 = localTransformMat4:inverse()
+	
+	-- Extract position from spatial data
+	positionVec3 = localTransformMat4:getPosVec3()
+	
+	-- Calculate new view angles based on mouse movement
+	horizontalAngleF = mouseData.m_movementX * inputVariables.mouse_jaw * inputVariables.mouse_sensitivity
+	verticalAngleF = mouseData.m_movementY * inputVariables.mouse_pitch * inputVariables.mouse_sensitivity
+	
+	-- Rotate the camera matrix by the view angles
+	-- Perform rotations only if the mouse is captured inside the game window
+	if mouseCaptured() or mouseRightKey:isActivated() then
+		-- Rotate camera up/down based on the X direction (left/right) of the view matrix (camera's inverse matrix)
+		localTransformMat4 = localTransformMat4:rotate(toRadianF(verticalAngleF), localTransformInverseMat4:getRotXVec3())
+		-- Rotate camera left/right on a fixed Y direction (up/down) to not introduce any roll
+		localTransformMat4 = localTransformMat4:rotate(toRadianF(horizontalAngleF), Vec3.new(0.0, 1.0, 0.0))
+	end
+		
+	-- Get the view direction that is facing forward
+	forwardDirectionVec3 = localTransformInverseMat4:getRotZVec3()
+	forwardDirectionVec3 = forwardDirectionVec3:normalize()
+	
+	-- Get the view direction that is facing to the right
+	rightDirectionVec3 = localTransformInverseMat4:getRotXVec3()
+	rightDirectionVec3 = rightDirectionVec3:normalize()
+	
+	-- Get the view direction that is facing up
+	upDirectionVec3 = localTransformInverseMat4:getRotYVec3()
+	upDirectionVec3 = upDirectionVec3:normalize()
+	
+	-- Increase movement speed if the sprint key is pressed
+	if sprintKey:isActivated() then
+		finalMovementSpeedF = movementSpeedF * movementSpeedMultF
+	else
+		finalMovementSpeedF = movementSpeedF
+	end
+	
+	-- Adjust camera position based on key presses and view direction
+	-- Forwards / backwards - Z direction
+	if forwardKey:isActivated() then
+		positionVec3 = positionVec3 - forwardDirectionVec3:mulF(finalMovementSpeedF * p_deltaTime)
+	end	
+	if backwardKey:isActivated() then
+		positionVec3 = positionVec3 + forwardDirectionVec3:mulF(finalMovementSpeedF * p_deltaTime)
+	end
+	
+	-- Left / right - X direction
+	if rightKey:isActivated() then
+		positionVec3 = positionVec3 + rightDirectionVec3:mulF(finalMovementSpeedF * p_deltaTime)
+	end	
+	if leftKey:isActivated() then
+		positionVec3 = positionVec3 - rightDirectionVec3:mulF(finalMovementSpeedF * p_deltaTime)
+	end	
+	
+	-- Up / down - Y direction
+	if upKey:isActivated() then
+		positionVec3 = positionVec3 + upDirectionVec3:mulF(finalMovementSpeedF * p_deltaTime)
+	end	
+	if downKey:isActivated() then
+		positionVec3 = positionVec3 - upDirectionVec3:mulF(finalMovementSpeedF * p_deltaTime)
+	end
+	
+	if mouseLeftKey:isActivated() then
+		mouseLeftKey:deactivate()
+		spawnObject.m_worldComponents.m_spatialConstructionInfo.m_localPosition = positionVec3 - forwardDirectionVec3:mulF(1.5)
+		spawnObject.m_worldComponents.m_spatialConstructionInfo.m_localRotationQuaternion = localTransformMat4:toQuat():inverse()
+		spawnObject.m_physicsComponents.m_rigidBodyConstructionInfo.m_linearVelocity = forwardDirectionVec3:mulF(-20.0)
+		
+		--spawnObject.m_worldComponents.m_spatialConstructionInfo.m_localRotationQuaternion = spatialData:getLocalSpaceData().m_spatialData.m_rotationQuaternion:inverse()
+		
+		createEntity(spawnObject)
+	end
+	
+	-- Set the new position of the camera, and keep the W variable the same
+	localTransformMat4:setPosVec4(Vec4.new(positionVec3, localTransformMat4:getPosVec4().w))
+	
+	-- Update the camera with the new matrix
+	spatialData:setLocalTransform(localTransformMat4)
+end

+ 4 - 2
Praxis3D/Data/Scripts/Kinematic_test.lua

@@ -14,7 +14,7 @@ function init ()
 	forwardKey:bind(inputVariables.forward_key)
 	upKey:bind(inputVariables.up_editor_key)
 	downKey:bind(inputVariables.down_editor_key)
-		
+	
 	print('Kinematic_test.lua script initialized.')
 end
 
@@ -26,6 +26,8 @@ function update (p_deltaTime)
 	positionVec3 = localTransformMat4:getPosVec3()
 	
 	positionModified = false
+	
+	spawnEntity = false
 		
 	if upKey:isActivated() then
 		positionVec3.y = positionVec3.y + (10.0 * p_deltaTime)
@@ -35,7 +37,7 @@ function update (p_deltaTime)
 		positionVec3.y = positionVec3.y - (10.0 * p_deltaTime)
 		positionModified = true
 	end
-	
+		
 	if(positionModified) then
 		spatialData:setLocalPosition(positionVec3)
 	end

+ 3 - 0
Praxis3D/Data/Shaders/geometryPass.frag

@@ -336,6 +336,9 @@ void main(void)
 		
 		if(LOD > LOD_PARALLAX_THRESHOLD)
 			newCoords = parallaxOcclusionMapping(texCoord, viewDir, LOD);
+			    
+		//if(newCoords.x > 1.0 || newCoords.y > 1.0 || newCoords.x < 0.0 || newCoords.y < 0.0)
+		//	discard;
 	}
 	
 	//if(distanceToFrag < 9.90)

+ 16 - 0
Praxis3D/Data/Shaders/test.comp

@@ -0,0 +1,16 @@
+#version 430 core
+
+layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+
+layout(rgba16f, binding = 0) uniform writeonly image2D imgOutput;
+
+void main() 
+{
+    vec4 value = vec4(0.0, 0.0, 0.0, 1.0);
+    ivec2 texelCoord = ivec2(gl_GlobalInvocationID.xy);
+	
+    value.x = float(texelCoord.x)/(gl_NumWorkGroups.x);
+    value.y = float(texelCoord.y)/(gl_NumWorkGroups.y);
+	
+    imageStore(imgOutput, texelCoord, value);
+}

+ 2 - 2
Praxis3D/Data/config.ini

@@ -13,13 +13,13 @@ default_texture default.png
 generate_mipmaps 1
 gl_texture_anisotropy 16
 camera_freelook_speed 25
-face_culling 0
+face_culling 1
 eye_adaption 0
 eye_adaption_intended_brightness 0.5
 mouse_captured 1
 mouse_warp_mode 0
 fov 80
-z_near 0.001
+z_near 0.1
 z_far 4000
 default_map componentTest.pmap
 atm_scattering_ground_frag_shader atmosphericScatteringPass_ground_simple.frag

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

@@ -7,6 +7,7 @@
 		"Initialize_success"				: "Has been initialized",
 		"Initialize_failure"				: "Failed to initialized",
 		"File_not_found"						: "File missing",
+		"Filename_empty"						: "Filename is empty",
 		"Destroy_obj_not_found"			: "Destruction: object not found",
 		"Glew_failed"								: "OpenGL Extension Wrangler Library has failed to initialize",
 		"Ifstream_failed"						: "Unable to read input file stream",

+ 3 - 1
Praxis3D/Source/CameraComponent.h

@@ -11,8 +11,10 @@ public:
 	{
 		CameraComponentConstructionInfo()
 		{
-
+			m_fov = Config::graphicsVar().fov;
 		}
+
+		float m_fov;
 	};
 
 	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)

+ 35 - 1
Praxis3D/Source/ComponentConstructorInfo.h

@@ -13,7 +13,41 @@ struct ComponentsConstructionInfo
 	{
 		m_name = "null";
 		m_id = NULL_ENTITY_ID;
-		m_parent = NULL_ENTITY_ID;
+		m_parent = 0;
+	}
+
+	ComponentsConstructionInfo(ComponentsConstructionInfo &p_other)
+	{
+		completeCopy(p_other);
+	}
+
+	ComponentsConstructionInfo &operator=(const ComponentsConstructionInfo &p_other)
+	{
+		m_name = p_other.m_name;
+		m_id = p_other.m_id;
+		m_parent = p_other.m_parent;
+
+		m_graphicsComponents = p_other.m_graphicsComponents;
+		m_guiComponents = p_other.m_guiComponents;
+		m_physicsComponents = p_other.m_physicsComponents;
+		m_scriptComponents = p_other.m_scriptComponents;
+		m_worldComponents = p_other.m_worldComponents;
+
+		return *this;
+	}
+
+	// Perform a complete copy, instantiating (with new) every member variable pointer, instead of just assigning the pointer to the same memory
+	void completeCopy(const ComponentsConstructionInfo &p_other)
+	{
+		m_name = p_other.m_name;
+		m_id = p_other.m_id;
+		m_parent = p_other.m_parent;
+
+		m_graphicsComponents.completeCopy(p_other.m_graphicsComponents);
+		m_guiComponents.completeCopy(p_other.m_guiComponents);
+		m_physicsComponents.completeCopy(p_other.m_physicsComponents);
+		m_scriptComponents.completeCopy(p_other.m_scriptComponents);
+		m_worldComponents.completeCopy(p_other.m_worldComponents);
 	}
 
 	void deleteConstructionInfo()

+ 4 - 0
Praxis3D/Source/Config.h

@@ -330,6 +330,7 @@ namespace Properties
 	Code(RigidBodyComponent,) \
 	Code(Size,) \
 	Code(Sphere,) \
+	Code(Velocity,) \
 	/* Script */ \
 	Code(Angle,) \
 	Code(Axis,) \
@@ -376,6 +377,7 @@ namespace Properties
 	Code(GameObject,) \
 	Code(ID,) \
 	Code(Parent,) \
+	Code(Prefab,) \
 	Code(SpatialComponent,) \
 	Code(World,) \
 	/* End of property IDs */ \
@@ -484,6 +486,7 @@ public:
 			object_directory_init_pool_size = 1000;
 			smoothing_tick_samples = 100;
 			running = true;
+			loadingState = true;
 		}
 
 		int change_ctrl_cml_notify_list_reserv;
@@ -498,6 +501,7 @@ public:
 		int object_directory_init_pool_size;
 		int smoothing_tick_samples;
 		bool running;
+		bool loadingState;
 	};
 	struct FramebfrVariables
 	{

+ 1 - 0
Praxis3D/Source/ErrorCodes.h

@@ -39,6 +39,7 @@ DECLARE_ENUM(ErrorType, ERROR_TYPES)
     Code(Initialize_success,) \
     Code(Initialize_failure,) \
     Code(File_not_found,) \
+    Code(Filename_empty,) \
 	/* General engine errors */\
     Code(Destroy_obj_not_found,) \
     Code(Glew_failed,) \

+ 3 - 2
Praxis3D/Source/ErrorHandler.cpp

@@ -27,6 +27,7 @@ ErrorHandler::ErrorHandler()
 	AssignErrorType(Initialize_success, Info);
 	AssignErrorType(Initialize_failure, Info);
 	AssignErrorType(File_not_found, Warning);
+	AssignErrorType(Filename_empty, Warning);
 	AssignErrorType(Destroy_obj_not_found, Warning);
 	AssignErrorType(Glew_failed, FatalError);
 	AssignErrorType(Ifstream_failed, Warning);
@@ -56,8 +57,8 @@ ErrorHandler::ErrorHandler()
 	AssignErrorType(SDL_video_init_failed, FatalError);
 	AssignErrorType(SDL_vsync_failed, Warning);
 	AssignErrorType(Window_creation_failed, FatalError);
-	AssignErrorType(Invalid_object_id, Error);
-	AssignErrorType(Duplicate_object_id, Error);
+	AssignErrorType(Invalid_object_id, Warning);
+	AssignErrorType(Duplicate_object_id, Warning);
 
 	// Add error sources to the hash map, and offset them by number of error codes, because they share the same hash map
 	for(unsigned int i = 0; i < Source_NumberOfErrorSources; i++)

+ 3 - 3
Praxis3D/Source/GUIScene.cpp

@@ -94,12 +94,12 @@ void GUIScene::loadInBackground()
 {
 }
 
-std::vector<SystemObject*> GUIScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
+std::vector<SystemObject*> GUIScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
-	return createComponents(p_entityID, p_constructionInfo.m_guiComponents);
+	return createComponents(p_entityID, p_constructionInfo.m_guiComponents, p_startLoading);
 }
 
-SystemObject *GUIScene::createComponent(const EntityID p_entityID, const GUISequenceComponent::GUISequenceComponentConstructionInfo &p_constructionInfo)
+SystemObject *GUIScene::createComponent(const EntityID p_entityID, const GUISequenceComponent::GUISequenceComponentConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {	
 	// If valid type was not specified, or object creation failed, return a null object instead
 	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();

+ 10 - 4
Praxis3D/Source/GUIScene.h

@@ -15,6 +15,12 @@ struct GUIComponentsConstructionInfo
 		m_guiSequenceConstructionInfo = nullptr;
 	}
 
+	// Perform a complete copy, instantiating (with new) every member variable pointer, instead of just assigning the pointer to the same memory
+	void completeCopy(const GUIComponentsConstructionInfo &p_other)
+	{
+		Utilities::performCopy<GUISequenceComponent::GUISequenceComponentConstructionInfo>(&m_guiSequenceConstructionInfo, &p_other.m_guiSequenceConstructionInfo);
+	}
+
 	void deleteConstructionInfo()
 	{
 		if(m_guiSequenceConstructionInfo != nullptr)
@@ -40,18 +46,18 @@ public:
 
 	void loadInBackground();
 
-	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*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const GUIComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true)
 	{
 		std::vector<SystemObject *> components;
 
 		if(p_constructionInfo.m_guiSequenceConstructionInfo != nullptr)
-			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_guiSequenceConstructionInfo));
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_guiSequenceConstructionInfo, p_startLoading));
 
 		return components;
 	}
 
-	SystemObject *createComponent(const EntityID p_entityID, const GUISequenceComponent::GUISequenceComponentConstructionInfo &p_constructionInfo);
+	SystemObject *createComponent(const EntityID p_entityID, const GUISequenceComponent::GUISequenceComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
 	ErrorCode destroyObject(SystemObject* p_systemObject);
 
 	void changeOccurred(ObservedSubject* p_subject, BitMask p_changeType) { }

+ 0 - 1
Praxis3D/Source/GeometryBuffer.cpp

@@ -92,7 +92,6 @@ ErrorCode GeometryBuffer::init()
 
 		// Create depth buffer
 		glBindTexture(GL_TEXTURE_2D, m_depthBuffer);
-		//glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_bufferWidth, m_bufferHeight, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
 		glTexImage2D(GL_TEXTURE_2D, 0, Config::FramebfrVariables().gl_depth_buffer_internal_format, m_bufferWidth, m_bufferHeight, 0, 
 					 Config::FramebfrVariables().gl_depth_buffer_texture_format, Config::FramebfrVariables().gl_depth_buffer_texture_type, NULL);
 		glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer, 0);

+ 1 - 1
Praxis3D/Source/LuaComponent.h

@@ -26,7 +26,7 @@ public:
 
 	LuaComponent(SystemScene *p_systemScene, std::string p_name, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::LuaComponent), m_luaSpatialData(*this), m_GUIData(*this)
 	{
-		m_luaScript = new LuaScript(m_luaSpatialData, m_GUIData);
+		m_luaScript = new LuaScript(m_systemScene, m_luaSpatialData, m_GUIData);
 		m_luaScriptLoaded = false;
 		m_luaSpatialData.setTrackLocalChanges(true);
 	}

+ 513 - 1
Praxis3D/Source/LuaScript.cpp

@@ -1,3 +1,5 @@
+
+#include "ComponentConstructorInfo.h"
 #include "LuaScript.h"
 
 namespace LuaDefinitions
@@ -5,4 +7,514 @@ namespace LuaDefinitions
 	DEFINE_ENUM(UserTypes, LUA_USER_TYPES)
 
 	DEFINE_ENUM(SpatialChanges, LUA_SPATIAL_CHANGES)
-}
+}
+
+void LuaScript::setFunctions()
+{
+	// Math functions
+	m_luaState.set_function("toRadianF", sol::resolve<float(const float)>(&glm::radians));
+	m_luaState.set_function("toRadianVec3", sol::resolve<glm::vec3(const glm::vec3 &)>(&glm::radians));
+	m_luaState.set_function("toRadianVec4", sol::resolve<glm::vec4(const glm::vec4 &)>(&glm::radians));
+	m_luaState.set_function("toDegreesF", sol::resolve<float(const float)>(&glm::degrees));
+	m_luaState.set_function("toDegreesVec3", sol::resolve<glm::vec3(const glm::vec3 &)>(&glm::degrees));
+	m_luaState.set_function("toDegreesVec4", sol::resolve<glm::vec4(const glm::vec4 &)>(&glm::degrees));
+	m_luaState.set_function("angleAxisQuat", sol::resolve<glm::quat(const float &, const glm::vec3 &)>(&glm::angleAxis));
+
+	// Input / Window functions
+	m_luaState.set_function("getMouseInfo", []() -> const Window::MouseInfo { return WindowLocator::get().getMouseInfo(); });
+	m_luaState.set_function("mouseCaptured", []() -> const bool { return Config::windowVar().mouse_captured; });
+	m_luaState.set_function("setFullscreen", [](const bool p_v1) -> const void { WindowLocator::get().setFullscreen(p_v1); });
+	m_luaState.set_function("setMouseCapture", [](const bool p_v1) -> const void { WindowLocator::get().setMouseCapture(p_v1); });
+	m_luaState.set_function("setVerticalSync", [](const bool p_v1) -> const void { WindowLocator::get().setVerticalSync(p_v1); });
+	m_luaState.set_function("setWindowTitle", [](const std::string &p_v1) -> const void { WindowLocator::get().setWindowTitle(p_v1); });
+
+	// Entity component functions
+	m_luaState.set_function("createEntity", [this](const ComponentsConstructionInfo &p_constructionInfo) -> EntityID { return static_cast<WorldScene *>(m_scriptScene->getSceneLoader()->getSystemScene(Systems::World))->createEntity(p_constructionInfo); });
+	m_luaState.set_function("importPrefab", [this](ComponentsConstructionInfo &p_constructionInfo, const std::string &p_filename) -> bool { return m_scriptScene->getSceneLoader()->importPrefab(p_constructionInfo, p_filename) == ErrorCode::Success; });
+
+	// Engine functions
+	m_luaState.set_function("setEngineRunning", [](const bool p_v1) -> const void {Config::m_engineVar.running = p_v1; });
+
+	// GUI functions
+	auto GUITable = m_luaState.create_table("GUI");
+	GUITable.set_function("Begin", [this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::Begin(p_v1.c_str()); }); });
+	GUITable.set_function("BeginChild", [this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::BeginChild(p_v1.c_str()); }); });
+	GUITable.set_function("BeginMenu", [this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::BeginMenu(p_v1.c_str()); }); });
+	GUITable.set_function("Button", [this](const std::string &p_v1, Conditional *p_v2) -> void { m_GUIData.addFunctor([=] { p_v2->m_flag = ImGui::Button(p_v1.c_str()); }); });
+	GUITable.set_function("Checkbox", [this](const std::string &p_v1, Conditional *p_v2) -> void { m_GUIData.addFunctor([=] { ImGui::Checkbox(p_v1.c_str(), &p_v2->m_flag); }); });
+	GUITable.set_function("ColorEdit3", [this](const std::string &p_v1, glm::vec3 *p_v2) -> void { m_GUIData.addFunctor([=] { ImGui::ColorEdit3(p_v1.c_str(), &(p_v2->x)); }); });
+	GUITable.set_function("ColorEdit4", [this](const std::string &p_v1, glm::vec4 *p_v2) -> void { m_GUIData.addFunctor([=] { ImGui::ColorEdit4(p_v1.c_str(), &(p_v2->x)); }); });
+	GUITable.set_function("End", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::End(); }); });
+	GUITable.set_function("EndChild", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::EndChild(); }); });
+	GUITable.set_function("EndMenu", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::EndMenu(); }); });
+	GUITable.set_function("EndMenuBar", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::EndMenuBar(); }); });
+	GUITable.set_function("MenuItem", [this](const std::string &p_v1, const std::string &p_v2, Conditional *p_v3) -> void { m_GUIData.addFunctor([=] { p_v3->m_flag = ImGui::MenuItem(p_v1.c_str(), p_v2.c_str()); }); });
+	GUITable.set_function("PlotLines", [this](const std::string &p_v1, const float *p_v2, int p_v3) -> const void { m_GUIData.addFunctor([=] { ImGui::PlotLines(p_v1.c_str(), p_v2, p_v3); }); });
+	GUITable.set_function("SliderFloat", [this](const std::string &p_v1, float *p_v2, const float p_v3, const float p_v4) -> const void { m_GUIData.addFunctor([=] { ImGui::SliderFloat(p_v1.c_str(), p_v2, p_v3, p_v4); }); });
+	GUITable.set_function("SameLine", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::SameLine(); }); });
+	GUITable.set_function("Text", sol::overload([this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::Text(p_v1.c_str()); }); },
+		[this](const std::string &p_v1, const float p_v2) -> const void { m_GUIData.addFunctor([=] { ImGui::Text(p_v1.c_str(), p_v2); }); },
+		[this](const std::string &p_v1, const float p_v2, const float p_v3) -> const void { m_GUIData.addFunctor([=] { ImGui::Text(p_v1.c_str(), p_v2, p_v3); }); }));
+	GUITable.set_function("TextColored", sol::overload([this](const glm::vec4 p_v1, const std::string &p_v2) -> const void { m_GUIData.addFunctor([=] { ImGui::TextColored(ImVec4(p_v1.x, p_v1.y, p_v1.z, p_v1.w), p_v2.c_str()); }); },
+		[this](const glm::vec4 p_v1, const std::string &p_v2, const float p_v3) -> const void { m_GUIData.addFunctor([=] { ImGui::TextColored(ImVec4(p_v1.x, p_v1.y, p_v1.z, p_v1.w), p_v2.c_str(), p_v3); }); },
+		[this](const glm::vec4 p_v1, const std::string &p_v2, const float p_v3, const float p_v4) -> const void { m_GUIData.addFunctor([=] { ImGui::TextColored(ImVec4(p_v1.x, p_v1.y, p_v1.z, p_v1.w), p_v2.c_str(), p_v3, p_v4); }); }));
+
+	// LuaScript callbacks
+	m_luaState.set_function("postChanges", &LuaScript::registerChange, this);
+	m_luaState.set_function(Config::scriptVar().createObjectFunctionName, &LuaScript::createObjectInLua, this);
+}
+
+void LuaScript::setUsertypes()
+{
+	// Config variables
+	m_luaState.new_usertype<Config::EngineVariables>("EngineVariables",
+		"change_ctrl_cml_notify_list_reserv", &Config::EngineVariables::change_ctrl_cml_notify_list_reserv,
+		"change_ctrl_grain_size", &Config::EngineVariables::change_ctrl_grain_size,
+		"change_ctrl_notify_list_reserv", &Config::EngineVariables::change_ctrl_notify_list_reserv,
+		"change_ctrl_oneoff_notify_list_reserv", &Config::EngineVariables::change_ctrl_oneoff_notify_list_reserv,
+		"change_ctrl_subject_list_reserv", &Config::EngineVariables::change_ctrl_subject_list_reserv,
+		"delta_time_divider", &Config::EngineVariables::delta_time_divider,
+		"gl_context_major_version", &Config::EngineVariables::gl_context_major_version,
+		"gl_context_minor_version", &Config::EngineVariables::gl_context_minor_version,
+		"object_directory_init_pool_size", &Config::EngineVariables::object_directory_init_pool_size,
+		"smoothing_tick_samples", &Config::EngineVariables::smoothing_tick_samples,
+		"running", &Config::EngineVariables::running);
+
+	m_luaState.new_usertype<Config::GameplayVariables>("GameplayVariables",
+		"camera_freelook_speed", &Config::GameplayVariables::camera_freelook_speed);
+
+	m_luaState.new_usertype<Config::InputVariables>("InputVariables",
+		"back_key", &Config::InputVariables::back_key,
+		"backward_editor_key", &Config::InputVariables::backward_editor_key,
+		"backward_key", &Config::InputVariables::backward_key,
+		"center_key", &Config::InputVariables::center_key,
+		"clip_mouse_key", &Config::InputVariables::clip_mouse_key,
+		"close_window_key", &Config::InputVariables::close_window_key,
+		"debug_1_key", &Config::InputVariables::debug_1_key,
+		"debug_2_key", &Config::InputVariables::debug_2_key,
+		"down_editor_key", &Config::InputVariables::down_editor_key,
+		"down_key", &Config::InputVariables::down_key,
+		"escape_key", &Config::InputVariables::escape_key,
+		"forward_editor_key", &Config::InputVariables::forward_editor_key,
+		"forward_key", &Config::InputVariables::forward_key,
+		"fullscreen_key", &Config::InputVariables::fullscreen_key,
+		"jump_key", &Config::InputVariables::jump_key,
+		"left_editor_key", &Config::InputVariables::left_editor_key,
+		"left_strafe_key", &Config::InputVariables::left_strafe_key,
+		"modifier_editor_key", &Config::InputVariables::modifier_editor_key,
+		"next_editor_key", &Config::InputVariables::next_editor_key,
+		"num_preallocated_keybinds", &Config::InputVariables::num_preallocated_keybinds,
+		"previous_editor_key", &Config::InputVariables::previous_editor_key,
+		"right_editor_key", &Config::InputVariables::right_editor_key,
+		"right_strafe_key", &Config::InputVariables::right_strafe_key,
+		"save_editor_key", &Config::InputVariables::save_editor_key,
+		"sprint_key", &Config::InputVariables::sprint_key,
+		"up_editor_key", &Config::InputVariables::up_editor_key,
+		"up_key", &Config::InputVariables::up_key,
+		"vsync_key", &Config::InputVariables::vsync_key,
+		"mouse_filter", &Config::InputVariables::mouse_filter,
+		"mouse_warp_mode", &Config::InputVariables::mouse_warp_mode,
+		"mouse_jaw", &Config::InputVariables::mouse_jaw,
+		"mouse_pitch", &Config::InputVariables::mouse_pitch,
+		"mouse_pitch_clip", &Config::InputVariables::mouse_pitch_clip,
+		"mouse_sensitivity", &Config::InputVariables::mouse_sensitivity);
+
+	m_luaState.new_usertype<Config::WindowVariables>("WindowVariables",
+		"name", &Config::WindowVariables::name,
+		"default_display", &Config::WindowVariables::default_display,
+		"window_position_x", &Config::WindowVariables::window_position_x,
+		"window_position_y", &Config::WindowVariables::window_position_y,
+		"window_size_fullscreen_x", &Config::WindowVariables::window_size_fullscreen_x,
+		"window_size_fullscreen_y", &Config::WindowVariables::window_size_fullscreen_y,
+		"window_size_windowed_x", &Config::WindowVariables::window_size_windowed_x,
+		"window_size_windowed_y", &Config::WindowVariables::window_size_windowed_y,
+		"fullscreen", &Config::WindowVariables::fullscreen,
+		"fullscreen_borderless", &Config::WindowVariables::fullscreen_borderless,
+		"mouse_captured", &Config::WindowVariables::mouse_captured,
+		"mouse_release_on_lost_focus", &Config::WindowVariables::mouse_release_on_lost_focus,
+		"resizable", &Config::WindowVariables::resizable,
+		"vertical_sync", &Config::WindowVariables::vertical_sync,
+		"window_in_focus", &Config::WindowVariables::window_in_focus);
+
+	// Math types
+	m_luaState.new_usertype<Int64Packer>("Int64");
+
+	m_luaState.new_usertype<glm::vec3>("Vec3",
+		sol::constructors<glm::vec3(), glm::vec3(float), glm::vec3(float, float, float), glm::vec3(glm::vec4)>(),
+		"x", &glm::vec3::x,
+		"y", &glm::vec3::y,
+		"z", &glm::vec3::z,
+		"addF", [](const glm::vec3 &v1, const float f) -> glm::vec3 { return v1 + f; },
+		"subF", [](const glm::vec3 &v1, const float f) -> glm::vec3 { return v1 - f; },
+		"mulF", [](const glm::vec3 &v1, const float f) -> glm::vec3 { return v1 * f; },
+		"divF", [](const glm::vec3 &v1, const float f) -> glm::vec3 { return v1 / f; },
+		"addVec3", [](const glm::vec3 &v1, const glm::vec3 &v2) -> glm::vec3 { return v1 + v2; },
+		"subVec3", [](const glm::vec3 &v1, const glm::vec3 &v2) -> glm::vec3 { return v1 - v2; },
+		"mulVec3", [](const glm::vec3 &v1, const glm::vec3 &v2) -> glm::vec3 { return v1 * v2; },
+		"divVec3", [](const glm::vec3 &v1, const glm::vec3 &v2) -> glm::vec3 { return v1 / v2; },
+		"normalize", [](const glm::vec3 &v1) -> glm::vec3 { return glm::normalize(v1); },
+		sol::meta_function::addition, [](const glm::vec3 &v1, glm::vec3 &v2) -> glm::vec3 { return v1 + v2; },
+		sol::meta_function::subtraction, [](const glm::vec3 &v1, glm::vec3 &v2) -> glm::vec3 { return v1 - v2; },
+		sol::meta_function::multiplication, [](const glm::vec3 &v1, glm::vec3 &v2) -> glm::vec3 { return v1 * v2; },
+		sol::meta_function::division, [](const glm::vec3 &v1, glm::vec3 &v2) -> glm::vec3 { return v1 / v2; });
+
+	m_luaState.new_usertype<glm::vec4>("Vec4",
+		sol::constructors<glm::vec4(), glm::vec4(float), glm::vec4(glm::vec3, float), glm::vec4(float, float, float, float)>(),
+		"x", &glm::vec4::x,
+		"y", &glm::vec4::y,
+		"z", &glm::vec4::z,
+		"w", &glm::vec4::w,
+		"addF", [](const glm::vec4 &v1, const float f) -> glm::vec4 { return v1 + f; },
+		"subF", [](const glm::vec4 &v1, const float f) -> glm::vec4 { return v1 - f; },
+		"mulF", [](const glm::vec4 &v1, const float f) -> glm::vec4 { return v1 * f; },
+		"divF", [](const glm::vec4 &v1, const float f) -> glm::vec4 { return v1 / f; },
+		"addVec4", [](const glm::vec4 &v1, const glm::vec4 &v2) -> glm::vec4 { return v1 + v2; },
+		"subVec4", [](const glm::vec4 &v1, const glm::vec4 &v2) -> glm::vec4 { return v1 - v2; },
+		"mulVec4", [](const glm::vec4 &v1, const glm::vec4 &v2) -> glm::vec4 { return v1 * v2; },
+		"divVec4", [](const glm::vec4 &v1, const glm::vec4 &v2) -> glm::vec4 { return v1 / v2; },
+		"normalize", [](const glm::vec4 &v1) -> glm::vec4 { return glm::normalize(v1); },
+		sol::meta_function::addition, [](const glm::vec4 &v1, glm::vec4 &v2) -> glm::vec4 { return v1 + v2; },
+		sol::meta_function::subtraction, [](const glm::vec4 &v1, glm::vec4 &v2) -> glm::vec4 { return v1 - v2; },
+		sol::meta_function::multiplication, [](const glm::vec4 &v1, glm::vec4 &v2) -> glm::vec4 { return v1 * v2; },
+		sol::meta_function::division, [](const glm::vec4 &v1, glm::vec4 &v2) -> glm::vec4 { return v1 / v2; });
+
+	m_luaState.new_usertype<glm::quat>("Quat",
+		sol::constructors<glm::quat(), glm::quat(glm::vec4)>(),
+		"x", &glm::quat::x,
+		"y", &glm::quat::y,
+		"z", &glm::quat::z,
+		"w", &glm::quat::w,
+		"mulF", [](const glm::quat &q1, const float f) -> glm::quat { return q1 * f; },
+		"divF", [](const glm::quat &q1, const float f) -> glm::quat { return q1 / f; },
+		"mulVec3", [](const glm::quat &q1, const glm::vec3 &v2) -> glm::quat { return q1 * v2; },
+		"normalize", [](const glm::quat &q1) -> glm::quat { return glm::normalize(q1); },
+		"inverse", [](const glm::quat &q1) -> glm::quat { return glm::inverse(q1); },
+		"rotateVec3", [](const glm::quat &q1, const glm::vec3 &v2) -> glm::vec3 { return glm::rotate(q1, v2); },
+		"toMat4", [](const glm::quat &q1) -> glm::mat4 { return glm::toMat4(q1); },
+		sol::meta_function::addition, [](const glm::quat &q1, glm::quat &q2) -> glm::quat { return q1 + q2; },
+		sol::meta_function::subtraction, [](const glm::quat &q1, glm::quat &q2) -> glm::quat { return q1 - q2; },
+		sol::meta_function::multiplication, [](const glm::quat &q1, glm::quat &q2) -> glm::quat { return q1 * q2; });
+
+	m_luaState.new_usertype<glm::mat4>("Mat4",
+		sol::constructors<glm::mat4(), glm::mat4(float)>(),
+		"mulF", [](const glm::mat4 &v1, const float f) -> glm::mat4 { return v1 * f; },
+		"divF", [](const glm::mat4 &v1, const float f) -> glm::mat4 { return v1 / f; },
+		"mulVec3", [](const glm::mat4 &m1, const glm::vec3 &v2) -> glm::vec4 { return m1 * glm::vec4(v2, 1.0f); },
+		"divVec3", [](const glm::mat4 &m1, const glm::vec3 &v2) -> glm::vec4 { return m1 / glm::vec4(v2, 1.0f); },
+		"mulVec4", [](const glm::mat4 &m1, const glm::vec4 &v2) -> glm::vec4 { return m1 * v2; },
+		"divVec4", [](const glm::mat4 &m1, const glm::vec4 &v2) -> glm::vec4 { return m1 / v2; },
+		"inverse", [](const glm::mat4 &m1) -> glm::mat4 { return glm::inverse(m1); },
+		"rotate", [](const glm::mat4 &m1, const float f1, const glm::vec3 &v1) -> glm::mat4 { return glm::rotate(m1, f1, v1); },
+		"toQuat", [](const glm::mat4 &m1) -> glm::quat { return glm::toQuat(m1); },
+		"getRotXVec3", [](const glm::mat4 &m1) -> glm::vec3 { return m1[0]; },
+		"getRotYVec3", [](const glm::mat4 &m1) -> glm::vec3 { return m1[1]; },
+		"getRotZVec3", [](const glm::mat4 &m1) -> glm::vec3 { return m1[2]; },
+		"getPosVec3", [](const glm::mat4 &m1) -> glm::vec3 { return m1[3]; },
+		"getRotXVec4", [](const glm::mat4 &m1) -> glm::vec4 { return m1[0]; },
+		"getRotYVec4", [](const glm::mat4 &m1) -> glm::vec4 { return m1[1]; },
+		"getRotZVec4", [](const glm::mat4 &m1) -> glm::vec4 { return m1[2]; },
+		"getPosVec4", [](const glm::mat4 &m1) -> glm::vec4 { return m1[3]; },
+		"setPosVec3", [](glm::mat4 &m1, const glm::vec3 &v2) -> void { m1[3] = glm::vec4(v2, 1.0f); },
+		"setPosVec4", [](glm::mat4 &m1, const glm::vec4 &v2) -> void { m1[3] = v2; },
+		sol::meta_function::addition, [](const glm::mat4 &m1, glm::mat4 &m2) -> glm::mat4 { return m1 + m2; },
+		sol::meta_function::subtraction, [](const glm::mat4 &m1, glm::mat4 &m2) -> glm::mat4 { return m1 - m2; },
+		sol::meta_function::multiplication, [](const glm::mat4 &m1, glm::mat4 &m2) -> glm::mat4 { return m1 * m2; },
+		sol::meta_function::division, [](const glm::mat4 &m1, glm::mat4 &m2) -> glm::mat4 { return m1 / m2; });
+
+	m_luaState.new_usertype<SpatialData>("SpatialData",
+		"clear", &SpatialData::clear,
+		"m_position", &SpatialData::m_position,
+		"m_rotationEuler", &SpatialData::m_rotationEuler,
+		"m_rotationQuaternion", &SpatialData::m_rotationQuat,
+		"m_scale", &SpatialData::m_scale);
+
+	m_luaState.new_usertype<SpatialTransformData>("SpatialTransformData",
+		"clear", &SpatialTransformData::clear,
+		"m_spatialData", &SpatialTransformData::m_spatialData);
+
+	m_luaState.new_usertype<SpatialDataManager>("SpatialDataManager",
+		"update", &SpatialDataManager::update,
+		"getLocalSpaceData", &SpatialDataManager::getLocalSpaceData,
+		"getLocalTransform", &SpatialDataManager::getLocalTransform,
+		"getParemtTransform", &SpatialDataManager::getParemtTransform,
+		"getWorldTransform", &SpatialDataManager::getWorldTransform,
+		"setLocalPosition", &SpatialDataManager::setLocalPosition,
+		"setLocalRotationEuler", sol::resolve<const void(const glm::vec3)>(&SpatialDataManager::setLocalRotation),
+		"setLocalRotationQuat", sol::resolve<const void(const glm::quat)>(&SpatialDataManager::setLocalRotation),
+		"setLocalScale", &SpatialDataManager::setLocalScale,
+		"setLocalTransform", &SpatialDataManager::setLocalTransform,
+		"setParentTransform", &SpatialDataManager::setParentTransform,
+		"setWorldTransform", &SpatialDataManager::setWorldTransform);
+
+	// Input types
+	m_luaState.new_usertype<Window::MouseInfo>("MouseInfo",
+		"m_movementCurrentFrameX", &Window::MouseInfo::m_movementCurrentFrameX,
+		"m_movementCurrentFrameY", &Window::MouseInfo::m_movementCurrentFrameY,
+		"m_movementPrevFrameX", &Window::MouseInfo::m_movementPrevFrameX,
+		"m_movementPrevFrameY", &Window::MouseInfo::m_movementPrevFrameY,
+		"m_wheelX", &Window::MouseInfo::m_wheelX,
+		"m_wheelY", &Window::MouseInfo::m_wheelY,
+		"m_movementX", &Window::MouseInfo::m_movementX,
+		"m_movementY", &Window::MouseInfo::m_movementY);
+
+	m_luaState.new_usertype<KeyCommand>("KeyCommand",
+		"activate", &KeyCommand::activate,
+		"deactivate", &KeyCommand::deactivate,
+		"isActivated", &KeyCommand::isActivated,
+		"bind", sol::resolve<void(const Scancode)>(&KeyCommand::bind),
+		"bindByName", sol::resolve<void(const std::string &)>(&KeyCommand::bind),
+		"unbind", &KeyCommand::unbind,
+		"unbindAll", &KeyCommand::unbindAll);
+
+	// Component construction info
+	m_luaState.new_usertype<ComponentsConstructionInfo>("ComponentsConstructionInfo",
+		sol::meta_function::garbage_collect, sol::destructor(&ComponentsConstructionInfo::deleteConstructionInfo),
+		"m_name", &ComponentsConstructionInfo::m_name,
+		"m_id", &ComponentsConstructionInfo::m_id,
+		"m_parent", &ComponentsConstructionInfo::m_parent,
+		"m_graphicsComponents", &ComponentsConstructionInfo::m_graphicsComponents,
+		"m_guiComponents", &ComponentsConstructionInfo::m_guiComponents,
+		"m_physicsComponents", &ComponentsConstructionInfo::m_physicsComponents,
+		"m_scriptComponents", &ComponentsConstructionInfo::m_scriptComponents,
+		"m_worldComponents", &ComponentsConstructionInfo::m_worldComponents);
+
+	m_luaState.new_usertype<GraphicsComponentsConstructionInfo>("GraphicsComponentsConstructionInfo",
+		sol::meta_function::garbage_collect, sol::destructor(&GraphicsComponentsConstructionInfo::deleteConstructionInfo),
+		"m_cameraConstructionInfo", &GraphicsComponentsConstructionInfo::m_cameraConstructionInfo,
+		"m_lightConstructionInfo", &GraphicsComponentsConstructionInfo::m_lightConstructionInfo,
+		"m_modelConstructionInfo", &GraphicsComponentsConstructionInfo::m_modelConstructionInfo,
+		"m_shaderConstructionInfo", &GraphicsComponentsConstructionInfo::m_shaderConstructionInfo,
+		"cameraPresent", [](const GraphicsComponentsConstructionInfo &c1) -> bool { return c1.m_cameraConstructionInfo != nullptr; },
+		"lightPresent", [](const GraphicsComponentsConstructionInfo &c1) -> bool { return c1.m_lightConstructionInfo != nullptr; },
+		"modelPresent", [](const GraphicsComponentsConstructionInfo &c1) -> bool { return c1.m_modelConstructionInfo != nullptr; },
+		"shaderPresent", [](const GraphicsComponentsConstructionInfo &c1) -> bool { return c1.m_shaderConstructionInfo != nullptr; },
+		"createCamera", [](GraphicsComponentsConstructionInfo &c1) -> void { if(c1.m_cameraConstructionInfo != nullptr) delete c1.m_cameraConstructionInfo; c1.m_cameraConstructionInfo = new CameraComponent::CameraComponentConstructionInfo(); },
+		"createLight", [](GraphicsComponentsConstructionInfo &c1) -> void { if(c1.m_lightConstructionInfo != nullptr) delete c1.m_lightConstructionInfo; c1.m_lightConstructionInfo = new LightComponent::LightComponentConstructionInfo(); },
+		"createModel", [](GraphicsComponentsConstructionInfo &c1) -> void { if(c1.m_modelConstructionInfo != nullptr) delete c1.m_modelConstructionInfo; c1.m_modelConstructionInfo = new ModelComponent::ModelComponentConstructionInfo(); },
+		"createShader", [](GraphicsComponentsConstructionInfo &c1) -> void { if(c1.m_shaderConstructionInfo != nullptr) delete c1.m_shaderConstructionInfo; c1.m_shaderConstructionInfo = new ShaderComponent::ShaderComponentConstructionInfo(); });
+
+	m_luaState.new_usertype<GUIComponentsConstructionInfo>("GUIComponentsConstructionInfo",
+		sol::meta_function::garbage_collect, sol::destructor(&GUIComponentsConstructionInfo::deleteConstructionInfo),
+		"m_guiSequenceConstructionInfo", &GUIComponentsConstructionInfo::m_guiSequenceConstructionInfo,
+		"guiSequencePresent", [](const GUIComponentsConstructionInfo &c1) -> bool { return c1.m_guiSequenceConstructionInfo != nullptr; },
+		"createGUISequence", [](GUIComponentsConstructionInfo &c1) -> void { if(c1.m_guiSequenceConstructionInfo != nullptr) delete c1.m_guiSequenceConstructionInfo; c1.m_guiSequenceConstructionInfo = new GUISequenceComponent::GUISequenceComponentConstructionInfo(); });
+
+	m_luaState.new_usertype<PhysicsComponentsConstructionInfo>("PhysicsComponentsConstructionInfo",
+		sol::meta_function::garbage_collect, sol::destructor(&PhysicsComponentsConstructionInfo::deleteConstructionInfo),
+		"m_rigidBodyConstructionInfo", &PhysicsComponentsConstructionInfo::m_rigidBodyConstructionInfo,
+		"rigidBodyPresent", [](const PhysicsComponentsConstructionInfo &c1) -> bool { return c1.m_rigidBodyConstructionInfo != nullptr; },
+		"createRigidBody", [](PhysicsComponentsConstructionInfo &c1) -> void { if(c1.m_rigidBodyConstructionInfo != nullptr) delete c1.m_rigidBodyConstructionInfo; c1.m_rigidBodyConstructionInfo = new RigidBodyComponent::RigidBodyComponentConstructionInfo(); });
+
+	m_luaState.new_usertype<ScriptComponentsConstructionInfo>("ScriptComponentsConstructionInfo",
+		sol::meta_function::garbage_collect, sol::destructor(&ScriptComponentsConstructionInfo::deleteConstructionInfo),
+		"m_luaConstructionInfo", &ScriptComponentsConstructionInfo::m_luaConstructionInfo,
+		"luaPresent", [](const ScriptComponentsConstructionInfo &c1) -> bool { return c1.m_luaConstructionInfo != nullptr; },
+		"createLua", [](ScriptComponentsConstructionInfo &c1) -> void { if(c1.m_luaConstructionInfo != nullptr) delete c1.m_luaConstructionInfo; c1.m_luaConstructionInfo = new LuaComponent::LuaComponentConstructionInfo(); });
+
+	m_luaState.new_usertype<WorldComponentsConstructionInfo>("WorldComponentsConstructionInfo",
+		sol::meta_function::garbage_collect, sol::destructor(&WorldComponentsConstructionInfo::deleteConstructionInfo),
+		"m_spatialConstructionInfo", &WorldComponentsConstructionInfo::m_spatialConstructionInfo,
+		"spatialPresent", [](const WorldComponentsConstructionInfo &c1) -> bool { return c1.m_spatialConstructionInfo != nullptr; },
+		"createSpatial", [](WorldComponentsConstructionInfo &c1) -> void { if(c1.m_spatialConstructionInfo != nullptr) delete c1.m_spatialConstructionInfo; c1.m_spatialConstructionInfo = new SpatialComponent::SpatialComponentConstructionInfo(); });
+
+	m_luaState.new_usertype<CameraComponent::CameraComponentConstructionInfo>("CameraComponentConstructionInfo",
+		"m_active", &CameraComponent::CameraComponentConstructionInfo::m_active,
+		"m_name", &CameraComponent::CameraComponentConstructionInfo::m_name,
+		"m_fov", &CameraComponent::CameraComponentConstructionInfo::m_fov);
+
+	m_luaState.new_usertype<LightComponent::LightComponentConstructionInfo>("LightComponentConstructionInfo",
+		"m_active", &LightComponent::LightComponentConstructionInfo::m_active,
+		"m_name", &LightComponent::LightComponentConstructionInfo::m_name,
+		"m_color", &LightComponent::LightComponentConstructionInfo::m_color,
+		"m_direction", &LightComponent::LightComponentConstructionInfo::m_direction,
+		"m_position", &LightComponent::LightComponentConstructionInfo::m_position,
+		"m_intensity", &LightComponent::LightComponentConstructionInfo::m_intensity,
+		"m_cutoffAngle", &LightComponent::LightComponentConstructionInfo::m_cutoffAngle,
+		"m_lightComponentType", &LightComponent::LightComponentConstructionInfo::m_lightComponentType);
+
+	m_luaState.new_usertype<ModelComponent::ModelComponentConstructionInfo>("ModelComponentConstructionInfo",
+		"m_active", &ModelComponent::ModelComponentConstructionInfo::m_active,
+		"m_name", &ModelComponent::ModelComponentConstructionInfo::m_name);
+
+	m_luaState.new_usertype<ShaderComponent::ShaderComponentConstructionInfo>("ShaderComponentConstructionInfo",
+		"m_active", &ShaderComponent::ShaderComponentConstructionInfo::m_active,
+		"m_name", &ShaderComponent::ShaderComponentConstructionInfo::m_name,
+		"m_geometryShaderFilename", &ShaderComponent::ShaderComponentConstructionInfo::m_geometryShaderFilename,
+		"m_vetexShaderFilename", &ShaderComponent::ShaderComponentConstructionInfo::m_vetexShaderFilename,
+		"m_fragmentShaderFilename", &ShaderComponent::ShaderComponentConstructionInfo::m_fragmentShaderFilename);
+
+	m_luaState.new_usertype<RigidBodyComponent::RigidBodyComponentConstructionInfo>("RigidBodyComponentConstructionInfo",
+		"m_active", &RigidBodyComponent::RigidBodyComponentConstructionInfo::m_active,
+		"m_name", &RigidBodyComponent::RigidBodyComponentConstructionInfo::m_name,
+		"m_friction", &RigidBodyComponent::RigidBodyComponentConstructionInfo::m_friction,
+		"m_mass", &RigidBodyComponent::RigidBodyComponentConstructionInfo::m_mass,
+		"m_restitution", &RigidBodyComponent::RigidBodyComponentConstructionInfo::m_restitution,
+		"m_kinematic", &RigidBodyComponent::RigidBodyComponentConstructionInfo::m_kinematic,
+		"m_linearVelocity", &RigidBodyComponent::RigidBodyComponentConstructionInfo::m_linearVelocity,
+		"m_collisionShapeType", &RigidBodyComponent::RigidBodyComponentConstructionInfo::m_collisionShapeType,
+		"m_collisionShapeSize", &RigidBodyComponent::RigidBodyComponentConstructionInfo::m_collisionShapeSize);
+
+	m_luaState.new_usertype<LuaComponent::LuaComponentConstructionInfo>("LuaComponentConstructionInfo",
+		"m_active", &LuaComponent::LuaComponentConstructionInfo::m_active,
+		"m_name", &LuaComponent::LuaComponentConstructionInfo::m_name,
+		"m_luaScriptFilename", &LuaComponent::LuaComponentConstructionInfo::m_luaScriptFilename);
+
+	m_luaState.new_usertype<SpatialComponent::SpatialComponentConstructionInfo>("SpatialComponentConstructionInfo",
+		"m_active", &SpatialComponent::SpatialComponentConstructionInfo::m_active,
+		"m_name", &SpatialComponent::SpatialComponentConstructionInfo::m_name,
+		"m_localPosition", &SpatialComponent::SpatialComponentConstructionInfo::m_localPosition,
+		"m_localRotationEuler", &SpatialComponent::SpatialComponentConstructionInfo::m_localRotationEuler,
+		"m_localRotationQuaternion", &SpatialComponent::SpatialComponentConstructionInfo::m_localRotationQuaternion,
+		"m_localScale", &SpatialComponent::SpatialComponentConstructionInfo::m_localScale);
+
+	// Misc types
+	m_luaState.new_usertype<Conditional>("Conditional",
+		"isChecked", &Conditional::isChecked,
+		"check", &Conditional::check,
+		"uncheck", &Conditional::uncheck,
+		"set", &Conditional::set);
+}
+
+void LuaScript::createObjectInLua(const unsigned int p_objectType, const std::string p_variableName)
+{
+	// Check if the object type is in a valid range and if the variable name isn't empty
+	if(p_objectType >= 0 && p_objectType < LuaDefinitions::UserTypes::NumOfTypes && !p_variableName.empty())
+	{
+		switch(p_objectType)
+		{
+		case LuaDefinitions::Conditional:
+		{
+			// Create a new Conditional
+			Conditional *newConditional = new Conditional();
+
+			// Set the given variable name in Lua to point to the created Conditional
+			m_luaState.set(p_variableName, newConditional);
+
+			// Add the conditional pointer to an array so it is not lost
+			m_conditionals.push_back(newConditional);
+		}
+		break;
+
+		case LuaDefinitions::EngineVariables:
+
+			// Set the given variable name in Lua to point to the EngineVariables object
+			m_luaState.set(p_variableName, Config::engineVar());
+
+			break;
+
+		case LuaDefinitions::GameplayVariables:
+
+			// Set the given variable name in Lua to point to the GameplayVariables object
+			m_luaState.set(p_variableName, Config::gameplayVar());
+
+			break;
+
+		case LuaDefinitions::InputVariables:
+
+			// Set the given variable name in Lua to point to the InputVariables object
+			m_luaState.set(p_variableName, Config::inputVar());
+
+			break;
+
+		case LuaDefinitions::KeyCommand:
+		{
+			// Create new key command
+			KeyCommand *keyCommand = new KeyCommand();
+
+			// Set the given variable name in Lua to point to the created key command
+			m_luaState.set(p_variableName, keyCommand);
+
+			// Add key command pointer to an array so it is not lost
+			m_keyCommands.push_back(keyCommand);
+		}
+		break;
+
+		case LuaDefinitions::MouseInfo:
+
+			// Set the given variable name in Lua to point to the MouseInfo object
+			m_luaState.set(p_variableName, WindowLocator::get().getMouseInfo());
+
+			break;
+
+		case LuaDefinitions::SpatialDataManager:
+
+			// Set the given variable name in Lua to point to the Spatial Data Manager object
+			m_luaState.set(p_variableName, &m_spatialData);
+
+			break;
+
+		case LuaDefinitions::WindowVariables:
+
+			// Set the given variable name in Lua to point to the WindowVariables object
+			m_luaState.set(p_variableName, Config::windowVar());
+
+			break;
+
+		case LuaDefinitions::ComponentsInfo:
+		{
+			// Create a new Conditional
+			ComponentsConstructionInfo *newConstructionInfo = new ComponentsConstructionInfo();
+
+			// Set the given variable name in Lua to point to the created Conditional
+			m_luaState.set(p_variableName, newConstructionInfo);
+
+			// Add the conditional pointer to an array so it is not lost
+			//m_conditionals.push_back(newConstructionInfo);
+		}
+		break;
+
+		case LuaDefinitions::GraphicsComponentInfo:
+		{
+			// Create a new Conditional
+			GraphicsComponentsConstructionInfo *newConstructionInfo = new GraphicsComponentsConstructionInfo();
+
+			// Set the given variable name in Lua to point to the created Conditional
+			m_luaState.set(p_variableName, newConstructionInfo);
+		}
+		break;
+
+		case LuaDefinitions::GUIComponentInfo:
+		{
+			// Create a new Conditional
+			GUIComponentsConstructionInfo *newConstructionInfo = new GUIComponentsConstructionInfo();
+
+			// Set the given variable name in Lua to point to the created Conditional
+			m_luaState.set(p_variableName, newConstructionInfo);
+		}
+		break;
+
+		case LuaDefinitions::PhysicsComponentInfo:
+		{
+			// Create a new Conditional
+			PhysicsComponentsConstructionInfo *newConstructionInfo = new PhysicsComponentsConstructionInfo();
+
+			// Set the given variable name in Lua to point to the created Conditional
+			m_luaState.set(p_variableName, newConstructionInfo);
+		}
+		break;
+
+		case LuaDefinitions::ScriptComponentInfo:
+		{
+			// Create a new Conditional
+			ScriptComponentsConstructionInfo *newConstructionInfo = new ScriptComponentsConstructionInfo();
+
+			// Set the given variable name in Lua to point to the created Conditional
+			m_luaState.set(p_variableName, newConstructionInfo);
+		}
+		break;
+
+		case LuaDefinitions::WorldComponentInfo:
+		{
+			// Create a new Conditional
+			WorldComponentsConstructionInfo *newConstructionInfo = new WorldComponentsConstructionInfo();
+
+			// Set the given variable name in Lua to point to the created Conditional
+			m_luaState.set(p_variableName, newConstructionInfo);
+		}
+		break;
+
+		default:
+			break;
+		}
+	}
+}

+ 14 - 339
Praxis3D/Source/LuaScript.h

@@ -24,6 +24,12 @@ namespace LuaDefinitions
     Code(MouseInfo,) \
 	Code(SpatialDataManager,) \
 	Code(WindowVariables,) \
+	Code(ComponentsInfo,) \
+	Code(GraphicsComponentInfo,) \
+	Code(GUIComponentInfo,) \
+	Code(PhysicsComponentInfo,) \
+	Code(ScriptComponentInfo,) \
+	Code(WorldComponentInfo,) \
 	Code(NumOfTypes, )
 	DECLARE_ENUM(UserTypes, LUA_USER_TYPES)
 
@@ -60,13 +66,13 @@ struct Conditional
 class LuaScript
 {
 public:
-	LuaScript(SpatialDataManager &p_spatialData, GUIDataManager &p_GUIData) : m_spatialData(p_spatialData), m_GUIData(p_GUIData)
+	LuaScript(SystemScene *p_scriptScene, SpatialDataManager &p_spatialData, GUIDataManager &p_GUIData) : m_scriptScene(p_scriptScene), m_spatialData(p_spatialData), m_GUIData(p_GUIData)
 	{ 
 		m_keyCommands.reserve(10);
 		m_conditionals.reserve(10);
 		m_currentChanges = Systems::Changes::None;
 	}
-	LuaScript(SpatialDataManager &p_spatialData, GUIDataManager &p_GUIData, std::string &p_scriptFilename) : m_spatialData(p_spatialData), m_GUIData(p_GUIData), m_luaScriptFilename(p_scriptFilename)
+	LuaScript(SystemScene *p_scriptScene, SpatialDataManager &p_spatialData, GUIDataManager &p_GUIData, std::string &p_scriptFilename) : m_scriptScene(p_scriptScene), m_spatialData(p_spatialData), m_GUIData(p_GUIData), m_luaScriptFilename(p_scriptFilename)
 	{
 		m_keyCommands.reserve(10);
 		m_conditionals.reserve(10);
@@ -224,347 +230,13 @@ private:
 		}
 	}
 	// Binds functions, so that they can be called from the lua script
-	void setFunctions()
-	{
-		// Math functions
-		m_luaState.set_function("toRadianF", sol::resolve<float(const float)>(&glm::radians));
-		m_luaState.set_function("toRadianVec3", sol::resolve<glm::vec3(const glm::vec3 &)>(&glm::radians));
-		m_luaState.set_function("toRadianVec4", sol::resolve<glm::vec4(const glm::vec4 &)>(&glm::radians));
-		m_luaState.set_function("toDegreesF", sol::resolve<float(const float)>(&glm::degrees));
-		m_luaState.set_function("toDegreesVec3", sol::resolve<glm::vec3(const glm::vec3 &)>(&glm::degrees));
-		m_luaState.set_function("toDegreesVec4", sol::resolve<glm::vec4(const glm::vec4 &)>(&glm::degrees));
-		m_luaState.set_function("angleAxisQuat", sol::resolve<glm::quat(const float &, const glm::vec3 &)>(&glm::angleAxis));
-
-		// Input / Window functions
-		m_luaState.set_function("getMouseInfo", []() -> const Window::MouseInfo { return WindowLocator::get().getMouseInfo(); });
-		m_luaState.set_function("mouseCaptured", []() -> const bool { return Config::windowVar().mouse_captured; });
-		m_luaState.set_function("setFullscreen", [](const bool p_v1) -> const void { WindowLocator::get().setFullscreen(p_v1); });
-		m_luaState.set_function("setMouseCapture", [](const bool p_v1) -> const void { WindowLocator::get().setMouseCapture(p_v1); });
-		m_luaState.set_function("setVerticalSync", [](const bool p_v1) -> const void { WindowLocator::get().setVerticalSync(p_v1); });
-		m_luaState.set_function("setWindowTitle", [](const std::string &p_v1) -> const void { WindowLocator::get().setWindowTitle(p_v1); });
-
-		// Engine functions
-		m_luaState.set_function("setEngineRunning", [](const bool p_v1) -> const void {Config::m_engineVar.running = p_v1; });
-
-		// GUI functions
-		auto GUITable = m_luaState.create_table("GUI");
-		GUITable.set_function("Begin", [this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::Begin(p_v1.c_str()); }); });
-		GUITable.set_function("BeginChild", [this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::BeginChild(p_v1.c_str()); }); });
-		GUITable.set_function("BeginMenu", [this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::BeginMenu(p_v1.c_str()); }); });
-		GUITable.set_function("Button", [this](const std::string &p_v1, Conditional *p_v2) -> void { m_GUIData.addFunctor([=] { p_v2->m_flag = ImGui::Button(p_v1.c_str()); }); });
-		GUITable.set_function("Checkbox", [this](const std::string &p_v1, Conditional *p_v2) -> void { m_GUIData.addFunctor([=] { ImGui::Checkbox(p_v1.c_str(), &p_v2->m_flag); }); });
-		GUITable.set_function("ColorEdit3", [this](const std::string &p_v1, glm::vec3 *p_v2) -> void { m_GUIData.addFunctor([=] { ImGui::ColorEdit3(p_v1.c_str(), &(p_v2->x)); }); });
-		GUITable.set_function("ColorEdit4", [this](const std::string &p_v1, glm::vec4 *p_v2) -> void { m_GUIData.addFunctor([=] { ImGui::ColorEdit4(p_v1.c_str(), &(p_v2->x)); }); });
-		GUITable.set_function("End", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::End(); }); });
-		GUITable.set_function("EndChild", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::EndChild(); }); });
-		GUITable.set_function("EndMenu", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::EndMenu(); }); });
-		GUITable.set_function("EndMenuBar", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::EndMenuBar(); }); });
-		GUITable.set_function("MenuItem", [this](const std::string &p_v1, const std::string &p_v2, Conditional *p_v3) -> void { m_GUIData.addFunctor([=] { p_v3->m_flag = ImGui::MenuItem(p_v1.c_str(), p_v2.c_str()); }); });
-		GUITable.set_function("PlotLines", [this](const std::string &p_v1, const float *p_v2, int p_v3) -> const void { m_GUIData.addFunctor([=] { ImGui::PlotLines(p_v1.c_str(), p_v2, p_v3); }); });
-		GUITable.set_function("SliderFloat", [this](const std::string &p_v1, float *p_v2, const float p_v3, const float p_v4) -> const void { m_GUIData.addFunctor([=] { ImGui::SliderFloat(p_v1.c_str(), p_v2, p_v3, p_v4); }); });
-		GUITable.set_function("SameLine", [this]() -> const void { m_GUIData.addFunctor([=] { ImGui::SameLine(); }); });
-		GUITable.set_function("Text", sol::overload([this](const std::string &p_v1) -> const void { m_GUIData.addFunctor([=] { ImGui::Text(p_v1.c_str()); }); },
-			[this](const std::string &p_v1, const float p_v2) -> const void { m_GUIData.addFunctor([=] { ImGui::Text(p_v1.c_str(), p_v2); }); },
-			[this](const std::string &p_v1, const float p_v2, const float p_v3) -> const void { m_GUIData.addFunctor([=] { ImGui::Text(p_v1.c_str(), p_v2, p_v3); }); }));
-		GUITable.set_function("TextColored", sol::overload([this](const glm::vec4 p_v1, const std::string &p_v2) -> const void { m_GUIData.addFunctor([=] { ImGui::TextColored(ImVec4(p_v1.x, p_v1.y, p_v1.z, p_v1.w), p_v2.c_str()); }); },
-			[this](const glm::vec4 p_v1, const std::string &p_v2, const float p_v3) -> const void { m_GUIData.addFunctor([=] { ImGui::TextColored(ImVec4(p_v1.x, p_v1.y, p_v1.z, p_v1.w), p_v2.c_str(), p_v3); }); },
-			[this](const glm::vec4 p_v1, const std::string &p_v2, const float p_v3, const float p_v4) -> const void { m_GUIData.addFunctor([=] { ImGui::TextColored(ImVec4(p_v1.x, p_v1.y, p_v1.z, p_v1.w), p_v2.c_str(), p_v3, p_v4); }); }));
-
-		// LuaScript callbacks
-		m_luaState.set_function("postChanges", &LuaScript::registerChange, this);
-		m_luaState.set_function(Config::scriptVar().createObjectFunctionName, &LuaScript::createObjectInLua, this);
-	}
+	void setFunctions();
 	// Defines usertypes, so that they can be used in the lua script
-	void setUsertypes()
-	{
-		// Config variables
-		m_luaState.new_usertype<Config::EngineVariables>("EngineVariables",
-			"change_ctrl_cml_notify_list_reserv", &Config::EngineVariables::change_ctrl_cml_notify_list_reserv,
-			"change_ctrl_grain_size", &Config::EngineVariables::change_ctrl_grain_size,
-			"change_ctrl_notify_list_reserv", &Config::EngineVariables::change_ctrl_notify_list_reserv,
-			"change_ctrl_oneoff_notify_list_reserv", &Config::EngineVariables::change_ctrl_oneoff_notify_list_reserv,
-			"change_ctrl_subject_list_reserv", &Config::EngineVariables::change_ctrl_subject_list_reserv,
-			"delta_time_divider", &Config::EngineVariables::delta_time_divider,
-			"gl_context_major_version", &Config::EngineVariables::gl_context_major_version,
-			"gl_context_minor_version", &Config::EngineVariables::gl_context_minor_version,
-			"object_directory_init_pool_size", &Config::EngineVariables::object_directory_init_pool_size,
-			"smoothing_tick_samples", &Config::EngineVariables::smoothing_tick_samples,
-			"running", &Config::EngineVariables::running);
-
-		m_luaState.new_usertype<Config::GameplayVariables>("GameplayVariables",
-			"camera_freelook_speed", &Config::GameplayVariables::camera_freelook_speed);
-
-		m_luaState.new_usertype<Config::InputVariables>("InputVariables",
-			"back_key", &Config::InputVariables::back_key,
-			"backward_editor_key", &Config::InputVariables::backward_editor_key,
-			"backward_key", &Config::InputVariables::backward_key,
-			"center_key", &Config::InputVariables::center_key,
-			"clip_mouse_key", &Config::InputVariables::clip_mouse_key,
-			"close_window_key", &Config::InputVariables::close_window_key,
-			"debug_1_key", &Config::InputVariables::debug_1_key,
-			"debug_2_key", &Config::InputVariables::debug_2_key,
-			"down_editor_key", &Config::InputVariables::down_editor_key,
-			"down_key", &Config::InputVariables::down_key,
-			"escape_key", &Config::InputVariables::escape_key,
-			"forward_editor_key", &Config::InputVariables::forward_editor_key,
-			"forward_key", &Config::InputVariables::forward_key,
-			"fullscreen_key", &Config::InputVariables::fullscreen_key,
-			"jump_key", &Config::InputVariables::jump_key,
-			"left_editor_key", &Config::InputVariables::left_editor_key,
-			"left_strafe_key", &Config::InputVariables::left_strafe_key,
-			"modifier_editor_key", &Config::InputVariables::modifier_editor_key,
-			"next_editor_key", &Config::InputVariables::next_editor_key,
-			"num_preallocated_keybinds", &Config::InputVariables::num_preallocated_keybinds,
-			"previous_editor_key", &Config::InputVariables::previous_editor_key,
-			"right_editor_key", &Config::InputVariables::right_editor_key,
-			"right_strafe_key", &Config::InputVariables::right_strafe_key,
-			"save_editor_key", &Config::InputVariables::save_editor_key,
-			"sprint_key", &Config::InputVariables::sprint_key,
-			"up_editor_key", &Config::InputVariables::up_editor_key,
-			"up_key", &Config::InputVariables::up_key,
-			"vsync_key", &Config::InputVariables::vsync_key,
-			"mouse_filter", &Config::InputVariables::mouse_filter,
-			"mouse_warp_mode", &Config::InputVariables::mouse_warp_mode,
-			"mouse_jaw", &Config::InputVariables::mouse_jaw,
-			"mouse_pitch", &Config::InputVariables::mouse_pitch,
-			"mouse_pitch_clip", &Config::InputVariables::mouse_pitch_clip,
-			"mouse_sensitivity", &Config::InputVariables::mouse_sensitivity);
-
-		m_luaState.new_usertype<Config::WindowVariables>("WindowVariables",
-			"name", &Config::WindowVariables::name,
-			"default_display", &Config::WindowVariables::default_display,
-			"window_position_x", &Config::WindowVariables::window_position_x,
-			"window_position_y", &Config::WindowVariables::window_position_y,
-			"window_size_fullscreen_x", &Config::WindowVariables::window_size_fullscreen_x,
-			"window_size_fullscreen_y", &Config::WindowVariables::window_size_fullscreen_y,
-			"window_size_windowed_x", &Config::WindowVariables::window_size_windowed_x,
-			"window_size_windowed_y", &Config::WindowVariables::window_size_windowed_y,
-			"fullscreen", &Config::WindowVariables::fullscreen,
-			"fullscreen_borderless", &Config::WindowVariables::fullscreen_borderless,
-			"mouse_captured", &Config::WindowVariables::mouse_captured,
-			"mouse_release_on_lost_focus", &Config::WindowVariables::mouse_release_on_lost_focus,
-			"resizable", &Config::WindowVariables::resizable,
-			"vertical_sync", &Config::WindowVariables::vertical_sync,
-			"window_in_focus", &Config::WindowVariables::window_in_focus);
-
-		// Math types
-		m_luaState.new_usertype<Int64Packer>("Int64");
-
-		m_luaState.new_usertype<glm::vec3>("Vec3",
-			sol::constructors<glm::vec3(), glm::vec3(float), glm::vec3(float, float, float), glm::vec3(glm::vec4)>(),
-			"x", &glm::vec3::x,
-			"y", &glm::vec3::y,
-			"z", &glm::vec3::z,
-			"addF", [](const glm::vec3 &v1, const float f) -> glm::vec3 { return v1 + f; },
-			"subF", [](const glm::vec3 &v1, const float f) -> glm::vec3 { return v1 - f; },
-			"mulF", [](const glm::vec3 &v1, const float f) -> glm::vec3 { return v1 * f; },
-			"divF", [](const glm::vec3 &v1, const float f) -> glm::vec3 { return v1 / f; },
-			"addVec3", [](const glm::vec3 &v1, const glm::vec3 &v2) -> glm::vec3 { return v1 + v2; },
-			"subVec3", [](const glm::vec3 &v1, const glm::vec3 &v2) -> glm::vec3 { return v1 - v2; },
-			"mulVec3", [](const glm::vec3 &v1, const glm::vec3 &v2) -> glm::vec3 { return v1 * v2; },
-			"divVec3", [](const glm::vec3 &v1, const glm::vec3 &v2) -> glm::vec3 { return v1 / v2; },
-			"normalize", [](const glm::vec3 &v1) -> glm::vec3 { return glm::normalize(v1); },
-			sol::meta_function::addition,		[](const glm::vec3 &v1, glm::vec3 &v2) -> glm::vec3 { return v1 + v2; },
-			sol::meta_function::subtraction,	[](const glm::vec3 &v1, glm::vec3 &v2) -> glm::vec3 { return v1 - v2; },
-			sol::meta_function::multiplication, [](const glm::vec3 &v1, glm::vec3 &v2) -> glm::vec3 { return v1 * v2; },
-			sol::meta_function::division,		[](const glm::vec3 &v1, glm::vec3 &v2) -> glm::vec3 { return v1 / v2; });
-
-		m_luaState.new_usertype<glm::vec4>("Vec4",
-			sol::constructors<glm::vec4(), glm::vec4(float), glm::vec4(glm::vec3, float), glm::vec4(float, float, float, float)>(),
-			"x", &glm::vec4::x,
-			"y", &glm::vec4::y,
-			"z", &glm::vec4::z,
-			"w", &glm::vec4::w,
-			"addF", [](const glm::vec4 &v1, const float f) -> glm::vec4 { return v1 + f; },
-			"subF", [](const glm::vec4 &v1, const float f) -> glm::vec4 { return v1 - f; },
-			"mulF", [](const glm::vec4 &v1, const float f) -> glm::vec4 { return v1 * f; },
-			"divF", [](const glm::vec4 &v1, const float f) -> glm::vec4 { return v1 / f; },
-			"addVec4", [](const glm::vec4 &v1, const glm::vec4 &v2) -> glm::vec4 { return v1 + v2; },
-			"subVec4", [](const glm::vec4 &v1, const glm::vec4 &v2) -> glm::vec4 { return v1 - v2; },
-			"mulVec4", [](const glm::vec4 &v1, const glm::vec4 &v2) -> glm::vec4 { return v1 * v2; },
-			"divVec4", [](const glm::vec4 &v1, const glm::vec4 &v2) -> glm::vec4 { return v1 / v2; },
-			"normalize", [](const glm::vec4 &v1) -> glm::vec4 { return glm::normalize(v1); },
-			sol::meta_function::addition, [](const glm::vec4 &v1, glm::vec4 &v2) -> glm::vec4 { return v1 + v2; },
-			sol::meta_function::subtraction, [](const glm::vec4 &v1, glm::vec4 &v2) -> glm::vec4 { return v1 - v2; },
-			sol::meta_function::multiplication, [](const glm::vec4 &v1, glm::vec4 &v2) -> glm::vec4 { return v1 * v2; },
-			sol::meta_function::division, [](const glm::vec4 &v1, glm::vec4 &v2) -> glm::vec4 { return v1 / v2; });
-
-		m_luaState.new_usertype<glm::quat>("Quat",
-			sol::constructors<glm::quat(), glm::quat(glm::vec4)>(),
-			"x", &glm::quat::x,
-			"y", &glm::quat::y,
-			"z", &glm::quat::z,
-			"w", &glm::quat::w,
-			"mulF", [](const glm::quat &q1, const float f) -> glm::quat { return q1 * f; },
-			"divF", [](const glm::quat &q1, const float f) -> glm::quat { return q1 / f; },
-			"mulVec3", [](const glm::quat &q1, const glm::vec3 &v2) -> glm::quat { return q1 * v2; },
-			"normalize", [](const glm::quat &q1) -> glm::quat { return glm::normalize(q1); },
-			"inverse", [](const glm::quat &q1) -> glm::quat { return glm::inverse(q1); },
-			"rotateVec3", [](const glm::quat &q1, const glm::vec3 &v2) -> glm::vec3 { return glm::rotate(q1, v2); },
-			"toMat4", [](const glm::quat &q1) -> glm::mat4 { return glm::toMat4(q1); },
-			sol::meta_function::addition, [](const glm::quat &q1, glm::quat &q2) -> glm::quat { return q1 + q2; },
-			sol::meta_function::subtraction, [](const glm::quat &q1, glm::quat &q2) -> glm::quat { return q1 - q2; },
-			sol::meta_function::multiplication, [](const glm::quat &q1, glm::quat &q2) -> glm::quat { return q1 * q2; });
-
-		m_luaState.new_usertype<glm::mat4>("Mat4",
-			sol::constructors<glm::mat4(), glm::mat4(float)>(),
-			"mulF", [](const glm::mat4 &v1, const float f) -> glm::mat4 { return v1 * f; },
-			"divF", [](const glm::mat4 &v1, const float f) -> glm::mat4 { return v1 / f; },
-			"mulVec3", [](const glm::mat4 &m1, const glm::vec3 &v2) -> glm::vec4 { return m1 * glm::vec4(v2, 1.0f); },
-			"divVec3", [](const glm::mat4 &m1, const glm::vec3 &v2) -> glm::vec4 { return m1 / glm::vec4(v2, 1.0f); },
-			"mulVec4", [](const glm::mat4 &m1, const glm::vec4 &v2) -> glm::vec4 { return m1 * v2; },
-			"divVec4", [](const glm::mat4 &m1, const glm::vec4 &v2) -> glm::vec4 { return m1 / v2; },
-			"inverse", [](const glm::mat4 &m1) -> glm::mat4 { return glm::inverse(m1); },
-			"rotate", [](const glm::mat4 &m1, const float f1, const glm::vec3 &v1) -> glm::mat4 { return glm::rotate(m1, f1, v1); },
-			"toQuat", [](const glm::mat4 &m1) -> glm::quat { return glm::toQuat(m1); },
-			"getRotXVec3", [](const glm::mat4 &m1) -> glm::vec3 { return m1[0]; },
-			"getRotYVec3", [](const glm::mat4 &m1) -> glm::vec3 { return m1[1]; },
-			"getRotZVec3", [](const glm::mat4 &m1) -> glm::vec3 { return m1[2]; },
-			"getPosVec3", [](const glm::mat4 &m1) -> glm::vec3 { return m1[3]; },
-			"getRotXVec4", [](const glm::mat4 &m1) -> glm::vec4 { return m1[0]; },
-			"getRotYVec4", [](const glm::mat4 &m1) -> glm::vec4 { return m1[1]; },
-			"getRotZVec4", [](const glm::mat4 &m1) -> glm::vec4 { return m1[2]; },
-			"getPosVec4", [](const glm::mat4 &m1) -> glm::vec4 { return m1[3]; },
-			"setPosVec3", [](glm::mat4 &m1, const glm::vec3 &v2) -> void { m1[3] = glm::vec4(v2, 1.0f); },
-			"setPosVec4", [](glm::mat4 &m1, const glm::vec4 &v2) -> void { m1[3] = v2; },
-			sol::meta_function::addition, [](const glm::mat4 &m1, glm::mat4 &m2) -> glm::mat4 { return m1 + m2; },
-			sol::meta_function::subtraction, [](const glm::mat4 &m1, glm::mat4 &m2) -> glm::mat4 { return m1 - m2; },
-			sol::meta_function::multiplication, [](const glm::mat4 &m1, glm::mat4 &m2) -> glm::mat4 { return m1 * m2; },
-			sol::meta_function::division, [](const glm::mat4 &m1, glm::mat4 &m2) -> glm::mat4 { return m1 / m2; });
-
-		m_luaState.new_usertype<SpatialData>("SpatialData",
-			"clear", &SpatialData::clear,
-			"m_position", &SpatialData::m_position,
-			"m_rotationEuler", &SpatialData::m_rotationEuler,
-			"m_scale", &SpatialData::m_scale);
-
-		m_luaState.new_usertype<SpatialTransformData>("SpatialTransformData",
-			"clear", &SpatialTransformData::clear,
-			"m_spatialData", &SpatialTransformData::m_spatialData);
-
-		m_luaState.new_usertype<SpatialDataManager>("SpatialDataManager",
-			"update", &SpatialDataManager::update,
-			"getLocalSpaceData", &SpatialDataManager::getLocalSpaceData,
-			"getLocalTransform", &SpatialDataManager::getLocalTransform,
-			"getParemtTransform", &SpatialDataManager::getParemtTransform,
-			"getWorldTransform", &SpatialDataManager::getWorldTransform,
-			"setLocalPosition", &SpatialDataManager::setLocalPosition,
-			"setLocalRotationEuler", sol::resolve<const void (const glm::vec3)>(&SpatialDataManager::setLocalRotation),
-			"setLocalRotationQuat", sol::resolve<const void(const glm::quat)>(&SpatialDataManager::setLocalRotation),
-			"setLocalScale", &SpatialDataManager::setLocalScale,
-			"setLocalTransform", &SpatialDataManager::setLocalTransform,
-			"setParentTransform", &SpatialDataManager::setParentTransform,
-			"setWorldTransform", &SpatialDataManager::setWorldTransform);
-
-		// Input types
-		m_luaState.new_usertype<Window::MouseInfo>("MouseInfo",
-			"m_movementCurrentFrameX", &Window::MouseInfo::m_movementCurrentFrameX,
-			"m_movementCurrentFrameY", &Window::MouseInfo::m_movementCurrentFrameY,
-			"m_movementPrevFrameX", &Window::MouseInfo::m_movementPrevFrameX,
-			"m_movementPrevFrameY", &Window::MouseInfo::m_movementPrevFrameY,
-			"m_wheelX", &Window::MouseInfo::m_wheelX,
-			"m_wheelY", &Window::MouseInfo::m_wheelY,
-			"m_movementX", &Window::MouseInfo::m_movementX,
-			"m_movementY", &Window::MouseInfo::m_movementY);
-
-		m_luaState.new_usertype<KeyCommand>("KeyCommand",
-			"activate", &KeyCommand::activate,
-			"deactivate", &KeyCommand::deactivate,
-			"isActivated", &KeyCommand::isActivated,
-			"bind", sol::resolve<void(const Scancode)>(&KeyCommand::bind),
-			"bindByName", sol::resolve<void(const std::string&)>(&KeyCommand::bind),
-			"unbind", &KeyCommand::unbind,
-			"unbindAll", &KeyCommand::unbindAll);
-
-		// Misc types
-		m_luaState.new_usertype<Conditional>("Conditional",
-			"isChecked", &Conditional::isChecked,
-			"check", &Conditional::check,
-			"uncheck", &Conditional::uncheck,
-			"set", &Conditional::set);
-	}
+	void setUsertypes();
 
 	// Creates and assigns objects to be used in the lua script
 	// Should only be called from the lua script
-	void createObjectInLua(const unsigned int p_objectType, const std::string p_variableName)
-	{
-		// Check if the object type is in a valid range and if the variable name isn't empty
-		if(p_objectType >= 0 && p_objectType < LuaDefinitions::UserTypes::NumOfTypes && !p_variableName.empty())
-		{
-			switch(p_objectType)
-			{
-			case LuaDefinitions::Conditional:
-			{
-				// Create a new Conditional
-				Conditional *newConditional = new Conditional();
-
-				// Set the given variable name in Lua to point to the created Conditional
-				m_luaState.set(p_variableName, newConditional);
-
-				// Add the conditional pointer to an array so it is not lost
-				m_conditionals.push_back(newConditional);
-			}
-				break;
-
-			case LuaDefinitions::EngineVariables:
-
-				// Set the given variable name in Lua to point to the EngineVariables object
-				m_luaState.set(p_variableName, Config::engineVar());
-
-				break;
-
-			case LuaDefinitions::GameplayVariables:
-
-				// Set the given variable name in Lua to point to the GameplayVariables object
-				m_luaState.set(p_variableName, Config::gameplayVar());
-
-				break;
-
-			case LuaDefinitions::InputVariables:
-
-				// Set the given variable name in Lua to point to the InputVariables object
-				m_luaState.set(p_variableName, Config::inputVar());
-
-				break;
-
-			case LuaDefinitions::KeyCommand:
-			{
-				// Create new key command
-				KeyCommand *keyCommand = new KeyCommand();
-
-				// Set the given variable name in Lua to point to the created key command
-				m_luaState.set(p_variableName, keyCommand);
-
-				// Add key command pointer to an array so it is not lost
-				m_keyCommands.push_back(keyCommand);
-			}
-				break;
-
-			case LuaDefinitions::MouseInfo:
-
-				// Set the given variable name in Lua to point to the MouseInfo object
-				m_luaState.set(p_variableName, WindowLocator::get().getMouseInfo());
-
-				break;
-
-			case LuaDefinitions::SpatialDataManager:
-
-				// Set the given variable name in Lua to point to the Spatial Data Manager object
-				m_luaState.set(p_variableName, &m_spatialData);
-
-				break;
-
-			case LuaDefinitions::WindowVariables:
-
-				// Set the given variable name in Lua to point to the WindowVariables object
-				m_luaState.set(p_variableName, Config::windowVar());
-
-				break;
-			default:
-				break;
-			}
-		}
-	}
+	void createObjectInLua(const unsigned int p_objectType, const std::string p_variableName);
 
 	// Registers a change in some data
 	// Should only be called from the lua script
@@ -588,6 +260,9 @@ private:
 	// An array of variable names and their value, that get additionally defined in the lua script
 	std::vector<std::pair<std::string, Property>> m_variables;
 
+	// Pointer to the scripting scene that owns this instance; required for getting things like scene loader for entity/component creation
+	SystemScene *m_scriptScene;
+
 	// Contains all spatial data
 	SpatialDataManager &m_spatialData;
 

+ 2 - 0
Praxis3D/Source/ModelComponent.h

@@ -421,6 +421,8 @@ public:
 
 	void performCheckIsLoadedToVideoMemory() 
 	{
+		setLoadedToVideoMemory(false);
+
 		for(decltype(m_modelData.size()) modelSize = m_modelData.size(), modelIndex = 0; modelIndex < modelSize; modelIndex++)
 		{
 			if(!m_modelData[modelIndex].m_model.isLoadedToVideoMemory())

+ 7 - 3
Praxis3D/Source/PhysicsScene.cpp

@@ -140,12 +140,12 @@ void PhysicsScene::loadInBackground()
 {
 }
 
-std::vector<SystemObject*> PhysicsScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
+std::vector<SystemObject*> PhysicsScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
-	return createComponents(p_entityID, p_constructionInfo.m_physicsComponents);
+	return createComponents(p_entityID, p_constructionInfo.m_physicsComponents, p_startLoading);
 }
 
-SystemObject *PhysicsScene::createComponent(const EntityID &p_entityID, const RigidBodyComponent::RigidBodyComponentConstructionInfo &p_constructionInfo)
+SystemObject *PhysicsScene::createComponent(const EntityID &p_entityID, const RigidBodyComponent::RigidBodyComponentConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
 	// If valid type was not specified, or object creation failed, return a null object instead
 	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();
@@ -233,6 +233,10 @@ SystemObject *PhysicsScene::createComponent(const EntityID &p_entityID, const Ri
 				component.m_rigidBody->setActivationState(DISABLE_DEACTIVATION);
 			}
 
+			// Set linear velocity if it is not zero
+			if(p_constructionInfo.m_linearVelocity != glm::vec3())
+				component.m_rigidBody->setLinearVelocity(Math::toBtVector3(p_constructionInfo.m_linearVelocity));
+
 			// Add the rigid body to the dynamics world, essentially loading it into the physics system
 			m_dynamicsWorld->addRigidBody(component.m_rigidBody);
 

+ 10 - 4
Praxis3D/Source/PhysicsScene.h

@@ -45,6 +45,12 @@ struct PhysicsComponentsConstructionInfo
 		m_rigidBodyConstructionInfo = nullptr;
 	}
 
+	// Perform a complete copy, instantiating (with new) every member variable pointer, instead of just assigning the pointer to the same memory
+	void completeCopy(const PhysicsComponentsConstructionInfo &p_other)
+	{
+		Utilities::performCopy<RigidBodyComponent::RigidBodyComponentConstructionInfo>(&m_rigidBodyConstructionInfo, &p_other.m_rigidBodyConstructionInfo);
+	}
+
 	void deleteConstructionInfo()
 	{
 		if(m_rigidBodyConstructionInfo != nullptr)
@@ -70,18 +76,18 @@ public:
 
 	void loadInBackground();
 
-	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*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const PhysicsComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true)
 	{
 		std::vector<SystemObject*> components;
 
 		if(p_constructionInfo.m_rigidBodyConstructionInfo != nullptr)
-			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_rigidBodyConstructionInfo));
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_rigidBodyConstructionInfo, p_startLoading));
 
 		return components;
 	}
 
-	SystemObject *createComponent(const EntityID &p_entityID, const RigidBodyComponent::RigidBodyComponentConstructionInfo &p_constructionInfo);
+	SystemObject *createComponent(const EntityID &p_entityID, const RigidBodyComponent::RigidBodyComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
 	ErrorCode destroyObject(SystemObject *p_systemObject);
 
 	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) { }

+ 1 - 1
Praxis3D/Source/PropertyLoader.cpp

@@ -13,7 +13,7 @@ ErrorCode PropertyLoader::loadFromFile(std::string p_filename)
 	else
 		// If both passed string and filename string are empty, return an error
 		if(m_filename.empty())
-			return ErrorCode::Property_no_filename;
+			return ErrorCode::Filename_empty;
 
 	std::ifstream file;
 	std::string singleLine, parsedString, processedString;

+ 1 - 2
Praxis3D/Source/RendererFrontend.cpp

@@ -331,5 +331,4 @@ void RendererFrontend::renderFrame(SceneObjects &p_sceneObjects, const float p_d
 	{
 		m_renderingPasses[i]->update(*m_renderPassData, p_sceneObjects, p_deltaTime);
 	}
-}
-
+}

+ 28 - 14
Praxis3D/Source/RendererScene.cpp

@@ -145,13 +145,19 @@ void RendererScene::update(const float p_deltaTime)
 					// Make the component active, so it is processed in the renderer
 					modelComponent.setActive(modelComponent.m_setActiveAfterLoading);
 
-					// Get all loadable objects from the model component
-					auto loadableObjectsFromModel = modelComponent.getLoadableObjects();
-
-					// Iterate over all loadable objects from the model component, and if any of them are not loaded to video memory already, add them to the to-load list
-					for(decltype(loadableObjectsFromModel.size()) size = loadableObjectsFromModel.size(), i = 0; i < size; i++)
-						if(!loadableObjectsFromModel[i].isLoadedToVideoMemory())
-							m_sceneObjects.m_loadToVideoMemory.emplace_back(loadableObjectsFromModel[i]);
+					//if(!modelComponent.isLoadedToVideoMemory())
+					modelComponent.performCheckIsLoadedToVideoMemory();
+
+					if(!modelComponent.isLoadedToVideoMemory())
+					{
+						// Get all loadable objects from the model component
+						auto loadableObjectsFromModel = modelComponent.getLoadableObjects();
+
+						// Iterate over all loadable objects from the model component, and if any of them are not loaded to video memory already, add them to the to-load list
+						for(decltype(loadableObjectsFromModel.size()) size = loadableObjectsFromModel.size(), i = 0; i < size; i++)
+							if(!loadableObjectsFromModel[i].isLoadedToVideoMemory())
+								m_sceneObjects.m_loadToVideoMemory.emplace_back(loadableObjectsFromModel[i]);
+					}
 				}
 			}
 			break;
@@ -301,12 +307,12 @@ void RendererScene::update(const float p_deltaTime)
 	calculateCamera(m_sceneObjects.m_camera.m_spatialData);
 }
 
-std::vector<SystemObject*> RendererScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
+std::vector<SystemObject*> RendererScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
-	return createComponents(p_entityID, p_constructionInfo.m_graphicsComponents);
+	return createComponents(p_entityID, p_constructionInfo.m_graphicsComponents, p_startLoading);
 }
 
-SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const CameraComponent::CameraComponentConstructionInfo &p_constructionInfo)
+SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const CameraComponent::CameraComponentConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
 	// If valid type was not specified, or object creation failed, return a null object instead
 	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();
@@ -335,7 +341,7 @@ SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const C
 	return returnObject;
 }
 
-SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const LightComponent::LightComponentConstructionInfo &p_constructionInfo)
+SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const LightComponent::LightComponentConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {	
 	// If valid type was not specified, or object creation failed, return a null object instead
 	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();
@@ -408,7 +414,7 @@ SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const L
 	return returnObject;
 }
 
-SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const ModelComponent::ModelComponentConstructionInfo &p_constructionInfo)
+SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const ModelComponent::ModelComponentConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
 	// If valid type was not specified, or object creation failed, return a null object instead
 	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();
@@ -434,6 +440,10 @@ SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const M
 			// Add the component to an array signifying that it is currently being loaded to memory
 			m_componentsLoadingToMemory.emplace_back(component);
 
+			// Start loading the component to memory in the background if the flag is set to do so
+			if(p_startLoading)
+				TaskManagerLocator::get().startBackgroundThread(std::bind(&ModelComponent::loadToMemory, &component));
+
 			returnObject = &component;
 		}
 		else // Remove the component if it failed to initialize
@@ -448,7 +458,7 @@ SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const M
 	return returnObject;
 }
 
-SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const ShaderComponent::ShaderComponentConstructionInfo &p_constructionInfo)
+SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const ShaderComponent::ShaderComponentConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {	
 	// If valid type was not specified, or object creation failed, return a null object instead
 	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();
@@ -489,7 +499,11 @@ SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const S
 			}
 
 			// Set the component as loaded, because the load function was called
-			component.setLoadedToMemory(true);
+			//component.setLoadedToMemory(true);
+
+			// Start loading the component to memory in the background if the flag is set to do so
+			if(p_startLoading)
+				TaskManagerLocator::get().startBackgroundThread(std::bind(&ShaderComponent::loadToMemory, &component));
 
 			returnObject = &component;
 		}

+ 19 - 10
Praxis3D/Source/RendererScene.h

@@ -32,6 +32,15 @@ struct GraphicsComponentsConstructionInfo
 		m_shaderConstructionInfo = nullptr;
 	}
 
+	// Perform a complete copy, instantiating (with new) every member variable pointer, instead of just assigning the pointer to the same memory
+	void completeCopy(const GraphicsComponentsConstructionInfo &p_other)
+	{
+		Utilities::performCopy<CameraComponent::CameraComponentConstructionInfo>(&m_cameraConstructionInfo, &p_other.m_cameraConstructionInfo);
+		Utilities::performCopy<LightComponent::LightComponentConstructionInfo>(&m_lightConstructionInfo, &p_other.m_lightConstructionInfo);
+		Utilities::performCopy<ModelComponent::ModelComponentConstructionInfo>(&m_modelConstructionInfo, &p_other.m_modelConstructionInfo);
+		Utilities::performCopy<ShaderComponent::ShaderComponentConstructionInfo>(&m_shaderConstructionInfo, &p_other.m_shaderConstructionInfo);
+	}
+
 	void deleteConstructionInfo()
 	{
 		if(m_cameraConstructionInfo != nullptr)
@@ -123,30 +132,30 @@ public:
 	// Processes all the objects and puts them in the separate vectors
 	void update(const float p_deltaTime);
 
-	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*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const GraphicsComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true)
 	{
 		std::vector<SystemObject *> components;
 
 		if(p_constructionInfo.m_cameraConstructionInfo != nullptr)
-			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_cameraConstructionInfo));
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_cameraConstructionInfo, p_startLoading));
 
 		if(p_constructionInfo.m_lightConstructionInfo != nullptr)
-			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_lightConstructionInfo));
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_lightConstructionInfo, p_startLoading));
 
 		if(p_constructionInfo.m_modelConstructionInfo != nullptr)
-			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_modelConstructionInfo));
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_modelConstructionInfo, p_startLoading));
 
 		if(p_constructionInfo.m_shaderConstructionInfo != nullptr)
-			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_shaderConstructionInfo));
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_shaderConstructionInfo, p_startLoading));
 
 		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);
+	SystemObject *createComponent(const EntityID &p_entityID, const CameraComponent::CameraComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
+	SystemObject *createComponent(const EntityID &p_entityID, const LightComponent::LightComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
+	SystemObject *createComponent(const EntityID &p_entityID, const ModelComponent::ModelComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
+	SystemObject *createComponent(const EntityID &p_entityID, const ShaderComponent::ShaderComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
 
 	ErrorCode destroyObject(SystemObject *p_systemObject);
 

+ 1 - 0
Praxis3D/Source/RigidBodyComponent.h

@@ -36,6 +36,7 @@ public:
 		bool m_kinematic;
 		CollisionShapeType m_collisionShapeType;
 		glm::vec3 m_collisionShapeSize;
+		glm::vec3 m_linearVelocity;
 	};
 
 	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)

+ 96 - 4
Praxis3D/Source/SceneLoader.cpp

@@ -6,6 +6,19 @@
 #include "PropertyLoader.h"
 #include "SceneLoader.h"
 
+SceneLoader::SceneLoader()
+{
+	m_changeController = nullptr;
+	m_loadInBackground = false;
+
+	for(int i = 0; i < Systems::NumberOfSystems; i++)
+		m_systemScenes[i] = g_nullSystemBase.createScene(this);
+}
+
+SceneLoader::~SceneLoader()
+{
+}
+
 ErrorCode SceneLoader::loadFromFile(const std::string &p_filename)
 {
 	ErrorCode returnError = ErrorCode::Success;
@@ -23,7 +36,6 @@ ErrorCode SceneLoader::loadFromFile(const std::string &p_filename)
 	}
 	else
 	{
-
 		std::vector<std::pair<const std::string &, SystemObject *>> createdObjects;
 
 		// Get systems property set
@@ -67,10 +79,8 @@ ErrorCode SceneLoader::loadFromFile(const std::string &p_filename)
 
 			for(decltype(constructionInfo.size()) i = 0, size = constructionInfo.size(); i < size; i++)
 			{
-				worldScene->createEntity(constructionInfo[i]);
+				worldScene->createEntity(constructionInfo[i], false);
 			}
-
-			std::cout << "TEST" << std::endl;
 		}
 		else
 		{
@@ -189,6 +199,79 @@ ErrorCode SceneLoader::saveToFile(const std::string p_filename)
 	return ErrorCode::Failure;
 }
 
+ErrorCode SceneLoader::importPrefab(ComponentsConstructionInfo &p_constructionInfo, const std::string &p_filename, const bool p_forceReload)
+{
+	ErrorCode returnError = ErrorCode::Success;
+
+	// Check if the given filename isn't empty
+	if(!p_filename.empty())
+	{
+		// Search for the given prefab (it might have been loaded before, already)
+		auto prefabIterator = m_prefabs.find(p_filename);
+
+		// If the prefab was already imported and exists in the map, use it
+		if(prefabIterator != m_prefabs.end())
+		{
+			if(p_forceReload)
+				returnError = importFromFile(p_constructionInfo, Config::filepathVar().prefab_path + p_filename);
+			else
+				p_constructionInfo.completeCopy(prefabIterator->second);
+		}
+		else // If the prefab doesn't exist in the map, import it
+		{
+			// Make sure calls from other threads are locked, while current call is in progress
+			// This is needed as the prefab that is being requested might be currently being imported
+			// Mutex prevents duplicate prefabs being loaded, and same data being changed.
+			SpinWait::Lock lock(m_mutex);
+
+			// Search for the prefab again, as it might have been imported from another thread call before mutex lock was released
+			auto prefabIteratorNew = m_prefabs.find(p_filename);
+			if(prefabIteratorNew != m_prefabs.end())
+			{
+				if(p_forceReload)
+					returnError = importFromFile(p_constructionInfo, Config::filepathVar().prefab_path + p_filename);
+				else
+					p_constructionInfo.completeCopy(prefabIterator->second);
+			}
+			else
+			{
+				// Load properties from file
+				PropertyLoader loadedProperties(Config::filepathVar().prefab_path + p_filename);
+				returnError = loadedProperties.loadFromFile();
+
+				if(returnError == ErrorCode::Success)
+				{
+					// Insert a new prefab into the map
+					ComponentsConstructionInfo &constructionInfo = m_prefabs.try_emplace(p_filename).first->second;
+
+					// Populate the newly imported prefab
+					importFromProperties(constructionInfo, loadedProperties.getPropertySet());
+
+					p_constructionInfo.completeCopy(constructionInfo);
+				}
+			}
+		}
+	}
+	else
+		returnError = ErrorCode::Filename_empty;
+
+	return returnError;
+}
+
+ErrorCode SceneLoader::importFromFile(ComponentsConstructionInfo &p_constructionInfo, const std::string &p_filename)
+{
+	ErrorCode returnError = ErrorCode::Success;
+
+	// Load properties from file
+	PropertyLoader loadedProperties(p_filename);
+	returnError = loadedProperties.loadFromFile();
+
+	if(returnError == ErrorCode::Success)
+		importFromProperties(p_constructionInfo, loadedProperties.getPropertySet());
+
+	return returnError;
+}
+
 void SceneLoader::importFromProperties(ComponentsConstructionInfo &p_constructionInfo, const PropertySet &p_properties)
 {
 	// Get the object name and ID
@@ -213,6 +296,12 @@ void SceneLoader::importFromProperties(ComponentsConstructionInfo &p_constructio
 				p_constructionInfo.m_parent = (EntityID)p_properties[i].getInt();
 			}
 			break;
+
+			case Properties::Prefab:
+			{
+				importPrefab(p_constructionInfo, p_properties[i].getString());
+			}
+			break;
 		}
 	}
 
@@ -576,6 +665,9 @@ void SceneLoader::importFromProperties(PhysicsComponentsConstructionInfo &p_cons
 				case Properties::Restitution:
 					p_constructionInfo.m_rigidBodyConstructionInfo->m_restitution = p_properties[i].getFloat();
 					break;
+				case Properties::Velocity:
+					p_constructionInfo.m_rigidBodyConstructionInfo->m_linearVelocity = p_properties[i].getVec3f();
+					break;
 				}
 			}
 		}

+ 16 - 16
Praxis3D/Source/SceneLoader.h

@@ -17,15 +17,8 @@ struct WorldComponentsConstructionInfo;
 class SceneLoader
 {
 public:
-	SceneLoader()
-	{
-		m_changeController = nullptr;
-		m_loadInBackground = false;
-
-		for(int i = 0; i < Systems::NumberOfSystems; i++)
-			m_systemScenes[i] = g_nullSystemBase.createScene(this);
-	}
-	~SceneLoader() { }
+	SceneLoader();
+	~SceneLoader();
 
 	inline void registerSystemScene(SystemScene *p_scene)
 	{
@@ -39,18 +32,16 @@ public:
 			m_changeController = p_changeCtrl;
 	}
 
-	// Returns an array of created objects, sorted by the system type
-	const inline std::vector<std::pair<const std::string&, SystemObject*>> &getCreatedObjects(Systems::TypeID p_systemType)
-	{
-		return m_createdObjects[p_systemType];
-	}
 	inline SystemScene *getSystemScene(Systems::TypeID p_systemType) const { return m_systemScenes[p_systemType]; }
 	inline UniversalScene *getChangeController() const { return m_changeController; }
 
 	ErrorCode loadFromFile(const std::string &p_filename);
 	ErrorCode saveToFile(const std::string p_filename = "");
 
+	ErrorCode importPrefab(ComponentsConstructionInfo &p_constructionInfo, const std::string &p_filename, const bool p_forceReload = false);
+
 private:
+	ErrorCode importFromFile(ComponentsConstructionInfo &p_constructionInfo, const std::string &p_filename);
 	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);
@@ -58,13 +49,22 @@ private:
 	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];
+	// Mutex used to block calls from other threads while import operation is in progress
+	SpinWait m_mutex;
 
-	std::vector<std::pair<const std::string&, SystemObject*>> m_createdObjects[Systems::NumberOfSystems];
+	// Contains all the prefabs that have already been imported before. Saves the time of importing them again, upon requesting
+	std::map<std::string, ComponentsConstructionInfo> m_prefabs;
 
+	// All of the engine's system scenes
+	SystemScene *m_systemScenes[Systems::NumberOfSystems];
+
+	// Change controller, used for storing and distributing messages between subjects and observers
 	UniversalScene *m_changeController;
 
+	// Should the imported objects be called to start loading in the background
 	bool m_loadInBackground;
+
+	// Holds the last loaded scene filename, used for exporting the scene back to file
 	std::string m_filename;
 };
 

+ 3 - 3
Praxis3D/Source/ScriptScene.cpp

@@ -115,12 +115,12 @@ ErrorCode ScriptScene::preload()
 	return ErrorCode::Success;
 }
 
-std::vector<SystemObject*> ScriptScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
+std::vector<SystemObject*> ScriptScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
-	return createComponents(p_entityID, p_constructionInfo.m_scriptComponents);
+	return createComponents(p_entityID, p_constructionInfo.m_scriptComponents, p_startLoading);
 }
 
-SystemObject *ScriptScene::createComponent(const EntityID &p_entityID, const LuaComponent::LuaComponentConstructionInfo &p_constructionInfo)
+SystemObject *ScriptScene::createComponent(const EntityID &p_entityID, const LuaComponent::LuaComponentConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {	
 	// If valid type was not specified, or object creation failed, return a null object instead
 	SystemObject *returnObject = g_nullSystemBase.getScene()->getNullObject();

+ 10 - 4
Praxis3D/Source/ScriptScene.h

@@ -23,6 +23,12 @@ struct ScriptComponentsConstructionInfo
 		m_luaConstructionInfo = nullptr;
 	}
 
+	// Perform a complete copy, instantiating (with new) every member variable pointer, instead of just assigning the pointer to the same memory
+	void completeCopy(const ScriptComponentsConstructionInfo &p_other)
+	{
+		Utilities::performCopy<LuaComponent::LuaComponentConstructionInfo>(&m_luaConstructionInfo, &p_other.m_luaConstructionInfo);
+	}
+
 	void deleteConstructionInfo()
 	{
 		if(m_luaConstructionInfo != nullptr)
@@ -48,18 +54,18 @@ public:
 
 	ErrorCode preload();
 
-	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*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ScriptComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true)
 	{
 		std::vector<SystemObject*> components;
 
 		if(p_constructionInfo.m_luaConstructionInfo != nullptr)
-			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_luaConstructionInfo));
+			components.push_back(createComponent(p_entityID, *p_constructionInfo.m_luaConstructionInfo, p_startLoading));
 
 		return components;
 	}
 
-	SystemObject *createComponent(const EntityID &p_entityID, const LuaComponent::LuaComponentConstructionInfo &p_constructionInfo);
+	SystemObject *createComponent(const EntityID &p_entityID, const LuaComponent::LuaComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
 	ErrorCode destroyObject(SystemObject *p_systemObject);
 
 	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType);

+ 1 - 1
Praxis3D/Source/System.cpp

@@ -21,7 +21,7 @@ SystemObject::~SystemObject()
 	ObjectDirectory::unregisterObject(*this);
 }
 
-std::vector<SystemObject*> SystemScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
+std::vector<SystemObject*> SystemScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
 	return std::vector<SystemObject*>();
 }

+ 3 - 2
Praxis3D/Source/System.h

@@ -75,7 +75,7 @@ public:
 	// 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 std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo);
+	virtual std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
 	virtual ErrorCode destroyObject(SystemObject *p_systemObject) = 0;
 	virtual SystemObject *getNullObject();
 
@@ -84,7 +84,8 @@ public:
 	virtual SystemTask *getSystemTask() = 0;
 	virtual Systems::TypeID getSystemType() = 0;
 	virtual BitMask getDesiredSystemChanges() { return Systems::Changes::None; };
-	
+	inline SceneLoader *getSceneLoader() { return m_sceneLoader; }
+
 protected:
 	bool m_initialized;
 	SystemBase *m_system;

+ 11 - 0
Praxis3D/Source/Utilities.h

@@ -260,4 +260,15 @@ namespace Utilities
 	{
 		return ((T)1 << p_bitShiftPosition);
 	}
+
+	// Copies one object to the other, performs nullptr checks and created a new object in memory if needed
+	template <class T_Component>
+	void performCopy(T_Component **p_copyTo, const T_Component * const *p_copyFrom)
+	{
+		if(*p_copyFrom != nullptr)
+			if(*p_copyTo != nullptr)
+				**p_copyTo = **p_copyFrom;
+			else
+				*p_copyTo = new T_Component(**p_copyFrom);
+	}
 }

+ 2 - 2
Praxis3D/Source/WorldEditObject.h

@@ -78,7 +78,7 @@ public:
 
 	virtual void update(const float p_deltaTime)
 	{
-		// Check status of next/previous keys. If they have been pressed,
+		/*/ Check status of next/previous keys. If they have been pressed,
 		// mark the selected object to be updated and set the appropriate next/previous object flag
 		if(m_nextKey.isActivated())
 		{
@@ -185,7 +185,7 @@ public:
 			// If an object is selected, update its data
 			//if(m_selectedObject != nullptr)
 			//	m_sceneLoader->getChangeController()->sendChange(this, m_selectedObject, Systems::Changes::Spacial::Position);
-		}
+		}*/
 	}
 
 	virtual BitMask getPotentialSystemChanges() { return Systems::Changes::All; }

+ 21 - 15
Praxis3D/Source/WorldScene.cpp

@@ -88,18 +88,24 @@ void WorldScene::update(const float p_deltaTime)
 
 }
 
-EntityID WorldScene::createEntity(const ComponentsConstructionInfo &p_constructionInfo)
+EntityID WorldScene::createEntity(const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
-	// Add entity to the registry and assign its entity ID
-	EntityID newEntity = addEntity(p_constructionInfo.m_id);
+	EntityID newEntity = 0;
 
-	// Log an error if the desired ID couldn't be assigned
-	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) + "\'");
+	if(p_constructionInfo.m_id != NULL_ENTITY_ID)
+	{
+		// Add entity to the registry and assign its entity ID
+		newEntity = addEntity(p_constructionInfo.m_id);
 
+		// Log an error if the desired ID couldn't be assigned
+		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) + "\'");
+	}
+	else // Do not request a specific entity ID if the requested ID is null
+		newEntity = addEntity();
 
 	// Add WORLD components
-	std::vector<SystemObject*> worldComponents = createComponents(newEntity, p_constructionInfo.m_worldComponents);
+	std::vector<SystemObject*> worldComponents = createComponents(newEntity, p_constructionInfo.m_worldComponents, p_startLoading);
 
 	SystemObject *spatialComponent = nullptr;
 
@@ -112,16 +118,16 @@ EntityID WorldScene::createEntity(const ComponentsConstructionInfo &p_constructi
 		}
 
 	// Add RENDERING components
-	std::vector<SystemObject*> renderingComponents = m_sceneLoader->getSystemScene(Systems::Graphics)->createComponents(newEntity, p_constructionInfo);
+	std::vector<SystemObject*> renderingComponents = m_sceneLoader->getSystemScene(Systems::Graphics)->createComponents(newEntity, p_constructionInfo, p_startLoading);
 
 	// Add GUI components
-	std::vector<SystemObject*> guiComponents = m_sceneLoader->getSystemScene(Systems::GUI)->createComponents(newEntity, p_constructionInfo);
+	std::vector<SystemObject*> guiComponents = m_sceneLoader->getSystemScene(Systems::GUI)->createComponents(newEntity, p_constructionInfo, p_startLoading);
 
 	// Add PHYSICS components
-	std::vector<SystemObject*> physicsComponents = m_sceneLoader->getSystemScene(Systems::Physics)->createComponents(newEntity, p_constructionInfo);
+	std::vector<SystemObject*> physicsComponents = m_sceneLoader->getSystemScene(Systems::Physics)->createComponents(newEntity, p_constructionInfo, p_startLoading);
 
 	// Add SCRIPTING components
-	std::vector<SystemObject*> scriptingComponents = m_sceneLoader->getSystemScene(Systems::Script)->createComponents(newEntity, p_constructionInfo);
+	std::vector<SystemObject*> scriptingComponents = m_sceneLoader->getSystemScene(Systems::Script)->createComponents(newEntity, p_constructionInfo, p_startLoading);
 
 	// Link subjects and observers of different components
 
@@ -161,17 +167,17 @@ EntityID WorldScene::createEntity(const ComponentsConstructionInfo &p_constructi
 	return newEntity;
 }
 
-std::vector<SystemObject*> WorldScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo)
+std::vector<SystemObject*> WorldScene::createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
-	return createComponents(p_entityID, p_constructionInfo.m_worldComponents);
+	return createComponents(p_entityID, p_constructionInfo.m_worldComponents, p_startLoading);
 }
 
-std::vector<SystemObject*> WorldScene::createComponents(const EntityID p_entityID, const WorldComponentsConstructionInfo &p_constructionInfo)
+std::vector<SystemObject*> WorldScene::createComponents(const EntityID p_entityID, const WorldComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading)
 {
 	std::vector<SystemObject*> components;
 
 	if(p_constructionInfo.m_spatialConstructionInfo != nullptr)
-		components.push_back(createComponent(p_entityID, *p_constructionInfo.m_spatialConstructionInfo));
+		components.push_back(createComponent(p_entityID, *p_constructionInfo.m_spatialConstructionInfo, p_startLoading));
 
 	return components;
 }

+ 10 - 4
Praxis3D/Source/WorldScene.h

@@ -17,6 +17,12 @@ struct WorldComponentsConstructionInfo
 		m_spatialConstructionInfo = nullptr;
 	}
 
+	// Perform a complete copy, instantiating (with new) every member variable pointer, instead of just assigning the pointer to the same memory
+	void completeCopy(const WorldComponentsConstructionInfo &p_other)
+	{
+		Utilities::performCopy<SpatialComponent::SpatialComponentConstructionInfo>(&m_spatialConstructionInfo, &p_other.m_spatialConstructionInfo);
+	}
+
 	void deleteConstructionInfo()
 	{
 		if(m_spatialConstructionInfo != nullptr)
@@ -41,13 +47,13 @@ public:
 
 	void loadInBackground() { }
 
-	EntityID createEntity(const ComponentsConstructionInfo &p_constructionInfo);
+	EntityID createEntity(const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
 
-	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo);
-	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const WorldComponentsConstructionInfo &p_constructionInfo);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const ComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
+	std::vector<SystemObject*> createComponents(const EntityID p_entityID, const WorldComponentsConstructionInfo &p_constructionInfo, const bool p_startLoading = true);
 	ErrorCode destroyObject(SystemObject *p_systemObject);
 
-	SystemObject *createComponent(const EntityID p_entityID, const SpatialComponent::SpatialComponentConstructionInfo &p_constructionInfo)
+	SystemObject *createComponent(const EntityID p_entityID, const SpatialComponent::SpatialComponentConstructionInfo &p_constructionInfo, const bool p_startLoading = true)
 	{
 		SpatialComponent *spatialComponent = nullptr;