Compare commits

..

5 Commits

435 changed files with 5143 additions and 27406 deletions
-11
View File
@@ -4,14 +4,3 @@ bin/
lib/ lib/
# Because apparently nobody has any self control # Because apparently nobody has any self control
*.orig *.orig
*.suo
*.sdf
tools/MayaExporter/MayaExporter/x64/Debug/
tools/MayaExporter/x64/Debug/
tools/MayaExporter/MayaExporter/Debug/
tools/MayaExporter/MayaExporter/GeneratedFiles/
tools/MayaExporter/MayaExporter/x64/*
tools/MayaExporter/x64/*
-9
View File
@@ -14,9 +14,6 @@ endif()
if(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
elseif(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif() endif()
#set(BUILD_SHARED_LIBS FALSE) #set(BUILD_SHARED_LIBS FALSE)
@@ -37,12 +34,6 @@ foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY})
endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES) endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES)
# DEBUG definition
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS
$<$<CONFIG:Debug>:DEBUG>
$<$<CONFIG:RelWithDebInfo>:DEBUG>
)
include(cotire) include(cotire)
add_subdirectory(src/Engine) add_subdirectory(src/Engine)
add_subdirectory(src/Game) add_subdirectory(src/Game)
+1 -2
View File
@@ -11,8 +11,7 @@ Libraries bundled along with binaries for Windows (MSVC14), available as a submo
| **[libpng](http://www.libpng.org/pub/png/libpng.html)** | 1.6.19 | [libpng License](http://www.libpng.org/pub/png/src/libpng-LICENSE.txt) | | **[libpng](http://www.libpng.org/pub/png/libpng.html)** | 1.6.19 | [libpng License](http://www.libpng.org/pub/png/src/libpng-LICENSE.txt) |
| **[Xerces-C++](https://xerces.apache.org/xerces-c)** | 3.1.2 | [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | **[Xerces-C++](https://xerces.apache.org/xerces-c)** | 3.1.2 | [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) |
| **[ImGui](https://github.com/ocornut/imgui)** | 2015-12-12 | [MIT License](https://github.com/ocornut/imgui/blob/de3a154f3801de22c8e0bd2aeabf663a70c05972/LICENSE) | | **[ImGui](https://github.com/ocornut/imgui)** | 2015-12-12 | [MIT License](https://github.com/ocornut/imgui/blob/de3a154f3801de22c8e0bd2aeabf663a70c05972/LICENSE) |
| **[nativefiledialog](https://github.com/mlabbe/nativefiledialog)** | 2016-01-08 | [nativefiledialog Licence](https://github.com/mlabbe/nativefiledialog/blob/master/LICENSE) | | **[nativefiledialog](https://github.com/mlabbe/nativefiledialog) | 2016-01-08 | https://github.com/mlabbe/nativefiledialog/blob/master/LICENSE |
| **[OpenAL](https://www.openal.org/)** | 1.1 | [OpenAL License](resources/Licenses/OpenAL.txt)
#### External libraries #### External libraries
Libraries that are too big to be bundled with the project. Libraries that are too big to be bundled with the project.
+1 -1
Submodule assets updated: 7531e441fe...c8e631f449
+8 -36
View File
@@ -6,16 +6,11 @@
//or you will get "fatal error C1189: #error: gl.h included before glew.h" //or you will get "fatal error C1189: #error: gl.h included before glew.h"
#include <vector> #include <vector>
#include <boost/optional.hpp>
#include "../Core/Ray.h" #include "Core/Ray.h"
#include "../Core/AABB.h" #include "Core/AABB.h"
#include "Rendering/RawModelCustom.h" #include "Engine/Rendering/RawModel.h"
//#include "Rendering/RawModelAssimp.h" #include "Core/Entity.h"
#include "../Core/Transform.h"
#include "../Core/Entity.h"
#include "../Core/EntityWrapper.h"
#include "EntityAABB.h"
class World; class World;
struct ComponentWrapper; struct ComponentWrapper;
@@ -28,21 +23,6 @@ bool RayVsAABB(const Ray& ray, const AABB& box);
//Return true if the ray hits the box, also outputs distance from ray origin to intersection point in [outDistance]. //Return true if the ray hits the box, also outputs distance from ray origin to intersection point in [outDistance].
bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance); bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance);
//Return true if the ray hits the triangle.
bool RayVsTriangle(const Ray& ray,
const glm::vec3& v0,
const glm::vec3& v1,
const glm::vec3& v2,
bool trueOnNegativeDistance = false);
//Return true if the ray hits the triangle, and the distance is less than outDistance.
bool RayVsTriangle(const Ray& ray,
const glm::vec3& v0,
const glm::vec3& v1,
const glm::vec3& v2,
float& outDistance,
float& outUCoord,
float& outVCoord,
bool trueOnNegativeDistance = false);
//Return true if the ray hits any of the triangles in the model. Stops checking when a hit is detected. //Return true if the ray hits any of the triangles in the model. Stops checking when a hit is detected.
bool RayVsModel(const Ray& ray, bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices, const std::vector<RawModel::Vertex>& modelVertices,
@@ -63,24 +43,16 @@ bool RayVsModel(const Ray& ray,
float& outUCoord, float& outUCoord,
float& outVCoord); float& outVCoord);
bool AABBvsTriangles(const AABB& box,
const RawModel::Vertex* modelVertices,
const std::vector<unsigned int>& modelIndices,
const glm::mat4& modelMatrix,
glm::vec3& boxVelocity,
float verticalStepHeight,
bool& isOnGround,
glm::vec3& outResolutionVector);
//Return true if the boxes are intersecting. //Return true if the boxes are intersecting.
bool AABBVsAABB(const AABB& a, const AABB& b); bool AABBVsAABB(const AABB& a, const AABB& b);
//Return true if the boxes are intersecting. //Return true if the boxes are intersecting.
//Also outputs the minimum translation that box [a] would need in order to resolve collision. //Also outputs the minimum translation that box [a] would need in order to resolve collision.
bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation); bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation);
bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon = 0.0001f);
// Calculates an absolute AABB from an entity AABB component //Returns true if the entity has a boundingbox. Outputs the aabb in [outBox].
boost::optional<EntityAABB> EntityAbsoluteAABB(EntityWrapper& entity, bool takeModelBox = false); bool GetEntityBox(World* world, EntityID entity, AABB& outBox, bool forceBoxFromModel = false);
boost::optional<EntityAABB> AbsoluteAABBExplosionEffect(EntityWrapper& entity); bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox);
} }
+15 -13
View File
@@ -4,26 +4,28 @@
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <glm/common.hpp> #include <glm/common.hpp>
#include "../Common.h" #include "Common.h"
#include "../Core/System.h" #include "Core/System.h"
#include "../Core/EventBroker.h" #include "Core/EventBroker.h"
#include "../Core/Octree.h" #include "Core/EKeyUp.h"
#include "EntityAABB.h"
class CollisionSystem : public PureSystem class CollisionSystem : public PureSystem
{ {
public: public:
CollisionSystem(World* world, EventBroker* eventBroker, Octree<EntityAABB>* octree) CollisionSystem(EventBroker* eventBroker)
: System(world, eventBroker) : PureSystem(eventBroker, "AABB")
, PureSystem("Collidable") , zPress(false)
, m_Octree(octree) {
{ } //TODO: Debug stuff, remove later.
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp);
}
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; virtual void UpdateComponent(World* world, ComponentWrapper& cAABB, double dt) override;
private: private:
Octree<EntityAABB>* m_Octree; bool zPress;
std::vector<EntityAABB> m_OctreeResult; EventRelay<CollisionSystem, Events::KeyUp> m_EKeyUp;
bool OnKeyUp(const Events::KeyUp &event);
}; };
#endif #endif
+7 -7
View File
@@ -2,7 +2,7 @@
#define Events_TriggerEnter_h__ #define Events_TriggerEnter_h__
#include "../Core/EventBroker.h" #include "../Core/EventBroker.h"
#include "../Core/EntityWrapper.h" #include "../Core/Entity.h"
namespace Events namespace Events
{ {
@@ -11,27 +11,27 @@ namespace Events
struct TriggerTouch : Event struct TriggerTouch : Event
{ {
/** The id of the entity that touches the trigger. */ /** The id of the entity that touches the trigger. */
EntityWrapper Entity; EntityID Entity;
/** The id of the trigger entity. */ /** The id of the trigger entity. */
EntityWrapper Trigger; EntityID Trigger;
}; };
/** Thrown once, when an entity has completely left a trigger. */ /** Thrown once, when an entity has completely left a trigger. */
struct TriggerLeave : Event struct TriggerLeave : Event
{ {
/** The id of the entity that left the trigger. */ /** The id of the entity that left the trigger. */
EntityWrapper Entity; EntityID Entity;
/** The id of the trigger entity. */ /** The id of the trigger entity. */
EntityWrapper Trigger; EntityID Trigger;
}; };
/** Thrown once, when an entity is completely contained inside a trigger. */ /** Thrown once, when an entity is completely contained inside a trigger. */
struct TriggerEnter : Event struct TriggerEnter : Event
{ {
/** The id of the entity that entered the trigger. */ /** The id of the entity that entered the trigger. */
EntityWrapper Entity; EntityID Entity;
/** The id of the trigger entity. */ /** The id of the trigger entity. */
EntityWrapper Trigger; EntityID Trigger;
}; };
} }
-22
View File
@@ -1,22 +0,0 @@
#ifndef EntityAABB_h__
#define EntityAABB_h__
#include "../Core/AABB.h"
#include "../Core/EntityWrapper.h"
struct EntityAABB : AABB
{
EntityAABB() = default;
EntityAABB(const glm::vec3& minPos, const glm::vec3& maxPos)
: AABB(minPos, maxPos)
{ }
EntityAABB(const AABB& aabb)
: AABB(aabb)
{ }
EntityWrapper Entity;
};
#endif
@@ -1,25 +0,0 @@
#ifndef FillFrustumOctreeSystem_h__
#define FillFrustumOctreeSystem_h__
#include "../Core/System.h"
#include "../Core/Octree.h"
#include "Collision.h"
#include "EntityAABB.h"
class FillFrustumOctreeSystem : public ImpureSystem, public PureSystem
{
public:
FillFrustumOctreeSystem(World* world, EventBroker* eventBroker, Octree<EntityAABB>* octree)
: System(world, eventBroker)
, PureSystem("Model")
, m_Octree(octree)
{ }
virtual void Update(double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
Octree<EntityAABB>* m_Octree;
};
#endif
@@ -1,25 +0,0 @@
#ifndef FillOctreeSystem_h__
#define FillOctreeSystem_h__
#include "../Core/System.h"
#include "../Core/Octree.h"
#include "Collision.h"
#include "EntityAABB.h"
class FillOctreeSystem : public ImpureSystem, public PureSystem
{
public:
FillOctreeSystem(World* world, EventBroker* eventBroker, Octree<EntityAABB>* octree, const std::string& fillComponentType)
: System(world, eventBroker)
, PureSystem(fillComponentType)
, m_Octree(octree)
{ }
virtual void Update(double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
Octree<EntityAABB>* m_Octree;
};
#endif
+12 -30
View File
@@ -4,51 +4,33 @@
#include <glm/common.hpp> #include <glm/common.hpp>
#include <unordered_set> #include <unordered_set>
#include "../Core/System.h" #include "Core/System.h"
#include "../Core/EventBroker.h" #include "Core/EventBroker.h"
#include "../Core/Octree.h"
#include "ETrigger.h" #include "ETrigger.h"
#include "EntityAABB.h"
class AABB; class AABB;
class TriggerSystem : public PureSystem class TriggerSystem : public PureSystem
{ {
public: public:
TriggerSystem(World* world, EventBroker* eventBroker, Octree<EntityAABB>* octree) TriggerSystem(EventBroker* eventBroker)
: System(world, eventBroker) : PureSystem(eventBroker, "Trigger")
, PureSystem("Trigger") {}
, m_Octree(octree)
{
EVENT_SUBSCRIBE_MEMBER(m_ETouch, &TriggerSystem::OnTouch);
EVENT_SUBSCRIBE_MEMBER(m_EEnter, &TriggerSystem::OnEnter);
EVENT_SUBSCRIBE_MEMBER(m_ELeave, &TriggerSystem::OnLeave);
}
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; virtual void UpdateComponent(World* world, ComponentWrapper& collision, double dt) override;
private: private:
Octree<EntityAABB>* m_Octree; std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesTouchingTrigger;
std::vector<EntityAABB> m_OctreeOut; std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesCompletelyInTrigger;
std::unordered_map<EntityWrapper, std::unordered_set<EntityWrapper>> m_EntitiesTouchingTrigger;
std::unordered_map<EntityWrapper, std::unordered_set<EntityWrapper>> m_EntitiesCompletelyInTrigger;
//TODO: Only exists for debug purposes, remove later.
EventRelay<TriggerSystem, Events::TriggerEnter> m_EEnter;
bool OnEnter(const Events::TriggerEnter &event);
EventRelay<TriggerSystem, Events::TriggerTouch> m_ETouch;
bool OnTouch(const Events::TriggerTouch &event);
EventRelay<TriggerSystem, Events::TriggerLeave> m_ELeave;
bool OnLeave(const Events::TriggerLeave &event);
//True if leave event was thrown. //True if leave event was thrown.
bool throwLeaveIfWasInTrigger(std::unordered_set<EntityWrapper>& triggerSet, EntityWrapper colliderENtity, EntityWrapper triggerEntity); bool throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId);
template<typename Event> template<typename Event>
void publish(EntityWrapper collider, EntityWrapper trigger) void publish(EntityID pId, EntityID tId)
{ {
Event e; Event e;
e.Trigger = trigger; e.Trigger = tId;
e.Entity = collider; e.Entity = pId;
m_EventBroker->Publish(e); m_EventBroker->Publish(e);
} }
}; };
-3
View File
@@ -1,11 +1,8 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <sstream>
#include <vector> #include <vector>
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <algorithm>
#include <array>
#include "Core/Util/Logging.h" #include "Core/Util/Logging.h"
#include "Core/Util/IfDebug.h" #include "Core/Util/IfDebug.h"
+4 -3
View File
@@ -9,19 +9,20 @@ public:
AABB() = default; AABB() = default;
//No checks are made. Values in minPos must be less than values in maxPos, i.e. min.x < max.x, etc. //No checks are made. Values in minPos must be less than values in maxPos, i.e. min.x < max.x, etc.
AABB(const glm::vec3& minPos, const glm::vec3& maxPos); AABB(const glm::vec3& minPos, const glm::vec3& maxPos);
AABB(const glm::vec4& minPos, const glm::vec4& maxPos);
//No checks are made. Size must consist of non-negative numbers. //No checks are made. Size must consist of non-negative numbers.
static AABB FromOriginSize(const glm::vec3& origin, const glm::vec3& size); virtual void CreateFromCenter(const glm::vec3& center, const glm::vec3& size);
virtual ~AABB(); virtual ~AABB();
const glm::vec3& MinCorner() const { return m_MinCorner; } const glm::vec3& MinCorner() const { return m_MinCorner; }
const glm::vec3& MaxCorner() const { return m_MaxCorner; } const glm::vec3& MaxCorner() const { return m_MaxCorner; }
const glm::vec3& Origin() const { return m_Origin; } const glm::vec3& Center() const { return m_Center; }
const glm::vec3 Size() const { return 2.0f * m_HalfSize; } const glm::vec3 Size() const { return 2.0f * m_HalfSize; }
const glm::vec3& HalfSize() const { return m_HalfSize; } const glm::vec3& HalfSize() const { return m_HalfSize; }
private: private:
glm::vec3 m_MinCorner; glm::vec3 m_MinCorner;
glm::vec3 m_MaxCorner; glm::vec3 m_MaxCorner;
glm::vec3 m_Origin; glm::vec3 m_Center;
glm::vec3 m_HalfSize; glm::vec3 m_HalfSize;
}; };
+3 -8
View File
@@ -5,19 +5,15 @@
struct ComponentInfo struct ComponentInfo
{ {
typedef int EnumType;
struct Meta_t struct Meta_t
{ {
std::string Annotation; std::string Annotation;
unsigned int Allocation = 0; unsigned int Allocation = 0;
std::map<std::string, std::string> FieldAnnotations; unsigned int Stride = 0;
std::map<std::string, std::map<std::string, EnumType>> FieldEnumDefinitions;
}; };
struct Field_t struct Field_t
{ {
std::string Name;
std::string Type; std::string Type;
unsigned int Offset; unsigned int Offset;
unsigned int Stride; unsigned int Stride;
@@ -25,10 +21,9 @@ struct ComponentInfo
std::string Name; std::string Name;
std::unordered_map<std::string, Field_t> Fields; std::unordered_map<std::string, Field_t> Fields;
std::vector<std::string> FieldsInOrder; std::vector<const Field_t*> FieldsInOrder;
unsigned int Stride = 0; Meta_t Meta;
std::shared_ptr<char> Defaults = nullptr; std::shared_ptr<char> Defaults = nullptr;
std::shared_ptr<Meta_t> Meta = nullptr;
}; };
template<> template<>
+1 -2
View File
@@ -43,7 +43,7 @@ public:
ComponentPool(const ::ComponentInfo& ci) ComponentPool(const ::ComponentInfo& ci)
: m_ComponentInfo(ci) : m_ComponentInfo(ci)
, m_Pool(ci.Meta->Allocation, sizeof(EntityID) + ci.Stride) , m_Pool(ci.Meta.Allocation, sizeof(EntityID) + ci.Meta.Stride)
{ } { }
ComponentPool(const ComponentPool& other) = delete; ComponentPool(const ComponentPool& other) = delete;
ComponentPool(const ComponentPool&& other) = delete; ComponentPool(const ComponentPool&& other) = delete;
@@ -61,7 +61,6 @@ public:
iterator begin() const; iterator begin() const;
iterator end() const; iterator end() const;
size_t size() const;
//Dumps information about what the pool memory looks like right now //Dumps information about what the pool memory looks like right now
//into an output stream (e.g. file/std::cout, anything that has an operator<<) //into an output stream (e.g. file/std::cout, anything that has an operator<<)
+19 -37
View File
@@ -18,37 +18,22 @@ struct ComponentWrapper
const ::EntityID EntityID; const ::EntityID EntityID;
char* Data; char* Data;
ComponentInfo::EnumType Enum(const char* fieldName, const char* enumKey) template <typename T>
T& Property(std::string name)
{ {
return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey); unsigned int offset = Info.Fields.at(name).Offset;
return *reinterpret_cast<T*>(&Data[offset]);
} }
template <typename T> template <typename T>
T& Field(std::string name) void SetProperty(std::string name, const T value) { Property<T>(name) = value; }
{
const ComponentInfo::Field_t& field = Info.Fields.at(name);
if (sizeof(T) > field.Stride) {
std::stringstream message;
message << "Type size of \"" << typeid(T).name() << "\" doesn't match size of component field \"" << Info.Name << "." << name << "\"!";
throw new std::runtime_error(message.str().c_str());
}
return *reinterpret_cast<T*>(&Data[field.Offset]);
}
template <typename T>
void SetField(std::string name, const T value) { Field<T>(name) = value; }
//template <typename T> //template <typename T>
//void SetField(std::string name, T& value) { Field<T>(name) = value; } //void SetProperty(std::string name, T& value) { Property<T>(name) = value; }
// Specialization for string literals // Specialization for string literals
template <std::size_t N> template <std::size_t N>
void SetField(std::string name, const char(&value)[N]) { Field<std::string>(name) = std::string(value); } void SetProperty(std::string name, const char(&value)[N]) { Property<std::string>(name) = std::string(value); }
void Copy(ComponentWrapper& destination)
{
memcpy(destination.Data, this->Data, Info.Stride);
}
struct SubscriptProxy struct SubscriptProxy
{ {
friend struct ComponentWrapper; friend struct ComponentWrapper;
@@ -62,21 +47,18 @@ struct ComponentWrapper
std::string m_PropertyName; std::string m_PropertyName;
public: public:
// Return the integer value of an enum type key for this field template <typename T>
ComponentInfo::EnumType Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); } operator T&() { return m_Component->Property<T>(m_PropertyName); }
template <typename T> template <typename T>
operator T&() { return m_Component->Field<T>(m_PropertyName); } void operator=(const T val) { m_Component->SetProperty<T>(m_PropertyName, val); }
template <typename T>
void operator=(const T val) { m_Component->SetField<T>(m_PropertyName, val); }
// TODO: Pass by reference and rvalue (universal reference?) // TODO: Pass by reference and rvalue (universal reference?)
//template <typename T> //template <typename T>
//void operator=(T& val) { m_Component->SetField<T>(m_PropertyName, val); } //void operator=(T& val) { m_Component->SetProperty<T>(m_PropertyName, val); }
// Specialization for string literals // Specialization for string literals
template <std::size_t N> template<std::size_t N>
void operator=(const char(&val)[N]) { m_Component->SetField<N>(m_PropertyName, val); } void operator=(const char(&val)[N]) { m_Component->SetProperty<N>(m_PropertyName, val); }
}; };
SubscriptProxy operator[](std::string propertyName) { return SubscriptProxy(this, propertyName); } SubscriptProxy operator[](std::string propertyName) { return SubscriptProxy(this, propertyName); }
}; };
@@ -86,25 +68,25 @@ class ComponentWrapperFactory
{ {
public: public:
ComponentWrapperFactory() = default; ComponentWrapperFactory() = default;
ComponentWrapperFactory(std::string componentTypeName, unsigned int allocation = 0) ComponentWrapperFactory(std::string componentTypeName, std::size_t allocation = 0)
{ {
m_ComponentInfo.Name = componentTypeName; m_ComponentInfo.Name = componentTypeName;
m_ComponentInfo.Meta->Allocation = allocation; m_ComponentInfo.Meta.Allocation = allocation;
} }
template <typename T> template <typename T>
void AddProperty(std::string fieldName, T defaultValue) void AddProperty(std::string fieldName, T defaultValue)
{ {
m_DefaultValues.push_back(defaultValue); m_DefaultValues.push_back(defaultValue);
m_ComponentInfo.Fields[fieldName].Type = typeid(T).name(); m_ComponentInfo.Fields[fieldName].Name = typeid(T).name();
m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Stride; m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Meta.Stride;
m_ComponentInfo.Fields[fieldName].Stride = sizeof(T); m_ComponentInfo.Fields[fieldName].Stride = sizeof(T);
m_ComponentInfo.Stride += sizeof(T); m_ComponentInfo.Meta.Stride += sizeof(T);
} }
ComponentInfo& Finalize() ComponentInfo& Finalize()
{ {
m_ComponentInfo.Defaults = std::shared_ptr<char>(new char[m_ComponentInfo.Stride]); m_ComponentInfo.Defaults = std::shared_ptr<char>(new char[m_ComponentInfo.Meta.Stride]);
std::size_t offset = 0; std::size_t offset = 0;
for (auto& val : m_DefaultValues) { for (auto& val : m_DefaultValues) {
memcpy(m_ComponentInfo.Defaults.get() + offset, val.Data.get(), val.Size); memcpy(m_ComponentInfo.Defaults.get() + offset, val.Data.get(), val.Size);
+31 -25
View File
@@ -3,10 +3,10 @@
#include <string> #include <string>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptors.hpp>
#include <ini_file/ini_file.hpp>
#include "../Common.h" #include "../Common.h"
#include "ResourceManager.h" #include "ResourceManager.h"
@@ -20,46 +20,52 @@ private:
public: public:
template <typename T> template <typename T>
T Get(std::string key, T defaultValue); T Get(std::string key, T defaultValue);
template <typename T>
std::vector<std::pair<std::string, T>> GetAll(std::string key);
template <typename T> template <typename T>
void Set(std::string key, T value); void Set(std::string key, T value);
const ini_file::section* GetSection(std::string section);
const ini_file::section_map& GetSections() { return m_Merged; }
const ini_file::param* GetParam(std::string key);
void SaveToDisk(); void SaveToDisk();
private: private:
boost::filesystem::path m_Path; boost::filesystem::path m_Path;
boost::property_tree::ptree m_PTreeDefaults; ini_file::section_map m_Defaults;
boost::property_tree::ptree m_PTreeOverrides; ini_file::section_map m_Overrides;
boost::property_tree::ptree m_PTreeMerged; ini_file::section_map m_Merged;
// Merge ini file section map b into a
void mergeINI(ini_file::section_map& a, const ini_file::section_map& b);
// Convert an ini key delimited by periods to a section and a param
boost::optional<std::pair<std::string, std::string>> tokenizeKey(std::string key);
}; };
template <typename T> template <typename T>
T ConfigFile::Get(std::string key, T defaultValue) T ConfigFile::Get(std::string key, T defaultValue)
{ {
return m_PTreeMerged.get<T>(key, defaultValue); auto param = GetParam(key);
} if (param == nullptr) {
return defaultValue;
}
template <typename T> return boost::lexical_cast<T>(param->get_value());
std::vector<std::pair<std::string, T>> ConfigFile::GetAll(std::string key)
{
std::vector<std::pair<std::string, T>> out;
auto parent = m_PTreeMerged.find(key);
if (parent == m_PTreeMerged.not_found()) {
return out;
}
for (auto& child : parent->second) {
T value = boost::lexical_cast<T>(child.second.data());
out.push_back(std::make_pair(child.first, value));
}
return out;
} }
template <typename T> template <typename T>
void ConfigFile::Set(std::string key, T value) void ConfigFile::Set(std::string key, T value)
{ {
m_PTreeOverrides.put<T>(key, value); std::string section;
m_PTreeMerged.put<T>(key, value); std::string param;
if (auto tokens = tokenizeKey(key)) {
std::tie(section, param) = *tokens;
} else {
LOG_WARNING("%s: Malformed config key \"%s\"", m_Path.string().c_str(), key.c_str());
return;
}
m_Overrides[section][param] = boost::lexical_cast<std::string>(value);
m_Merged[section][param] = boost::lexical_cast<std::string>(value);
} }
#endif #endif
+157
View File
@@ -0,0 +1,157 @@
#ifndef DeveloperConsole_h__
#define DeveloperConsole_h__
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
#include "../Common.h"
#include "ConfigFile.h"
class DeveloperConsole
{
public:
DeveloperConsole() = delete;
static void MergeConfig(std::string configFile)
{
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
LOG_DEBUG("Debug.LogLevel %i", config->Get<int>("Debug.LogLevel", -1));
config->Set("Debug.LogLevel", 8);
LOG_DEBUG("Debug.LogLevel %i", config->Get<int>("Debug.LogLevel", -1));
config->Set("Test.TesTest.Testies", "Hello");
config->SaveToDisk();
for (auto& section : config->GetSections()) {
for (auto& param : *section.second) {
std::cout << "// " << param.second->get_comment() << std::endl;
std::cout << section.first << "." << param.first << " " << param.second->get_value() << std::endl;
}
}
for (auto& section : config->GetSections()) {
for (auto& param : *section.second) {
std::string key = section.first + "." + param.first;
m_VariableBindingSetters[key] = [config, key](std::string value) {
config->Set<std::string>(key, value);
};
m_VariableBindingGetters[key] = [config, key]() {
return config->Get<std::string>(key, "");
};
}
}
}
template <typename T>
static typename std::enable_if<std::is_enum<T>::value, void>::type
BindVariable(std::string path, T& variable)
{
BindVariable<T, std::underlying_type<T>::type>(path, variable);
}
template <typename T, typename R = T>
static typename std::enable_if<!std::is_enum<R>::value, void>::type
BindVariable(std::string path, T& variable)
{
m_VariableBindingSetters[path] = [&variable](std::string value) {
variable = static_cast<T>(boost::lexical_cast<R>(value));
};
m_VariableBindingGetters[path] = [&variable]() {
return boost::lexical_cast<std::string>(static_cast<R>(variable));
};
}
static void Consume(const std::string& command)
{
if (command.empty()) {
return;
}
boost::char_separator<char> argumentSeparator(" ");
tokenizer tokens(command, argumentSeparator);
for (tokenizer::const_iterator it = tokens.begin(); it != tokens.end(); it++) {
consumeToken(it, tokens.end());
}
}
static void Consume(std::istream& stream)
{
std::string input;
std::getline(stream, input);
Consume(input);
/*if (stream.peek() == '\n') {
printValue(key);
} else {
std::string newValue;
stream >> newValue;
if (m_VariableBindingSetters.find(key) != m_VariableBindingSetters.end()) {
m_VariableBindingSetters.at(key)(newValue);
} else {
std::cout << "Unknown path: " << key << std::endl;
}
return;
for (auto& config : m_ConfigFiles) {
config->Set(key, newValue);
config->SaveToDisk();
LOG_DEBUG("Key %s set to new value %s and saved to disk.", key.c_str(), newValue.c_str());
}
} */
}
private:
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
static std::map<std::string, std::function<std::string()>> m_VariableBindingGetters;
static std::map<std::string, std::function<void(std::string)>> m_VariableBindingSetters;
static std::map<std::string, std::function<std::string(std::string)>> m_VariableBindingMappers;
static std::map<std::string, std::string> m_VariableDocumentation;
static void consumeToken(tokenizer::iterator& token, const tokenizer::iterator end)
{
tokenizer::iterator next = token;
next++;
if (next == end) {
printValue(token);
} else {
setValue(token, end);
}
}
static void printValue(tokenizer::iterator token)
{
std::string key = *token;
std::string value;
if (m_VariableBindingGetters.find(key) != m_VariableBindingGetters.end()) {
std::cout << key << " = " << m_VariableBindingGetters.at(key)() << std::endl;
} else {
std::cout << "Unknown path: " << key << std::endl;
}
return;
if (!value.empty()) {
std::cout << key << " = " << value << std::endl;
} else {
std::cerr << "Unknown path: " << key << std::endl;
}
}
static void setValue(tokenizer::iterator& token, const tokenizer::iterator end)
{
std::string key = *token;
std::string value = *(++token);
if (m_VariableBindingSetters.find(key) != m_VariableBindingSetters.end()) {
m_VariableBindingSetters.at(key)(value);
} else {
std::cout << "Unknown path: " << key << std::endl;
}
}
};
#endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef ECaptured_h__
#define ECaptured_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
//triggers when a capturePoint has been taken over
struct Captured : Event
{
int TeamNumberThatCapturedCapturePoint;
EntityID CapturePointID;
};
}
#endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef EComponentAttached_h__
#define EComponentAttached_h__
#include "EventBroker.h"
#include "World.h"
#include "Entity.h"
#include "ComponentWrapper.h"
namespace Events
{
struct ComponentAttached : Event
{
EntityWrapper Entity;
ComponentWrapper Component;
};
}
#endif
-21
View File
@@ -1,21 +0,0 @@
#ifndef EComponentDeleted_h__
#define EComponentDeleted_h__
#include "../Common.h"
#include "Event.h"
#include "Entity.h"
namespace Events
{
struct ComponentDeleted : Event
{
EntityID Entity;
std::string ComponentType;
// True if the component was deleted as a result of the entity it was attached to being deleted
bool Cascaded;
};
}
#endif
-19
View File
@@ -1,19 +0,0 @@
#ifndef EEntityDeleted_h__
#define EEntityDeleted_h__
#include "Event.h"
#include "Entity.h"
namespace Events
{
struct EntityDeleted : Event
{
EntityID DeletedEntity;
// True if the entity deletion was triggered because the entity's parent was deleted before it
bool Cascaded;
};
}
#endif
-3
View File
@@ -11,9 +11,6 @@ struct KeyDown : Event
{ {
/** GLFW key code */ /** GLFW key code */
int KeyCode; int KeyCode;
bool ModCtrl;
bool ModAlt;
bool ModShift;
}; };
} }
-3
View File
@@ -11,9 +11,6 @@ struct KeyUp : Event
{ {
/** GLFW key code */ /** GLFW key code */
int KeyCode; int KeyCode;
bool ModCtrl;
bool ModAlt;
bool ModShift;
}; };
} }
-22
View File
@@ -1,22 +0,0 @@
#ifndef EPause_h__
#define EPause_h__
#include "EventBroker.h"
#include "World.h"
namespace Events
{
struct Pause : Event
{
::World* World;
};
struct Resume : Event
{
::World* World;
};
}
#endif
-17
View File
@@ -1,17 +0,0 @@
#ifndef EPickupSpawned_h__
#define EPickupSpawned_h__
#include "Core/Event.h"
#include "Core/EntityWrapper.h"
namespace Events
{
struct PickupSpawned : Event
{
EntityWrapper Pickup;
};
}
#endif
+5 -4
View File
@@ -2,16 +2,17 @@
#define EPlayerDamage_h__ #define EPlayerDamage_h__
#include "EventBroker.h" #include "EventBroker.h"
#include "../Core/EntityWrapper.h" #include "../Core/Entity.h"
namespace Events namespace Events
{ {
struct PlayerDamage : Event struct PlayerDamage : Event
{ {
//NOTE: this struct is missing information on what the damageSource is double DamageAmount;
EntityWrapper Player; EntityID PlayerDamagedID;
double Damage; //optional TypeOfDamage
std::string TypeOfDamage;
}; };
} }
+3 -2
View File
@@ -2,7 +2,7 @@
#define EPlayerDeath_h__ #define EPlayerDeath_h__
#include "EventBroker.h" #include "EventBroker.h"
#include "../Core/EntityWrapper.h" #include "../Core/Entity.h"
namespace Events namespace Events
{ {
@@ -10,7 +10,8 @@ namespace Events
struct PlayerDeath : Event struct PlayerDeath : Event
{ {
//KilledBy,KilledByWhat is optional for now. It might be used later in the playerlog-system //KilledBy,KilledByWhat is optional for now. It might be used later in the playerlog-system
EntityWrapper Player; EntityID KilledBy;
EntityID PlayerID;
std::string KilledByWhat; std::string KilledByWhat;
}; };
+6 -6
View File
@@ -2,16 +2,16 @@
#define EPlayerHealthPickup_h__ #define EPlayerHealthPickup_h__
#include "EventBroker.h" #include "EventBroker.h"
#include "../Core/EntityWrapper.h" #include "../Core/Entity.h"
namespace Events namespace Events
{ {
struct PlayerHealthPickup : Event struct PlayerHealthPickup : Event
{ {
EntityWrapper Player; double HealthAmount;
double HealthAmount; EntityID PlayerHealedID;
}; };
} }
-20
View File
@@ -1,20 +0,0 @@
#ifndef EPlayerSpawned_h__
#define EPlayerSpawned_h__
#include "Core/Event.h"
#include "Core/EntityWrapper.h"
namespace Events
{
struct PlayerSpawned : Event
{
int PlayerID;
EntityWrapper Player;
EntityWrapper Spawner;
std::string PlayerName;
};
}
#endif
-17
View File
@@ -1,17 +0,0 @@
#ifndef EShoot_h__
#define EShoot_h__
#include "EventBroker.h"
#include "../Core/EntityWrapper.h"
namespace Events
{
struct Shoot : Event
{
EntityWrapper Player;
};
}
#endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef EWin_h__
#define EWin_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
//triggers when a team has captured all capturePoints
struct Win : Event
{
//can be 0 = none, 1,2
int TeamThatWon;
};
}
#endif
-1
View File
@@ -4,5 +4,4 @@
typedef unsigned int EntityID; typedef unsigned int EntityID;
const static unsigned int EntityID_Invalid = -1; const static unsigned int EntityID_Invalid = -1;
#endif #endif
+8 -8
View File
@@ -285,7 +285,7 @@ private:
XSValue::Status status; XSValue::Status status;
XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, status); XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, status);
compInfo.Meta->Allocation += val->fData.fValue.f_int; compInfo.Meta.Allocation += val->fData.fValue.f_int;
} }
// Save documentation string // Save documentation string
@@ -293,11 +293,11 @@ private:
if (documentationTags->getLength() != 0) { if (documentationTags->getLength() != 0) {
auto child = documentationTags->item(0)->getFirstChild(); auto child = documentationTags->item(0)->getFirstChild();
if (child != nullptr) { if (child != nullptr) {
compInfo.Meta->Annotation = XSTR(child->getNodeValue()); compInfo.Meta.Annotation = XSTR(child->getNodeValue());
} }
} }
// TODO: Parse annotation string XML // TODO: Parse annotation string XML
// compInfo.Meta->Allocation = ... // compInfo.Meta.Allocation = ...
} else { } else {
std::cout << "Warning: Component is missing an annotation!" << std::endl; std::cout << "Warning: Component is missing an annotation!" << std::endl;
} }
@@ -344,7 +344,7 @@ private:
fieldOffset += getTypeStride(type); fieldOffset += getTypeStride(type);
} }
compInfo.Stride = fieldOffset; compInfo.Meta.Stride = fieldOffset;
m_ComponentInfo[compInfo.Name] = compInfo; m_ComponentInfo[compInfo.Name] = compInfo;
} }
} }
@@ -367,14 +367,14 @@ private:
std::string componentName = XSTR(component->getLocalName()); std::string componentName = XSTR(component->getLocalName());
auto& compInfo = m_ComponentInfo.at(componentName); auto& compInfo = m_ComponentInfo.at(componentName);
compInfo.Meta->Allocation += 1; compInfo.Meta.Allocation += 1;
} }
std::cout << "COMPONENT INFO" << std::endl; std::cout << "COMPONENT INFO" << std::endl;
for (auto& pair : m_ComponentInfo) { for (auto& pair : m_ComponentInfo) {
ComponentInfo& ci = pair.second; ComponentInfo& ci = pair.second;
std::cout << "Component: " << ci.Name << " (" << ci.Meta->Annotation << ")" << std::endl; std::cout << "Component: " << ci.Name << " (" << ci.Meta.Annotation << ")" << std::endl;
std::cout << " Allocation: " << ci.Meta->Allocation << std::endl; std::cout << " Allocation: " << ci.Meta.Allocation << std::endl;
std::cout << " Fields:" << std::endl; std::cout << " Fields:" << std::endl;
// Calculate component size // Calculate component size
@@ -393,7 +393,7 @@ private:
cs.ComponentName = ci.Name; cs.ComponentName = ci.Name;
cs.Stride = stride; cs.Stride = stride;
cs.Info = ci; cs.Info = ci;
cs.Data = new char[stride*ci.Meta->Allocation]; cs.Data = new char[stride*ci.Meta.Allocation];
m_ComponentStore[cs.ComponentName] = cs; m_ComponentStore[cs.ComponentName] = cs;
} }
} }
+148 -19
View File
@@ -73,15 +73,88 @@ public:
ComponentField ComponentField
}; };
EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader); EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader)
: m_Handler(handler)
, m_Reader(reader)
{
// 0 is imaginary world entity
m_EntityStack.push(0);
m_StateStack.push(State::Unknown);
}
void startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) override; void startElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname, const xercesc::Attributes& attrs) override
void characters(const XMLCh* const chars, const XMLSize_t length) override; {
void endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) override; std::string name = XS::ToString(_localName);
void warning(const xercesc::SAXParseException& e); if (m_StateStack.top() == State::Unknown || m_StateStack.top() == State::Entity) {
void error(const xercesc::SAXParseException& e); if (name == "Entity") {
void fatalError(const xercesc::SAXParseException& e); m_StateStack.push(State::Entity);
onStartEntity(attrs);
return;
}
if (name == "EntityRef") {
onStartEntityRef(attrs);
return;
}
}
std::string uri = XS::ToString(_uri);
if (m_StateStack.top() == State::Entity) {
if (uri == "components") {
m_StateStack.push(State::Component);
onStartComponent(name);
return;
}
}
if (m_StateStack.top() == State::Component) {
m_StateStack.push(State::ComponentField);
onStartComponentField(name, attrs);
return;
}
}
void characters(const XMLCh* const chars, const XMLSize_t length) override
{
if (m_StateStack.top() == State::ComponentField) {
char* transcoded = xercesc::XMLString::transcode(chars);
onFieldData(transcoded);
}
}
void endElement(const XMLCh* const _uri, const XMLCh* const _localName, const XMLCh* const _qname) override
{
std::string name = XS::ToString(_localName);
if (m_StateStack.top() == State::Entity) {
if (name == "Entity") {
m_StateStack.pop();
onEndEntity();
return;
}
}
std::string uri = XS::ToString(_uri);
if (m_StateStack.top() == State::Component) {
//if (uri == "components") {
m_StateStack.pop();
onEndComponent(name);
return;
//}
}
if (m_StateStack.top() == State::ComponentField) {
m_StateStack.pop();
onEndComponentField(name);
return;
}
}
void fatalError(const xercesc::SAXParseException& e)
{
XS::ToString s(e.getMessage());
LOG_ERROR("SAXParseException: %s", ((std::string)s).c_str());
//throw e;
}
private: private:
const EntityFileHandler* m_Handler; const EntityFileHandler* m_Handler;
@@ -95,14 +168,73 @@ private:
std::string m_CurrentField; std::string m_CurrentField;
std::map<std::string, std::string> m_CurrentAttributes; std::map<std::string, std::string> m_CurrentAttributes;
void onStartEntity(const xercesc::Attributes& attrs); void onStartEntity(const xercesc::Attributes& attrs)
void onEndEntity(); {
void onStartEntityRef(const xercesc::Attributes& attrs); EntityID parent = m_EntityStack.top();
void onStartComponent(const std::string& name);
void onEndComponent(const std::string& name); if (m_Handler->m_OnStartEntityCallback) {
void onStartComponentField(const std::string& field, const xercesc::Attributes& attrs); std::string name;
void onEndComponentField(const std::string& field); auto xName = attrs.getValue(XS::ToXMLCh("name"));
void onFieldData(char* data); if (xName != nullptr) {
name = XS::ToString(xName);
}
m_Handler->m_OnStartEntityCallback(m_NextEntityID, parent, name);
}
m_EntityStack.push(m_NextEntityID);
m_NextEntityID++;
}
void onEndEntity()
{
m_EntityStack.pop();
}
void onStartEntityRef(const xercesc::Attributes& attrs)
{
std::string path = XS::ToString(attrs.getValue(XS::ToXMLCh("file")));
xercesc::SAX2XMLReader* parser = xercesc::XMLReaderFactory::createXMLReader();
parser->setContentHandler(this);
parser->setErrorHandler(this);
parser->parse(path.c_str());
delete parser;
}
void onStartComponent(const std::string& name)
{
//LOG_DEBUG(" Component: %s", name.c_str());
m_CurrentComponent = name;
if (m_Handler->m_OnStartComponentCallback) {
m_Handler->m_OnStartComponentCallback(m_EntityStack.top(), name);
}
}
void onEndComponent(const std::string& name) { }
void onStartComponentField(const std::string& field, const xercesc::Attributes& attrs)
{
//LOG_DEBUG(" Field: %s", field.c_str());
m_CurrentField = field;
m_CurrentAttributes.clear();
for (int i = 0; i < attrs.getLength(); i++) {
auto name = attrs.getQName(i);
auto value = attrs.getValue(name);
//LOG_DEBUG(" %s = %s", (char*)XS::ToString(name), (char*)XS::ToString(value));
m_CurrentAttributes[XS::ToString(name).operator std::string()] = XS::ToString(value).operator std::string();
}
if (m_Handler->m_OnStartFieldCallback) {
m_Handler->m_OnStartFieldCallback(m_EntityStack.top(), m_CurrentComponent, field, m_CurrentAttributes);
}
}
void onEndComponentField(const std::string& field) { }
void onFieldData(char* data)
{
//LOG_DEBUG(" Data: %s", data);
if (m_Handler->m_OnStartFieldDataCallback) {
m_Handler->m_OnStartFieldDataCallback(m_EntityStack.top(), m_CurrentComponent, m_CurrentField, data);
}
xercesc::XMLString::release(&data);
}
}; };
class EntityFileXMLErrorHandler : public xercesc::ErrorHandler class EntityFileXMLErrorHandler : public xercesc::ErrorHandler
@@ -137,13 +269,12 @@ private:
class EntityFile : public Resource class EntityFile : public Resource
{ {
friend class ResourceManager; friend class ResourceManager;
friend class EntityFileSAXHandler;
private: private:
EntityFile(boost::filesystem::path path); EntityFile(boost::filesystem::path path);
~EntityFile(); ~EntityFile();
public: public:
static unsigned int GetTypeStride(std::string typeName); static std::size_t GetTypeStride(std::string typeName);
static void WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map<std::string, std::string>& attributes); static void WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map<std::string, std::string>& attributes);
static void WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData); static void WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData);
@@ -157,8 +288,6 @@ private:
xercesc::SAX2XMLReader* m_SAX2XMLReader; xercesc::SAX2XMLReader* m_SAX2XMLReader;
//std::map<std::string, ::ComponentInfo> m_ComponentInfo; //std::map<std::string, ::ComponentInfo> m_ComponentInfo;
//std::vector<std::string> m_EntityReferences; //std::vector<std::string> m_EntityReferences;
static void setReaderFeatures(xercesc::SAX2XMLReader* reader);
}; };
#endif #endif
+1 -2
View File
@@ -9,13 +9,12 @@ class EntityFileParser
public: public:
EntityFileParser(const EntityFile* entityFile); EntityFileParser(const EntityFile* entityFile);
EntityID MergeEntities(World* world, EntityID baseParent = EntityID_Invalid); void MergeEntities(World* world);
private: private:
const EntityFile* m_EntityFile; const EntityFile* m_EntityFile;
EntityFileHandler m_Handler; EntityFileHandler m_Handler;
World* m_World = nullptr; World* m_World = nullptr;
EntityID m_FirstEntity = EntityID_Invalid;
// Maps EntityIDs local to the file to real IDs in the world after they've been // Maps EntityIDs local to the file to real IDs in the world after they've been
// created in order to resolve parent-child relationships. // created in order to resolve parent-child relationships.
std::map<EntityID, EntityID> m_EntityIDMapper; std::map<EntityID, EntityID> m_EntityIDMapper;
@@ -5,7 +5,6 @@
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp> #include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp> #include <xercesc/framework/psvi/XSParticle.hpp>
#include <xercesc/framework/psvi/XSModelGroup.hpp> #include <xercesc/framework/psvi/XSModelGroup.hpp>
#include <xercesc/framework/psvi/XSModelGroupDefinition.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp> #include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/psvi/XSValue.hpp> #include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp> #include <xercesc/framework/MemBufFormatTarget.hpp>
@@ -32,7 +31,6 @@ private:
void onStartComponent(EntityID entity, std::string type); void onStartComponent(EntityID entity, std::string type);
void parseComponentInfo(); void parseComponentInfo();
void parseDefaults(); void parseDefaults();
std::string parseAnnotationXML(const XMLCh* xml);
}; };
#endif #endif
-58
View File
@@ -1,58 +0,0 @@
#ifndef EntityWrapper_h__
#define EntityWrapper_h__
#include <boost/optional.hpp>
#include <boost/functional/hash.hpp>
#include "ComponentWrapper.h"
class World;
struct EntityWrapper
{
EntityWrapper()
: World(nullptr)
, ID(EntityID_Invalid)
{ }
EntityWrapper(::World* world, EntityID id)
: World(world)
, ID(id)
{ }
::World* World;
EntityID ID;
static const EntityWrapper Invalid;
const std::string Name();
bool HasComponent(const std::string& componentType);
void AttachComponent(const char* componentName);
EntityWrapper Parent();
EntityWrapper FirstChildByName(const std::string& name);
EntityWrapper FirstParentWithComponent(const std::string& componentType);
bool IsChildOf(EntityWrapper potentialParent);
bool Valid();
ComponentWrapper operator[](const char* componentName);
bool operator==(const EntityWrapper& e) const;
bool operator!=(const EntityWrapper& e) const;
explicit operator EntityID() const;
private:
EntityWrapper firstChildByNameRecursive(const std::string& name, EntityID parent);
};
namespace std
{
template<> struct hash<EntityWrapper>
{
std::size_t operator()(const EntityWrapper& e) const
{
std::size_t seed = 0;
boost::hash_combine(seed, e.World);
boost::hash_combine(seed, e.ID);
return seed;
}
};
}
#endif
+2 -2
View File
@@ -43,7 +43,7 @@ template <typename ContextType, typename EventType>
class EventRelay : public BaseEventRelay class EventRelay : public BaseEventRelay
{ {
public: public:
typedef std::function<bool(EventType&)> CallbackType; typedef std::function<bool(const EventType&)> CallbackType;
EventRelay() EventRelay()
: m_Callback(nullptr) : m_Callback(nullptr)
@@ -65,7 +65,7 @@ template <typename ContextType, typename EventType>
bool EventRelay<ContextType, EventType>::Receive(const std::shared_ptr<Event> event) bool EventRelay<ContextType, EventType>::Receive(const std::shared_ptr<Event> event)
{ {
if (m_Callback != nullptr) { if (m_Callback != nullptr) {
return m_Callback(*static_cast<EventType*>(event.get())); return m_Callback(*static_cast<const EventType*>(event.get()));
} else { } else {
return false; return false;
} }
-77
View File
@@ -1,77 +0,0 @@
#ifndef Frustum_h__
#define Frustum_h__
#include "../GLM.h"
#include "AABB.h"
#include <bitset>
//A frustum defined by 6 planes.
struct Frustum
{
//Contains points P in: dot(normal, P) + d = 0
struct Plane
{
glm::vec3 Normal;
float Distance;
};
enum class Output
{
Inside,
Outside,
Intersects
};
Plane Planes[6];
Frustum() = default;
Frustum(glm::mat4x4 viewProjMatrix)
{
//Order: Right, left, top, bottom, far, near.
int sign = 1;
for (int i = 0; i < 6; ++i) {
sign = -sign;
int index = i / 2;
Plane& plane = Planes[i];
plane.Normal.x = viewProjMatrix[0].w + sign * viewProjMatrix[0][index];
plane.Normal.y = viewProjMatrix[1].w + sign * viewProjMatrix[1][index];
plane.Normal.z = viewProjMatrix[2].w + sign * viewProjMatrix[2][index];
plane.Distance = viewProjMatrix[3].w + sign * viewProjMatrix[3][index];
float divByNormalLength = 1.0f / glm::length(plane.Normal);
plane.Normal *= divByNormalLength;
plane.Distance *= divByNormalLength;
}
}
Output VsAABB(const AABB& box) const
{
const glm::vec3& maxCorner = box.MaxCorner();
const glm::vec3& minCorner = box.MinCorner();
bool completelyInside = true;
for (const Plane& p : Planes) {
bool anyWasInside = false;
bool anyWasOutside = false;
//If points are on both sides of the plane, we can stop.
for (int i = 0; i < 8 && (!anyWasInside || !anyWasOutside); ++i) {
std::bitset<3> bits(i);
glm::vec3 corner;
corner.x = bits.test(0) ? maxCorner.x : minCorner.x;
corner.y = bits.test(1) ? maxCorner.y : minCorner.y;
corner.z = bits.test(2) ? maxCorner.z : minCorner.z;
if (glm::dot(p.Normal, corner) > -p.Distance) {
anyWasInside = true;
} else {
anyWasOutside = true;
}
}
if (!anyWasInside) {
return Output::Outside;
}
if (anyWasOutside) {
completelyInside = false;
}
}
return completelyInside ? Output::Inside : Output::Intersects;
}
};
#endif
+4 -14
View File
@@ -5,14 +5,6 @@
template <typename T> template <typename T>
class MemoryPoolForwardIterator; class MemoryPoolForwardIterator;
namespace DisableMemoryPool
{
//if true -> Pool allocation is not used when calling Allocate/Free, just use regular dynamic allocation.
//if false -> Use pool allocation.
//Should default to false, unless the DisableMemoryPool is true in the Config.ini files.
extern bool Value;
}
//This is the class to use if you want to allocate blocks (slots) of raw memory, with a fixed maximum size (stride). //This is the class to use if you want to allocate blocks (slots) of raw memory, with a fixed maximum size (stride).
//Additionally, if you know that every memory-block will contain one object of a specific type, (i.e. the stride for the slot //Additionally, if you know that every memory-block will contain one object of a specific type, (i.e. the stride for the slot
//will the size of the object type) you should use ObjectPool<T> instead, your life will become easier. //will the size of the object type) you should use ObjectPool<T> instead, your life will become easier.
@@ -88,8 +80,8 @@ public:
//If element cannot be allocated in the pool, because the memory ran out, memory is allocated dynamically with malloc() "outside the pool". //If element cannot be allocated in the pool, because the memory ran out, memory is allocated dynamically with malloc() "outside the pool".
char* Allocate() char* Allocate()
{ {
for (; m_CurrentAllocSlot < m_NumSlots && m_SlotIsAllocated[m_CurrentAllocSlot] && !DisableMemoryPool::Value; ++m_CurrentAllocSlot); for (; m_CurrentAllocSlot < m_NumSlots && m_SlotIsAllocated[m_CurrentAllocSlot]; ++m_CurrentAllocSlot);
if (m_CurrentAllocSlot < m_NumSlots && !DisableMemoryPool::Value) { if (m_CurrentAllocSlot < m_NumSlots) {
if (m_LowestAllocatedSlot > m_CurrentAllocSlot) if (m_LowestAllocatedSlot > m_CurrentAllocSlot)
m_LowestAllocatedSlot = m_CurrentAllocSlot; m_LowestAllocatedSlot = m_CurrentAllocSlot;
//Mark the slot as allocated. //Mark the slot as allocated.
@@ -101,9 +93,7 @@ public:
else { else {
m_ExtraMemory.push_back((char*)malloc(m_Stride)); m_ExtraMemory.push_back((char*)malloc(m_Stride));
//We should preferably not enter here to avoid performance issues. Set more numMaxElements in constructor instead. //We should preferably not enter here to avoid performance issues. Set more numMaxElements in constructor instead.
if (!DisableMemoryPool::Value) { LOG_WARNING("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size());
LOG_DEBUG("Allocated slots exceed Pool size, extra memory allocated dynamically. Pool size: %u, dynamic size: %u.", m_NumSlots, m_ExtraMemory.size());
}
return m_ExtraMemory.back(); return m_ExtraMemory.back();
} }
} }
@@ -118,7 +108,7 @@ public:
//(i.e. IsAllocatedInPool may give false positives) //(i.e. IsAllocatedInPool may give false positives)
//if it was malloc():ed //if it was malloc():ed
//so, we may enter here even if we shouldn't. //so, we may enter here even if we shouldn't.
if (!DisableMemoryPool::Value && IsAllocatedInPool(obj)) { if (IsAllocatedInPool(obj)) {
--m_NumAllocatedSlots; --m_NumAllocatedSlots;
const size_t freeSlot = (obj - m_StartAddress) / m_Stride; const size_t freeSlot = (obj - m_StartAddress) / m_Stride;
m_SlotIsAllocated[freeSlot] = false; m_SlotIsAllocated[freeSlot] = false;
+104
View File
@@ -0,0 +1,104 @@
#ifndef OctTree_h__
#define OctTree_h__
#include "Core/AABB.h"
class Ray;
class OctTree
{
public:
struct Output
{
float CollideDistance;
};
OctTree();
~OctTree();
//For the root OctTree, [octTreeBounds] should be a box containing the entire level.
OctTree(const AABB& octTreeBounds, int subDivisions);
//We cannot copy the OctTree as of now, because of the recursive dynamic allocation.
//Define these if the OctTree suddenly needs to be copied, think of the children OctChild* ptrs.
OctTree(const OctTree& other) = delete;
OctTree(const OctTree&& other) = delete;
OctTree& operator= (const OctTree& other) = delete;
//Add a dynamic object (one that moves around) into the tree.
void AddDynamicObject(const AABB& box);
//Add a static object (that does not move) into the tree.
void AddStaticObject(const AABB& box);
//Get the boxes that are in the same area as the input [box], the boxes are put in [outBoxes].
void BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes);
//Empty the tree of all objects, static and dynamic.
void ClearObjects();
//Empty the tree of all dynamic objects. Static objects remain in the tree.
void ClearDynamicObjects();
//Returns true if the ray collides with something in the tree. Result is written to [data].
bool RayCollides(const Ray& ray, Output& data);
//Returns true if the box collides with something in the tree.
//On collision with a box, that box is written to [outBoxIntersected].
//Note: More efficient than calling BoxesInSameRegion from outside and testing there.
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected);
private:
struct OctChild; //Fwd declaration;
struct ContainedObject
{
ContainedObject()
: Box(AABB())
, Checked(false)
{}
ContainedObject(AABB box)
: Box(box)
, Checked(false)
{}
AABB Box;
bool Checked;
};
OctChild* m_Root;
std::vector<ContainedObject> m_StaticObjects;
std::vector<ContainedObject> m_DynamicObjects;
bool m_UpdatedOnce;
unsigned int m_BoxID;
glm::vec3 m_PrevPos;
glm::quat m_PrevOri;
void falsifyObjectChecks();
struct OctChild
{
~OctChild();
OctChild(const AABB& octTreeBounds,
int subDivisions,
std::vector<OctTree::ContainedObject>& staticObjects,
std::vector<OctTree::ContainedObject>& dynamicObjects);
OctChild(const OctChild& other) = delete;
OctChild(const OctChild&& other) = delete;
OctChild& operator= (const OctChild& other) = delete;
void AddDynamicObject(const AABB& box);
void AddStaticObject(const AABB& box);
void BoxesInSameRegion(const AABB& box, std::vector<AABB>& outBoxes) const;
void ClearObjects();
void ClearDynamicObjects();
bool RayCollides(const Ray& ray, Output& data) const;
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const;
OctChild* m_Children[8];
//Indices into the lists in OctTree.
std::vector<int> m_StaticObjIndices;
std::vector<int> m_DynamicObjIndices;
AABB m_Box;
//Reference to the lists in OctTree.
std::vector<OctTree::ContainedObject>& m_StaticObjectsRef;
std::vector<OctTree::ContainedObject>& m_DynamicObjectsRef;
inline bool hasChildren() const;
int childIndexContainingPoint(const glm::vec3& point) const;
std::vector<int> childIndicesContainingBox(const AABB& box) const;
};
};
#endif
-287
View File
@@ -1,287 +0,0 @@
#ifndef Octree_h__
#define Octree_h__
#include <type_traits>
#include "../Common.h"
#include "AABB.h"
#include "Frustum.h"
//Fwd declarations.
class Ray;
namespace OctSpace
{
struct Output;
struct ContainedObject;
struct Child;
}
//T needs to be AABB, or inherit from AABB.
//T also needs to have a default constructor.
template<typename T>
class Octree
{
public:
Octree() = delete;
~Octree();
//For the root Octree, [octreeBounds] should be a box containing the entire level.
Octree(const AABB& octreeBounds, int subDivisions);
//We cannot copy the Octree as of now, because of the recursive dynamic allocation.
//Define these if the Octree suddenly needs to be copied, think of the children Child* ptrs.
Octree(const Octree& other) = delete;
Octree(const Octree&& other) = delete;
Octree& operator= (const Octree& other) = delete;
//Add a dynamic object (one that moves around) into the tree.
void AddDynamicObject(const T& object);
//Add a static object (that does not move) into the tree.
void AddStaticObject(const T& object);
//Get the objects that are in the same area as the input [box], the objects are put in [outObjects].
//The type Box must be AABB, or inherit from AABB.
template<typename Box>
void ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects);
//Get the objects that are inside the frustum, the objects are put in outObjects.
void ObjectsInFrustum(const Frustum& frustum, std::vector<T>& outObjects);
//Empty the tree of all objects, static and dynamic.
void ClearObjects();
//Empty the tree of all dynamic objects. Static objects remain in the tree.
void ClearDynamicObjects();
//Returns true if the ray collides with something in the tree. Result is written to [data].
bool RayCollides(const Ray& ray, OctSpace::Output& data);
//Returns true if the box collides with something in the tree.
//On collision with a box, that box is written to [outBoxIntersected].
//Note: More efficient than calling ObjectsInSameRegion from outside and testing there.
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected);
private:
OctSpace::Child* m_Root;
std::vector<OctSpace::ContainedObject> m_StaticObjects;
std::vector<OctSpace::ContainedObject> m_DynamicObjects;
void falsifyObjectChecks();
};
namespace OctSpace
{
struct Output
{
float CollideDistance;
};
struct ContainedObject
{
ContainedObject()
: Box(nullptr)
, Checked(false)
{}
template<typename BoxlikeObject>
ContainedObject(const BoxlikeObject& box)
: Box(new BoxlikeObject(box))
, Checked(false)
{}
std::unique_ptr<AABB> Box;
bool Checked;
};
struct Child
{
~Child();
Child(const AABB& octTreeBounds,
int subDivisions,
std::vector<ContainedObject>& staticObjects,
std::vector<ContainedObject>& dynamicObjects);
Child(const Child& other) = delete;
Child(const Child&& other) = delete;
Child& operator= (const Child& other) = delete;
void AddDynamicObject(const AABB& box);
void AddStaticObject(const AABB& box);
template<typename T, typename Box>
void ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects) const;
template<typename T>
void ObjectsInFrustum(const Frustum& frustum, std::vector<T>& outObjects, bool takeAllDontTest) const;
void ClearObjects();
void ClearDynamicObjects();
bool RayCollides(const Ray& ray, Output& data) const;
bool BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected) const;
Child* m_Children[8];
//Indices into the lists in Octree.
std::vector<int> m_StaticObjIndices;
std::vector<int> m_DynamicObjIndices;
AABB m_Box;
//Reference to the lists in Octree.
std::vector<ContainedObject>& m_StaticObjectsRef;
std::vector<ContainedObject>& m_DynamicObjectsRef;
inline bool hasChildren() const { return m_Children[0] != nullptr; }
int childIndexContainingPoint(const glm::vec3& point) const;
std::vector<int> childIndicesContainingBox(const AABB& box) const;
};
}
template<typename T>
Octree<T>::Octree(const AABB& octTreeBounds, int subDivisions)
: m_Root(new OctSpace::Child(octTreeBounds, subDivisions, m_StaticObjects, m_DynamicObjects))
{
static_assert(std::is_base_of<AABB, T>::value, "template argument type T in Octree must be a subclass of AABB.");
}
template<typename T>
Octree<T>::~Octree()
{
delete m_Root;
}
template<typename T>
void Octree<T>::AddDynamicObject(const T& object)
{
m_Root->AddDynamicObject(object);
m_DynamicObjects.emplace_back(object);
}
template<typename T>
void Octree<T>::AddStaticObject(const T& object)
{
m_Root->AddStaticObject(object);
m_StaticObjects.emplace_back(object);
}
template<typename T>
template<typename Box>
void Octree<T>::ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects)
{
static_assert(std::is_base_of<AABB, Box>::value, "template argument type Box in Octree<T>::ObjectsInSameRegion must be a subclass of AABB.");
falsifyObjectChecks();
m_Root->ObjectsInSameRegion(box, outObjects);
}
template<typename T>
void Octree<T>::ObjectsInFrustum(const Frustum& frustum, std::vector<T>& outObjects)
{
falsifyObjectChecks();
m_Root->ObjectsInFrustum(frustum, outObjects, false);
}
template<typename T>
void Octree<T>::ClearObjects()
{
m_StaticObjects.clear();
m_DynamicObjects.clear();
m_Root->ClearObjects();
}
template<typename T>
void Octree<T>::ClearDynamicObjects()
{
m_DynamicObjects.clear();
m_Root->ClearDynamicObjects();
}
template<typename T>
bool Octree<T>::RayCollides(const Ray& ray, OctSpace::Output& data)
{
falsifyObjectChecks();
data.CollideDistance = -1;
return m_Root->RayCollides(ray, data);
}
template<typename T>
bool Octree<T>::BoxCollides(const AABB& boxToTest, AABB& outBoxIntersected)
{
falsifyObjectChecks();
return m_Root->BoxCollides(boxToTest, outBoxIntersected);
}
template<typename T>
void Octree<T>::falsifyObjectChecks()
{
for (auto& obj : m_StaticObjects) {
obj.Checked = false;
}
for (auto& obj : m_DynamicObjects) {
obj.Checked = false;
}
}
template<typename T, typename Box>
void OctSpace::Child::ObjectsInSameRegion(const Box& box, std::vector<T>& outObjects) const
{
if (hasChildren()) {
for (auto i : childIndicesContainingBox(box)) {
m_Children[i]->ObjectsInSameRegion(box, outObjects);
}
} else {
size_t startIndex = outObjects.size();
int numDuplicates = 0;
outObjects.resize(outObjects.size() + m_StaticObjIndices.size() + m_DynamicObjIndices.size());
for (size_t i = 0; i < m_StaticObjIndices.size(); ++i) {
ContainedObject& obj = m_StaticObjectsRef[m_StaticObjIndices[i]];
if (obj.Checked) {
++numDuplicates;
} else {
obj.Checked = true;
outObjects[startIndex + i - numDuplicates] = *static_cast<T*>(obj.Box.get());
}
}
for (size_t i = 0; i < m_DynamicObjIndices.size(); ++i) {
ContainedObject& obj = m_DynamicObjectsRef[m_DynamicObjIndices[i]];
if (obj.Checked) {
++numDuplicates;
} else {
obj.Checked = true;
outObjects[startIndex + i - numDuplicates] = *static_cast<T*>(obj.Box.get());
}
}
for (size_t i = 0; i < numDuplicates; ++i) {
outObjects.pop_back();
}
}
}
template<typename T>
void OctSpace::Child::ObjectsInFrustum(const Frustum& frustum, std::vector<T>& outObjects, bool takeAllDontTest) const
{
if (hasChildren()) {
for (const Child* c : m_Children) {
Frustum::Output out = Frustum::Output::Inside;
if (!takeAllDontTest) {
out = frustum.VsAABB(c->m_Box);
if (out == Frustum::Output::Outside) {
continue;
}
}
c->ObjectsInFrustum(frustum, outObjects, out == Frustum::Output::Inside);
}
} else {
size_t startIndex = outObjects.size();
int numDuplicates = 0;
outObjects.resize(outObjects.size() + m_StaticObjIndices.size() + m_DynamicObjIndices.size());
for (size_t i = 0; i < m_StaticObjIndices.size(); ++i) {
ContainedObject& obj = m_StaticObjectsRef[m_StaticObjIndices[i]];
if (obj.Checked || frustum.VsAABB(*obj.Box) == Frustum::Output::Outside) {
++numDuplicates;
} else {
obj.Checked = true;
outObjects[startIndex + i - numDuplicates] = *static_cast<T*>(obj.Box.get());
}
}
for (size_t i = 0; i < m_DynamicObjIndices.size(); ++i) {
ContainedObject& obj = m_DynamicObjectsRef[m_DynamicObjIndices[i]];
if (obj.Checked || frustum.VsAABB(*obj.Box) == Frustum::Output::Outside) {
++numDuplicates;
} else {
obj.Checked = true;
outObjects[startIndex + i - numDuplicates] = *static_cast<T*>(obj.Box.get());
}
}
for (size_t i = 0; i < numDuplicates; ++i) {
outObjects.pop_back();
}
}
}
#endif
+1 -5
View File
@@ -2,15 +2,11 @@
#define Ray_h__ #define Ray_h__
#include "../GLM.h" #include "../GLM.h"
#include "../Common.h" #include "Common.h"
class Ray class Ray
{ {
public: public:
Ray()
: m_Origin(glm::vec3(0.f))
, m_Direction(glm::vec3(0, 0, 1))
{}
Ray(const glm::vec3& origin, const glm::vec3& dir) Ray(const glm::vec3& origin, const glm::vec3& dir)
: m_Origin(origin) : m_Origin(origin)
, m_Direction(glm::normalize(dir)) , m_Direction(glm::normalize(dir))
+39 -135
View File
@@ -12,6 +12,7 @@
/** Base Resource class. /** Base Resource class.
Implement this class for every resource to be handled by the resource manager. Implement this class for every resource to be handled by the resource manager.
Implement Create() to return a new object of that type.
*/ */
class Resource class Resource
{ {
@@ -21,23 +22,6 @@ protected:
Resource() { } Resource() { }
public: public:
//Should be thrown in a Resource's constructor if it cannot complete because another resource is still loading.
//Not actually an error, just a message to the ResourceManager.
struct StillLoadingException : public std::exception
{
virtual const char* what() const throw()
{
return "Resource is still loading.";
}
};
struct FailedLoadingException : public std::exception
{
FailedLoadingException(char const* const _Message)
: std::exception(_Message)
{ }
FailedLoadingException() :std::exception("Resource failed to load.") { };
};
// Pretend that this is a pure virtual function that you have to implement // Pretend that this is a pure virtual function that you have to implement
// FIXME: Why did we do this again instead of just using the constructor? // FIXME: Why did we do this again instead of just using the constructor?
// static Resource* Create(std::string resourceName); // static Resource* Create(std::string resourceName);
@@ -49,15 +33,6 @@ public:
unsigned int ResourceID; unsigned int ResourceID;
}; };
//Any class inheriting from this class will always be loaded on the master thread, not on a parallel worker thread.
//This is important in case some instructions must be executed on the main thread, e.g. OpenGL commands, like glBindBuffer.
//This resource can still be loaded asyncronously, but it will not be loaded in a thread, instead it's constructor will
//be called once on every ResourceManager::Load, just throw StillLoadingException in the constructor if it is not done yet.
class ThreadUnsafeResource : public Resource
{
friend class ResourceManager;
};
/** Singleton resource manager to keep track of and cache any external engine assets */ /** Singleton resource manager to keep track of and cache any external engine assets */
class ResourceManager class ResourceManager
{ {
@@ -65,7 +40,6 @@ private:
ResourceManager(); ResourceManager();
public: public:
static bool UseThreading;
/*static ResourceManager& Instance() /*static ResourceManager& Instance()
{ {
static ResourceManager s; static ResourceManager s;
@@ -75,6 +49,15 @@ public:
template <typename T> template <typename T>
static void RegisterType(std::string typeName); static void RegisterType(std::string typeName);
/** Preloads a resource and caches it for future use
@tparam T Resource type.
@param resourceName Fully qualified name of the resource to preload.
*/
template <typename T>
static void Preload(std::string resourceName);
static void Preload(std::string resourceType, std::string resourceName);
/** Checks if a resource is in cache /** Checks if a resource is in cache
@param resourceType Resource type as string. @param resourceType Resource type as string.
@@ -82,20 +65,15 @@ public:
*/ */
// TODO: Templateify // TODO: Templateify
static bool IsResourceLoaded(std::string resourceType, std::string resourceName); static bool IsResourceLoaded(std::string resourceType, std::string resourceName);
/** Return value should always be a valid pointer, will throw an exception on error.
If the resource has been loaded already, returns a pointer to it.
If Async is false: Hot-loads a resource, caches it for future use, and returns a pointer to it. /** Hot-loads a resource and caches it for future use
If Async is true: If the resource is not loaded yet, starts loading the resource
in the background and throws Resource::StillLoadingException immediately.
@tparam T Resource type. @tparam T Resource type.
@tparam async Set this to true if the resource should be loaded asyncronously.
@param resourceName Fully qualified name of the resource to load. @param resourceName Fully qualified name of the resource to load.
*/ */
template <typename T, bool async = false> template <typename T>
static T* Load(const std::string& resourceName, Resource* parent = nullptr); static T* Load(std::string resourceName, Resource* parent = nullptr);
static Resource* Load(std::string resourceType, std::string resourceName, Resource* parent = nullptr);
/** Reloads an already loaded resource, keeping its resource ID intact. /** Reloads an already loaded resource, keeping its resource ID intact.
@@ -109,31 +87,19 @@ public:
static void Update(); static void Update();
private: private:
//This is a haxy way to make sure that IsMainThread is run when the program starts, so the master thread id is set.
struct MasterThreadChecker
{
MasterThreadChecker()
{
ResourceManager::IsMainThread();
}
};
const static MasterThreadChecker m_Checker;
static std::unordered_map<std::string, std::string> m_CompilerTypenameToResourceType; static std::unordered_map<std::string, std::string> m_CompilerTypenameToResourceType;
static std::unordered_map<std::string, std::function<Resource*(std::string)>> m_FactoryFunctions; // type -> factory function static std::unordered_map<std::string, std::function<Resource*(std::string)>> m_FactoryFunctions; // type -> factory function
static std::unordered_map<std::pair<std::string, std::string>, Resource*> m_ResourceCache; // (type, name) -> resource static std::unordered_map<std::pair<std::string, std::string>, Resource*> m_ResourceCache; // (type, name) -> resource
static std::unordered_map<std::string, Resource*> m_ResourceFromName; // name -> resource static std::unordered_map<std::string, Resource*> m_ResourceFromName; // name -> resource
static std::unordered_map<Resource*, Resource*> m_ResourceParents; // resource -> parent resource static std::unordered_map<Resource*, Resource*> m_ResourceParents; // resource -> parent resource
static std::unordered_map<std::pair<std::string, std::string>, boost::thread> m_LoadingThreads; // (type, name) -> loading thread
static std::unordered_map<std::pair<std::string, std::string>, std::exception_ptr> m_LoadingThreadExceptions; // (type, name) -> exceptions
static boost::recursive_mutex m_Mutex;
// TODO: Getters for IDs // TODO: Getters for IDs
static unsigned int m_CurrentResourceTypeID; static unsigned int m_CurrentResourceTypeID;
static std::unordered_map<std::string, unsigned int> m_ResourceTypeIDs; static std::unordered_map<std::string, unsigned int> m_ResourceTypeIDs;
// Number of resources of a type. Doubles as local ID. // Number of resources of a type. Doubles as local ID.
static std::unordered_map<unsigned int, unsigned int> m_ResourceCount; static std::unordered_map<unsigned int, unsigned int> m_ResourceCount;
// Flag to suppress hot-load warnings when a preloading resource chain loads another resource
static bool m_Preloading;
static FileWatcher m_FileWatcher; static FileWatcher m_FileWatcher;
static void fileWatcherCallback(std::string path, FileWatcher::FileEventFlags flags); static void fileWatcherCallback(std::string path, FileWatcher::FileEventFlags flags);
@@ -142,13 +108,22 @@ private:
static unsigned int GetNewResourceID(unsigned int typeID); static unsigned int GetNewResourceID(unsigned int typeID);
// Internal: Create a resource and cache it // Internal: Create a resource and cache it
static Resource* createResourceThrowing(const std::string& resourceType, const std::string& resourceName, Resource* parent); static Resource* CreateResource(std::string resourceType, std::string resourceName, Resource* parent);
static Resource* createResource(const std::string& resourceType, const std::string& resourceName, Resource* parent, std::exception_ptr& exception);
static Resource* cacheResource(Resource* resource, const std::string& resourceType, const std::string& resourceName, Resource* parent);
static bool IsMainThread();
}; };
template <typename T>
T* ResourceManager::Load(std::string resourceName, Resource* parent /* = nullptr */)
{
auto resourceTypename = typeid(T).name();
auto it = m_CompilerTypenameToResourceType.find(resourceTypename);
if (it == m_CompilerTypenameToResourceType.end()) {
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename);
return nullptr;
}
return static_cast<T*>(Load(it->second, resourceName, parent));
}
template <typename T> template <typename T>
void ResourceManager::RegisterType(std::string typeName) void ResourceManager::RegisterType(std::string typeName)
{ {
@@ -156,88 +131,17 @@ void ResourceManager::RegisterType(std::string typeName)
m_FactoryFunctions[typeName] = [](std::string resourceName) { return new T(resourceName); }; m_FactoryFunctions[typeName] = [](std::string resourceName) { return new T(resourceName); };
} }
template <typename T, bool async> template <typename T>
static T* ResourceManager::Load(const std::string& resourceName, Resource* parent /* = nullptr */) void ResourceManager::Preload(std::string resourceName)
{ {
auto resourceTypename = typeid(T).name(); auto resourceTypename = typeid(T).name();
auto iter = m_CompilerTypenameToResourceType.find(resourceTypename); auto it = m_CompilerTypenameToResourceType.find(resourceTypename);
if (iter == m_CompilerTypenameToResourceType.end()) { if (it == m_CompilerTypenameToResourceType.end()) {
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename); LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": type not registered", resourceName.c_str(), resourceTypename);
throw Resource::FailedLoadingException(); return;
} }
std::string resourceType = iter->second; Preload(it->second, resourceName);
constexpr bool mustNotLoadInThread = std::is_base_of<ThreadUnsafeResource, T>::value;
if (mustNotLoadInThread && !IsMainThread()) {
LOG_ERROR("Failed to Load \"%s\": ThreadUnsafeResource type \"%s\" load in the constructor of another resource that is loaded asyncronously.", resourceName.c_str(), iter->second.c_str());
throw Resource::FailedLoadingException();
}
auto cacheKey = std::make_pair(resourceType, resourceName);
decltype(m_ResourceCache)::iterator it;
//If a thread has already been launched to load this resource.
auto tIt = m_LoadingThreads.find(cacheKey);
if (UseThreading && tIt != m_LoadingThreads.end()) {
if (async) {
//Throw StillLoadingException if the thread is still working.
if (!tIt->second.try_join_for(boost::chrono::nanoseconds(1))) {
throw Resource::StillLoadingException();
}
//Else we know the thread has completed.
} else {
//Wait for the thread to finish loading.
tIt->second.join();
}
//When the thread is done, delete the thread.
m_LoadingThreads.erase(tIt);
//Rethrow the thread exception if it threw any.
auto excIt = m_LoadingThreadExceptions.find(cacheKey);
std::exception_ptr exception = excIt->second;
m_LoadingThreadExceptions.erase(excIt);
if (exception) {
std::rethrow_exception(exception);
}
}
//If resource has already been cached and completely loaded.
{
boost::lock_guard<decltype(m_Mutex)> guard(m_Mutex);
it = m_ResourceCache.find(cacheKey);
if (it != m_ResourceCache.end()) {
if (it->second != nullptr) {
return static_cast<T*>(it->second);
} else {
//Don't return null on failure, exception instead.
throw Resource::FailedLoadingException();
}
}
}
//If resource is not cached..
if (UseThreading && async) {
if (mustNotLoadInThread) {
try {
return static_cast<T*>(createResourceThrowing(resourceType, resourceName, parent));
} catch (const Resource::StillLoadingException&) {
throw;
}
} else {
//Create a thread that loads the resource into cache.
m_LoadingThreads[cacheKey] = boost::thread(createResource, resourceType, resourceName, parent, m_LoadingThreadExceptions[cacheKey]);
throw Resource::StillLoadingException();
}
} else {
//load and return the resource.
while (true) {
try {
return static_cast<T*>(createResourceThrowing(resourceType, resourceName, parent));
} catch (const Resource::StillLoadingException&) {
continue;
} catch (const std::exception&) {
throw;
}
}
}
} }
#endif #endif
+12 -13
View File
@@ -3,7 +3,6 @@
#include "EventBroker.h" #include "EventBroker.h"
#include "World.h" #include "World.h"
#include "EntityWrapper.h"
#include "ComponentWrapper.h" #include "ComponentWrapper.h"
class System class System
@@ -11,41 +10,41 @@ class System
friend class SystemPipeline; friend class SystemPipeline;
protected: protected:
System(World* world, EventBroker) { } System(EventBroker* eventBroker)
System(World* world, EventBroker* eventBroker) : m_EventBroker(eventBroker)
: m_World(world)
, m_EventBroker(eventBroker)
{ } { }
virtual ~System() = default; virtual ~System() = default;
World* m_World;
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
}; };
class PureSystem : public virtual System class PureSystem : public System
{ {
friend class SystemPipeline; friend class SystemPipeline;
protected: protected:
PureSystem(std::string componentType) PureSystem(EventBroker* eventBroker, std::string componentType)
: m_ComponentType(componentType) : System(eventBroker)
, m_ComponentType(componentType)
{ } { }
virtual ~PureSystem() = default; virtual ~PureSystem() = default;
const std::string m_ComponentType; const std::string m_ComponentType;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) = 0; virtual void UpdateComponent(World* world, ComponentWrapper& component, double dt) = 0;
}; };
class ImpureSystem : public virtual System class ImpureSystem : public System
{ {
friend class SystemPipeline; friend class SystemPipeline;
protected: protected:
ImpureSystem() = default; ImpureSystem(EventBroker* eventBroker)
: System(eventBroker)
{ }
virtual ~ImpureSystem() = default; virtual ~ImpureSystem() = default;
virtual void Update(double dt) = 0; virtual void Update(World* world, double dt) = 0;
}; };
#endif #endif
+14 -42
View File
@@ -5,19 +5,13 @@
#include "EventBroker.h" #include "EventBroker.h"
#include "System.h" #include "System.h"
#include "World.h" #include "World.h"
#include "EPause.h"
class SystemPipeline class SystemPipeline
{ {
public: public:
SystemPipeline(World* world, EventBroker* eventBroker) SystemPipeline(EventBroker* eventBroker)
: m_World(world) : m_EventBroker(eventBroker)
, m_EventBroker(eventBroker) { }
{
EVENT_SUBSCRIBE_MEMBER(m_EPause, &SystemPipeline::OnPause);
EVENT_SUBSCRIBE_MEMBER(m_EResume, &SystemPipeline::OnResume);
}
~SystemPipeline() ~SystemPipeline()
{ {
for (UnorderedSystems& group : m_OrderedSystemGroups) { for (UnorderedSystems& group : m_OrderedSystemGroups) {
@@ -35,11 +29,11 @@ public:
m_OrderedSystemGroups.resize(updateOrderLevel + 1); m_OrderedSystemGroups.resize(updateOrderLevel + 1);
} }
UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel]; UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel];
System* system = new T(m_World, m_EventBroker, args...); System* system = new T(m_EventBroker, args...);
group.Systems[typeid(T).name()] = system; group.Systems[typeid(T).name()] = system;
PureSystem* pureSystem = dynamic_cast<PureSystem*>(system); if (std::is_base_of<PureSystem, T>::value) {
if (pureSystem != nullptr) { PureSystem* pureSystem = static_cast<PureSystem*>(system);
if (!pureSystem->m_ComponentType.empty()) { if (!pureSystem->m_ComponentType.empty()) {
group.PureSystems[pureSystem->m_ComponentType].push_back(pureSystem); group.PureSystems[pureSystem->m_ComponentType].push_back(pureSystem);
} else { } else {
@@ -47,18 +41,14 @@ public:
} }
} }
ImpureSystem* impureSystem = dynamic_cast<ImpureSystem*>(system); if (std::is_base_of<ImpureSystem, T>::value) {
if (impureSystem != nullptr) { ImpureSystem* impureSystem = static_cast<ImpureSystem*>(system);
group.ImpureSystems.push_back(impureSystem); group.ImpureSystems.push_back(impureSystem);
} }
} }
void Update(double dt) void Update(World* world, double dt)
{ {
if (m_Paused) {
dt = 0.0;
}
for (UnorderedSystems& group : m_OrderedSystemGroups) { for (UnorderedSystems& group : m_OrderedSystemGroups) {
// Process events // Process events
for (auto& pair : group.Systems) { for (auto& pair : group.Systems) {
@@ -66,30 +56,27 @@ public:
} }
// Update // Update
for (auto& system : group.ImpureSystems) {
system->Update(dt);
}
for (auto& pair : group.PureSystems) { for (auto& pair : group.PureSystems) {
const std::string& componentName = pair.first; const std::string& componentName = pair.first;
auto& systems = pair.second; auto& systems = pair.second;
const ComponentPool* pool = m_World->GetComponents(componentName); const ComponentPool* pool = world->GetComponents(componentName);
if (pool == nullptr) { if (pool == nullptr) {
continue; continue;
} }
for (auto& component : *pool) { for (auto& component : *pool) {
for (auto& system : systems) { for (auto& system : systems) {
system->UpdateComponent(EntityWrapper(m_World, component.EntityID), component, dt); system->UpdateComponent(world, component, dt);
} }
} }
} }
for (auto& system : group.ImpureSystems) {
system->Update(world, dt);
}
} }
} }
private: private:
World* m_World;
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
bool m_Paused = false;
struct UnorderedSystems struct UnorderedSystems
{ {
std::map<std::string, System*> Systems; std::map<std::string, System*> Systems;
@@ -97,21 +84,6 @@ private:
std::vector<ImpureSystem*> ImpureSystems; std::vector<ImpureSystem*> ImpureSystems;
}; };
std::vector<UnorderedSystems> m_OrderedSystemGroups; std::vector<UnorderedSystems> m_OrderedSystemGroups;
EventRelay<SystemPipeline, Events::Pause> m_EPause;
bool OnPause(const Events::Pause& e) {
if (e.World == m_World) {
m_Paused = true;
}
return true;
}
EventRelay<SystemPipeline, Events::Resume> m_EResume;
bool OnResume(const Events::Resume& e) {
if (e.World == m_World) {
m_Paused = false;
}
return true;
}
}; };
#endif #endif
-25
View File
@@ -1,25 +0,0 @@
#ifndef Transform_h__
#define Transform_h__
#include "../GLM.h"
#include "World.h"
#include "EntityWrapper.h"
namespace Transform
{
glm::mat4 AbsoluteTransformation(EntityWrapper entity);
glm::vec3 AbsolutePosition(EntityWrapper entity);
glm::vec3 AbsolutePosition(World* world, EntityID entity);
glm::vec3 AbsoluteOrientationEuler(EntityWrapper entity);
glm::quat AbsoluteOrientation(EntityWrapper entity);
glm::quat AbsoluteOrientation(World* world, EntityID entity);
glm::vec3 AbsoluteScale(EntityWrapper entity);
glm::vec3 AbsoluteScale(World* world, EntityID entity);
glm::mat4 ModelMatrix(EntityWrapper entity);
glm::mat4 ModelMatrix(EntityID entity, World* world);
glm::vec3 TransformPoint(const glm::vec3& point, const glm::mat4& matrix);
}
#endif
-22
View File
@@ -1,22 +0,0 @@
#ifndef UniformScaleSystem_h__
#define UniformScaleSystem_h__
#include "../GLM.h"
#include "System.h"
#include "../Rendering/ESetCamera.h"
class UniformScaleSystem : public PureSystem
{
public:
UniformScaleSystem(World* world, EventBroker* eventBroker);
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) override;
private:
EntityWrapper m_Camera = EntityWrapper::Invalid;
EventRelay<UniformScaleSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(const Events::SetCamera& e);
};
#endif
+2 -2
View File
@@ -42,7 +42,7 @@ enum class FileWatcher::FileEventFlags
}; };
inline FileWatcher::FileEventFlags operator|(FileWatcher::FileEventFlags a, FileWatcher::FileEventFlags b) { return static_cast<FileWatcher::FileEventFlags>(static_cast<int>(a) | static_cast<int>(b)); } inline FileWatcher::FileEventFlags operator|(FileWatcher::FileEventFlags a, FileWatcher::FileEventFlags b) { return static_cast<FileWatcher::FileEventFlags>(static_cast<int>(a) | static_cast<int>(b)); }
inline bool operator&(FileWatcher::FileEventFlags a, FileWatcher::FileEventFlags b) { return (static_cast<int>(a) & static_cast<int>(b)) != 0; } inline bool operator&(FileWatcher::FileEventFlags a, FileWatcher::FileEventFlags b) { return static_cast<int>(a)& static_cast<int>(b); }
class FileWatcher::Worker class FileWatcher::Worker
{ {
@@ -54,7 +54,7 @@ public:
private: private:
struct FileInfo struct FileInfo
{ {
std::size_t Size; int Size;
std::time_t Timestamp; std::time_t Timestamp;
}; };
+1 -1
View File
@@ -4,7 +4,7 @@
// } // }
// NOTE: condition statement is not executed at all in release mode. // NOTE: condition statement is not executed at all in release mode.
#ifndef DEBUG_IF #ifndef DEBUG_IF
#ifdef DEBUG #ifndef DEBUG
#define DEBUG_IF(c) if(c) #define DEBUG_IF(c) if(c)
#else #else
#define DEBUG_IF(c) if(false) #define DEBUG_IF(c) if(false)
+57 -6
View File
@@ -29,9 +29,41 @@ enum _LOG_LEVEL
extern _LOG_LEVEL LOG_LEVEL; extern _LOG_LEVEL LOG_LEVEL;
extern const char* _LOG_LEVEL_PREFIX[]; const static char* _LOG_LEVEL_PREFIX[] =
{
"EE: ",
"",
"WW: ",
"DD: "
};
extern void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int line, const char* format, ...); static void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsigned int line, const char* format, ...)
{
if (logLevel > LOG_LEVEL) {
return;
}
char* message = nullptr;
va_list args;
va_start(args, format);
size_t size = vsnprintf(message, 0, format, args) + 1;
va_end(args);
va_start(args, format);
message = new char[size];
vsnprintf(message, size, format, args);
va_end(args);
if (logLevel == LOG_LEVEL_ERROR) {
std::cerr << file << ":" << line << " " << func << std::endl;
std::cerr << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
} else {
std::cout << _LOG_LEVEL_PREFIX[logLevel] << message << std::endl;
}
delete[] message;
}
#define LOG(logLevel, format, ...) \ #define LOG(logLevel, format, ...) \
_LOG(logLevel, __BASE_FILE__, __func__, __LINE__, format, ##__VA_ARGS__) _LOG(logLevel, __BASE_FILE__, __func__, __LINE__, format, ##__VA_ARGS__)
@@ -45,11 +77,30 @@ extern void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsign
#define LOG_INFO(format, ...) \ #define LOG_INFO(format, ...) \
LOG(LOG_LEVEL_INFO, format, ##__VA_ARGS__) LOG(LOG_LEVEL_INFO, format, ##__VA_ARGS__)
#ifdef DEBUG
#define LOG_DEBUG(format, ...) \ #define LOG_DEBUG(format, ...) \
LOG(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__) LOG(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
#else
#define LOG_DEBUG(format, ...) // Set the log level temporarily for the current scope
#endif #define LOG_LEVEL_SCOPE(logLevel) \
_LOG_LEVEL_SCOPED_HELPER<logLevel> _logLevelScopedHelper;
template <_LOG_LEVEL LEVEL>
class _LOG_LEVEL_SCOPED_HELPER
{
public:
_LOG_LEVEL_SCOPED_HELPER()
{
m_OriginalLogLevel = LOG_LEVEL;
LOG_LEVEL = LEVEL;
}
~_LOG_LEVEL_SCOPED_HELPER()
{
LOG_LEVEL = m_OriginalLogLevel;
}
private:
_LOG_LEVEL m_OriginalLogLevel;
};
#endif // Logging_h__ #endif // Logging_h__
+5 -13
View File
@@ -5,15 +5,11 @@
#include "Entity.h" #include "Entity.h"
#include "ObjectPool.h" #include "ObjectPool.h"
#include "ComponentPool.h" #include "ComponentPool.h"
#include "EventBroker.h"
class World class World
{ {
public: public:
World() = default; World() = default;
World(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{ }
~World(); ~World();
// Create empty entity // Create empty entity
@@ -25,21 +21,19 @@ public:
// Register a component type and allocate space for it // Register a component type and allocate space for it
void RegisterComponent(ComponentInfo& ci); void RegisterComponent(ComponentInfo& ci);
// Attach a component to an entity and fill it with default values // Attach a component to an entity and fill it with default values
ComponentWrapper AttachComponent(EntityID entity, const std::string& componentType); ComponentWrapper AttachComponent(EntityID entity, std::string componentType);
// Check if an entity has a component // Check if an entity has a component
bool HasComponent(EntityID entity, const std::string& componentType) const; bool HasComponent(EntityID entity, std::string componentType) const;
// Get a component of an entity // Get a component of an entity
ComponentWrapper GetComponent(EntityID entity, const std::string& componentType); ComponentWrapper GetComponent(EntityID entity, std::string componentType);
// Delete a component off an entity // Delete a component off an entity
void DeleteComponent(EntityID entity, const std::string& componentType); void DeleteComponent(EntityID entity, std::string componentType);
// Get all components of the specified type // Get all components of the specified type
const ComponentPool* GetComponents(const std::string& componentType); const ComponentPool* GetComponents(std::string componentType);
// Get entity parent // Get entity parent
EntityID GetParent(EntityID entity); EntityID GetParent(EntityID entity);
// Change the parent of an entity // Change the parent of an entity
void SetParent(EntityID entity, EntityID parent); void SetParent(EntityID entity, EntityID parent);
// Get children of an entity
const std::pair<std::unordered_multimap<EntityID, EntityID>::const_iterator, std::unordered_multimap<EntityID, EntityID>::const_iterator> GetChildren(EntityID entity);
// Get all component pools // Get all component pools
const std::unordered_map<std::string, ComponentPool*>& GetComponentPools() const { return m_ComponentPools; } const std::unordered_map<std::string, ComponentPool*>& GetComponentPools() const { return m_ComponentPools; }
// Get the entity children map // Get the entity children map
@@ -50,7 +44,6 @@ public:
std::string GetName(EntityID entity) const; std::string GetName(EntityID entity) const;
private: private:
EventBroker* m_EventBroker = nullptr;
EntityID m_CurrentEntityID = 0; EntityID m_CurrentEntityID = 0;
std::unordered_map<EntityID, EntityID> m_EntityParents; std::unordered_map<EntityID, EntityID> m_EntityParents;
@@ -60,7 +53,6 @@ private:
std::unordered_map<EntityID, std::string> m_EntityNames; std::unordered_map<EntityID, std::string> m_EntityNames;
EntityID generateEntityID(); EntityID generateEntityID();
void deleteEntityRecursive(EntityID entity, bool cascaded = false);
}; };
#endif #endif
@@ -1,115 +0,0 @@
#ifndef EditorCameraInputController_h__
#define EditorCameraInputController_h__
#include <imgui/imgui.h>
#include "../Input/FirstPersonInputController.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
#include "../Core/EMouseScroll.h"
#include "../Core/ConfigFile.h"
template <typename EventContext>
class EditorCameraInputController : public FirstPersonInputController<EventContext>
{
public:
EditorCameraInputController(EventBroker* eventBroker, unsigned int playerID)
: FirstPersonInputController(eventBroker, playerID)
{
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorCameraInputController::OnMousePress);
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorCameraInputController::OnMouseRelease);
EVENT_SUBSCRIBE_MEMBER(m_EMouseScroll, &EditorCameraInputController::OnMouseScroll);
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
m_SpeedMultiplier = m_Config->Get<float>("Editor.CameraSpeed", 3.f);
}
virtual const glm::vec3 Movement() const override { return m_Movement * static_cast<float>(m_SpeedMultiplier); }
void Enable() { m_Enabled = true; }
void Disable() { m_Enabled = false; }
virtual bool OnCommand(const Events::InputCommand& e) override
{
if (glm::abs(e.Value) > 0 && !m_MouseLocked) {
return false;
}
ImGuiIO& io = ImGui::GetIO();
if (glm::abs(e.Value) > 0 && (io.WantCaptureKeyboard || io.WantCaptureMouse)) {
return false;
}
if (e.Command == "Jump") {
if (e.Value > 0) {
m_Movement.y = glm::max(e.Value, 1.f);
} else {
m_Movement.y = 0.f;
}
}
if (e.Command == "Crouch") {
if (e.Value > 0) {
m_Movement.y = glm::min(-e.Value, -1.f);
} else {
m_Movement.y = 0.f;
}
}
if (e.Command == "Sprint") {
if (e.Value > 0) {
m_SpeedMultiplier *= 2.f;
} else {
m_SpeedMultiplier /= 2.f;
}
}
return FirstPersonInputController::OnCommand(e);
}
protected:
ConfigFile* m_Config;
bool m_Enabled = false;
double m_SpeedMultiplier = 1.f;
EventRelay<EventContext, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e)
{
if (!m_Enabled) {
return false;
}
if (e.Button == GLFW_MOUSE_BUTTON_2) {
ImGuiIO& io = ImGui::GetIO();
if (!io.WantCaptureMouse) {
LockMouse();
}
}
return true;
}
EventRelay<EventContext, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e)
{
if (!m_Enabled) {
return false;
}
if (e.Button == GLFW_MOUSE_BUTTON_2) {
UnlockMouse();
}
return true;
}
EventRelay<EventContext, Events::MouseScroll> m_EMouseScroll;
bool OnMouseScroll(const Events::MouseScroll& e)
{
if (!m_Enabled) {
return false;
}
m_SpeedMultiplier += e.DeltaY * (0.1 * m_SpeedMultiplier);
m_Config->Set("Editor.CameraSpeed", m_SpeedMultiplier);
m_Config->SaveToDisk();
return true;
}
};
#endif
-183
View File
@@ -1,183 +0,0 @@
#ifndef EditorGUI_h__
#define EditorGUI_h__
#include <imgui/imgui.h>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui/imgui_internal.h>
#include <nativefiledialog/nfd.h>
#include <boost/filesystem.hpp>
#include <boost/any.hpp>
#include <boost/algorithm/string/replace.hpp>
#include "../Common.h"
#include "../GLM.h"
#include <glm/gtx/common.hpp>
#include "EditorWidgetSystem.h"
#include "../Core/EventBroker.h"
#include "../Core/World.h"
#include "../Core/EntityWrapper.h"
#include "../Core/ResourceManager.h"
#include "../Core/EPause.h"
#include "../Core/EKeyDown.h"
#include "../Core/ELockMouse.h"
#include "../Core/EFileDropped.h"
#include "../Rendering/Texture.h"
class EditorGUI
{
public:
EditorGUI(World* world, EventBroker* eventBroker);
enum class WidgetMode
{
Translate,
Rotate,
Scale
};
enum class WidgetSpace
{
Global,
Local
};
void Draw();
void SelectEntity(EntityWrapper entity);
void SetDirty(EntityWrapper entity);
// Called when an entity is selected in the entity tree
typedef std::function<void(EntityWrapper)> OnEntitySelectedCallback_t;
void SetEntitySelectedCallback(OnEntitySelectedCallback_t f) { m_OnEntitySelected = f; }
// Called when the user means to import an entity file.
// @param EntityWrapper The entity to parent the imported entity to. The entity will be imported into the world of this entity.
// @param boost::filesystem::path The path to the entity to import
// @return EntityWrapper The newly created entity
typedef std::function<EntityWrapper(EntityWrapper, boost::filesystem::path)> OnEntityImport_t;
void SetEntityImportCallback(OnEntityImport_t f) { m_OnEntityImport = f; }
// Called when the user means to save an entity to file.
// Permitted to throw exceptions on save failure.
typedef std::function<void(EntityWrapper, boost::filesystem::path)> OnEntitySave_t;
void SetEntitySaveCallback(OnEntitySave_t f) { m_OnEntitySave = f; }
// Called when the user means to create a new entity.
// @param EntityWrapper The parent of the entity to be created
// @return EntityWrapper The newly created entity
typedef std::function<EntityWrapper(EntityWrapper)> OnEntityCreate_t;
void SetEntityCreateCallback(OnEntityCreate_t f) { m_OnEntityCreate = f; }
// Called when the user means to delete an entity.
typedef std::function<void(EntityWrapper)> OnEntityDelete_t;
void SetEntityDeleteCallback(OnEntityDelete_t f) { m_OnEntityDelete = f; }
// Called when the user means to change the parent of an entity.
typedef std::function<void(EntityWrapper, EntityWrapper)> OnEntityChangeParent_t;
void SetEntityChangeParentCallback(OnEntityChangeParent_t f) { m_OnEntityChangeParent = f; }
// Called when the user means to rename an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnEntityChangeName_t;
void SetEntityChangeNameCallback(OnEntityChangeName_t f) { m_OnEntityChangeName = f; }
// Called when the user means to attach a new component to an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnComponentAttach_t;
void SetComponentAttachCallback(OnComponentAttach_t f) { m_OnComponentAttach = f; }
// Called when the user means to delete a component off an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnComponentDelete_t;
void SetComponentDeleteCallback(OnComponentDelete_t f) { m_OnComponentDelete = f; }
// Called when the user selects a widget mode.
typedef std::function<void(WidgetMode)> OnWidgetMode_t;
void SetWidgetModeCallback(OnWidgetMode_t f) { m_OnWidgetMode = f; }
// Called when the user selects a widget space.
typedef std::function<void(WidgetSpace)> OnWidgetSpace_t;
void SetWidgetSpaceCallback(OnWidgetSpace_t f) { m_OnWidgetSpace = f; }
private:
World* m_World;
EventBroker* m_EventBroker;
struct EntityFileInfo
{
boost::filesystem::path Path;
bool Dirty = false;
};
// Config variables
const boost::filesystem::path m_DefaultEntityPath = boost::filesystem::path("Schema") / boost::filesystem::path("Entities");
// State
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid;
std::unordered_map<EntityWrapper, EntityFileInfo> m_EntityFiles;
EntityWrapper m_CurrentlyDragging = EntityWrapper::Invalid;
std::string m_LastErrorMessage;
WidgetMode m_CurrentWidgetMode = WidgetMode::Translate;
WidgetSpace m_CurrentWidgetSpace = WidgetSpace::Global;
std::set<std::string> m_ModalsToOpen;
std::map<std::string, boost::any> m_ModalData;
std::string m_DroppedFile = "";
bool m_Paused = false;
bool m_MouseLocked = false;
// Callbacks
OnEntitySelectedCallback_t m_OnEntitySelected = nullptr;
OnEntityImport_t m_OnEntityImport = nullptr;
OnEntitySave_t m_OnEntitySave = nullptr;
OnEntityCreate_t m_OnEntityCreate = nullptr;
OnEntityDelete_t m_OnEntityDelete = nullptr;
OnEntityChangeParent_t m_OnEntityChangeParent = nullptr;
OnEntityChangeName_t m_OnEntityChangeName = nullptr;
OnComponentAttach_t m_OnComponentAttach = nullptr;
OnComponentDelete_t m_OnComponentDelete = nullptr;
OnWidgetMode_t m_OnWidgetMode = nullptr;
OnWidgetSpace_t m_OnWidgetSpace = nullptr;
// Events
EventRelay<EditorGUI, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown& e);
EventRelay<EditorGUI, Events::FileDropped> m_EFileDropped;
bool OnFileDropped(const Events::FileDropped& e);
EventRelay<EditorGUI, Events::Pause> m_EPause;
bool OnPause(const Events::Pause& e);
EventRelay<EditorGUI, Events::Resume> m_EResume;
bool OnResume(const Events::Resume& e);
EventRelay<EditorGUI, Events::LockMouse> m_ELockMouse;
bool OnLockMouse(const Events::LockMouse& e);
EventRelay<EditorGUI, Events::UnlockMouse> m_EUnlockMouse;
bool OnUnlockMouse(const Events::UnlockMouse& e);
// Utility functions
boost::filesystem::path fileOpenDialog();
boost::filesystem::path fileSaveDialog();
const std::string formatEntityName(EntityWrapper entity);
GLuint tryLoadTexture(std::string filePath);
void openModal(const std::string& modal);
void setWidgetMode(WidgetMode mode);
void toggleWidgetSpace();
static bool compareCharArray(const char* c1, const char* c2);
// Entity file handling methods
void entityImport(World* world);
void entitySave(EntityWrapper entity, bool saveAs = false);
void entityCreate(World* world, EntityWrapper parent);
void entityDelete(EntityWrapper entity);
void entityChangeParent(EntityWrapper entity, EntityWrapper parent);
// UI drawing methods
void drawMenu();
void drawTools();
void drawEntities(World* world);
void drawEntitiesRecursive(World* world, EntityID parent);
bool drawEntityNode(EntityWrapper entity);
void drawComponents(EntityWrapper entity);
bool drawComponentNode(EntityWrapper entity, const ComponentInfo& componentType);
bool drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field);
bool drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field);
void drawModals();
// Custom UI elements
bool createDeleteButton(const std::string& componentType);
void createWidgetToolButton(WidgetMode mode);
};
#endif
@@ -1,27 +0,0 @@
#ifndef EditorRenderSystem_h__
#define EditorRenderSystem_h__
#include "../Core/System.h"
#include "../Rendering/IRenderer.h"
#include "../Rendering/ModelJob.h"
#include "../Rendering/Camera.h"
#include "../Rendering/ESetCamera.h"
class EditorRenderSystem : public ImpureSystem
{
public:
EditorRenderSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame);
virtual void Update(double dt) override;
private:
IRenderer* m_Renderer;
RenderFrame* m_RenderFrame;
Camera* m_EditorCamera;
EntityWrapper m_CurrentCamera = EntityWrapper::Invalid;
EventRelay<EditorRenderSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(Events::SetCamera& e);
};
#endif
-29
View File
@@ -1,29 +0,0 @@
#include <numeric>
#include <iomanip>
#include <imgui/imgui.h>
#include "../Common.h"
#include "../GLM.h"
#include "../OpenGL.h"
class EditorStats
{
public:
EditorStats();
void Draw(double dt);
private:
// FPS graph
const unsigned int m_SampleSize = 100;
unsigned int m_FrameCount = 0;
std::vector<double> m_FrameTimes;
double m_TimeAccumulator = 0.0;
double m_AveragedSamplesPerSecond = 10.0;
const unsigned int m_AveragedSampleSize = 100;
unsigned int m_CurrentAveragedSampleIndex = 0;
std::vector<double> m_AveragedSamples;
void drawFPSGraph(double dt);
void drawRAMUsage(double dt);
void drawVRAMStats(double dt);
};
+74 -52
View File
@@ -1,72 +1,94 @@
#include <imgui/imgui.h>
#include <glm/gtx/common.hpp>
#include <boost/filesystem/path.hpp>
#include <nativefiledialog/nfd.h>
#include "../Core/System.h" #include "../Core/System.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
#include "../Core/EMouseMove.h"
#include "../Core/ConfigFile.h"
#include "../Input/EInputCommand.h"
#include "../Rendering/IRenderer.h" #include "../Rendering/IRenderer.h"
#include "../Rendering/Camera.h" #include "../Rendering/EPicking.h"
#include "../Rendering/ESetCamera.h" #include "../Core/EFileDropped.h"
#include "../Core/World.h" #include "../Rendering/RenderQueueFactory.h"
#include "../Core/SystemPipeline.h"
#include "../Core/ResourceManager.h"
#include "../Core/EntityFilePreprocessor.h" #include "../Core/EntityFilePreprocessor.h"
#include "../Core/EntityFileParser.h" #include "../Core/EntityFileParser.h"
#include "../Core/EntityFileWriter.h" #include "../Core/EntityFileWriter.h"
#include "../Core/EMousePress.h"
#include "../Input/EInputCommand.h"
#include "EditorGUI.h"
#include "EditorStats.h"
#include "EditorCameraInputController.h"
class EditorSystem : public ImpureSystem class EditorSystem : public ImpureSystem
{ {
public: public:
EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame); EditorSystem(EventBroker* eventBroker, IRenderer* renderer);
~EditorSystem();
void Update(double dt); virtual void Update(World* world, double dt) override;
void Enable();
void Disable();
private: private:
IRenderer* m_Renderer; IRenderer* m_Renderer;
RenderFrame* m_RenderFrame; World* m_World = nullptr;
World* m_EditorWorld;
SystemPipeline* m_EditorWorldSystemPipeline;
//Camera* m_EditorCamera;
EntityWrapper m_EditorCamera = EntityWrapper::Invalid;
EntityWrapper m_ActualCamera = EntityWrapper::Invalid;
EditorCameraInputController<EditorSystem>* m_EditorCameraInputController;
EditorGUI* m_EditorGUI;
EditorStats* m_EditorStats;
// State bool m_Enabled;
double m_LastTime = 0.f; bool m_Visible;
bool m_Enabled = true; boost::filesystem::path m_DefaultEntityDir;
EditorGUI::WidgetMode m_WidgetMode = EditorGUI::WidgetMode::Translate; boost::filesystem::path m_CurrentFile;
EditorGUI::WidgetSpace m_WidgetSpace = EditorGUI::WidgetSpace::Global; std::vector<glm::vec2> m_PickingQueue;
EntityWrapper m_Widget = EntityWrapper::Invalid;
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid;
// Utility functions enum class WidgetMode
EntityWrapper importEntity(EntityWrapper parent, boost::filesystem::path filePath); {
void setWidgetMode(EditorGUI::WidgetMode mode); None,
Translate,
Rotate,
Scale
} m_WidgetMode = WidgetMode::None;
// GUI callbacks enum class WidgetSpace
void OnEntitySelected(EntityWrapper entity); {
void OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath); Local,
EntityWrapper OnEntityCreate(EntityWrapper parent); Global
void OnEntityDelete(EntityWrapper entity); } m_WidgetSpace = WidgetSpace::Global;
void OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent);
void OnEntityChangeName(EntityWrapper entity, const std::string& name); EntityID m_Widget = EntityID_Invalid;
void OnComponentAttach(EntityWrapper entity, const std::string& componentType); EntityID m_WidgetX = EntityID_Invalid;
void OnComponentDelete(EntityWrapper entity, const std::string& componentType); EntityID m_WidgetPlaneX = EntityID_Invalid;
void OnWidgetSpace(EditorGUI::WidgetSpace widgetSpace); EntityID m_WidgetY = EntityID_Invalid;
EntityID m_WidgetPlaneY = EntityID_Invalid;
EntityID m_WidgetZ = EntityID_Invalid;
EntityID m_WidgetPlaneZ = EntityID_Invalid;
EntityID m_WidgetOrigin = EntityID_Invalid;
glm::vec3 m_WidgetCurrentAxis;
float m_WidgetPickingDepth = 0.f;
EntityID m_Selection = EntityID_Invalid;
EntityID m_LastSelection = EntityID_Invalid;
EntityID m_UIDraggingEntity = EntityID_Invalid;
glm::vec3 m_Position;
std::string m_LastDroppedFile;
static boost::filesystem::path openDialog(boost::filesystem::path defaultPath);
static boost::filesystem::path saveDialog(boost::filesystem::path defaultPath);
// Events
EventRelay<EditorSystem, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<EditorSystem, Events::WidgetDelta> m_EWidgetDelta;
bool OnWidgetDelta(const Events::WidgetDelta& e);
EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand; EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e); bool OnInputCommand(const Events::InputCommand& e);
EventRelay<EditorSystem, Events::SetCamera> m_ESetCamera; EventRelay<EditorSystem, Events::MouseRelease> m_EMouseRelease;
bool OnSetCamera(const Events::SetCamera& e); bool OnMouseRelease(const Events::MouseRelease& e);
EventRelay<EditorSystem, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<EditorSystem, Events::MouseMove> m_EMouseMove;
bool OnMouseMove(const Events::MouseMove& e);
EventRelay<EditorSystem, Events::Picking> m_EPicking;
bool OnPicking(const Events::Picking& e);
EventRelay<EditorSystem, Events::FileDropped> m_EFileDropped;
bool OnFileDropped(const Events::FileDropped& e);
void createWidget();
void updateWidget();
void setWidgetMode(WidgetMode newMode);
void setWidgetSpace(WidgetSpace space);
void drawUI(World* world, double dt);
bool createDeleteButton(std::string componentType);
bool createEntityNode(World* world, EntityID entity);
void changeParent(EntityID entity, EntityID newParent);
void fileImport(World* world);
void fileSave(World* world);
void fileSaveAs(World* world);
}; };
@@ -1,49 +0,0 @@
#ifndef EditorWidgetSystem_h__
#define EditorWidgetSystem_h__
#include <imgui/imgui.h>
#include "../GLM.h"
#include "../Core/System.h"
#include "../Rendering/IRenderer.h"
#include "../Rendering/Util/ScreenCoords.h"
#include "../Core/EMouseMove.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
namespace Events
{
struct WidgetDelta : Event
{
glm::vec3 Translation;
glm::vec3 Rotation;
glm::vec3 Scale;
};
}
class EditorWidgetSystem : public ImpureSystem, PureSystem
{
public:
EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer);
virtual void Update(double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cEditorWidget, double dt) override;
private:
IRenderer* m_Renderer;
// State
EntityWrapper m_PickEntity = EntityWrapper::Invalid;
PickData m_PickData;
glm::vec2 m_MouseDelta;
EventRelay<EditorWidgetSystem, Events::MouseMove> m_EMouseMove;
bool OnMouseMove(const Events::MouseMove& e);
EventRelay<EditorWidgetSystem, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<EditorWidgetSystem, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e);
};
#endif
+1 -2
View File
@@ -7,5 +7,4 @@
#include <glm/gtx/rotate_vector.hpp> #include <glm/gtx/rotate_vector.hpp>
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp> #include <glm/gtx/quaternion.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/projection.hpp>
+1 -1
View File
@@ -40,7 +40,7 @@ public:
m_TexturePressed = resourceName; m_TexturePressed = resourceName;
} }
void Draw(RenderScene& rq) override void Draw(RenderQueueCollection& rq) override
{ {
if (m_Texture == nullptr && !m_TextureReleased.empty()) { if (m_Texture == nullptr && !m_TextureReleased.empty()) {
SetTexture(m_TextureReleased); SetTexture(m_TextureReleased);
+2 -2
View File
@@ -212,7 +212,7 @@ public:
virtual void Update(double dt) { } virtual void Update(double dt) { }
void DrawLayered(RenderScene& rq) void DrawLayered(RenderQueueCollection& rq)
{ {
if (this->Hidden()) if (this->Hidden())
return; return;
@@ -232,7 +232,7 @@ public:
} }
} }
virtual void Draw(RenderScene& rq) { } virtual void Draw(RenderQueueCollection& rq) { }
protected: protected:
::EventBroker* m_EventBroker; ::EventBroker* m_EventBroker;
+1 -1
View File
@@ -16,7 +16,7 @@ public:
void EnableScissor() { m_ScissorEnabled = true; } void EnableScissor() { m_ScissorEnabled = true; }
void DisableScissor() { m_ScissorEnabled = false; } void DisableScissor() { m_ScissorEnabled = false; }
void Draw(RenderScene& rq) override void Draw(RenderQueueCollection& rq) override
{ {
if (m_Texture == nullptr) if (m_Texture == nullptr)
return; return;
+1 -3
View File
@@ -2,7 +2,6 @@
#define Events_InputCommand_h__ #define Events_InputCommand_h__
#include "Core/EventBroker.h" #include "Core/EventBroker.h"
#include "Core/EntityWrapper.h"
namespace Events namespace Events
{ {
@@ -10,8 +9,7 @@ namespace Events
struct InputCommand : Event struct InputCommand : Event
{ {
/** Numerical ID of the player. */ /** Numerical ID of the player. */
int PlayerID; unsigned int PlayerID;
EntityWrapper Player;
/** The command that was sent. */ /** The command that was sent. */
std::string Command; std::string Command;
/** The value of the command. */ /** The value of the command. */
+47 -216
View File
@@ -4,236 +4,67 @@
#include "../GLM.h" #include "../GLM.h"
#include "../Core/InputController.h" #include "../Core/InputController.h"
#include "../Core/ELockMouse.h" #include "../Core/ELockMouse.h"
#include "../Game/Events/EDashAbility.h"
#include "InputHandler.h"
template <typename EventContext> template <typename EventContext>
class FirstPersonInputController : public InputController<EventContext> class FirstPersonInputController : public InputController<EventContext>
{ {
public: public:
FirstPersonInputController(EventBroker* eventBroker, int playerID); FirstPersonInputController(EventBroker* eventBroker, unsigned int playerID)
: InputController(eventBroker)
virtual const glm::vec3 Movement() const { return m_Movement; } , m_PlayerID(playerID)
virtual const glm::vec3 Rotation() const { return m_Rotation; } {
virtual bool Jumping() const { return m_Jumping; } EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &FirstPersonInputController::OnLockMouse);
virtual bool Crouching() const { return m_Crouching; } EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &FirstPersonInputController::OnUnlockMouse);
virtual bool DoubleJumping() const { return m_DoubleJumping; }
virtual void SetDoubleJumping(bool isDoubleJumping) {
m_DoubleJumping = isDoubleJumping;
} }
void LockMouse(); const glm::quat Orientation() const { return m_Orientation; }
void UnlockMouse();
virtual bool OnCommand(const Events::InputCommand& e) override; void LockMouse()
virtual void Reset(); {
Events::LockMouse e;
m_EventBroker->Publish(e);
m_MouseLocked = true;
}
void AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer); void UnlockMouse()
virtual bool AssaultDashDoubleTapped() const { return m_AssaultDashDoubleTapped; } {
virtual bool PlayerIsDashing() const { return m_PlayerIsDashing; } Events::UnlockMouse e;
m_EventBroker->Publish(e);
m_MouseLocked = false;
}
protected: virtual bool OnCommand(const Events::InputCommand& e) override
const int m_PlayerID; {
bool m_MouseLocked = false; if (m_PlayerID != e.PlayerID) {
glm::vec3 m_Rotation; return false;
glm::vec3 m_Movement; }
bool m_Jumping = false;
bool m_DoubleJumping = false;
bool m_Crouching = false;
//assault dash membervariables - needed to calculate the doubletap- and dashlogic
double m_AssaultDashDoubleTapDeltaTime = 0.0;
double m_AssaultDashCoolDownTimer = 0.0;
//i will let m_AssaultDashDoubleTapSensitivityTimer stay hardcoded, its not really a gamevariable (more an inputvariable),
//and its very unlikely that someone wants to change that value
const float m_AssaultDashDoubleTapSensitivityTimer = 0.25f;
std::string m_AssaultDashTapDirection = "";
std::string m_CurrentDirectionVector = "";
bool m_AssaultDashDoubleTapped = false;
bool m_PlayerIsDashing = false;
bool m_ShiftDashing = false;
bool m_ValidDoubleTap = false;
//specialabilitys if (m_MouseLocked) {
bool m_MovementKeyDown = false; if (e.Command == "Pitch") {
bool m_SpecialAbilityKeyDown = false; float val = glm::radians(e.Value);
m_Orientation = m_Orientation * glm::angleAxis<float>(-val, glm::vec3(1, 0, 0));
return true;
}
EventRelay<EventContext, Events::LockMouse> m_ELockMouse; if (e.Command == "Yaw") {
bool OnLockMouse(const Events::LockMouse& e); float val = glm::radians(e.Value);
EventRelay<EventContext, Events::UnlockMouse> m_EUnlockMouse; m_Orientation = glm::angleAxis<float>(-val, glm::vec3(0, 1, 0)) * m_Orientation;
bool OnUnlockMouse(const Events::UnlockMouse& e); return true;
}; }
}
template <typename EventContext>
FirstPersonInputController<EventContext>::FirstPersonInputController(EventBroker* eventBroker, int playerID)
: InputController(eventBroker)
, m_PlayerID(playerID)
{
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &FirstPersonInputController::OnLockMouse);
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &FirstPersonInputController::OnUnlockMouse);
}
template <typename EventContext>
void FirstPersonInputController<EventContext>::Reset()
{
m_Rotation = glm::vec3(0.f, 0.f, 0.f);
m_Jumping = false;
}
template <typename EventContext>
void FirstPersonInputController<EventContext>::LockMouse()
{
Events::LockMouse e;
m_EventBroker->Publish(e);
m_MouseLocked = true;
}
template <typename EventContext>
void FirstPersonInputController<EventContext>::UnlockMouse()
{
Events::UnlockMouse e;
m_EventBroker->Publish(e);
m_MouseLocked = false;
}
template <typename EventContext>
bool FirstPersonInputController<EventContext>::OnCommand(const Events::InputCommand& e)
{
if (m_PlayerID != e.PlayerID) {
return false; return false;
} }
if (e.Command == "Pitch") { protected:
float val = glm::radians(e.Value); const unsigned int m_PlayerID;
m_Rotation.x += -val; glm::quat m_Orientation;
//m_Rotation.x = glm::clamp(m_Rotation.x, -glm::half_pi<float>(), glm::half_pi<float>()); bool m_MouseLocked = false;
}
EventRelay<EventContext, Events::LockMouse> m_ELockMouse;
if (e.Command == "Yaw") { bool OnLockMouse(const Events::LockMouse& e) { m_MouseLocked = true; return true; }
float val = glm::radians(e.Value); EventRelay<EventContext, Events::UnlockMouse> m_EUnlockMouse;
m_Rotation.y += -val; bool OnUnlockMouse(const Events::UnlockMouse& e) { m_MouseLocked = false; return true; }
} };
if (e.Command == "Forward" || e.Command == "Right") {
if (e.Command == "Forward") {
float val = glm::clamp(e.Value, -1.f, 1.f);
m_Movement.z = -val;
}
if (e.Command == "Right") {
float val = glm::clamp(e.Value, -1.f, 1.f);
m_Movement.x = val;
}
if (glm::length2(m_Movement) > 0) {
m_Movement = glm::normalize(m_Movement);
}
}
if (e.Command == "Forward" || e.Command == "Right") {
if (e.Value != 0) {
m_CurrentDirectionVector = e.Command == "Right" ? (e.Value > 0 ? "Right" : "Left") : (e.Value > 0 ? "Forward" : "Backward");
}
//if value = 0 then you have just released this key
if (e.Value != 0) {
m_MovementKeyDown = true;
//if you pressed the same key within m_AssaultDashDoubleTapSensitivityTimer then you have doubletapped it
if (m_AssaultDashDoubleTapDeltaTime < m_AssaultDashDoubleTapSensitivityTimer && m_AssaultDashTapDirection == m_CurrentDirectionVector) {
m_ValidDoubleTap = true;
}
} else {
//== 0
m_MovementKeyDown = false;
//you have just released the key, store what key it was and reset the doubletap-sensitivity-timer
m_AssaultDashTapDirection = m_CurrentDirectionVector;
m_AssaultDashDoubleTapDeltaTime = 0.f;
}
}
if (e.Command == "Jump") {
m_Jumping = e.Value > 0;
}
if (e.Command == "Crouch") {
m_Crouching = e.Value > 0;
}
if (e.Command == "SpecialAbility") {
if (e.Value > 0) {
m_SpecialAbilityKeyDown = true;
} else {
m_SpecialAbilityKeyDown = false;
}
}
if (m_SpecialAbilityKeyDown && m_MovementKeyDown) {
m_ShiftDashing = true;
} else {
m_ShiftDashing = false;
}
return true;
}
template <typename EventContext>
bool FirstPersonInputController<EventContext>::OnUnlockMouse(const Events::UnlockMouse& e)
{
m_MouseLocked = false;
return true;
}
template <typename EventContext>
bool FirstPersonInputController<EventContext>::OnLockMouse(const Events::LockMouse& e)
{
m_MouseLocked = true;
return true;
}
template <typename EventContext>
void FirstPersonInputController<EventContext>::AssaultDashCheck(double dt, bool isJumping, double assaultDashCoolDownMaxTimer) {
m_AssaultDashDoubleTapDeltaTime += dt;
m_AssaultDashCoolDownTimer -= dt;
//cooldown = assaultDashCoolDownMaxTimer sec, pretend the dash lasts 0.25 sec (for friction to do its work)
if (m_AssaultDashCoolDownTimer > (assaultDashCoolDownMaxTimer - 0.25f)) {
m_PlayerIsDashing = true;
} else {
m_PlayerIsDashing = false;
}
//dashing with shift
if (m_ShiftDashing && m_AssaultDashCoolDownTimer <= 0.0f && !isJumping) {
//player is dashing with shift
//the wanted-direction is set in playermovement already so we dont need to check what direction we want to dash in!
m_AssaultDashCoolDownTimer = assaultDashCoolDownMaxTimer;
m_AssaultDashDoubleTapped = true;
m_AssaultDashDoubleTapDeltaTime = 0.f;
//moving to the side has priority
return;
}
//dashing with doubletap - check if doubletap to dash enabled
if (ResourceManager::Load<ConfigFile>("Input.ini")->Get<bool>("Keyboard.DoubleTapToDash", false)) {
return;
}
//reset the DoubleTapped state in case we recently doubleTapped (doubletap will only happen during 1 frame)
if (m_AssaultDashDoubleTapped) {
m_AssaultDashDoubleTapped = false;
}
//check if we have received a valid doubletap
if (!m_ValidDoubleTap) {
return;
}
m_ValidDoubleTap = false;
if (!(m_AssaultDashCoolDownTimer <= 0.0f && !isJumping)) {
//if we cant dash at the moment, then just reset the tap-sensitivity-timer
m_AssaultDashDoubleTapDeltaTime = 0.f;
return;
}
//ok, we have a valid tap, lets do it
m_AssaultDashDoubleTapped = true;
m_AssaultDashDoubleTapDeltaTime = 0.f;
m_AssaultDashCoolDownTimer = assaultDashCoolDownMaxTimer;
Events::DashAbility e;
m_EventBroker->Publish(e);
}
#endif #endif
-1
View File
@@ -1,7 +1,6 @@
#ifndef InputProxy_h__ #ifndef InputProxy_h__
#define InputProxy_h__ #define InputProxy_h__
#include <boost/tokenizer.hpp>
#include "../Common.h" #include "../Common.h"
#include "../Core/ResourceManager.h" #include "../Core/ResourceManager.h"
#include "../Core/ConfigFile.h" #include "../Core/ConfigFile.h"
+22 -49
View File
@@ -3,12 +3,9 @@
#include <string> #include <string>
#include <ctime> #include <ctime>
#include <limits>
#include <queue>
#include <glm/common.hpp> #include <glm/common.hpp>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/shared_array.hpp>
#include "Network/Network.h" #include "Network/Network.h"
#include "Network/MessageType.h" #include "Network/MessageType.h"
@@ -18,9 +15,6 @@
#include "Core/EventBroker.h" #include "Core/EventBroker.h"
#include "Core/ConfigFile.h" #include "Core/ConfigFile.h"
#include "Input/EInputCommand.h" #include "Input/EInputCommand.h"
#include "Core/EPlayerDamage.h"
#include "Network/EInterpolate.h"
#include "Core/EPlayerSpawned.h"
class Client : public Network class Client : public Network
{ {
@@ -29,6 +23,7 @@ public:
~Client(); ~Client();
void Start(World* world, EventBroker* eventBroker) override; void Start(World* world, EventBroker* eventBroker) override;
void Update() override; void Update() override;
void Close();
private: private:
// Assio UDP logic // Assio UDP logic
boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
@@ -36,76 +31,54 @@ private:
boost::asio::ip::udp::socket m_Socket; boost::asio::ip::udp::socket m_Socket;
// Sending message to server logic // Sending message to server logic
size_t bytesRead = 0; int bytesRead = -1;
char readBuf[INPUTSIZE] = { 0 }; char readBuf[1024] = { 0 };
int snapshotInterval = 33;
std::clock_t previousSnapshotMessage = std::clock();
// Packet loss logic // Packet loss logic
PacketID m_PacketID = 0; unsigned int m_PacketID = 0;
PacketID m_PreviousPacketID = 0; unsigned int m_PreviousPacketID = 0;
PacketID m_SendPacketID = 0; unsigned int m_SendPacketID = 0;
// Game logic // Game logic
World* m_World; World* m_World;
std::string m_PlayerName; std::string m_PlayerName;
PlayerID m_PlayerID = -1; int m_PlayerID = -1;
EntityID m_ServerEntityID = std::numeric_limits<EntityID>::max();
bool m_IsConnected = false;
EntityWrapper m_LocalPlayer = EntityWrapper::Invalid;
// Server Client Lookup map
// Assumes that root node for client and server is EntityID 0.
// Don't Add items to these two maps with insert, use insertIntoServerClientMaps(EntityID, EntityID)!!!!
std::unordered_map<EntityID, EntityID> m_ServerIDToClientID;
std::unordered_map<EntityID, EntityID> m_ClientIDToServerID;
// Network logic // Network logic
PlayerDefinition m_PlayerDefinitions[8]; PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
SnapshotDefinitions m_NextSnapshot; SnapshotDefinitions m_NextSnapshot;
bool m_ThreadIsRunning = true;
double m_DurationOfPingTime; double m_DurationOfPingTime;
std::clock_t m_StartPingTime; std::clock_t m_StartPingTime;
std::clock_t m_TimeSinceSentInputs; // Use to check if we should send disconnect message
unsigned int m_SendInputIntervalMs; // if game is turned of by closing window.
std::vector<Events::InputCommand> m_InputCommandBuffer; bool m_WasStarted = false;
// Private member functions // Private member functions
void readFromServer(); void readFromServer();
size_t receive(char* data); void sendSnapshotToServer();
int receive(char* data, size_t length);
void send(Packet& packet); void send(Packet& packet);
void connect(); void connect();
void disconnect(); void disconnect();
void ping();
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
void parseMessageType(Packet& packet); void parseMessageType(Packet& packet);
void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType); void parseEventMessage(Packet& packet);
void parseConnect(Packet& packet); void parseConnect(Packet& packet);
void parsePlayerConnected(Packet& packet);
void parsePing(); void parsePing();
void parseKick(); void parseServerPing();
void parsePlayersSpawned(Packet& packet);
void parseEntityDeletion(Packet& packet);
void parseComponentDeletion(Packet& packet);
void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType);
void parseSnapshot(Packet& packet); void parseSnapshot(Packet& packet);
void identifyPacketLoss(); void identifyPacketLoss();
bool hasServerTimedOut(); bool isConnected();
EntityID createPlayer(); EntityID createPlayer();
void sendInputCommands();
void sendLocalPlayerTransform();
void becomePlayer();
// Mapping Logic
// Returns if local EntityID exist in map
bool clientServerMapsHasEntity(EntityID clientEntityID);
// Returns if server EntityID exist in map
bool serverClientMapsHasEntity(EntityID serverEntityID);
void insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
void deleteFromServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
// Events // Events
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
EventRelay<Client, Events::InputCommand> m_EInputCommand; EventRelay<Client, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e); bool OnInputCommand(const Events::InputCommand &e);
EventRelay<Client, Events::PlayerDamage> m_EPlayerDamage;
bool OnPlayerDamage(const Events::PlayerDamage& e);
EventRelay<Client, Events::PlayerSpawned> m_EPlayerSpawned;
bool OnPlayerSpawned(const Events::PlayerSpawned& e);
}; };
#endif #endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef Events_Interpolate_h__
#define Events_Interpolate_h__
#include <boost/shared_array.hpp>
#include "Core/EventBroker.h"
#include "Core/Entity.h"
namespace Events
{
struct Interpolate : Event
{
EntityID Entity;
boost::shared_array<char> DataArray;
};
}
#endif
@@ -1,18 +0,0 @@
#ifndef Events_PlayerDisconnected
#define Events_PlayerDisconnected
#include "Core/EventBroker.h"
#include "Core/Entity.h"
namespace Events
{
struct PlayerDisconnected : public Event
{
unsigned int PlayerID;
EntityID Entity;
};
}
#endif
+7 -14
View File
@@ -5,20 +5,13 @@
// Used to determine what type of message was sent. // Used to determine what type of message was sent.
enum class MessageType enum class MessageType
{ {
Connect, Connect,
Disconnect, Disconnect,
Ping, ClientPing,
Message, ServerPing,
Snapshot, Message,
OnInputCommand, Snapshot,
OnPlayerDamage, Event,
PlayerConnected,
BecomePlayer,
Kick,
OnPlayerSpawned,
EntityDeleted,
ComponentDeleted,
PlayerTransform
}; };
#endif #endif
+2 -21
View File
@@ -1,20 +1,12 @@
#ifndef Network_h__ #ifndef Network_h__
#define Network_h__ #define Network_h__
#include <ctime>
#include "Core/World.h" #include "Core/World.h"
#include "Core/EventBroker.h" #include "Core/EventBroker.h"
#include "Network/Packet.h" #include "Network/Packet.h"
#include "Network/NetworkData.h"
#include "Core/ResourceManager.h"
#include "Core/ConfigFile.h"
#include <fstream>
#include <iostream>
#define INPUTSIZE 32000 #define MAXCONNECTIONS 8
typedef unsigned int PlayerID; #define INPUTSIZE 128
typedef unsigned int PacketID;
class Network class Network
{ {
@@ -22,17 +14,6 @@ public:
virtual ~Network() { }; virtual ~Network() { };
virtual void Start(World* m_world, EventBroker *eventBroker) = 0; virtual void Start(World* m_world, EventBroker *eventBroker) = 0;
virtual void Update() = 0; virtual void Update() = 0;
protected:
// For Debug
bool isReadingData = false;
NetworkData m_NetworkData;
unsigned int m_SaveDataIntervalMs = 1000;
std::clock_t m_SaveDataTimer;
unsigned int m_MaxConnections;
double m_TimeoutMs;
void saveToFile();
void updateNetworkData();
void initialize();
}; };
#endif #endif
-18
View File
@@ -1,18 +0,0 @@
#ifndef NetworkData_h__
#define NetworkData_h__
#include <vector>
struct NetworkData {
double TotalTime = 0;
size_t TotalDataReceived = 0;
size_t TotalDataSent = 0;
size_t AmountOfMessagesReceived = 0;
unsigned int AmountOfMessagesSent = 0;
// Interval based
size_t DataReceivedThisInterval = 0;
size_t DataSentThisInterval = 0;
// pair: first=reveived, second=send
std::vector<std::pair<size_t, size_t>> BandwidthBytes;
};
#endif
+9 -17
View File
@@ -13,19 +13,16 @@ public:
// arg2: PacketID for identifying packet loss. // arg2: PacketID for identifying packet loss.
Packet(MessageType type, unsigned int& packetID); Packet(MessageType type, unsigned int& packetID);
// Used to create packet from already existing data buffer. // Used to create packet from already existing data buffer.
Packet(char* data, const size_t sizeOfPacket); Packet(char* data, const int sizeOfPacket);
Packet(MessageType type);
~Packet(); ~Packet();
void Init(MessageType type, unsigned int& packetID);
// Add primitive types like int, float, char... // Add primitive types like int, float, char...
template<typename T> template<typename T>
void WritePrimitive(T val) void WritePrimitive(T val)
{ {
// Check if we are trying to add more than the package can fit. // Check if we are trying to add more than the package can fit.
if (m_MaxPacketSize < m_Offset + sizeof(T)) { if (m_MaxPacketSize < m_Offset + sizeof(T)) {
LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for! New size is %i bytes\n", m_MaxPacketSize*2); LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for!");
resizeData();
} }
memcpy(m_Data + m_Offset, &val, sizeof(T)); memcpy(m_Data + m_Offset, &val, sizeof(T));
m_Offset += sizeof(T); m_Offset += sizeof(T);
@@ -44,26 +41,21 @@ public:
return returnValue; return returnValue;
} }
// Add a string to the message // Add a string to the message
void WriteString(const std::string& str); void WriteString(std::string str);
// Add data to the message // Add data to the message
void WriteData(char* data, int sizeOfData); void WriteData(char* data, int sizeOfData);
// Pops the first element as if it was a string. // Pops the first element as if it was a string.
std::string ReadString(); std::string ReadString();
char* ReadData(int SizeOfData); char* ReadData(int SizeOfData);
void ChangePacketID(unsigned int& packetID);
size_t Size() { return m_Offset; }; int Size() { return m_Offset; };
char* Data() { return m_Data; }; char* Data() { return m_Data; };
size_t DataReadSize() { return m_ReturnDataOffset; }
size_t MaxSize() { return m_MaxPacketSize; }
size_t HeaderSize() { return m_HeaderSize; }
private: private:
char* m_Data; char* m_Data;
size_t m_ReturnDataOffset = 0; unsigned int m_ReturnDataOffset = 0;
size_t m_Offset = 0; int m_Offset = 0;
size_t m_MaxPacketSize = 512; unsigned int m_MaxPacketSize = 128;
size_t m_HeaderSize = 0;
void resizeData();
}; };
#endif #endif
+1 -4
View File
@@ -1,14 +1,11 @@
#ifndef PlayerDefinition_h__ #ifndef PlayerDefinition_h__
#define PlayerDefinition_h__ #define PlayerDefinition_h__
#include <string> #include <string>
#include "../Core/Entity.h"
struct PlayerDefinition { struct PlayerDefinition {
::EntityID EntityID = EntityID_Invalid; int EntityID = -1;
std::string Name = ""; std::string Name = "";
boost::asio::ip::udp::endpoint Endpoint; boost::asio::ip::udp::endpoint Endpoint;
unsigned int PacketID;
std::clock_t StopTime;
}; };
#endif #endif
+26 -35
View File
@@ -11,13 +11,7 @@
#include "Network/PlayerDefinition.h" #include "Network/PlayerDefinition.h"
#include "Core/World.h" #include "Core/World.h"
#include "Core/EventBroker.h" #include "Core/EventBroker.h"
#include "../Network/Network.h" #include "Network/Network.h"
#include "Input/EInputCommand.h"
#include "Core/EPlayerDamage.h"
#include "Network/EPlayerDisconnected.h"
#include "Core/EPlayerSpawned.h"
#include "Core/EEntityDeleted.h"
#include "Core/EComponentDeleted.h"
class Server : public Network class Server : public Network
{ {
@@ -26,69 +20,66 @@ public:
~Server(); ~Server();
void Start(World* m_world, EventBroker *eventBroker) override; void Start(World* m_world, EventBroker *eventBroker) override;
void Update() override; void Update() override;
void Close();
private: private:
// UDP logic // UDP logic
boost::asio::ip::udp::endpoint m_ReceiverEndpoint; boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
boost::asio::io_service m_IOService; boost::asio::io_service m_IOService;
boost::asio::ip::udp::socket m_Socket; boost::asio::ip::udp::socket m_Socket;
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
// Sending messages to client logic // Sending messages to client logic
std::map<PlayerID, PlayerDefinition> m_ConnectedPlayers; char readBuffer[1024] = { 0 };
// HACK: Fix INPUTSIZE int bytesRead = 0;
char readBuffer[INPUTSIZE] = { 0 };
size_t bytesRead = 0;
// time for previouse message // time for previouse message
std::clock_t previousePingMessage = std::clock(); std::clock_t previousePingMessage = std::clock();
std::clock_t previousSnapshotMessage = std::clock(); std::clock_t previousSnapshotMessage = std::clock();
std::clock_t timOutTimer = std::clock(); std::clock_t timOutTimer = std::clock();
// How often we send messages (milliseconds) // How often we send messages (milliseconds)
float pingIntervalMs; int intervalMs = 1000;
float snapshotInterval; int snapshotInterval = 50;
int checkTimeOutInterval = 100; int checkTimeOutInterval = 100;
int m_NextPlayerID = 0;
//Timers //Timers
std::clock_t m_StartPingTime; std::clock_t m_StartPingTime;
std::clock_t m_StopTimes[8];
// Game logic // Game logic
World* m_World; World* m_World;
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
// vec.size() = ammount of players to create, stores playerID's
std::vector<unsigned int> m_PlayersToCreate;
// Packet loss logic // Packet loss logic
PacketID m_PacketID = 0; unsigned int m_PacketID;
PacketID m_PreviousPacketID = 0; unsigned int m_PreviousPacketID;
unsigned int m_SendPacketID;
// Close logic
bool m_ThreadIsRunning = true;
// Private member functions // Private member functions
size_t receive(char* data); int receive(char* data, size_t length);
void readFromClients(); void readFromClients();
void send(PlayerID player, Packet& packet); void send(Packet& packet, int playerID);
void send(Packet& packet); void send(Packet& packet);
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
void broadcast(std::string message);
void broadcast(Packet& packet); void broadcast(Packet& packet);
void sendSnapshot(); void sendSnapshot();
void addChildrenToPacket(Packet& packet, EntityID entityID);
void sendPing(); void sendPing();
void checkForTimeOuts(); void checkForTimeOuts();
void disconnect(PlayerID playerID); void disconnect(int i);
void parseMessageType(Packet& packet); void parseMessageType(Packet& packet);
void parseOnInputCommand(Packet& packet); void parseEvent(Packet& packet);
void parseOnPlayerDamage(Packet& packet);
void parseConnect(Packet& packet); void parseConnect(Packet& packet);
void parseDisconnect(); void parseDisconnect();
void parseClientPing(); void parseClientPing();
void parsePing(); void parseServerPing();
void parseSnapshot(Packet& packet);
void identifyPacketLoss(); void identifyPacketLoss();
void kick(PlayerID player); EntityID createPlayer();
PlayerID GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint);
// Debug event
EventRelay<Server, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
EventRelay<Server, Events::PlayerSpawned> m_EPlayerSpawned;
bool OnPlayerSpawned(const Events::PlayerSpawned& e);
EventRelay<Server, Events::EntityDeleted> m_EEntityDeleted;
bool OnEntityDeleted(const Events::EntityDeleted& e);
EventRelay<Server, Events::ComponentDeleted> m_EComponentDeleted;
bool OnComponentDeleted(const Events::ComponentDeleted& e);
void parsePlayerTransform(Packet& packet);
}; };
#endif #endif
@@ -1,31 +0,0 @@
#ifndef AnimationSystem_h__
#define AnimationSystem_h__
#include "GLM.h"
#include "Common.h"
#include "Core/System.h"
#include "Core/ResourceManager.h"
#include "Rendering/Model.h"
#include "Rendering/EAnimationComplete.h"
#include "Rendering/Skeleton.h"
#include <imgui/imgui.h>
class AnimationSystem : public PureSystem
{
public:
AnimationSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("Animation")
{
}
~AnimationSystem() { }
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& animationComponent, double dt) override;
private:
float angle = 0.f;
bool b_forward = false;
char bone[100];
};
#endif
+1 -1
View File
@@ -3,7 +3,7 @@
#include "../Core/ResourceManager.h" #include "../Core/ResourceManager.h"
class BaseTexture : public ThreadUnsafeResource class BaseTexture : public Resource
{ {
friend class ResourceManager; friend class ResourceManager;
@@ -1,29 +0,0 @@
#ifndef BoneAttachmentSystem_h__
#define BoneAttachmentSystem_h__
#include "GLM.h"
#include "Common.h"
#include "Core/System.h"
#include "Core/ResourceManager.h"
#include "Rendering/Model.h"
#include "Rendering/Skeleton.h"
//Needs to be a higher orderlevel than AnimationSystem
class BoneAttachmentSystem : public PureSystem
{
public:
BoneAttachmentSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("BoneAttachment")
{
}
~BoneAttachmentSystem() { }
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& BoneAttachmentComponent, double dt) override;
private:
};
#endif
+8 -8
View File
@@ -2,7 +2,6 @@
#define Camera_h__ #define Camera_h__
#include "../GLM.h" #include "../GLM.h"
#include "../Core/Util/Rectangle.h"
class Camera class Camera
{ {
@@ -27,11 +26,13 @@ public:
glm::quat Orientation() const { return m_Orientation; } glm::quat Orientation() const { return m_Orientation; }
void SetOrientation(glm::quat val); void SetOrientation(glm::quat val);
glm::mat4 ProjectionMatrix() const { return m_ProjectionMatrix; } /*float Pitch() const { return m_Pitch; }
void SetProjectionMatrix(glm::mat4 val); void Pitch(float val);
float Yaw() const { return m_Yaw; }
void Yaw(float val);*/
glm::mat4 ProjectionMatrix() const { return m_ProjectionMatrix; }
glm::mat4 ViewMatrix() const { return m_ViewMatrix; } glm::mat4 ViewMatrix() const { return m_ViewMatrix; }
void SetViewMatrix(glm::mat4 val);
float AspectRatio() const { return m_AspectRatio; } float AspectRatio() const { return m_AspectRatio; }
void SetAspectRatio(float val); void SetAspectRatio(float val);
@@ -45,12 +46,11 @@ public:
float FarClip() const { return m_FarClip; } float FarClip() const { return m_FarClip; }
void SetFarClip(float val); void SetFarClip(float val);
void UpdateViewMatrix();
void UpdateProjectionMatrix();
glm::vec2 WorldToScreen(glm::vec3 worldCoord, Rectangle resolution);
private: private:
void UpdateViewMatrix();
void UpdateProjectionMatrix();
glm::vec3 m_Position; glm::vec3 m_Position;
glm::quat m_Orientation; glm::quat m_Orientation;
@@ -0,0 +1,63 @@
#include <imgui/imgui.h>
#include "../Input/FirstPersonInputController.h"
template <typename EventContext>
class DebugCameraInputController : public FirstPersonInputController<EventContext>
{
public:
DebugCameraInputController(EventBroker* eventBroker, unsigned int playerID)
: FirstPersonInputController(eventBroker, playerID)
{ }
const glm::vec3 Position() const { return m_Position; }
void SetBaseSpeed(float speed) { m_BaseSpeed = speed; }
virtual bool OnCommand(const Events::InputCommand& e) override
{
ImGuiIO& io = ImGui::GetIO();
if (e.Command == "PrimaryFire") {
if (e.Value > 0) {
if (!io.WantCaptureMouse) {
LockMouse();
}
} else {
UnlockMouse();
}
return false;
}
if (!io.WantCaptureKeyboard) {
if (e.Command == "Right") {
float value = std::max(-1.f, std::min(e.Value, 1.f));
m_Velocity.x = value;
}
if (e.Command == "Forward") {
float value = std::max(-1.f, std::min(e.Value, 1.f));
m_Velocity.z = -value;
}
if (e.Command == "Sprint") {
if (e.Value > 0.f) {
m_Speed = m_BaseSpeed * 2.f * (e.Value);
} else {
m_Speed = m_BaseSpeed;
}
}
}
return FirstPersonInputController::OnCommand(e);
}
void Update(double dt)
{
if (glm::length2(m_Velocity) > 0) {
m_Position += m_Orientation * (glm::normalize(m_Velocity) * m_Speed * (float)dt);
}
}
protected:
glm::vec3 m_Position = glm::vec3(0, 0, 0);
glm::vec3 m_Velocity = glm::vec3(0, 0, 0);
float m_BaseSpeed = 2.0f;
float m_Speed = m_BaseSpeed;
};
@@ -1,35 +0,0 @@
#ifndef DirectionalLightJob_h__
#define DirectionalLightJob_h__
#include <cstdint>
#include "../Common.h"
#include "../GLM.h"
#include "../Core/ComponentWrapper.h"
#include "RenderJob.h"
#include "../Core/Transform.h"
#include "../Core/World.h"
struct DirectionalLightJob : RenderJob
{
DirectionalLightJob(ComponentWrapper transformComponent, ComponentWrapper directionalLightComponent, World* m_World)
: RenderJob()
{
Direction = glm::vec4(0,0,-1,0) * glm::inverse(Transform::AbsoluteOrientation(m_World, transformComponent.EntityID));
//Direction = glm::vec4((glm::vec3)directionalLightComponent["Direction"], 0.f);
Color = (glm::vec4)directionalLightComponent["Color"];
Intensity = (double)directionalLightComponent["Intensity"];
};
glm::vec4 Direction;
glm::vec4 Color;
float Intensity;
void CalculateHash() override
{
Hash = 0;
}
};
#endif
-53
View File
@@ -1,53 +0,0 @@
#ifndef DrawBloomPass_h__
#define DrawBloomPass_h__
#include "IRenderer.h"
#include "DrawBloomPassState.h"
//#include "LightCullingPass.h" Finalpass om den skall skickas in
#include "FrameBuffer.h"
#include "ShaderProgram.h"
//#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawBloomPass
{
public:
DrawBloomPass(IRenderer* renderer /* ,Texture or finalpass*/ );
~DrawBloomPass() { }
void InitializeTextures();
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void InitializeBuffers();
void ClearBuffer();
void FillGaussianBuffer(FrameBuffer* fb);
void Draw(GLuint texture);
//Getters
//Return the blurred result of the texture that was sent into draw
GLuint GaussianTexture() const { return m_GaussianTexture_vert; }
private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
Texture* m_WhiteTexture;
Model* m_ScreenQuad;
const IRenderer* m_Renderer;
//const LightCullingPass* m_LightCullingPass
GLuint m_iterations = 9;
GLuint m_GaussianTexture_horiz;
GLuint m_GaussianTexture_vert;
FrameBuffer m_GaussianFrameBuffer_horiz;
FrameBuffer m_GaussianFrameBuffer_vert;
ShaderProgram* m_GaussianProgram_horiz;
ShaderProgram* m_GaussianProgram_vert;
};
#endif
@@ -1,15 +0,0 @@
#ifndef DrawBloomPassState_h__
#define DrawBloomPassState_h__
#include "Rendering/RenderState.h"
class DrawBloomPassState : public RenderState
{
public:
DrawBloomPassState();
~DrawBloomPassState();
private:
};
#endif
@@ -1,29 +0,0 @@
#ifndef DrawColorCorrectionPass_h__
#define DrawColorCorrectionPass_h__
#include "IRenderer.h"
#include "DrawScreenQuadPassState.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
//#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
#include "imgui/imgui.h"
class DrawColorCorrectionPass
{
public:
DrawColorCorrectionPass(IRenderer* renderer);
~DrawColorCorrectionPass() { }
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(GLuint sceneTexture, GLuint bloomTexture, GLuint sceneTextureLowRes, GLuint bloomTextureLowRes, GLfloat gamma, GLfloat exposure);
private:
const IRenderer* m_Renderer;
ShaderProgram* m_ColorCorrectionProgram;
Model* m_ScreenQuad;
};
#endif
-85
View File
@@ -1,85 +0,0 @@
#ifndef DrawFinalPass_h__
#define DrawFinalPass_h__
#include "IRenderer.h"
#include "DrawFinalPassState.h"
#include "LightCullingPass.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawFinalPass
{
public:
DrawFinalPass(IRenderer* renderer, LightCullingPass* lightCullingPass);
~DrawFinalPass() { }
void InitializeTextures();
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(RenderScene& scene);
void ClearBuffer();
//Return the texture that is used in later stages to apply the bloom effect
GLuint BloomTexture() const { return m_BloomTexture; }
GLuint BloomTextureLowRes() const { return m_BloomTextureLowRes; }
//Return the texture with diffuse and lighting of the scene.
GLuint SceneTexture() const { return m_SceneTexture; }
GLuint SceneTextureLowRes() const { return m_SceneTextureLowRes; }
//Return the framebuffer used in the scene rendering stage.
FrameBuffer* FinalPassFrameBuffer() { return &m_FinalPassFrameBuffer; }
FrameBuffer* FinalPassFrameBufferLowRes() { return &m_FinalPassFrameBufferLowRes; }
private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
void GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint format, GLenum type, GLint numMipMaps) const;
void DrawModelRenderQueues(std::list<std::shared_ptr<RenderJob>>& jobs, RenderScene& scene);
void DrawShieldToStencilBuffer(std::list<std::shared_ptr<RenderJob>>& jobs, RenderScene& scene);
void DrawShieldedModelRenderQueue(std::list<std::shared_ptr<RenderJob>>& jobs, RenderScene& scene);
void DrawToDepthBuffer(std::list<std::shared_ptr<RenderJob>>& jobs, RenderScene& scene);
void BindExplosionUniforms(GLuint shaderHandle, std::shared_ptr<ExplosionEffectJob>& job, RenderScene& scene);
void BindModelUniforms(GLuint shaderHandle, std::shared_ptr<ModelJob>& job, RenderScene& scene);
void BindExplosionTextures(GLuint shaderHandle, std::shared_ptr<ExplosionEffectJob>& job);
void BindModelTextures(GLuint shaderHandle, std::shared_ptr<ModelJob>& job);
Texture* m_WhiteTexture;
Texture* m_BlackTexture;
Texture* m_NeutralNormalTexture;
Texture* m_GreyTexture;
FrameBuffer m_FinalPassFrameBuffer;
FrameBuffer m_FinalPassFrameBufferLowRes;
GLuint m_BloomTexture;
GLuint m_SceneTexture;
GLuint m_BloomTextureLowRes;
GLuint m_SceneTextureLowRes;
GLuint m_DepthBuffer;
GLuint m_DepthBufferLowRes;
//maqke this component based i guess?
GLuint m_ShieldPixelRate = 16;
const IRenderer* m_Renderer;
const LightCullingPass* m_LightCullingPass;
ShaderProgram* m_ForwardPlusProgram;
ShaderProgram* m_ExplosionEffectProgram;
ShaderProgram* m_ExplosionEffectSplatMapProgram;
ShaderProgram* m_ForwardPlusSplatMapProgram;
ShaderProgram* m_ShieldToStencilProgram;
ShaderProgram* m_FillDepthBufferProgram;
ShaderProgram* m_ForwardPlusSkinnedProgram;
ShaderProgram* m_ExplosionEffectSkinnedProgram;
ShaderProgram* m_ExplosionEffectSplatMapSkinnedProgram;
ShaderProgram* m_ForwardPlusSplatMapSkinnedProgram;
ShaderProgram* m_ShieldToStencilSkinnedProgram;
ShaderProgram* m_FillDepthBufferSkinnedProgram;
};
#endif
@@ -1,22 +0,0 @@
#ifndef DrawFinalPassState_h__
#define DrawFinalPassState_h__
#include "Rendering/RenderState.h"
class DrawFinalPassState : public RenderState
{
public:
DrawFinalPassState(GLuint frameBuffer);
~DrawFinalPassState();
private:
};
class DrawStencilState : public RenderState
{
public:
DrawStencilState(GLuint frameBuffer);
~DrawStencilState();
};
#endif
+36
View File
@@ -0,0 +1,36 @@
#ifndef DrawScenePass_h__
#define DrawScenePass_h__
#include "IRenderer.h"
#include "DrawScenePassState.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawScenePass
{
public:
DrawScenePass(IRenderer* renderer);
~DrawScenePass() { }
void InitializeTextures();
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(RenderQueueCollection& rq);
//Getters
private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
Texture* m_WhiteTexture;
const IRenderer* m_Renderer;
ShaderProgram* m_BasicForwardProgram;
};
#endif
@@ -0,0 +1,15 @@
#ifndef DrawScenePassState_h__
#define DrawScenePassState_h__
#include "Rendering/RenderState.h"
class DrawScenePassState : public RenderState
{
public:
DrawScenePassState();
~DrawScenePassState();
private:
};
#endif
@@ -1,28 +0,0 @@
#ifndef DrawScreenQuadPass_h__
#define DrawScreenQuadPass_h__
#include "IRenderer.h"
#include "DrawScreenQuadPassState.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
//#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawScreenQuadPass
{
public:
DrawScreenQuadPass(IRenderer* renderer);
~DrawScreenQuadPass() { }
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(GLuint texture);
private:
const IRenderer* m_Renderer;
ShaderProgram* m_DrawQuadProgram;
Model* m_ScreenQuad;
};
#endif
@@ -1,15 +0,0 @@
#ifndef DrawScreenQuadPassState_h__
#define DrawScreenQuadPassState_h__
#include "Rendering/RenderState.h"
class DrawScreenQuadPassState : public RenderState
{
public:
DrawScreenQuadPassState();
~DrawScreenQuadPassState();
private:
};
#endif
+1 -1
View File
@@ -9,7 +9,7 @@ class DummyRenderer : public IRenderer
{ {
public: public:
virtual void Initialize() override; virtual void Initialize() override;
virtual void Draw(RenderFrame& rq) override; virtual void Draw(RenderQueueCollection& rq) override;
}; };
#endif #endif
@@ -1,18 +0,0 @@
#ifndef Events_AnimationComplete_h__
#define Events_AnimationComplete_h__
#include "../Core/EventBroker.h"
#include "../Core/EntityWrapper.h"
namespace Events
{
struct AnimationComplete : Event
{
EntityWrapper Entity;
std::string Name;
};
}
#endif
+74
View File
@@ -0,0 +1,74 @@
#ifndef Events_Picking_h__
#define Events_Picking_h__
#include "../OpenGL.h"
#include "../GLM.h"
#include "../Core/EventBroker.h"
#include "Util/ScreenCoords.h"
#include "FrameBuffer.h"
#include "../Core/Entity.h"
#include "Util/UnorderedMapVec2.h"
namespace Events
{
/** Thrown Every frame, use functions to pick*/
struct Picking : Event
{
public:
Picking(FrameBuffer* pickingBuffer, GLuint* depthBuffer, glm::mat4 projectionMatrix, glm::mat4 viewMatrix, Rectangle resolution, const std::unordered_map<glm::vec2, EntityID>* pickingColorsToEntity)
: PickingBuffer(pickingBuffer)
, DepthBuffer(depthBuffer)
, ProjectionMatrix(projectionMatrix)
, ViewMatrix(viewMatrix)
, Resolution(resolution)
, PickingColorsToEntity(pickingColorsToEntity)
{ }
struct PickData
{
//Picked Entity
EntityID Entity;
//World position of the "pick"
glm::vec3 Position;
// Depth
float Depth;
};
PickData Pick(glm::vec2 screenCoord) const
{
PickData pickData;
// Invert screen y coordinate
screenCoord.y = Resolution.Height - screenCoord.y;
ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer);
pickData.Depth = data.Depth;
auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1]));
if (it != PickingColorsToEntity->end()) {
pickData.Entity = it->second;
} else {
pickData.Entity = EntityID_Invalid;
}
pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix);
return pickData;
}
private:
FrameBuffer* PickingBuffer;
GLuint* DepthBuffer;
const glm::mat4 ProjectionMatrix;
const glm::mat4 ViewMatrix;
const Rectangle Resolution;
const std::unordered_map<glm::vec2, EntityID>* PickingColorsToEntity;
};
}
#endif
-17
View File
@@ -1,17 +0,0 @@
#ifndef Events_SetCamera_h__
#define Events_SetCamera_h__
#include "../Core/EventBroker.h"
#include "../Core/EntityWrapper.h"
namespace Events
{
struct SetCamera : Event
{
EntityWrapper CameraEntity;
};
}
#endif
@@ -1,106 +0,0 @@
#ifndef ExplosionEffectJob_h__
#define ExplosionEffectJob_h__
#include <cstdint>
#include "../Common.h"
#include "../GLM.h"
#include "../Core/ComponentWrapper.h"
#include "Texture.h"
#include "Model.h"
#include "RenderJob.h"
#include "../Core/ResourceManager.h"
#include "Camera.h"
#include "../Core/World.h"
struct ExplosionEffectJob : ModelJob
{
ExplosionEffectJob(ComponentWrapper explosionEffectComponent, ::Model* model, Camera* camera, glm::mat4 matrix, ::RawModel::MaterialProperties matGroup, ComponentWrapper modelComponent, ::World* world, glm::vec4 fillColor, float fillPercentage)
: ModelJob(model, camera, matrix, matGroup, modelComponent, world, fillColor, fillPercentage)
{
ExplosionOrigin = (glm::vec3)explosionEffectComponent["ExplosionOrigin"];
TimeSinceDeath = (double)explosionEffectComponent["TimeSinceDeath"];
ExplosionDuration = (double)explosionEffectComponent["ExplosionDuration"];
EndColor = (glm::vec4)explosionEffectComponent["EndColor"];
Randomness = (bool)explosionEffectComponent["Randomness"];
RandomnessScalar = (double)explosionEffectComponent["RandomnessScalar"];
Velocity = (glm::vec2)explosionEffectComponent["Velocity"];
ColorByDistance = (bool)explosionEffectComponent["ColorByDistance"];
ExponentialAccelaration = (bool)explosionEffectComponent["ExponentialAccelaration"];
};
glm::vec3 ExplosionOrigin;
double TimeSinceDeath = 0.f; //Seconds
double ExplosionDuration = 2.f;
//bool Gravity = true;
//double GravityForce = 1.f; // Speed
//double ObjectRadius = 2.f; // TODO: Change this for object radius when it's available
glm::vec4 EndColor;
bool Randomness = false;
float RandomnessScalar = 1.f;
glm::vec2 Velocity;
bool ColorByDistance = false;
//bool ReverseAnimation = false;
//bool Wireframe = false;
bool ExponentialAccelaration = false;
std::array<float, 50> RandomNumbers = {
0.3257552917701f,
0.07601508315467f,
0.57408909014151f,
0.0f,
0.8618231368539f,
0.074957156588769f,
0.39413607511396f,
0.54579346698979f,
0.83222648353885f,
0.83635707285086f,
0.34473986148124f,
0.98092448710507f,
0.46346380070944f,
0.7308761201477f,
0.70832470371776f,
0.28268750909841f,
0.26291620883295f,
0.07685032816457f,
0.30760929515008f,
0.2781575388639f ,
0.016950582161988f ,
0.25787915254844f ,
0.76293767279151f ,
0.67730279903733f ,
0.49042877018937f ,
0.13002237823327f ,
0.62803373841012f ,
0.94525353747665f ,
0.32893980076953f ,
0.95952951719962f ,
0.056386206790985f ,
0.012030893476694f ,
0.93090049220757f,
0.83579883064879f,
0.79733513938139f,
0.8796381046435f ,
0.94160434600972f ,
0.76901855588379f ,
0.50253688101775f ,
0.82457069578793f ,
0.80157403359263f ,
0.87291810189975f ,
0.64679548919517f ,
0.42664138899494f ,
0.77171308303797f ,
0.75567959237643f ,
0.45190826265696f ,
0.59844922628181f ,
0.56534937655802f ,
0.195656257307f};
void CalculateHash() override
{
Hash = 0;
}
};
#endif
-36
View File
@@ -1,36 +0,0 @@
#ifndef Font_h__
#define Font_h__
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include "../OpenGL.h"
#include "../GLM.h"
#include "../Core/ResourceManager.h"
class Font : public Resource
{
friend class ResourceManager;
private:
Font(std::string path);
public:
struct Character {
GLuint TextureID; // ID handle of the glyph texture
glm::ivec2 Size; // Size of glyph
glm::ivec2 Bearing; // Offset from baseline to left/top of glyph
GLuint Advance; // Offset to advance to next glyph
};
int FontSize = 16;
~Font();
std::map<GLchar, Character> m_Characters;
};
#endif
+16 -20
View File
@@ -9,43 +9,39 @@
#include "Camera.h" #include "Camera.h"
#include "RenderQueue.h" #include "RenderQueue.h"
#include "Model.h" #include "Model.h"
#include "../Core/World.h" //So temp
struct PickData
{
EntityID Entity;
glm::vec3 Position; //World position
float Depth;
::Camera* Camera;
const ::World* World;
};
class IRenderer class IRenderer
{ {
public: public:
GLFWwindow* Window() const { return m_Window; } GLFWwindow* Window() const { return m_Window; }
//Returns screen size including window border and header
Rectangle Resolution() const { return m_Resolution; } Rectangle Resolution() const { return m_Resolution; }
virtual void SetResolution(const Rectangle& resolution) { m_Resolution = resolution; } void SetResolution(const Rectangle& resolution) { m_Resolution = resolution; }
bool Fullscreen() { return m_Fullscreen; } bool Fullscreen() { return m_Fullscreen; }
virtual void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; } void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; }
bool VSYNC() const { return m_VSYNC; } bool VSYNC() const { return m_VSYNC; }
virtual void SetVSYNC(bool vsync) { m_VSYNC = vsync; } void SetVSYNC(bool vsync) { m_VSYNC = vsync; }
//Returns screen size excluding window border and header ::Camera* Camera() const { return m_Camera; }
Rectangle GetViewportSize() const { return m_ViewportSize; } void SetCamera(::Camera* camera)
{
if (camera == nullptr) {
m_Camera = m_DefaultCamera;
} else {
m_Camera = camera;
}
}
virtual void Initialize() = 0; virtual void Initialize() = 0;
virtual void Update(double dt) = 0; virtual void Update(double dt) = 0;
virtual void Draw(RenderFrame& rq) = 0; virtual void Draw(RenderQueueCollection& rq) = 0;
virtual PickData Pick(glm::vec2 screenCord) = 0;
protected: protected:
Rectangle m_Resolution = Rectangle::Rectangle(1280, 720); Rectangle m_Resolution = Rectangle::Rectangle(1280, 720);
Rectangle m_ViewportSize = Rectangle::Rectangle(1280, 720);
bool m_Fullscreen = false; bool m_Fullscreen = false;
bool m_VSYNC = false; bool m_VSYNC = false;
int m_GLVersion[2]; int m_GLVersion[2];
std::string m_GLVendor; std::string m_GLVendor;
::Camera* m_DefaultCamera;
::Camera* m_Camera = nullptr;
GLFWwindow* m_Window = nullptr; GLFWwindow* m_Window = nullptr;
}; };
@@ -1,84 +0,0 @@
#ifndef LightCullingPass_h__
#define LightCullingPass_h__
#define TILE_SIZE 16
#define MAX_LIGHTS_PER_TILE 200
#include "IRenderer.h"
#include "LightCullingPassState.h"
#include "ShaderProgram.h"
#include "RenderQueue.h"
class LightCullingPass
{
public:
LightCullingPass(IRenderer* renderer);
~LightCullingPass();
void GenerateNewFrustum(RenderScene& scene);
void OnResolutionChange();
void SetSSBOSizes();
void CullLights(RenderScene& scene);
void FillLightList(RenderScene& scene);
GLuint FrustumSSBO() const { return m_FrustumSSBO; }
GLuint LightSSBO() const { return m_LightSSBO; }
GLuint LightGridSSBO() const { return m_LightGridSSBO; }
GLuint LightOffsetSSBO() const { return m_LightOffsetSSBO; }
GLuint LightIndexSSBO() const { return m_LightIndexSSBO; }
private:
void InitializeSSBOs();
void InitializeShaderPrograms();
const IRenderer* m_Renderer;
GLuint m_FrustumSSBO = 0;
GLuint m_LightSSBO = 0;
GLuint m_LightGridSSBO = 0;
GLuint m_LightOffsetSSBO = 0;
GLuint m_LightIndexSSBO = 0;
ShaderProgram* m_CalculateFrustumProgram;
ShaderProgram* m_LightCullProgram;
int m_NumberOfTiles = 0;
struct Plane {
glm::vec3 Normal = glm::vec3(0.f);
float d = 0;
};
struct Frustum {
Plane Planes[4];
};
Frustum* m_Frustums;
//This should be a component
struct LightSource {
glm::vec4 Position = glm::vec4(0.f);
glm::vec4 Direction = glm::vec4(10.f);
glm::vec4 Color = glm::vec4(1.f);
float Radius = 5.f;
float Intensity = 0.8f;
float Falloff = 0.3f;
enum Type_t { Zero, Point, Directional, Spot } Type;
};
std::vector<LightSource> m_LightSources;
struct LightGrid {
float Start = 0;
float Amount = 0;
glm::vec2 Padding = glm::vec2(1.f, 2.f);
};
LightGrid* m_LightGrid;
int m_LightOffset = 0;
float* m_LightIndex;
};
#endif
+5 -13
View File
@@ -1,12 +1,10 @@
#ifndef Model_h__ #ifndef Model_h__
#define Model_h__ #define Model_h__
#include "Rendering/RawModelCustom.h" #include "RawModel.h"
//#include "Rendering/RawModelAssimp.h"
#include "../OpenGL.h" #include "../OpenGL.h"
#include "Core/AABB.h"
class Model : public ThreadUnsafeResource class Model : public RawModel
{ {
friend class ResourceManager; friend class ResourceManager;
@@ -15,20 +13,14 @@ private:
public: public:
~Model(); ~Model();
const std::vector<RawModel::MaterialProperties>& MaterialGroups() const { return m_RawModel->m_Materials; }
const glm::mat4& Matrix() const { return m_RawModel->m_Matrix; }
const RawModel::Vertex* Vertices() const { return m_RawModel->Vertices(); }
unsigned int NumberOfVertices() const { return m_RawModel->NumVertices(); }
const AABB& Box() const { return m_Box; }
bool IsSkinned() const { return m_RawModel->IsSkinned(); }
GLuint VAO; GLuint VAO;
GLuint ElementBuffer; GLuint ElementBuffer;
RawModel* m_RawModel;
private: private:
AABB m_Box;
GLuint VertexBuffer; GLuint VertexBuffer;
GLuint DiffuseVertexColorBuffer;
GLuint SpecularVertexColorBuffer;
GLuint NormalBuffer; GLuint NormalBuffer;
GLuint TangentNormalsBuffer; GLuint TangentNormalsBuffer;
GLuint BiTangentNormalsBuffer; GLuint BiTangentNormalsBuffer;

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