Compare commits

..

2 Commits

Author SHA1 Message Date
Jace 13a6cf5a9b Groundwork for Steam Controller support 2015-12-11 00:41:51 +01:00
Jace b4df0c49ae Groundwork for input command proxy 2015-12-11 00:37:48 +01:00
157 changed files with 1807 additions and 9474 deletions
+10 -12
View File
@@ -1,21 +1,19 @@
#### Bundled libraries
Libraries bundled along with binaries for Windows (MSVC14), available as a submodule in the *deps* directory of the source tree.
| Project | Version | License |
| ---------------------------------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **[GLFW](http://www.glfw.org)** | 3.1.2 | [zlib/libpng License](http://www.glfw.org/license.html) |
| **[GLM](http://glm.g-truc.net/0.9.5/index.html)** | 0.9.7.1 | [MIT License](http://glm.g-truc.net/copying.txt) |
| **[GLEW](http://glew.sourceforge.net)** | 1.13.0 | [Modified BSD License](http://glew.sourceforge.net/glew.txt), [Mesa 3-D License](http://glew.sourceforge.net/mesa.txt), [Khronos License](http://glew.sourceforge.net/khronos.txt) |
| **[Assimp](http://assimp.sourceforge.net)** | 3.1.1 | [BSD 3-Clause License](http://assimp.sourceforge.net/main_license.html) |
| **[zlib](http://www.zlib.net)** | 1.28 | [zlib License](http://www.zlib.net/zlib_license.html) |
| **[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) |
| **[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 | https://github.com/mlabbe/nativefiledialog/blob/master/LICENSE |
| Project | Version | License |
| ------------------------------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **[GLFW](http://www.glfw.org)** | 3.1.2 | [zlib/libpng License](http://www.glfw.org/license.html) |
| **[GLM](http://glm.g-truc.net/0.9.5/index.html)** | 0.9.7.1 | [MIT License](http://glm.g-truc.net/copying.txt) |
| **[GLEW](http://glew.sourceforge.net)** | 1.13.0 | [Modified BSD License](http://glew.sourceforge.net/glew.txt), [Mesa 3-D License](http://glew.sourceforge.net/mesa.txt), [Khronos License](http://glew.sourceforge.net/khronos.txt) |
| **[Assimp](http://assimp.sourceforge.net)** | 3.1.1 | [BSD 3-Clause License](http://assimp.sourceforge.net/main_license.html) |
| **[zlib](http://www.zlib.net)** | 1.28 | [zlib License](http://www.zlib.net/zlib_license.html) |
| **[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) |
#### External libraries
Libraries that are too big to be bundled with the project.
| Project | Version | License | Root folder environment variable (Windows) |
| ---------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- | ------------------------------------------ |
| **[Boost](http://www.boost.org)** | 1.60.0+ | [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt) | BOOST_ROOT |
| **[Boost](http://www.boost.org)** | 1.59.0+ | [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt) | BOOST_ROOT |
+1 -1
Submodule assets updated: c8e631f449...b37468222e
+1 -1
Submodule deps updated: bf83f099ba...9861acd762
-59
View File
@@ -1,59 +0,0 @@
#ifndef Collision_h__
#define Collision_h__
//NOTE: Collision.h needs to be #included before <GLFW/glfw3.h>,
//because Collision #includes "RawModel.h", which has "Texture.h", which has "OpenGL.h" which must be #included first
//or you will get "fatal error C1189: #error: gl.h included before glew.h"
#include <vector>
#include "Core/Ray.h"
#include "Core/AABB.h"
#include "Engine/Rendering/RawModel.h"
#include "Core/Entity.h"
class World;
struct ComponentWrapper;
namespace Collision
{
//Return true if the ray hits the box.
bool RayAABBIntr(const Ray& ray, const AABB& box);
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].
bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance);
//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,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices);
//Return true if the ray hits any of the triangles in the model.
//Also returns the position of the intersection point. Will loop through all the whole model indices.
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices,
glm::vec3& outHitPosition);
//Return true if the ray hits any of the triangles in the model.
//Also returns the distance from the ray origin to the closest
//intersection point, and the barycentric u,v-coordinates. Will loop through all the whole model indices.
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices,
float& outDistance,
float& outUCoord,
float& outVCoord);
//Return true if the boxes are intersecting.
bool AABBVsAABB(const AABB& a, const AABB& b);
//Return true if the boxes are intersecting.
//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 IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon = 0.0001f);
//Returns true if the entity has a boundingbox. Outputs the aabb in [outBox].
bool GetEntityBox(World* world, EntityID entity, AABB& outBox, bool forceBoxFromModel = false);
bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox);
}
#endif
@@ -1,31 +0,0 @@
#ifndef CollisionSystem_h__
#define CollisionSystem_h__
#include <GLFW/glfw3.h>
#include <glm/common.hpp>
#include "Common.h"
#include "Core/System.h"
#include "Core/EventBroker.h"
#include "Core/EKeyUp.h"
class CollisionSystem : public PureSystem
{
public:
CollisionSystem(EventBroker* eventBroker)
: PureSystem(eventBroker, "AABB")
, zPress(false)
{
//TODO: Debug stuff, remove later.
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp);
}
virtual void UpdateComponent(World* world, ComponentWrapper& cAABB, double dt) override;
private:
bool zPress;
EventRelay<CollisionSystem, Events::KeyUp> m_EKeyUp;
bool OnKeyUp(const Events::KeyUp &event);
};
#endif
-39
View File
@@ -1,39 +0,0 @@
#ifndef Events_TriggerEnter_h__
#define Events_TriggerEnter_h__
#include "../Core/EventBroker.h"
#include "../Core/Entity.h"
namespace Events
{
/** Thrown once, when an entity is only touching a trigger. */
struct TriggerTouch : Event
{
/** The id of the entity that touches the trigger. */
EntityID Entity;
/** The id of the trigger entity. */
EntityID Trigger;
};
/** Thrown once, when an entity has completely left a trigger. */
struct TriggerLeave : Event
{
/** The id of the entity that left the trigger. */
EntityID Entity;
/** The id of the trigger entity. */
EntityID Trigger;
};
/** Thrown once, when an entity is completely contained inside a trigger. */
struct TriggerEnter : Event
{
/** The id of the entity that entered the trigger. */
EntityID Entity;
/** The id of the trigger entity. */
EntityID Trigger;
};
}
#endif
-38
View File
@@ -1,38 +0,0 @@
#ifndef TriggerSystem_h__
#define TriggerSystem_h__
#include <glm/common.hpp>
#include <unordered_set>
#include "Core/System.h"
#include "Core/EventBroker.h"
#include "ETrigger.h"
class AABB;
class TriggerSystem : public PureSystem
{
public:
TriggerSystem(EventBroker* eventBroker)
: PureSystem(eventBroker, "Trigger")
{}
virtual void UpdateComponent(World* world, ComponentWrapper& collision, double dt) override;
private:
std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesTouchingTrigger;
std::unordered_map<EntityID, std::unordered_set<EntityID>> m_EntitiesCompletelyInTrigger;
//True if leave event was thrown.
bool throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId);
template<typename Event>
void publish(EntityID pId, EntityID tId)
{
Event e;
e.Trigger = tId;
e.Entity = pId;
m_EventBroker->Publish(e);
}
};
#endif
+1 -2
View File
@@ -4,5 +4,4 @@
#include <map>
#include <unordered_map>
#include "Core/Util/Logging.h"
#include "Core/Util/IfDebug.h"
#include "Core/Util/Logging.h"
-29
View File
@@ -1,29 +0,0 @@
#ifndef AABB_h__
#define AABB_h__
#include "../GLM.h"
class AABB
{
public:
AABB() = default;
//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::vec4& minPos, const glm::vec4& maxPos);
//No checks are made. Size must consist of non-negative numbers.
virtual void CreateFromCenter(const glm::vec3& center, const glm::vec3& size);
virtual ~AABB();
const glm::vec3& MinCorner() const { return m_MinCorner; }
const glm::vec3& MaxCorner() const { return m_MaxCorner; }
const glm::vec3& Center() const { return m_Center; }
const glm::vec3 Size() const { return 2.0f * m_HalfSize; }
const glm::vec3& HalfSize() const { return m_HalfSize; }
private:
glm::vec3 m_MinCorner;
glm::vec3 m_MaxCorner;
glm::vec3 m_Center;
glm::vec3 m_HalfSize;
};
#endif
+2 -9
View File
@@ -12,16 +12,9 @@ struct ComponentInfo
unsigned int Stride = 0;
};
struct Field_t
{
std::string Type;
unsigned int Offset;
unsigned int Stride;
};
std::string Name;
std::unordered_map<std::string, Field_t> Fields;
std::vector<const Field_t*> FieldsInOrder;
std::unordered_map<std::string, std::string> FieldTypes;
std::unordered_map<std::string, unsigned int> FieldOffsets;
Meta_t Meta;
std::shared_ptr<char> Defaults = nullptr;
};
+1 -3
View File
@@ -20,7 +20,7 @@ public:
~ComponentPoolForwardIterator() = default;
ComponentPoolForwardIterator& operator=(const ComponentPoolForwardIterator& other) = default;
ComponentPoolForwardIterator& operator++();
ComponentPoolForwardIterator operator++(int);
ComponentPoolForwardIterator& operator++(int);
bool operator!=(const ComponentPoolForwardIterator& other) const;
bool operator==(const ComponentPoolForwardIterator& other) const;
ComponentWrapper operator*() const;
@@ -54,8 +54,6 @@ public:
ComponentWrapper Allocate(EntityID entity);
// Get the component belonging to a specific entity
ComponentWrapper GetByEntity(EntityID ent);
// Returns true if the pool contains a component for the specified entity
bool KnowsEntity(EntityID ent);
// Delete a component and free its memory
void Delete(ComponentWrapper& wrapper);
+3 -4
View File
@@ -21,7 +21,7 @@ struct ComponentWrapper
template <typename T>
T& Property(std::string name)
{
unsigned int offset = Info.Fields.at(name).Offset;
unsigned int offset = Info.FieldOffsets.at(name);
return *reinterpret_cast<T*>(&Data[offset]);
}
@@ -78,9 +78,8 @@ public:
void AddProperty(std::string fieldName, T defaultValue)
{
m_DefaultValues.push_back(defaultValue);
m_ComponentInfo.Fields[fieldName].Name = typeid(T).name();
m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Meta.Stride;
m_ComponentInfo.Fields[fieldName].Stride = sizeof(T);
m_ComponentInfo.FieldTypes[fieldName] = typeid(T).name();
m_ComponentInfo.FieldOffsets[fieldName] = m_ComponentInfo.Meta.Stride;
m_ComponentInfo.Meta.Stride += sizeof(T);
}
+10 -34
View File
@@ -3,10 +3,9 @@
#include <string>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptors.hpp>
#include <ini_file/ini_file.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include "../Common.h"
#include "ResourceManager.h"
@@ -23,49 +22,26 @@ public:
template <typename T>
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();
private:
private:
boost::filesystem::path m_Path;
ini_file::section_map m_Defaults;
ini_file::section_map m_Overrides;
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);
boost::property_tree::ptree m_PTreeDefaults;
boost::property_tree::ptree m_PTreeOverrides;
boost::property_tree::ptree m_PTreeMerged;
};
template <typename T>
T ConfigFile::Get(std::string key, T defaultValue)
{
auto param = GetParam(key);
if (param == nullptr) {
return defaultValue;
}
return boost::lexical_cast<T>(param->get_value());
return m_PTreeMerged.get<T>(key, defaultValue);
}
template <typename T>
void ConfigFile::Set(std::string key, T value)
{
std::string section;
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);
m_PTreeOverrides.put<T>(key, value);
m_PTreeMerged.put<T>(key, value);
}
#endif
-157
View File
@@ -1,157 +0,0 @@
#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
-16
View File
@@ -1,16 +0,0 @@
#ifndef EFileDropped_h__
#define EFileDropped_h__
#include "EventBroker.h"
namespace Events
{
struct FileDropped : Event
{
std::string Path;
};
}
#endif
-17
View File
@@ -1,17 +0,0 @@
#ifndef Events_KeyboardChar_h__
#define Events_KeyboardChar_h__
#include "EventBroker.h"
namespace Events
{
struct KeyboardChar : Event
{
double Timestamp = 0.f;
unsigned int Char = 0;
};
}
#endif
-17
View File
@@ -1,17 +0,0 @@
#ifndef Events_MouseScroll_h__
#define Events_MouseScroll_h__
#include "EventBroker.h"
namespace Events
{
struct MouseScroll : Event
{
double DeltaX;
double DeltaY;
};
}
#endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef EPlayerDamage_h__
#define EPlayerDamage_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
namespace Events
{
struct PlayerDamage : Event
{
double DamageAmount;
EntityID PlayerDamagedID;
//optional TypeOfDamage
std::string TypeOfDamage;
};
}
#endif
-20
View File
@@ -1,20 +0,0 @@
#ifndef EPlayerDeath_h__
#define EPlayerDeath_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
namespace Events
{
struct PlayerDeath : Event
{
//KilledBy,KilledByWhat is optional for now. It might be used later in the playerlog-system
EntityID KilledBy;
EntityID PlayerID;
std::string KilledByWhat;
};
}
#endif
-18
View File
@@ -1,18 +0,0 @@
#ifndef EPlayerHealthPickup_h__
#define EPlayerHealthPickup_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
namespace Events
{
struct PlayerHealthPickup : Event
{
double HealthAmount;
EntityID PlayerHealedID;
};
}
#endif
-1
View File
@@ -2,6 +2,5 @@
#define Entity_h__
typedef unsigned int EntityID;
const static unsigned int EntityID_Invalid = -1;
#endif
-293
View File
@@ -1,293 +0,0 @@
#ifndef EntityFile_h__
#define EntityFile_h__
#include <stack>
#include <boost/lexical_cast.hpp>
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/sax2/SAX2XMLReader.hpp>
#include <xercesc/sax2/XMLReaderFactory.hpp>
#include <xercesc/sax2/DefaultHandler.hpp>
#include <xercesc/sax2/Attributes.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLChar.hpp>
#include <xercesc/sax2/DefaultHandler.hpp>
#include <xercesc/framework/XMLDocumentHandler.hpp>
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp>
#include <xercesc/framework/psvi/XSModelGroup.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMLSInput.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include "../GLM.h"
#include "Util/XercesString.h"
#include "ResourceManager.h"
#include "Entity.h"
#include "ComponentInfo.h"
class EntityFileHandler
{
friend class EntityFileSAXHandler;
public:
// @param EntityID The entity found
// @param EntityID The parent of the entity
typedef std::function<void(EntityID, EntityID, const std::string&)> OnStartEntityCallback;
void SetStartEntityCallback(OnStartEntityCallback c) { m_OnStartEntityCallback = c; }
// @param EntityID The entity the component corresponds to
// @param std::string Type name of the component
typedef std::function<void(EntityID, const std::string&)> OnStartComponentCallback;
void SetStartComponentCallback(OnStartComponentCallback c) { m_OnStartComponentCallback = c; }
// @param EntityID Entity
// @param std::string Component name
// @param std::string Field name
// @param std::map<std::string, std::string> Field attribute names and values
typedef std::function<void(EntityID, const std::string&, const std::string&, const std::map<std::string, std::string>&)> OnStartFieldCallback;
void SetStartFieldCallback(OnStartFieldCallback c) { m_OnStartFieldCallback = c; }
// @param EntityID Entity
// @param std::string Component name
// @param std::string Field name
// @param char* Field data
typedef std::function<void(EntityID, const std::string&, const std::string&, const char*)> OnStartFieldDataCallback;
void SetStartFieldDataCallback(OnStartFieldDataCallback c) { m_OnStartFieldDataCallback = c; }
private:
OnStartEntityCallback m_OnStartEntityCallback = nullptr;
OnStartComponentCallback m_OnStartComponentCallback = nullptr;
OnStartFieldCallback m_OnStartFieldCallback = nullptr;
OnStartFieldDataCallback m_OnStartFieldDataCallback = nullptr;
};
class EntityFileSAXHandler : public xercesc::DefaultHandler
{
public:
enum class State
{
Unknown,
Entity,
Component,
ComponentField
};
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
{
std::string name = XS::ToString(_localName);
if (m_StateStack.top() == State::Unknown || m_StateStack.top() == State::Entity) {
if (name == "Entity") {
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:
const EntityFileHandler* m_Handler;
xercesc::XMLGrammarPool* m_GrammarPool;
xercesc::SAX2XMLReader* m_Reader;
//State m_CurrentScope = State::Unknown;
std::stack<State> m_StateStack;
unsigned int m_NextEntityID = 0;
std::stack<EntityID> m_EntityStack;
std::string m_CurrentComponent;
std::string m_CurrentField;
std::map<std::string, std::string> m_CurrentAttributes;
void onStartEntity(const xercesc::Attributes& attrs)
{
EntityID parent = m_EntityStack.top();
if (m_Handler->m_OnStartEntityCallback) {
std::string name;
auto xName = attrs.getValue(XS::ToXMLCh("name"));
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
{
public:
void warning(const xercesc::SAXParseException& e) override
{
reportParseException("Warning", e);
}
void error(const xercesc::SAXParseException& e) override
{
reportParseException("Error", e);
}
void fatalError(const xercesc::SAXParseException& e) override
{
reportParseException("FATAL ERROR", e);
}
void resetErrors() override { }
private:
void reportParseException(std::string type, const xercesc::SAXParseException& e)
{
char* message = xercesc::XMLString::transcode(e.getMessage());
char* systemID = xercesc::XMLString::transcode(e.getSystemId());
std::cerr << systemID << ":" << e.getLineNumber() << ":" << e.getColumnNumber() << std::endl;
std::cerr << type << ": " << message << std::endl;
xercesc::XMLString::release(&systemID);
xercesc::XMLString::release(&message);
}
};
class EntityFile : public Resource
{
friend class ResourceManager;
private:
EntityFile(boost::filesystem::path path);
~EntityFile();
public:
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 WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData);
xercesc::XMLGrammarPool* GrammarPool() const { return m_GrammarPool; }
void Parse(const EntityFileHandler* handler) const;
private:
boost::filesystem::path m_FilePath;
xercesc::XMLGrammarPool* m_GrammarPool;
xercesc::SAX2XMLReader* m_SAX2XMLReader;
//std::map<std::string, ::ComponentInfo> m_ComponentInfo;
//std::vector<std::string> m_EntityReferences;
};
#endif
-28
View File
@@ -1,28 +0,0 @@
#ifndef EntityFileParser_h__
#define EntityFileParser_h__
#include "EntityFile.h"
#include "World.h"
class EntityFileParser
{
public:
EntityFileParser(const EntityFile* entityFile);
void MergeEntities(World* world);
private:
const EntityFile* m_EntityFile;
EntityFileHandler m_Handler;
World* m_World = nullptr;
// Maps EntityIDs local to the file to real IDs in the world after they've been
// created in order to resolve parent-child relationships.
std::map<EntityID, EntityID> m_EntityIDMapper;
void onStartEntity(EntityID entity, EntityID parent, const std::string& name);
void onStartComponent(EntityID entity, const std::string& component);
void onStartComponentField(EntityID entity, const std::string& componentType, const std::string& fieldName, const std::map<std::string, std::string>& attributes);
void onFieldData(EntityID entity, const std::string& componentType, const std::string& fieldName, const char* fieldData);
};
#endif
@@ -1,36 +0,0 @@
#ifndef EntityFilePreprocessor_h__
#define EntityFilePreprocessor_h__
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp>
#include <xercesc/framework/psvi/XSModelGroup.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include "Util/XercesString.h"
#include "ResourceManager.h"
#include "World.h"
#include "EntityFile.h"
class EntityFilePreprocessor
{
public:
EntityFilePreprocessor(const EntityFile* entityFile);
void RegisterComponents(World* world);
private:
const EntityFile* m_EntityFile;
std::map<std::string, unsigned int> m_ComponentCounts;
std::map<std::string, ComponentInfo> m_ComponentInfo;
void onStartComponent(EntityID entity, std::string type);
void parseComponentInfo();
void parseDefaults();
};
#endif
-39
View File
@@ -1,39 +0,0 @@
#ifndef EntityFileWriter_h__
#define EntityFileWriter_h__
#include <boost/filesystem.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include "Util/XercesString.h"
#include "EntityFile.h"
#include "World.h"
class EntityFileWriter
{
public:
EntityFileWriter(boost::filesystem::path file)
: m_FilePath(file)
{
using namespace xercesc;
m_DOMImplementation = DOMImplementationRegistry::getDOMImplementation(XS::ToXMLCh("LS"));
m_DOMLSSerializer = static_cast<DOMImplementationLS*>(m_DOMImplementation)->createLSSerializer();
m_DOMLSSerializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTDiscardDefaultContent, true);
m_DOMLSSerializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
}
void WriteWorld(World* world);
void WriteEntity(World* world, EntityID entity);
private:
boost::filesystem::path m_FilePath;
xercesc::DOMImplementation* m_DOMImplementation;
xercesc::DOMLSSerializer* m_DOMLSSerializer;
void appendEntityChildren(xercesc::DOMElement* parentElement, const World* world, EntityID entity);
void appentEntityComponents(xercesc::DOMElement* parentElemetn, const World* world, EntityID entity);
};
#endif
+141
View File
@@ -0,0 +1,141 @@
#ifndef EntityXMLFile_h__
#define EntityXMLFile_h__
#include <sstream>
#include "../Common.h"
#include "../GLM.h"
#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMLSInput.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLFloat.hpp>
#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp>
#include <xercesc/framework/psvi/XSModelGroup.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include "ResourceManager.h"
#include "Entity.h"
#include "ComponentInfo.h"
class World;
class EntityPreprocessorXMLErrorHandler : public xercesc::DOMErrorHandler
{
public:
bool handleError(const xercesc::DOMError &e) override
{
char* message = xercesc::XMLString::transcode(e.getMessage());
std::cerr << "Preprocessor DOMError: " << message << std::endl;
xercesc::XMLString::release(&message);
return false;
}
};
class EntityParserXMLErrorHandler : public xercesc::ErrorHandler
{
public:
void warning(const xercesc::SAXParseException& e) override
{
reportParseException("Warning", e);
}
void error(const xercesc::SAXParseException& e) override
{
reportParseException("Error", e);
}
void fatalError(const xercesc::SAXParseException& e) override
{
reportParseException("FATAL ERROR", e);
}
void resetErrors() override { }
private:
void reportParseException(std::string type, const xercesc::SAXParseException& e)
{
char* message = xercesc::XMLString::transcode(e.getMessage());
char* systemID = xercesc::XMLString::transcode(e.getSystemId());
std::cerr << systemID << ":" << e.getLineNumber() << ":" << e.getColumnNumber() << std::endl;
std::cerr << type << ": " << message << std::endl;
xercesc::XMLString::release(&systemID);
xercesc::XMLString::release(&message);
}
};
class XSTR
{
public:
XSTR(const XMLCh* const xmlString)
{
m_AsChar = xercesc::XMLString::transcode(xmlString);
}
XSTR(const char* normalString)
{
m_AsXMLCh = xercesc::XMLString::transcode(normalString);
}
~XSTR()
{
if (m_AsChar != nullptr) {
xercesc::XMLString::release(&m_AsChar);
}
if (m_AsXMLCh != nullptr) {
xercesc::XMLString::release(&m_AsXMLCh);
}
}
operator const char*() const { return m_AsChar; }
operator const XMLCh*() const { return m_AsXMLCh; }
private:
char* m_AsChar = nullptr;
XMLCh* m_AsXMLCh = nullptr;
};
class EntityXMLFile : public Resource
{
friend class ResourceManager;
private:
EntityXMLFile(std::string path);
public:
~EntityXMLFile();
void PopulateWorld(World* world);
private:
static unsigned int InstanceCount;
std::string m_EntityFile;
xercesc::XMLGrammarPool* m_GrammarPool = nullptr;
EntityParserXMLErrorHandler* m_ErrorHandler = nullptr;
xercesc::XercesDOMParser* m_DOMParser = nullptr;
xercesc::DOMDocument* m_DOMDocument = nullptr;
std::map<std::string, ComponentInfo> m_ComponentInfo;
// Preprocesses the entity file to insert include-by-copy child entities
// TODO: Make this work in memory instead of saving to file
void preprocess(std::string inPath, std::string outPath);
void parseComponentInfo();
void parseDefaults();
void predictComponentAllocation();
void parseEntityGraph(World* world, xercesc::DOMElement* parent, EntityID parentEntity);
std::size_t getTypeStride(std::string typeName);
float getFloatAttribute(const xercesc::DOMElement* element, const char* attribute) const;
void writeData(const xercesc::DOMElement* element, std::string typeName, char* outData);
};
#endif
+67 -71
View File
@@ -13,127 +13,123 @@
relay = decltype(relay)(std::bind(handler, this, std::placeholders::_1)); \
m_EventBroker->Subscribe(relay);
typedef unsigned int EventID;
class EventBroker;
class BaseEventRelay
{
friend class EventBroker;
friend class EventBroker;
protected:
BaseEventRelay(std::string contextTypeName, std::string eventTypeName)
: m_ContextTypeName(contextTypeName)
, m_EventTypeName(eventTypeName)
, m_Broker(nullptr)
{ }
~BaseEventRelay();
BaseEventRelay(std::string contextTypeName, std::string eventTypeName)
: m_ContextTypeName(contextTypeName)
, m_EventTypeName(eventTypeName)
, m_Broker(nullptr)
{ }
~BaseEventRelay();
public:
virtual bool Receive(const std::shared_ptr<Event> event) = 0;
virtual bool Receive(const std::shared_ptr<Event> event) = 0;
protected:
EventID m_EventID;
std::string m_ContextTypeName;
std::string m_EventTypeName;
EventBroker* m_Broker;
std::string m_ContextTypeName;
std::string m_EventTypeName;
EventBroker* m_Broker;
};
template <typename ContextType, typename EventType>
class EventRelay : public BaseEventRelay
{
public:
typedef std::function<bool(const EventType&)> CallbackType;
typedef std::function<bool(const EventType&)> CallbackType;
EventRelay()
: m_Callback(nullptr)
, BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name())
{ }
EventRelay(CallbackType callback)
: m_Callback(callback)
, BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name())
{ }
EventRelay()
: m_Callback(nullptr)
, BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name())
{ }
EventRelay(CallbackType callback)
: m_Callback(callback)
, BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name())
{ }
protected:
bool Receive(const std::shared_ptr<Event> event) override;
bool Receive(const std::shared_ptr<Event> event) override;
private:
CallbackType m_Callback;
CallbackType m_Callback;
};
template <typename ContextType, typename EventType>
bool EventRelay<ContextType, EventType>::Receive(const std::shared_ptr<Event> event)
{
if (m_Callback != nullptr) {
return m_Callback(*static_cast<const EventType*>(event.get()));
} else {
return false;
}
if (m_Callback != nullptr) {
return m_Callback(*static_cast<const EventType*>(event.get()));
} else {
return false;
}
}
class EventBroker
{
template <typename ContextType, typename EventType> friend class EventRelay;
template <typename ContextType, typename EventType> friend class EventRelay;
public:
EventBroker()
{
m_EventQueueRead = std::make_shared<EventQueue_t>();
m_EventQueueWrite = std::make_shared<EventQueue_t>();
}
EventBroker()
{
m_EventQueueRead = std::make_shared<EventQueue_t>();
m_EventQueueWrite = std::make_shared<EventQueue_t>();
}
void Subscribe(BaseEventRelay &relay);
template <typename EventType>
void Publish(const EventType &event);
/*
Process all events in a given context.
Returns: Number of events processed
*/
template <typename ContextType>
int Process();
int Process(std::string contextTypeName);
void Swap();
void Clear();
void Unsubscribe(BaseEventRelay &relay);
void Subscribe(BaseEventRelay &relay);
template <typename EventType>
void Publish(const EventType &event);
/*
Process all events in a given context.
Returns: Number of events processed
*/
template <typename ContextType>
int Process();
int Process(std::string contextTypeName);
void Swap();
void Clear();
void Unsubscribe(BaseEventRelay &relay);
private:
bool m_IsProcessing = false;
EventID m_NextEventID = 0;
bool m_IsProcessing = false;
typedef std::string ContextTypeName_t; // typeid(ContextType).name()
typedef std::string EventTypeName_t; // typeid(EventType).name()
typedef std::string ContextTypeName_t; // typeid(ContextType).name()
typedef std::string EventTypeName_t; // typeid(EventType).name()
typedef std::unordered_multimap<EventTypeName_t, BaseEventRelay*> EventRelays_t;
typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t;
ContextRelays_t m_ContextRelays;
std::vector<BaseEventRelay*> m_RelaysToSubscribe;
std::vector<std::tuple<EventID, ContextTypeName_t, EventTypeName_t>> m_RelaysToUnsubscribe;
typedef std::unordered_multimap<EventTypeName_t, BaseEventRelay*> EventRelays_t;
typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t;
ContextRelays_t m_ContextRelays;
std::vector<BaseEventRelay*> m_RelaysToSubscribe;
std::vector<BaseEventRelay*> m_RelaysToUnsubscribe;
typedef std::list<std::pair<EventTypeName_t, std::shared_ptr<Event>>> EventQueue_t;
std::shared_ptr<EventQueue_t> m_EventQueueRead;
std::shared_ptr<EventQueue_t> m_EventQueueWrite;
typedef std::list<std::pair<EventTypeName_t, std::shared_ptr<Event>>> EventQueue_t;
std::shared_ptr<EventQueue_t> m_EventQueueRead;
std::shared_ptr<EventQueue_t> m_EventQueueWrite;
void subscribeImmediate(BaseEventRelay& relay);
void unsubscribeImmediate(std::tuple<EventID, ContextTypeName_t, EventTypeName_t> identifier);
void subscribeImmediate(BaseEventRelay& relay);
void unsubscribeImmediate(BaseEventRelay& relay);
};
template <typename EventType>
void EventBroker::Publish(const EventType &event)
{
/*auto itpair = m_Subscribers.equal_range(typeid(EventType).name());
for (auto it = itpair.first; it != itpair.second; ++it)
{
it->second->Receive(event);
}*/
/*auto itpair = m_Subscribers.equal_range(typeid(EventType).name());
for (auto it = itpair.first; it != itpair.second; ++it)
{
it->second->Receive(event);
}*/
m_EventQueueWrite->push_back(std::make_pair(typeid(EventType).name(), std::shared_ptr<EventType>(new EventType(event))));
m_EventQueueWrite->push_back(std::make_pair(typeid(EventType).name(), std::shared_ptr<EventType>(new EventType(event))));
}
template <typename ContextType>
int EventBroker::Process()
{
const std::string contextTypeName = typeid(ContextType).name();
return Process(contextTypeName);
const std::string contextTypeName = typeid(ContextType).name();
return Process(contextTypeName);
}
#endif
+7 -4
View File
@@ -11,22 +11,25 @@ template <typename EventContext>
class InputController
{
public:
InputController(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
InputController(std::shared_ptr<dd::EventBroker> eventBroker)
: EventBroker(eventBroker)
{ Initialize(); }
virtual void Initialize()
{
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &InputController::OnCommand);
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &InputController::OnMouseMove);
}
virtual bool OnCommand(const Events::InputCommand& e) { return false; }
virtual bool OnCommand(const Events::InputCommand &event) { return false; }
virtual bool OnMouseMove(const Events::MouseMove &event) { return false; }
protected:
EventBroker* m_EventBroker;
std::shared_ptr<dd::EventBroker> EventBroker;
private:
EventRelay<EventContext, Events::InputCommand> m_EInputCommand;
EventRelay<EventContext, Events::MouseMove> m_EMouseMove;
};
#endif
-10
View File
@@ -8,15 +8,12 @@
#include "EventBroker.h"
#include "EKeyDown.h"
#include "EKeyUp.h"
#include "EKeyboardChar.h"
#include "EMousePress.h"
#include "EMouseRelease.h"
#include "EMouseMove.h"
#include "EMouseScroll.h"
#include "ELockMouse.h"
#include "EGamepadAxis.h"
#include "EGamepadButton.h"
#include "EFileDropped.h"
class InputManager
{
@@ -67,13 +64,6 @@ private:
void PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis);
void PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button);
static std::vector<unsigned int> GLFWCharCallbackQueue;
static void GLFWCharCallback(GLFWwindow* window, unsigned int c);
static std::vector<std::pair<double, double>> GLFWScrollCallbackQueue;
static void GLFWScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
static std::vector<std::string> GLFWDropCallbackQueue;
static void GLFWDropCallback(GLFWwindow* window, int count, const char* paths[]);
};
#endif
+1 -1
View File
@@ -253,7 +253,7 @@ public:
}
//Postfix increment i.e. iter++. Prefer pre-increment (++iter) for efficiency.
MemoryPoolForwardIterator operator++(int)
MemoryPoolForwardIterator& operator++(int)
{
MemoryPoolForwardIterator<T> copyIter(*this);
operator++();
-104
View File
@@ -1,104 +0,0 @@
#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
-31
View File
@@ -1,31 +0,0 @@
#ifndef Ray_h__
#define Ray_h__
#include "../GLM.h"
#include "Common.h"
class Ray
{
public:
Ray(const glm::vec3& origin, const glm::vec3& dir)
: m_Origin(origin)
, m_Direction(glm::normalize(dir))
{
DEBUG_IF(true) {
if (glm::any(glm::isnan(m_Direction))) {
LOG_WARNING("Ray Direction was set to the zero-vector, expect unknown side effects and/or crashes.");
}
}
}
const glm::vec3& Origin() const { return m_Origin; }
const glm::vec3& Direction() const { return m_Direction; }
//Sets the ray origin at parameter.
void SetOrigin(const glm::vec3& origin) { m_Origin = origin; }
//Normalizes the parameter and sets direction to it.
void SetDirection(const glm::vec3& direction) { m_Direction = glm::normalize(direction); }
private:
glm::vec3 m_Origin;
glm::vec3 m_Direction;
};
#endif // Ray_h__
+6 -31
View File
@@ -9,42 +9,17 @@ class System
{
friend class SystemPipeline;
protected:
System(EventBroker* eventBroker)
public:
System(const EventBroker* eventBroker, std::string componentType)
: m_EventBroker(eventBroker)
{ }
virtual ~System() = default;
EventBroker* m_EventBroker;
};
class PureSystem : public System
{
friend class SystemPipeline;
protected:
PureSystem(EventBroker* eventBroker, std::string componentType)
: System(eventBroker)
, m_ComponentType(componentType)
{ }
virtual ~PureSystem() = default;
const std::string m_ComponentType;
virtual void Update(World* world, ComponentWrapper& component, double dt) = 0;
virtual void UpdateComponent(World* world, ComponentWrapper& component, double dt) = 0;
};
class ImpureSystem : public System
{
friend class SystemPipeline;
protected:
ImpureSystem(EventBroker* eventBroker)
: System(eventBroker)
{ }
virtual ~ImpureSystem() = default;
virtual void Update(World* world, double dt) = 0;
private:
const EventBroker* m_EventBroker;
std::string m_ComponentType;
};
#endif
+21 -52
View File
@@ -9,81 +9,50 @@
class SystemPipeline
{
public:
SystemPipeline(EventBroker* eventBroker)
SystemPipeline(const EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{ }
~SystemPipeline()
{
for (UnorderedSystems& group : m_OrderedSystemGroups) {
for (auto& pair : group.Systems) {
delete pair.second;
for (auto& pair : m_Systems) {
for (auto& system : pair.second) {
delete system;
}
}
}
template <typename T, typename... Arguments>
//All systems with orderlevel 0 will be updated first, then 1, 2, etc.
void AddSystem(int updateOrderLevel, Arguments... args)
void AddSystem(Arguments... args)
{
if (updateOrderLevel + 1 > m_OrderedSystemGroups.size()) {
m_OrderedSystemGroups.resize(updateOrderLevel + 1);
}
UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel];
System* system = new T(m_EventBroker, args...);
group.Systems[typeid(T).name()] = system;
if (std::is_base_of<PureSystem, T>::value) {
PureSystem* pureSystem = static_cast<PureSystem*>(system);
if (!pureSystem->m_ComponentType.empty()) {
group.PureSystems[pureSystem->m_ComponentType].push_back(pureSystem);
} else {
LOG_ERROR("Failed to add pure system \"%s\": Missing component type!", typeid(T).name());
}
}
if (std::is_base_of<ImpureSystem, T>::value) {
ImpureSystem* impureSystem = static_cast<ImpureSystem*>(system);
group.ImpureSystems.push_back(impureSystem);
if (!system->m_ComponentType.empty()) {
m_Systems[system->m_ComponentType].push_back(system);
} else {
LOG_ERROR("Failed to add system \"%s\": Missing component type!", typeid(T).name());
delete system;
}
}
void Update(World* world, double dt)
{
for (UnorderedSystems& group : m_OrderedSystemGroups) {
// Process events
for (auto& pair : group.Systems) {
m_EventBroker->Process(pair.first);
for (auto& pair : m_Systems) {
const std::string& componentName = pair.first;
auto& systems = pair.second;
const ComponentPool* pool = world->GetComponents(componentName);
if (pool == nullptr) {
continue;
}
// Update
for (auto& pair : group.PureSystems) {
const std::string& componentName = pair.first;
auto& systems = pair.second;
const ComponentPool* pool = world->GetComponents(componentName);
if (pool == nullptr) {
continue;
for (auto& component : *pool) {
for (auto& system : systems) {
system->Update(world, component, dt);
}
for (auto& component : *pool) {
for (auto& system : systems) {
system->UpdateComponent(world, component, dt);
}
}
}
for (auto& system : group.ImpureSystems) {
system->Update(world, dt);
}
}
}
private:
EventBroker* m_EventBroker;
struct UnorderedSystems
{
std::map<std::string, System*> Systems;
std::map<std::string, std::vector<PureSystem*>> PureSystems;
std::vector<ImpureSystem*> ImpureSystems;
};
std::vector<UnorderedSystems> m_OrderedSystemGroups;
const EventBroker* m_EventBroker;
std::unordered_map<std::string, std::vector<System*>> m_Systems;
};
#endif
-12
View File
@@ -1,12 +0,0 @@
// Example:
// DEBUG_IF(condition) {
// // This code is executed only in debug mode and if condition is true.
// }
// NOTE: condition statement is not executed at all in release mode.
#ifndef DEBUG_IF
#ifndef DEBUG
#define DEBUG_IF(c) if(c)
#else
#define DEBUG_IF(c) if(false)
#endif
#endif
-23
View File
@@ -80,27 +80,4 @@ static void _LOG(_LOG_LEVEL logLevel, const char* file, const char* func, unsign
#define LOG_DEBUG(format, ...) \
LOG(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
// Set the log level temporarily for the current scope
#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__
-46
View File
@@ -1,46 +0,0 @@
#ifndef Util_XercesString_h__
#define Util_XercesString_h__
#include <string>
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/XMLString.hpp>
namespace XS
{
class ToString
{
public:
ToString(const XMLCh* const str) { m_AsChar = xercesc::XMLString::transcode(str); }
~ToString()
{
if (m_AsChar != nullptr) {
xercesc::XMLString::release(&m_AsChar);
}
}
operator std::string() const { return std::string(m_AsChar); }
private:
char* m_AsChar = nullptr;
};
class ToXMLCh
{
public:
ToXMLCh(const std::string str) { m_Transcoded = xercesc::XMLString::transcode(str.c_str()); }
ToXMLCh(const char* str) { m_Transcoded = xercesc::XMLString::transcode(str); }
~ToXMLCh()
{
if (m_Transcoded != nullptr) {
xercesc::XMLString::release(&m_Transcoded);
}
}
operator const XMLCh*() const { return m_Transcoded; }
private:
XMLCh* m_Transcoded = nullptr;
};
}
#endif
+2 -21
View File
@@ -14,43 +14,24 @@ public:
// Create empty entity
EntityID CreateEntity(EntityID parent = 0);
// Delete entity and all components within
void DeleteEntity(EntityID entity);
// Check if an entity exists
bool ValidEntity(EntityID entity) const;
// Register a component type and allocate space for it
void RegisterComponent(ComponentInfo& ci);
// Attach a component to an entity and fill it with default values
ComponentWrapper AttachComponent(EntityID entity, std::string componentType);
// Check if an entity has a component
bool HasComponent(EntityID entity, std::string componentType) const;
// Get a component of an entity
ComponentWrapper GetComponent(EntityID entity, std::string componentType);
// Delete a component off an entity
void DeleteComponent(EntityID entity, std::string componentType);
// Get all components of the specified type
const ComponentPool* GetComponents(std::string componentType);
// Get entity parent
EntityID GetParent(EntityID entity);
// Change the parent of an entity
void SetParent(EntityID entity, EntityID parent);
// Get all component pools
const std::unordered_map<std::string, ComponentPool*>& GetComponentPools() const { return m_ComponentPools; }
// Get the entity children map
const std::unordered_multimap<EntityID, EntityID>& GetEntityChildren() const { return m_EntityChildren; }
// Set the textual name of an entity
void SetName(EntityID entity, const std::string& name);
// Get the textual name of an entity
std::string GetName(EntityID entity) const;
private:
EntityID m_CurrentEntityID = 0;
EntityID m_CurrentEntityID = 1;
std::unordered_map<EntityID, EntityID> m_EntityParents;
// TODO: This should be a more effective structure
std::unordered_multimap<EntityID, EntityID> m_EntityChildren;
std::unordered_map<std::string, ComponentPool*> m_ComponentPools;
std::unordered_map<EntityID, std::string> m_EntityNames;
EntityID generateEntityID();
};
-94
View File
@@ -1,94 +0,0 @@
#include <imgui/imgui.h>
#include <glm/gtx/common.hpp>
#include <boost/filesystem/path.hpp>
#include <nativefiledialog/nfd.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/EPicking.h"
#include "../Core/EFileDropped.h"
#include "../Rendering/RenderQueueFactory.h"
#include "../Core/EntityFilePreprocessor.h"
#include "../Core/EntityFileParser.h"
#include "../Core/EntityFileWriter.h"
class EditorSystem : public ImpureSystem
{
public:
EditorSystem(EventBroker* eventBroker, IRenderer* renderer);
virtual void Update(World* world, double dt) override;
private:
IRenderer* m_Renderer;
World* m_World = nullptr;
bool m_Enabled;
bool m_Visible;
boost::filesystem::path m_DefaultEntityDir;
boost::filesystem::path m_CurrentFile;
std::vector<glm::vec2> m_PickingQueue;
enum class WidgetMode
{
None,
Translate,
Rotate,
Scale
} m_WidgetMode = WidgetMode::None;
enum class WidgetSpace
{
Local,
Global
} m_WidgetSpace = WidgetSpace::Global;
EntityID m_Widget = EntityID_Invalid;
EntityID m_WidgetX = EntityID_Invalid;
EntityID m_WidgetPlaneX = EntityID_Invalid;
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);
EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
EventRelay<EditorSystem, Events::MouseRelease> m_EMouseRelease;
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);
};
+24
View File
@@ -0,0 +1,24 @@
#ifndef Events_BindGamepadAxis_h__
#define Events_BindGamepadAxis_h__
#include "Core/EventBroker.h"
#include "Core/EGamepadAxis.h"
namespace Events
{
/** Called to bind a gamepad axis to an input command. */
struct BindGamepadAxis : Event
{
/** The axis to bind. */
Gamepad::Axis Axis;
/** The command to send. */
std::string Command;
/** The value to send for positive stimulation.
Multiplied by the 0-1 clamped value of the axis.
*/
float Value;
};
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef Events_BindGamepadButton_h__
#define Events_BindGamepadButton_h__
#include "Core/EventBroker.h"
#include "Core/EGamepadButton.h"
namespace Events
{
/** Called to bind a gamepad button to an input command. */
struct BindGamepadButton : Event
{
/** The gamepad button to bind. */
Gamepad::Button Button;
/** The command to send. */
std::string Command;
/** The value to send for positive stimulation.
Multiplied by the 0-1 clamped value of the button.
*/
float Value;
};
}
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef Events_BindKey_h__
#define Events_BindKey_h__
#include "Core/EventBroker.h"
namespace Events
{
/** Called to bind a keyboard key to an input command. */
struct BindKey : Event
{
/** The GLFW key code to bind. */
int KeyCode;
/** The command to send. */
std::string Command;
/** The value to send for positive stimulation.
Multiplied by the 0-1 clamped value of the key.
*/
float Value;
};
}
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef Events_BindMouseButton_h__
#define Events_BindMouseButton_h__
#include "Core/EventBroker.h"
namespace Events
{
/** Called to bind a mouse button to an input command. */
struct BindMouseButton : Event
{
/** The GLFW mouse button code to bind. */
int Button;
/** The command to send. */
std::string Command;
/** The value to send for positive stimulation.
Multiplied by the 0-1 clamped value of the button.
*/
float Value;
};
}
#endif
@@ -1,70 +0,0 @@
#ifndef FirstPersonInputController_h__
#define FirstPersonInputController_h__
#include "../GLM.h"
#include "../Core/InputController.h"
#include "../Core/ELockMouse.h"
template <typename EventContext>
class FirstPersonInputController : public InputController<EventContext>
{
public:
FirstPersonInputController(EventBroker* eventBroker, unsigned int playerID)
: InputController(eventBroker)
, m_PlayerID(playerID)
{
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &FirstPersonInputController::OnLockMouse);
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &FirstPersonInputController::OnUnlockMouse);
}
const glm::quat Orientation() const { return m_Orientation; }
void LockMouse()
{
Events::LockMouse e;
m_EventBroker->Publish(e);
m_MouseLocked = true;
}
void UnlockMouse()
{
Events::UnlockMouse e;
m_EventBroker->Publish(e);
m_MouseLocked = false;
}
virtual bool OnCommand(const Events::InputCommand& e) override
{
if (m_PlayerID != e.PlayerID) {
return false;
}
if (m_MouseLocked) {
if (e.Command == "Pitch") {
float val = glm::radians(e.Value);
m_Orientation = m_Orientation * glm::angleAxis<float>(-val, glm::vec3(1, 0, 0));
return true;
}
if (e.Command == "Yaw") {
float val = glm::radians(e.Value);
m_Orientation = glm::angleAxis<float>(-val, glm::vec3(0, 1, 0)) * m_Orientation;
return true;
}
}
return false;
}
protected:
const unsigned int m_PlayerID;
glm::quat m_Orientation;
bool m_MouseLocked = false;
EventRelay<EventContext, Events::LockMouse> m_ELockMouse;
bool OnLockMouse(const Events::LockMouse& e) { m_MouseLocked = true; return true; }
EventRelay<EventContext, Events::UnlockMouse> m_EUnlockMouse;
bool OnUnlockMouse(const Events::UnlockMouse& e) { m_MouseLocked = false; return true; }
};
#endif
-25
View File
@@ -1,25 +0,0 @@
#ifndef InputHandler_h__
#define InputHandler_h__
#include "../Common.h"
#include "../Core/EventBroker.h"
#include "InputProxy.h"
class InputHandler
{
public:
InputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
: m_EventBroker(eventBroker)
, m_InputProxy(inputProxy)
{ }
virtual bool BindOrigin(std::string origin, std::string command, float value) = 0;
virtual void Update(double dt) { }
virtual float GetCommandValue(std::string command) = 0;
protected:
EventBroker* m_EventBroker;
InputProxy* m_InputProxy;
};
#endif
+127 -27
View File
@@ -1,46 +1,146 @@
#ifndef InputProxy_h__
#define InputProxy_h__
#ifndef InputSystem_h__
#define InputSystem_h__
#include "../Common.h"
#include "../Core/ResourceManager.h"
#include "../Core/ConfigFile.h"
#include <array>
#include <unordered_map>
#include <steam/steam_api.h>
#include "Core/EKeyUp.h"
#include "Core/EKeyDown.h"
#include "Core/EMousePress.h"
#include "Core/EMouseRelease.h"
#include "Core/EGamepadAxis.h"
#include "Core/EGamepadButton.h"
#include "Core/Util/EnumClassHash.h"
#include "EBindKey.h"
#include "EBindMouseButton.h"
#include "EBindGamepadAxis.h"
#include "EBindGamepadButton.h"
#include "EInputCommand.h"
#include "EBindOrigin.h"
class InputHandler;
class InputProxy;
class InputHandler
{
public:
InputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
: m_EventBroker(eventBroker)
, m_InputProxy(inputProxy)
{ }
virtual void Update(double dt) { }
virtual bool BindOrigin(std::string origin, std::string command, float value) = 0;
protected:
EventBroker* m_EventBroker;
InputProxy* m_InputProxy;
};
class InputProxy
{
public:
InputProxy(EventBroker* eventBroker);
~InputProxy();
void LoadBindings(std::string file);
void Update(double dt);
void Process();
InputProxy(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_EBindOrigin, &InputProxy::OnBindOrigin);
}
void Update(double dt)
{
m_EventBroker->Process<InputProxy>();
m_EventBroker->Process<InputHandler>();
for (auto& handler : m_Handlers) {
handler->Update(dt);
}
}
void Process()
{
// Accumulate the input values of all unique commands published by input handlers
for (auto& pair : m_CommandQueue) {
Events::InputCommand e;
e.PlayerID = pair.first.first;
e.Command = pair.first.second;
e.Value = 0;
for (auto& value : pair.second) {
e.Value += value;
}
e.Value = std::max(-1.f, std::min(e.Value, 1.f));
m_EventBroker->Publish(e);
LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID);
}
m_CommandQueue.clear();
}
template <typename T>
void AddHandler();
void Publish(const Events::InputCommand& e);
void AddHandler()
{
m_Handlers.push_back(new T(m_EventBroker, this));
}
void Publish(const Events::InputCommand& e)
{
auto key = std::make_pair(e.PlayerID, e.Command);
m_CommandQueue[key].push_back(e.Value);
}
protected:
EventBroker* m_EventBroker;
std::vector<InputHandler*> m_Handlers;
std::map<std::string, std::set<InputHandler*>> m_CommandHandlers;
// Represents every unique command (has of PlayerID & Command) and all values reported for that command this frame
// Represents every unique command (has of PlayerID & Command) and all values reported for that command
std::map<std::pair<unsigned int, std::string>, std::vector<float>> m_CommandQueue;
std::map<std::string, float> m_CurrentCommandValues;
std::map<std::string, float> m_LastCommandValues;
EventRelay<InputProxy, Events::BindOrigin> m_EBindOrigin;
bool OnBindOrigin(const Events::BindOrigin& e);
bool OnBindOrigin(const Events::BindOrigin& e)
{
bool originBound = false;
for (auto& handler : m_Handlers) {
bool result = handler->BindOrigin(e.Origin, e.Command, e.Value);
if (result) {
if (originBound) {
LOG_WARNING("Multiple handlers responded to binding input origin \"%s\"!", e.Origin.c_str());
}
originBound = true;
}
}
if (!originBound) {
LOG_ERROR("No input handler responded to binding input origin \"%s\"!", e.Origin.c_str());
}
return originBound;
}
//std::unordered_map<std::string, std::unordered_map<int, float>> m_CommandMouseButtonValues; // command string -> mouse button value for command
//std::unordered_map<std::string, std::unordered_map<Gamepad::Axis, float, EnumClassHash>> m_CommandGamepadAxisValues; // command string -> gamepad axis value for command
//std::unordered_map<std::string, std::unordered_map<Gamepad::Button, float, EnumClassHash>> m_CommandGamepadButtonValues; // command string -> gamepad button value for command
//// Input binding tables
//std::unordered_multimap<int, std::tuple<std::string, float>> m_MouseButtonBindings; // GLFW_MOUSE_BUTTON... -> command string
//std::unordered_multimap<Gamepad::Axis, std::tuple<std::string, float>, EnumClassHash> m_GamepadAxisBindings; // Gamepad::Axis -> command string & value
//std::unordered_multimap<Gamepad::Button, std::tuple<std::string, float>, EnumClassHash> m_GamepadButtonBindings; // Gamepad::Button -> command string
//// Input events
//EventRelay<InputProxy, Events::MousePress> m_EMousePress;
//bool OnMousePress(const Events::MousePress &event);
//EventRelay<InputProxy, Events::MouseRelease> m_EMouseRelease;
//bool OnMouseRelease(const Events::MouseRelease &event);
//EventRelay<InputProxy, Events::GamepadAxis> m_EGamepadAxis;
//bool OnGamepadAxis(const Events::GamepadAxis &event);
//EventRelay<InputProxy, Events::GamepadButtonDown> m_EGamepadButtonDown;
//bool OnGamepadButtonDown(const Events::GamepadButtonDown &event);
//EventRelay<InputProxy, Events::GamepadButtonUp> m_EGamepadButtonUp;
//bool OnGamepadButtonUp(const Events::GamepadButtonUp &event);
//// Input binding events
//EventRelay<InputProxy, Events::BindMouseButton> m_EBindMouseButton;
//bool OnBindMouseButton(const Events::BindMouseButton &event);
//EventRelay<InputProxy, Events::BindGamepadAxis> m_EBindGamepadAxis;
//bool OnBindGamepadAxis(const Events::BindGamepadAxis &event);
//EventRelay<InputProxy, Events::BindGamepadButton> m_EBindGamepadButton;
//bool OnBindGamepadButton(const Events::BindGamepadButton &event);
//float GetCommandTotalValue(std::string command);
//void PublishCommand(int playerID, std::string command, float value);
};
template <typename T>
void InputProxy::AddHandler()
{
m_Handlers.push_back(new T(m_EventBroker, this));
}
#endif
+52 -13
View File
@@ -1,28 +1,67 @@
#ifndef KeyboardInputHandler_h__
#define KeyboardInputHandler_h__
#include <GLFW/glfw3.h>
#include "InputHandler.h"
#include "InputProxy.h"
#include "Core/EKeyDown.h"
#include "Core/EKeyUp.h"
class KeyboardInputHandler : public InputHandler
{
public:
KeyboardInputHandler(EventBroker* eventBroker, InputProxy* inputProxy);
KeyboardInputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
: InputHandler(eventBroker, inputProxy)
{
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &KeyboardInputHandler::OnKeyDown);
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &KeyboardInputHandler::OnKeyUp);
bool BindOrigin(std::string origin, std::string command, float value) override;
virtual float GetCommandValue(std::string command) override;
m_OriginKeyCodes["R"] = GLFW_KEY_R;
}
bool BindOrigin(std::string origin, std::string command, float value) override
{
auto originIt = m_OriginKeyCodes.find(origin);
if (originIt == m_OriginKeyCodes.end()) {
return false;
}
int keyCode = originIt->second;
m_KeyBindings[keyCode] = std::make_tuple(command, value);
return true;
}
private:
std::unordered_map<std::string, int> m_OriginKeyCodes;
std::unordered_map<int, std::tuple<std::string, float>> m_KeyBindings; // GLFW_KEY... -> command string & value
std::unordered_map<std::string, float> m_CommandValues;
EventRelay<InputHandler, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown& e);
EventRelay<InputHandler, Events::KeyUp> m_EKeyUp;
bool OnKeyUp(const Events::KeyUp& e);
};
bool OnKeyDown(const Events::KeyDown& e)
{
auto it = m_KeyBindings.find(e.KeyCode);
if (it == m_KeyBindings.end()) {
return false;
}
#endif
Events::InputCommand ic;
ic.PlayerID = 0;
std::tie(ic.Command, ic.Value) = it->second;
m_InputProxy->Publish(ic);
return true;
}
EventRelay<InputHandler, Events::KeyUp> m_EKeyUp;
bool OnKeyUp(const Events::KeyUp& e)
{
auto it = m_KeyBindings.find(e.KeyCode);
if (it == m_KeyBindings.end()) {
return false;
}
Events::InputCommand ic;
ic.PlayerID = 0;
std::tie(ic.Command, std::ignore) = it->second;
ic.Value = 0;
m_InputProxy->Publish(ic);
return true;
}
};
-38
View File
@@ -1,38 +0,0 @@
#ifndef MouseInputHandler_h__
#define MouseInputHandler_h__
#include <GLFW/glfw3.h>
#include "InputHandler.h"
#include "Core/EMousePress.h"
#include "Core/EMouseRelease.h"
#include "Core/EMouseMove.h"
class MouseInputHandler : public InputHandler
{
public:
MouseInputHandler(EventBroker* eventBroker, InputProxy* inputProxy);
bool BindOrigin(std::string origin, std::string command, float value) override;
virtual float GetCommandValue(std::string command) override;
private:
std::unordered_map<std::string, int> m_OriginCodes;
std::unordered_map<std::string, char> m_OriginAxes;
std::unordered_map<int, std::tuple<std::string, float>> m_Bindings; // GLFW_MOUSE_BUTTON... -> command string & value
std::unordered_map<char, std::tuple<std::string, float>> m_Axes; // Axis -> command string & value
std::unordered_map<std::string, float> m_CommandValues;
std::unordered_map<std::string, float> m_ContinuousCommandValues;
EventRelay<InputHandler, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<InputHandler, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e);
EventRelay<InputHandler, Events::MouseMove> m_EMouseMove;
bool OnMouseMove(const Events::MouseMove& e);
bool hasOrigin(std::string origin);
};
#endif
@@ -0,0 +1,98 @@
#include <steam/steam_api.h>
#include "InputProxy.h"
class SteamControllerInputHandler : public InputHandler
{
public:
SteamControllerInputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
: InputHandler(eventBroker, inputProxy)
{
SteamController()->Init();
}
~SteamControllerInputHandler()
{
SteamController()->Shutdown();
}
void Update(double dt) override
{
std::array<ControllerHandle_t, STEAM_CONTROLLER_MAX_COUNT> controllers;
int numControllers = SteamController()->GetConnectedControllers(controllers.data());
for (int i = 0; i < numControllers; i++) {
auto controllerHandle = controllers.at(i);
auto actionSetHandle = SteamController()->GetActionSetHandle("InGameControls");
//SteamController()->ShowBindingPanel(controllerHandle);
SteamController()->ActivateActionSet(controllerHandle, actionSetHandle);
for (auto& command : m_Commands) {
Events::InputCommand ic;
ic.PlayerID = i + 1;
ic.Command = command.first;
auto digitalActionHandle = m_DigitalActionHandles.at(ic.Command);
auto handle = SteamController()->GetDigitalActionHandle("DebugReload");
auto data = SteamController()->GetDigitalActionData(controllerHandle, handle);
LOG_DEBUG("Controller %i, active %i, value %i", i, data.bActive, data.bState);
if (data.bState) {
ic.Value = command.second;
} else {
ic.Value = 0.f;
}
//m_InputProxy->Publish(ic);
}
}
}
bool BindOrigin(std::string origin, std::string command, float value) override
{
if (origin != "SteamController") {
return false;
}
m_Commands[command] = value;
m_DigitalActionHandles[command] = SteamController()->GetDigitalActionHandle(command.c_str());
return true;
}
private:
std::map<std::string, float> m_Commands;
std::map<std::string, ControllerDigitalActionHandle_t> m_DigitalActionHandles;
//std::unordered_map<std::string, std::unordered_map<int, float>> m_CommandKeyboardValues; // command string -> keyboard key value for command
std::unordered_map<int, std::tuple<std::string, float>> m_KeyBindings; // GLFW_KEY... -> command string & value
EventRelay<InputHandler, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown& e)
{
auto it = m_KeyBindings.find(e.KeyCode);
if (it == m_KeyBindings.end()) {
return false;
}
Events::InputCommand ic;
ic.PlayerID = 0;
std::tie(ic.Command, ic.Value) = it->second;
m_InputProxy->Publish(ic);
return true;
}
EventRelay<InputHandler, Events::KeyUp> m_EKeyUp;
bool OnKeyUp(const Events::KeyUp& e)
{
auto it = m_KeyBindings.find(e.KeyCode);
if (it == m_KeyBindings.end()) {
return false;
}
Events::InputCommand ic;
ic.PlayerID = 0;
std::tie(ic.Command, std::ignore) = it->second;
ic.Value = 0;
m_InputProxy->Publish(ic);
return true;
}
};
+4 -74
View File
@@ -1,84 +1,14 @@
#ifndef Client_h__
#define Client_h__
#include <string>
#include <ctime>
#include <boost\asio.hpp>
#include <glm/common.hpp>
#include <boost/asio.hpp>
#include "Network/Network.h"
#include "Network/MessageType.h"
#include "Network/PlayerDefinition.h"
#include "Network/SnapshotDefinitions.h"
#include "Core/World.h"
#include "Core/EventBroker.h"
#include "Core/ConfigFile.h"
#include "Input/EInputCommand.h"
class Client : public Network
class Client
{
public:
Client(ConfigFile* config);
~Client();
void Start(World* world, EventBroker* eventBroker) override;
void Update() override;
void Close();
private:
// Assio UDP logic
boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
boost::asio::io_service m_IOService;
boost::asio::ip::udp::socket m_Socket;
Client();
~Client();
// Sending message to server logic
int bytesRead = -1;
char readBuf[1024] = { 0 };
int snapshotInterval = 33;
std::clock_t previousSnapshotMessage = std::clock();
// Packet loss logic
unsigned int m_PacketID = 0;
unsigned int m_PreviousPacketID = 0;
unsigned int m_SendPacketID = 0;
// Game logic
World* m_World;
std::string m_PlayerName;
int m_PlayerID = -1;
// Network logic
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
SnapshotDefinitions m_NextSnapshot;
bool m_ThreadIsRunning = true;
double m_DurationOfPingTime;
std::clock_t m_StartPingTime;
// Use to check if we should send disconnect message
// if game is turned of by closing window.
bool m_WasStarted = false;
// Private member functions
void readFromServer();
void sendSnapshotToServer();
int receive(char* data, size_t length);
void send(Packet& packet);
void connect();
void disconnect();
void ping();
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
void parseMessageType(Packet& packet);
void parseEventMessage(Packet& packet);
void parseConnect(Packet& packet);
void parsePing();
void parseServerPing();
void parseSnapshot(Packet& packet);
void identifyPacketLoss();
bool isConnected();
EntityID createPlayer();
// Events
EventBroker* m_EventBroker;
EventRelay<Client, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand &e);
};
#endif
-17
View File
@@ -1,17 +0,0 @@
#ifndef MessageType_h__
#define MessageType_h__
// Message types used by both server and client.
// Used to determine what type of message was sent.
enum class MessageType
{
Connect,
Disconnect,
ClientPing,
ServerPing,
Message,
Snapshot,
Event,
};
#endif
-19
View File
@@ -1,19 +0,0 @@
#ifndef Network_h__
#define Network_h__
#include "Core/World.h"
#include "Core/EventBroker.h"
#include "Network/Packet.h"
#define MAXCONNECTIONS 8
#define INPUTSIZE 128
class Network
{
public:
virtual ~Network() { };
virtual void Start(World* m_world, EventBroker *eventBroker) = 0;
virtual void Update() = 0;
};
#endif
-61
View File
@@ -1,61 +0,0 @@
#ifndef Packet_h__
#define Packet_h__
#include <string>
#include "Network/MessageType.h"
#include "Core/Util/Logging.h"
// Defines the
class Packet
{
public:
// arg1: Type of message (Connect, Disconnect...)
// arg2: PacketID for identifying packet loss.
Packet(MessageType type, unsigned int& packetID);
// Used to create packet from already existing data buffer.
Packet(char* data, const int sizeOfPacket);
~Packet();
// Add primitive types like int, float, char...
template<typename T>
void WritePrimitive(T val)
{
// Check if we are trying to add more than the package can fit.
if (m_MaxPacketSize < m_Offset + sizeof(T)) {
LOG_WARNING("Packet AddPrimitive(): You are trying to add more than we have allocated for!");
}
memcpy(m_Data + m_Offset, &val, sizeof(T));
m_Offset += sizeof(T);
}
// Pops the first element as if it was a primitive.
template<typename T>
T ReadPrimitive()
{
if (m_Offset < m_ReturnDataOffset + sizeof(T)) {
LOG_WARNING("Packet PopFrontPrimitive(): You are trying to remove more than what exists in this packet!");
return -1;
}
T returnValue;
memcpy(&returnValue, m_Data + m_ReturnDataOffset, sizeof(T));
m_ReturnDataOffset += sizeof(T);
return returnValue;
}
// Add a string to the message
void WriteString(std::string str);
// Add data to the message
void WriteData(char* data, int sizeOfData);
// Pops the first element as if it was a string.
std::string ReadString();
char* ReadData(int SizeOfData);
int Size() { return m_Offset; };
char* Data() { return m_Data; };
private:
char* m_Data;
unsigned int m_ReturnDataOffset = 0;
int m_Offset = 0;
unsigned int m_MaxPacketSize = 128;
};
#endif
-11
View File
@@ -1,11 +0,0 @@
#ifndef PlayerDefinition_h__
#define PlayerDefinition_h__
#include <string>
struct PlayerDefinition {
int EntityID = -1;
std::string Name = "";
boost::asio::ip::udp::endpoint Endpoint;
};
#endif
+4 -77
View File
@@ -1,85 +1,12 @@
#ifndef Server_h__
#define Server_h__
#include <string>
#include <ctime>
#include <boost\asio.hpp>
#include <glm/common.hpp>
#include <boost/asio/ip/udp.hpp>
#include "Network/MessageType.h"
#include "Network/PlayerDefinition.h"
#include "Core/World.h"
#include "Core/EventBroker.h"
#include "Network/Network.h"
class Server : public Network
class Server
{
public:
Server();
~Server();
void Start(World* m_world, EventBroker *eventBroker) override;
void Update() override;
void Close();
private:
// UDP logic
boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
boost::asio::io_service m_IOService;
boost::asio::ip::udp::socket m_Socket;
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
// Sending messages to client logic
char readBuffer[1024] = { 0 };
int bytesRead = 0;
// time for previouse message
std::clock_t previousePingMessage = std::clock();
std::clock_t previousSnapshotMessage = std::clock();
std::clock_t timOutTimer = std::clock();
// How often we send messages (milliseconds)
int intervalMs = 1000;
int snapshotInterval = 50;
int checkTimeOutInterval = 100;
//Timers
std::clock_t m_StartPingTime;
std::clock_t m_StopTimes[8];
// Game logic
World* m_World;
EventBroker* m_EventBroker;
// vec.size() = ammount of players to create, stores playerID's
std::vector<unsigned int> m_PlayersToCreate;
// Packet loss logic
unsigned int m_PacketID;
unsigned int m_PreviousPacketID;
unsigned int m_SendPacketID;
// Close logic
bool m_ThreadIsRunning = true;
// Private member functions
int receive(char* data, size_t length);
void readFromClients();
void send(Packet& packet, int playerID);
void send(Packet& packet);
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
void broadcast(std::string message);
void broadcast(Packet& packet);
void sendSnapshot();
void sendPing();
void checkForTimeOuts();
void disconnect(int i);
void parseMessageType(Packet& packet);
void parseEvent(Packet& packet);
void parseConnect(Packet& packet);
void parseDisconnect();
void parseClientPing();
void parseServerPing();
void parseSnapshot(Packet& packet);
void identifyPacketLoss();
EntityID createPlayer();
Server();
~Server();
};
#endif
@@ -1,12 +0,0 @@
#ifndef SnapshotDefinitions_h__
#define SnapshotDefinitions_h__
struct SnapshotDefinitions
{
// "+Forward" is 8 characters * sizeof(char) = 8
std::string InputForward;
// "+Right" is 6 characters * sizeof(char) = 6
std::string InputRight;
};
#endif
@@ -1,63 +0,0 @@
#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;
};
-36
View File
@@ -1,36 +0,0 @@
#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
@@ -1,15 +0,0 @@
#ifndef DrawScenePassState_h__
#define DrawScenePassState_h__
#include "Rendering/RenderState.h"
class DrawScenePassState : public RenderState
{
public:
DrawScenePassState();
~DrawScenePassState();
private:
};
#endif
+2 -7
View File
@@ -34,26 +34,21 @@ public:
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.Entity = -1;
}
pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix);
pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, Resolution.Width - screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix);
return pickData;
}
+1 -1
View File
@@ -35,7 +35,7 @@ public:
virtual void Draw(RenderQueueCollection& rq) = 0;
protected:
Rectangle m_Resolution = Rectangle::Rectangle(1280, 720);
Rectangle m_Resolution = Rectangle(1280, 720);
bool m_Fullscreen = false;
bool m_VSYNC = false;
int m_GLVersion[2];
@@ -1,77 +0,0 @@
#include <imgui/imgui.h>
#include "../OpenGL.h"
#include "IRenderer.h"
#include "RenderState.h"
#include "../Core/EventBroker.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
#include "../Core/EMouseMove.h"
#include "../Core/EMouseScroll.h"
#include "../Core/EKeyDown.h"
#include "../Core/EKeyUp.h"
#include "../Core/EKeyboardChar.h"
class ImGuiRenderState : public RenderState
{
public:
ImGuiRenderState()
: RenderState()
{
BindFramebuffer(0);
Enable(GL_BLEND);
BlendEquation(GL_FUNC_ADD);
BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Disable(GL_CULL_FACE);
Disable(GL_DEPTH_TEST);
Enable(GL_SCISSOR_TEST);
}
};
class ImGuiRenderPass
{
public:
ImGuiRenderPass(IRenderer* renderer, EventBroker* eventBroker);
void Update(double dt);
void Draw();
private:
IRenderer* m_Renderer;
EventBroker* m_EventBroker;
GLFWwindow* g_Window;
double g_DeltaTime = 0.0;
float g_MouseWheel = 0.f;
GLuint g_FontTexture;
int g_ShaderHandle;
int g_VertHandle;
int g_FragHandle;
int g_AttribLocationTex;
int g_AttribLocationProjMtx;
int g_AttribLocationPosition;
int g_AttribLocationUV;
int g_AttribLocationColor;
GLuint g_VboHandle;
GLuint g_VaoHandle;
GLuint g_ElementsHandle;
EventRelay<ImGuiRenderPass, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<ImGuiRenderPass, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e);
EventRelay<ImGuiRenderPass, Events::MouseMove> m_EMouseMove;
bool OnMouseMove(const Events::MouseMove& e);
EventRelay<ImGuiRenderPass, Events::MouseScroll> m_EMouseScroll;
bool OnMouseScroll(const Events::MouseScroll& e);
EventRelay<ImGuiRenderPass, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown& e);
EventRelay<ImGuiRenderPass, Events::KeyUp> m_EKeyUp;
bool OnKeyUp(const Events::KeyUp& e);
EventRelay<ImGuiRenderPass, Events::KeyboardChar> m_EKeyboardChar;
bool OnKeyboardChar(const Events::KeyboardChar& e);
bool createDeviceObjects();
bool createFontsTexture();
void newFrame();
};
-49
View File
@@ -1,49 +0,0 @@
#ifndef PickingPass_h__
#define PickingPass_h__
#include "IRenderer.h"
#include "PickingPassState.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
#include "Util/UnorderedMapVec2.h"
#include "../Core/EventBroker.h"
#include "EPicking.h"
class PickingPass
{
public:
PickingPass(IRenderer* renderer, EventBroker* eb);
~PickingPass();
void InitializeTextures();
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(RenderQueueCollection& rq);
//Getters
const ShaderProgram& PickingProgram() const { return *m_PickingProgram; }
const std::unordered_map<glm::vec2, EntityID>& PickingColorsToEntity() const { return m_PickingColorsToEntity; }
GLuint PickingTexture() const { return m_PickingTexture; }
GLuint DepthBuffer() const { return m_DepthBuffer; }
const FrameBuffer& PickingBuffer() const { return m_PickingBuffer; }
private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
EventBroker* m_EventBroker;
const IRenderer* m_Renderer;
ShaderProgram* m_PickingProgram;
std::unordered_map<glm::vec2, EntityID> m_PickingColorsToEntity;
GLuint m_PickingTexture;
GLuint m_DepthBuffer;
FrameBuffer m_PickingBuffer;
};
#endif
@@ -1,15 +0,0 @@
#ifndef PickingPassState_h__
#define PickingPassState_h__
#include "Rendering/RenderState.h"
class PickingPassState : public RenderState
{
public:
PickingPassState(GLuint frameBuffer);
~PickingPassState();
private:
};
#endif
@@ -13,12 +13,8 @@ public:
RenderQueueFactory();
void Update(World* world);
RenderQueueCollection RenderQueues() const { return m_RenderQueues; }
static glm::vec3 AbsolutePosition(World* world, EntityID entity);
static glm::quat AbsoluteOrientation(World* world, EntityID entity);
static glm::vec3 AbsoluteScale(World* world, EntityID entity);
private:
RenderQueueCollection m_RenderQueues;
@@ -26,6 +22,10 @@ private:
void FillLights(World* world, RenderQueue* renderQueue);
glm::mat4 ModelMatrix(World* world, EntityID entity);
glm::vec3 AbsolutePosition(World* world, EntityID entity);
glm::quat AbsoluteOrientation(World* world, EntityID entity);
glm::vec3 AbsoluteScale(World* world, EntityID entity);
};
#endif
-27
View File
@@ -1,27 +0,0 @@
#ifndef RenderState_h__
#define RenderState_h__
#include <functional>
#include "../Common.h"
#include "../OpenGL.h"
#include "../GLM.h"
class RenderState
{
public:
RenderState() = default;
~RenderState();
bool Enable(GLenum cap);
bool Disable(GLenum cap);
bool CullFace(GLenum mode);
bool ClearColor(glm::vec4 color);
bool Clear(GLbitfield mask);
bool BindFramebuffer(GLint framebuffer);
bool BlendEquation(GLenum mode);
bool BlendFunc(GLenum sfactor, GLenum dfactor);
private:
std::vector<std::function<void(void)>> m_ResetFunctions;
};
#endif
+21 -84
View File
@@ -10,26 +10,9 @@
#include "Util/UnorderedMapVec2.h"
#include "FrameBuffer.h"
#include "../Core/World.h"
#include "PickingPass.h"
#include "DrawScenePass.h"
#include "DebugCameraInputController.h"
#define TILE_SIZE 16
#define NUM_LIGHTS 3
enum lightType
{
Point,
Spot,
Directional,
Area
};
#include "../Core/EventBroker.h"
#include "EPicking.h"
#include "ImGuiRenderPass.h"
class Renderer : public IRenderer
{
@@ -38,90 +21,44 @@ public:
: m_EventBroker(eventBroker)
{ }
virtual void Initialize() override;
virtual void Update(double dt) override;
virtual void Draw(RenderQueueCollection& rq) override;
virtual void Initialize() override;
virtual void Update(double dt) override;
virtual void Draw(RenderQueueCollection& rq) override;
private:
//----------------------Variables----------------------//
//----------------------Variables----------------------//
EventBroker* m_EventBroker;
std::shared_ptr<DebugCameraInputController<Renderer>> m_DebugCameraInputController;
Texture* m_ErrorTexture;
Texture* m_WhiteTexture;
float m_CameraMoveSpeed;
Texture* m_ErrorTexture;
Texture* m_WhiteTexture;
float m_CameraMoveSpeed;
FrameBuffer m_PickingBuffer;
GLuint m_PickingTexture;
GLuint m_DepthBuffer;
Model* m_ScreenQuad;
Model* m_UnitQuad;
Model* m_UnitSphere;
DrawScenePass* m_DrawScenePass;
PickingPass* m_PickingPass;
ImGuiRenderPass* m_ImGuiRenderPass;
std::unordered_map<glm::vec2, EntityID> m_PickingColorsToEntity;
//----------------------Functions----------------------//
void InitializeWindow();
void InitializeShaders();
//----------------------Functions----------------------//
void InitializeWindow();
void InitializeShaders();
void InitializeTextures();
void InitializeSSBOs();
void InitializeRenderPasses();
void InitializeFrameBuffers();
//TODO: Renderer: Get InputUpdate out of renderer
void InputUpdate(double dt);
//void PickingPass(RenderQueueCollection& rq);
void InputUpdate(double dt);
void PickingPass(RenderQueueCollection& rq);
void DrawScreenQuad(GLuint textureToDraw);
void DrawScene(RenderQueueCollection& rq);
//----------------------Forward+-----------------------//
void CalculateFrustum();
void CullLights();
//Frustum
struct Plane {
glm::vec3 Normal;
float d;
};
struct Frustum {
Plane Planes[4];
};
Frustum m_Frustums[80*45]; //TODO: Renderer: Make this change with resolution
//Lights
void TEMPCreateLights();
//TODO: Renderer: Add Directionllights, spotlights and area lights to this as type.
struct PointLight {
glm::vec4 Position = glm::vec4(0.f);
glm::vec4 Color = glm::vec4(1.f);
float Radius = 5.f;
float Intensity = 0.8f;
float Falloff = 0.3f;
float Padding = 1337;
};
PointLight m_PointLights[NUM_LIGHTS];
struct LightGrid {
int Amount;
int Start;
glm::vec2 Padding;
};
LightGrid m_LightGrid[80*45];
int m_LightOffset = 0;
int m_LightIndex[80*45*200];
//-------------------------SSBO------------------------//
GLuint m_FrustumSSBO = 0;
GLuint m_LightSSBO = 1;
GLuint m_LightGridSSBO = 2;
GLuint m_LightOffsetSSBO = 3;
GLuint m_LightIndexSSBO = 4;
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type);
//--------------------ShaderPrograms-------------------//
ShaderProgram* m_BasicForwardProgram;
ShaderProgram* m_DrawScreenQuadProgram;
ShaderProgram* m_CalculateFrustumProgram;
ShaderProgram* m_LightCullProgram;
ShaderProgram m_BasicForwardProgram;
ShaderProgram m_PickingProgram;
ShaderProgram m_DrawScreenQuadProgram;
};
#endif
+3 -10
View File
@@ -1,9 +1,6 @@
#ifndef ShaderProgram_h__
#define ShaderProgram_h__
#include "../Common.h"
#include "../OpenGL.h"
#include "../Core/ResourceManager.h"
#include <fstream>
class Shader
@@ -63,13 +60,11 @@ public:
: ShaderType(fileName) { }
};
class ShaderProgram : public Resource
class ShaderProgram
{
friend class ResourceManager;
private:
ShaderProgram(std::string)
: m_ShaderProgramHandle(0) { }
public:
ShaderProgram()
: m_ShaderProgramHandle(0) { }
~ShaderProgram();
void AddShader(std::shared_ptr<Shader> shader);
@@ -84,5 +79,3 @@ private:
GLuint m_ShaderProgramHandle;
std::vector<std::shared_ptr<Shader>> m_Shaders;
};
#endif
+1 -1
View File
@@ -9,7 +9,7 @@ inline bool _GLERROR(const char* info, const char* file, const char* func, unsig
GLenum error = glGetError();
if (error != GL_NO_ERROR)
{
_LOG(LOG_LEVEL_ERROR, file, func, line, "GL Error: %s, %i, %s", info, error, gluErrorString(error));
_LOG(LOG_LEVEL_ERROR, file, func, line, "GL Error: %s %i %s", info, error, gluErrorString(error));
return true;
}
+6 -26
View File
@@ -11,22 +11,11 @@
#include "Rendering/RenderQueueFactory.h"
#include "Input/InputProxy.h"
#include "Input/KeyboardInputHandler.h"
#include "Input/MouseInputHandler.h"
#include "Input/SteamControllerInputHandler.h"
#include "Core/EKeyDown.h"
#include "Core/EntityFilePreprocessor.h"
#include "Core/EntityXMLFile.h"
#include "Core/SystemPipeline.h"
#include "RaptorCopterSystem.h"
#include "PlayerSystem.h"
#include "Editor/EditorSystem.h"
#include "Core/EntityFile.h"
#include "Core/EntityFileParser.h"
// Network
#include <boost/thread.hpp>
#include "Network/Network.h"
#include "Network/Server.h"
#include "Network/Client.h"
class Game
{
@@ -48,21 +37,12 @@ private:
World* m_World;
SystemPipeline* m_SystemPipeline;
RenderQueueFactory* m_RenderQueueFactory;
// Network variables
boost::thread m_NetworkThread;
// Network methods
void networkFunction();
Network* m_ClientOrServer;
bool m_IsClientOrServer = false;
EventRelay<Game, Events::InputCommand> m_EInputCommand;
bool debugOnInputCommand(const Events::InputCommand& e);
void debugInitialize();
void debugTick(double dt);
EventRelay<Client, Events::KeyDown> m_EKeyDown;
EventRelay<Game, Events::KeyUp> m_EKeyUp;
bool testOnKeyUp(const Events::KeyUp& e);
void testIntialize();
void testTick(double dt);
};
#endif
-36
View File
@@ -1,36 +0,0 @@
#ifndef HealthSystem_h__
#define HealthSystem_h__
#include <GLFW/glfw3.h>
#include <glm/common.hpp>
#include "Common.h"
#include "Core/System.h"
#include "Core\EPlayerDamage.h";
#include "Core\EPlayerHealthPickup.h";
#include "Core\EPlayerDeath.h";
#include <tuple>
#include <vector>
class HealthSystem : public PureSystem
{
public:
HealthSystem(EventBroker* eventBroker);
//updatecomponent
virtual void UpdateComponent(World* world, ComponentWrapper& health, double dt) override;
private:
//methods which will take care of specific events
EventRelay<HealthSystem, Events::PlayerDamage> m_EPlayerDamage;
bool HealthSystem::OnPlayerDamaged(const Events::PlayerDamage& e);
EventRelay<HealthSystem, Events::PlayerHealthPickup> m_EPlayerHealthPickup;
bool HealthSystem::OnPlayerHealthPickup(const Events::PlayerHealthPickup& e);
//vector which will keep track of health changes
std::vector<std::tuple<EntityID, double>> m_DeltaHealthVector;
};
#endif
-33
View File
@@ -1,33 +0,0 @@
#ifndef PlayerSystem_h__
#define PlayerSystem_h__
#include <GLFW/glfw3.h>
#include <glm/common.hpp>
#include "Common.h"
#include "Core/System.h"
#include "Collision/ETrigger.h"
class PlayerSystem : public PureSystem
{
public:
PlayerSystem(EventBroker* eventBroker)
: PureSystem(eventBroker, "Player")
{
EVENT_SUBSCRIBE_MEMBER(m_ETouch, &PlayerSystem::OnTouch);
EVENT_SUBSCRIBE_MEMBER(m_EEnter, &PlayerSystem::OnEnter);
EVENT_SUBSCRIBE_MEMBER(m_ELeave, &PlayerSystem::OnLeave);
}
virtual void UpdateComponent(World* world, ComponentWrapper& player, double dt) override;
private:
float m_Speed = 5;
EventRelay<PlayerSystem, Events::TriggerEnter> m_EEnter;
bool OnEnter(const Events::TriggerEnter &event);
EventRelay<PlayerSystem, Events::TriggerTouch> m_ETouch;
bool PlayerSystem::OnTouch(const Events::TriggerTouch &event);
EventRelay<PlayerSystem, Events::TriggerLeave> m_ELeave;
bool PlayerSystem::OnLeave(const Events::TriggerLeave &event);
};
#endif
+4 -4
View File
@@ -1,14 +1,14 @@
#include "Common.h"
#include "Core/System.h"
class RaptorCopterSystem : public PureSystem
class RaptorCopterSystem : public System
{
public:
RaptorCopterSystem(EventBroker* eventBroker)
: PureSystem(eventBroker, "RaptorCopter")
RaptorCopterSystem(const EventBroker* eventBroker)
: System(eventBroker, "RaptorCopter")
{ }
virtual void UpdateComponent(World* world, ComponentWrapper& raptorCopter, double dt) override
virtual void Update(World* world, ComponentWrapper& raptorCopter, double dt) override
{
ComponentWrapper& transform = world->GetComponent(raptorCopter.EntityID, "Transform");
(glm::vec3&)transform["Orientation"] += (float)(double)raptorCopter["Speed"] * (float)dt * (glm::vec3)raptorCopter["Axis"];
+1 -11
View File
@@ -1,19 +1,9 @@
[Debug]
LogLevel=1
LoadMap=
EditorEnabled=false
[Video]
Fullscreen=false
VSYNC=false
Width=1280
Height=720
FOV=45
[Networking]
StartNetwork=false
IsServer=false
Name=Bob
Address=127.0.0.1
Port=13
Height=720
-24
View File
@@ -1,24 +0,0 @@
[Mouse]
Sensitivity=0.5
InvertPitch=false
[Bindings]
MouseLeft=PrimaryFire
MouseX=Yaw
MouseY=Pitch
W=+Forward
S=-Forward
D=+Right
A=-Right
R=Reload
Space=Jump
LeftControl=Crouch
LeftShift=Sprint
F1=ToggleEditor
1=EditorToolMove
2=EditorToolRotate
3=EditorToolScale
X=EditorToggleTransformSpace
C=ConnectToServer
N=SwitchToServer
M=SwitchToClient
-4
View File
@@ -5,8 +5,4 @@
<xs:include schemaLocation="Components/Model.xsd"/>
<xs:include schemaLocation="Components/Test.xsd"/>
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
<xs:include schemaLocation="Components/Player.xsd"/>
<xs:include schemaLocation="Components/AABB.xsd"/>
<xs:include schemaLocation="Components/Trigger.xsd"/>
<xs:include schemaLocation="Components/Health.xsd"/>
</xs:schema>
-4
View File
@@ -1,4 +0,0 @@
<c:AABB>
<BoxCenter X="0" Y="0" Z="0"/>
<BoxSize X="1" Y="1" Z="1"/>
</c:AABB>
-14
View File
@@ -1,14 +0,0 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="AABB">
<xs:complexType>
<xs:all>
<xs:element name="BoxCenter" type="t:Vector" minOccurs="0"/>
<xs:element name="BoxSize" type="t:Vector" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
-4
View File
@@ -1,4 +0,0 @@
<c:Health>
<Health>100</Health>
<MaxHealth>100</MaxHealth>
</c:Health>
-14
View File
@@ -1,14 +0,0 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="Health">
<xs:complexType>
<xs:all>
<xs:element name="Health" type="t:double" minOccurs="0"/>
<xs:element name="MaxHealth" type="t:double" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
-7
View File
@@ -1,7 +0,0 @@
<c:Player>
<Velocity X="0" Y="0" Z="0"/>
<Forward>false</Forward>
<Left>false</Left>
<Back>false</Back>
<Right>false</Right>
</c:Player>
-17
View File
@@ -1,17 +0,0 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="Player">
<xs:complexType>
<xs:all>
<xs:element name="Velocity" type="t:Vector" minOccurs="0"/>
<xs:element name="Forward" type="t:bool" minOccurs="0"/>
<xs:element name="Left" type="t:bool" minOccurs="0"/>
<xs:element name="Back" type="t:bool" minOccurs="0"/>
<xs:element name="Right" type="t:bool" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+6
View File
@@ -0,0 +1,6 @@
<c:Test>
<Integer>1</Integer>
<Float>1.333</Float>
<Vector X="1.33333" Y="2.33333" Z="3.33333"/>
<Quaternion X="1.33333" Y="2.33333" Z="3.33333" W="4.44444"/>
</c:Test>
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="Test">
<xs:annotation>
<xs:documentation>ECS Test Component</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Integer" type="t:int" minOccurs="0"/>
<xs:element name="Double" type="t:double" minOccurs="0"/>
<xs:element name="String" type="t:string" minOccurs="0"/>
<xs:element name="Vector" type="t:Vector" minOccurs="0"/>
<xs:element name="Quaternion" type="t:Quaternion" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+1 -1
View File
@@ -1,5 +1,5 @@
<c:Transform>
<Position X="0" Y="0" Z="0"/>
<Orientation X="0" Y="0" Z="0"/>
<Orientation X="0" Y="0" Z="0" W="0"/>
<Scale X="1" Y="1" Z="1"/>
</c:Transform>
-2
View File
@@ -1,2 +0,0 @@
<c:Trigger>
</c:Trigger>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="Trigger">
</xs:element>
</xs:schema>
@@ -1,122 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components">
<Components>
<c:Transform>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
<c:Model>
<Resource>Models/DummyScene.obj</Resource>
</c:Model>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="-1.5"/>
<Scale X="1" Y="1" Z="1"/>
</c:Transform>
<c:Model>
<Resource>Models/ScaleWidget.obj</Resource>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="1.5"/>
<Scale X="2" Y="2" Z="2"/>
</c:Transform>
<c:Model>
<Resource>Models/RotationWidgetX.obj</Resource>
</c:Model>
<c:Trigger>
</c:Trigger>
</Components>
</Entity>
<Entity>
<Components>
<c:Player>
<Velocity X="0" Y="0" Z="0"/>
</c:Player>
<c:Transform>
<Position X="2.5"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
</c:Model>
<c:AABB>
</c:AABB>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="-0"/>
<Scale X="1" Y="1" Z="1"/>
</c:Transform>
<!--<c:Move>
<Speed>1</Speed>
<Direction X="-1"/>
<Rotation Y="3.14"/>
</c:Move>-->
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Orientation X="0.0" Y="0" Z="1.0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitRaptor.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="-0.01" Y="0.55"/>
<Orientation X="0" Y="0" Z="-1"/>
</c:Transform>
<c:RaptorCopter>
<Speed>20</Speed>
<Axis Y="1"/>
</c:RaptorCopter>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Scale X="1.7" Y="0.03" Z="0.1"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Scale X="1.7" Y="0.03" Z="0.1"/>
<Orientation X="0" Y="1.57" Z="0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components">
<Components>
<c:Transform>
<Position X="0" Y="0" Z="0"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0" Z="0"/>
<Scale X="100" Y="1" Z="100"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitPlane.obj</Resource>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="1" Y="1" Z="0"/>
<Orientation X="0" Y="0.78539" Z="0"/>
</c:Transform>
<c:Model>
<Resource>An error</Resource>
</c:Model>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="2" Y="0" Z="0"/>
<Orientation X="0" Y="0.78539" Z="0"/>
</c:Transform>
<c:Model>
<Resource>An error</Resource>
</c:Model>
</Components>
<Children>
</Children>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components">
<Components>
<c:Transform/>
</Components>
</Entity>
@@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Entity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd" xmlns:c="components" name="RaptorCopter">
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Orientation X="0.0" Y="0" Z="0.0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitRaptor.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
<c:RaptorCopter>
<Speed>20</Speed>
<Axis Y="1"/>
</c:RaptorCopter>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0.4"/>
<Scale X="0.1" Y="0.4" Z="0.1"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCylinder.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0.6"/>
<Scale X="1.7" Y="0.03" Z="0.1"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0.6"/>
<Scale X="1.7" Y="0.03" Z="0.1"/>
<Orientation X="0" Y="1.57" Z="0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
+17 -23
View File
@@ -25,30 +25,12 @@
<Components>
<c:Transform>
<Position X="1.5"/>
<Scale X="2" Y="2" Z="2"/>
</c:Transform>
<c:Model>
<Resource>Models/RotationWidget.obj</Resource>
</c:Model>
<c:Trigger>
</c:Trigger>
</Components>
</Entity>
<!--<Entity>
<Components>
<c:Player>
<Velocity X="0" Y="0" Z="0"/>
</c:Player>
<c:Transform>
<Position X="2.5"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
</c:Model>
<c:AABB>
</c:AABB>
</Components>
</Entity>-->
<Entity>
<Components>
<c:Transform>
@@ -66,7 +48,7 @@
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Orientation X="0.0" Y="0" Z="1.0"/>
<Orientation X="0.0" Y="0" Z="0.0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitRaptor.obj</Resource>
@@ -77,8 +59,8 @@
<Entity>
<Components>
<c:Transform>
<Position X="-0.01" Y="0.55"/>
<Orientation X="0" Y="0" Z="-1"/>
<Position X="0" Y="0"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
<c:RaptorCopter>
<Speed>20</Speed>
@@ -89,7 +71,19 @@
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Position X="0" Y="0.4"/>
<Scale X="0.1" Y="0.4" Z="0.1"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCylinder.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0.6"/>
<Scale X="1.7" Y="0.03" Z="0.1"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
@@ -102,7 +96,7 @@
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Position X="0" Y="0.6"/>
<Scale X="1.7" Y="0.03" Z="0.1"/>
<Orientation X="0" Y="1.57" Z="0"/>
</c:Transform>
-10
View File
@@ -14,8 +14,6 @@
<xs:element ref="c:Model" minOccurs="0"/>
<xs:element ref="c:Test" minOccurs="0"/>
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
<xs:element ref="c:Player" minOccurs="0"/>
<xs:element ref="c:Health" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
@@ -24,19 +22,11 @@
<xs:complexType>
<xs:sequence>
<xs:element ref="Entity" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="EntityRef" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:attribute name="file" type="xs:string" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute ref="xml:base"/>
<xs:attribute name="name" type="xs:string" minOccurs="0" default=""/>
</xs:complexType>
</xs:element>
</xs:schema>
-73
View File
@@ -1,73 +0,0 @@
#version 430
#define TILE_SIZE 16
#define NUM_TILES 3600
uniform mat4 P;
uniform vec2 ScreenDimensions;
struct Plane {
vec3 Normal;
float d;
};
struct Frustum {
Plane Planes[4];
};
layout (std430, binding = 0) buffer FrustumBuffer
{
Frustum Data[3600];
} Frustums;
vec4 ConvertToView(vec4 ScreenCoords)
{
vec2 normalizedScreenCoords = ScreenCoords.xy / ScreenDimensions;
vec4 clipSpace = vec4( vec2(normalizedScreenCoords.x, normalizedScreenCoords.y) * 2.0 - 1.0, ScreenCoords.z, ScreenCoords.w);
vec4 view = inverse(P) * clipSpace;
view = view / view.w;
return view;
}
Plane ComputePlane( vec3 p0, vec3 p1, vec3 p2 )
{
Plane plane;
vec3 v0 = p1 - p0;
vec3 v2 = p2 - p0;
plane.Normal = normalize( cross( v0, v2 ) );
plane.d = dot( vec3(plane.Normal), p0 ); // Always 0 probably
return plane;
}
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main ()
{
if(gl_GlobalInvocationID.x * TILE_SIZE < ScreenDimensions.x && gl_GlobalInvocationID.y * TILE_SIZE < ScreenDimensions.y) {
//Top-Left = 0 | Top-Right = 1
//Bottom-Left = 2 | Bottom-Right = 3
vec4 ScreenCoords[4];
ScreenCoords[0] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y + 1 ) * TILE_SIZE, -1.0, 1.0); // Z-axis might need to be 1
ScreenCoords[1] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y + 1) * TILE_SIZE, -1.0, 1.0);
ScreenCoords[2] = vec4(gl_GlobalInvocationID.x * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
ScreenCoords[3] = vec4((gl_GlobalInvocationID.x + 1) * TILE_SIZE, (gl_GlobalInvocationID.y) * TILE_SIZE, -1.0, 1.0);
vec3 ViewVectors[4];
for(int i = 0; i < 4; i++) {
ViewVectors[i] = vec3(ConvertToView(ScreenCoords[i]));
}
vec3 EyePos = vec3(0,0,0);
Frustum f;
f.Planes[0] = ComputePlane(EyePos, ViewVectors[2], ViewVectors[0]);
f.Planes[1] = ComputePlane(EyePos, ViewVectors[1], ViewVectors[3]);
f.Planes[2] = ComputePlane(EyePos, ViewVectors[0], ViewVectors[1]);
f.Planes[3] = ComputePlane(EyePos, ViewVectors[3], ViewVectors[2]);
Frustums.Data[gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*80] = f;
}
}
-35
View File
@@ -1,35 +0,0 @@
#version 430
//in uvec3 gl_NumWorkGroups;
//in uvec3 gl_WorkGroupID;
//in uvec3 gl_LocalInvocationID;
//in uvec3 gl_GlobalInvocationID;
//in uint gl_LocalInvocationIndex;
#define NUM_LIGHTS 3
#define MAX_LIGHTS_PER_TILE 200
#define NUM_TILES 3600
struct Plane {
vec3 Normal;
float d;
};
struct Frustum {
Plane Planes[4];
};
layout (std430, binding = 0) buffer FrustumBuffer
{
Frustum Data[3600];
} Frustums;
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main ()
{
if(1 == 1) {
}
}
+2 -34
View File
@@ -60,6 +60,7 @@ file(GLOB SOURCE_FILES_Rendering_Util
"${INCLUDE_PATH}/Rendering/Util/*.h"
"Rendering/Util/*.cpp"
)
source_group(Rendering FILES ${SOURCE_FILES_Rendering})
source_group(Rendering\\Util FILES ${SOURCE_FILES_Rendering_Util})
@@ -69,18 +70,6 @@ file(GLOB SOURCE_FILES_GUI
)
source_group(GUI FILES ${SOURCE_FILES_GUI})
file(GLOB SOURCE_FILES_Collision
"${INCLUDE_PATH}/Collision/*.h"
"Collision/*.cpp"
)
source_group(Collision FILES ${SOURCE_FILES_Collision})
file(GLOB SOURCE_FILES_Editor
"${INCLUDE_PATH}/Editor/*.h"
"Editor/*.cpp"
)
source_group(Editor FILES ${SOURCE_FILES_Editor})
set(SOURCE_FILES
${SOURCE_FILES_Core}
${SOURCE_FILES_Core_Util}
@@ -89,29 +78,8 @@ set(SOURCE_FILES
${SOURCE_FILES_GUI}
${SOURCE_FILES_Rendering}
${SOURCE_FILES_Rendering_Util}
${SOURCE_FILES_Collision}
${SOURCE_FILES_Editor}
${CMAKE_SOURCE_DIR}/deps/include/imgui/imgui.cpp
${CMAKE_SOURCE_DIR}/deps/include/imgui/imgui_draw.cpp
${CMAKE_SOURCE_DIR}/deps/include/imgui/imgui_demo.cpp
${CMAKE_SOURCE_DIR}/deps/include/ini_file/ini_file.cpp
${CMAKE_SOURCE_DIR}/deps/include/nativefiledialog/nfd_common.c
)
# nativefiledialog
if(WIN32)
set(SOURCE_FILES ${SOURCE_FILES}
${CMAKE_SOURCE_DIR}/deps/include/nativefiledialog/nfd_win.cpp
)
endif()
if(UNIX)
set(SOURCE_FILES ${SOURCE_FILES}
${CMAKE_SOURCE_DIR}/deps/include/nativefiledialog/nfd_gtk.c
# TODO: Link with GTK+ here!
)
endif()
set(LIBRARIES
${OPENGL_LIBRARIES}
${GLEW_LIBRARIES}
@@ -135,4 +103,4 @@ target_link_libraries(Engine
${LIBRARIES}
)
#set_target_properties(Engine PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${INCLUDE_PATH}/PrecompiledHeader.h")
#cotire(Engine)
#cotire(Engine)
-282
View File
@@ -1,282 +0,0 @@
#include <algorithm>
#include "Collision/Collision.h"
#include "Engine/GLM.h"
#include "Core/World.h"
#include "Rendering/Model.h"
namespace Collision
{
//note: this one hasnt been delta adjusted like RayVsAABB has
bool RayAABBIntr(const Ray& ray, const AABB& box)
{
glm::vec3 w = 75.0f * ray.Direction();
glm::vec3 v = glm::abs(w);
glm::vec3 c = ray.Origin() - box.Center() + w;
glm::vec3 half = box.HalfSize();
if (abs(c.x) > v.x + half.x) {
return false;
}
if (abs(c.y) > v.y + half.y) {
return false;
}
if (abs(c.z) > v.z + half.z) {
return false;
}
if (abs(c.y*w.z - c.z*w.y) > half.y*v.z + half.z*v.y) {
return false;
}
if (abs(c.x*w.z - c.z*w.x) > half.x*v.z + half.z*v.x) {
return false;
}
return !(abs(c.x*w.y - c.y*w.x) > half.x*v.y + half.y*v.x);
}
bool RayVsAABB(const Ray& ray, const AABB& box)
{
float dummy;
return RayVsAABB(ray, box, dummy);
}
bool RayVsAABB(const Ray& ray, const AABB& box, float& outDistance)
{
glm::vec3 invdir = 1.0f / ray.Direction();
glm::vec3 origin = ray.Origin();
float t1 = (box.MinCorner().x - origin.x)*invdir.x;
float t2 = (box.MaxCorner().x - origin.x)*invdir.x;
float t3 = (box.MinCorner().y - origin.y)*invdir.y;
float t4 = (box.MaxCorner().y - origin.y)*invdir.y;
float t5 = (box.MinCorner().z - origin.z)*invdir.z;
float t6 = (box.MaxCorner().z - origin.z)*invdir.z;
float tmin = std::max(std::max(std::min(t1, t2), std::min(t3, t4)), std::min(t5, t6));
float tmax = std::min(std::min(std::max(t1, t2), std::max(t3, t4)), std::max(t5, t6));
//if (tmax < 0 || tmin > tmax)
//if tmin,tmax are almost the same (i.e. hitting exactly in the corner) then tmin might be slightly
//greater than tmax becuase of floating-precision problems. fixed by adding a small delta to tmax
if (tmax < 0 || tmin>(tmax + 0.0001f))
return false;
outDistance = (tmin > 0) ? tmin : tmax;
return true;
}
bool AABBVsAABB(const AABB& a, const AABB& b)
{
const glm::vec3& aCenter = a.Center();
const glm::vec3& bCenter = b.Center();
const glm::vec3& aHSize = a.HalfSize();
const glm::vec3& bHSize = b.HalfSize();
//Test will probably exit because of the X and Z axes more often, so test them first.
if (abs(aCenter[0] - bCenter[0]) > (aHSize[0] + bHSize[0])) {
return false;
}
if (abs(aCenter[2] - bCenter[2]) > (aHSize[2] + bHSize[2])) {
return false;
}
return (abs(aCenter[1] - bCenter[1]) <= (aHSize[1] + bHSize[1]));
}
bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation)
{
minimumTranslation = glm::vec3(0, 0, 0);
const glm::vec3& aMax = a.MaxCorner();
const glm::vec3& bMax = b.MaxCorner();
const glm::vec3& aMin = a.MinCorner();
const glm::vec3& bMin = b.MinCorner();
const glm::vec3& bSize = b.Size();
const glm::vec3& aSize = a.Size();
float minOffset = INFINITY;
float off;
auto axisesIntersecting = glm::tvec3<bool, glm::highp>(false, false, false);
for (int i = 0; i < 3; ++i) {
off = bMax[i] - aMin[i];
if (off > 0 && off < bSize[i] + aSize[i]) {
if (off < minOffset) {
minimumTranslation = glm::vec3();
minimumTranslation[i] = minOffset = off;
}
axisesIntersecting[i] = true;
}
off = aMax[i] - bMin[i];
if (off > 0 && off < bSize[i] + aSize[i]) {
if (off < minOffset) {
minOffset = off;
minimumTranslation = glm::vec3();
minimumTranslation[i] = -off;
}
axisesIntersecting[i] = true;
}
}
return glm::all(axisesIntersecting);
}
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices)
{
for (int i = 0; i < modelIndices.size(); ++i) {
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
glm::vec3 m = ray.Origin() - v0;
glm::vec3 MxE1 = glm::cross(m, e1);
glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);
float DetInv = glm::dot(e1, DxE2);
if (std::abs(DetInv) < FLT_EPSILON) {
continue;
}
DetInv = 1.0f / DetInv;
float u = glm::dot(m, DxE2) * DetInv;
float v = glm::dot(ray.Direction(), MxE1) * DetInv;
//u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
if ((u + 0.001f) < 0 || (v + 0.001f) < 0 || 1 < u + v) {
continue;
}
//Here, u and v are positive, u+v <= 1, and if distance is positive - triangle is hit.
if (0 <= glm::dot(e2, MxE1) * DetInv) {
return true;
}
}
return false;
}
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices,
float& outDistance,
float& outUCoord,
float& outVCoord)
{
outDistance = INFINITY;
bool hit = false;
for (int i = 0; i < modelIndices.size(); ++i) {
glm::vec3 v0 = modelVertices[modelIndices[i]].Position;
glm::vec3 e1 = modelVertices[modelIndices[++i]].Position - v0; //v1 - v0
glm::vec3 e2 = modelVertices[modelIndices[++i]].Position - v0; //v2 - v0
glm::vec3 m = ray.Origin() - v0;
glm::vec3 MxE1 = glm::cross(m, e1);
glm::vec3 DxE2 = glm::cross(ray.Direction(), e2);//pVec
float DetInv = glm::dot(e1, DxE2);
if (std::abs(DetInv) < FLT_EPSILON) {
continue;
}
DetInv = 1.0f / DetInv;
float dist = glm::dot(e2, MxE1) * DetInv;
if (dist >= outDistance) {
continue;
}
float u = glm::dot(m, DxE2) * DetInv;
float v = glm::dot(ray.Direction(), MxE1) * DetInv;
//u,v can be very close to 0 but still negative sometimes. added a deltafactor to compensate for that problem
//If u and v are positive, u+v <= 1, dist is positive, and less than closest.
if (0 <= (u + 0.001f) && 0 <= (v + 0.001f) && u + v <= 1 && 0 <= dist) {
outDistance = dist;
outUCoord = u;
outVCoord = v;
hit = true;
}
}
return hit;
}
bool RayVsModel(const Ray& ray,
const std::vector<RawModel::Vertex>& modelVertices,
const std::vector<unsigned int>& modelIndices,
glm::vec3& outHitPosition)
{
float u;
float v;
float dist;
bool hit = RayVsModel(ray, modelVertices, modelIndices, dist, u, v);
outHitPosition = ray.Origin() + dist * ray.Direction();
return hit;
}
bool IsSameBoxProbably(const AABB& first, const AABB& second, const float epsilon)
{
const glm::vec3& ma1 = first.MaxCorner();
const glm::vec3& ma2 = first.MaxCorner();
const glm::vec3& mi1 = second.MinCorner();
const glm::vec3& mi2 = second.MinCorner();
return (std::abs(ma1.x - ma2.x) < epsilon) &&
(std::abs(mi1.x - mi2.x) < epsilon) &&
(std::abs(ma1.z - ma2.z) < epsilon) &&
(std::abs(mi1.z - mi2.z) < epsilon) &&
(std::abs(ma1.y - ma2.y) < epsilon) &&
(std::abs(mi1.y - mi2.y) < epsilon);
}
bool attachAABBComponentFromModel(World* world, EntityID id)
{
if (!world->HasComponent(id, "Model")) {
return false;
}
ComponentWrapper model = world->GetComponent(id, "Model");
ComponentWrapper collision = world->AttachComponent(id, "AABB");
Model* modelRes = ResourceManager::Load<Model>(model["Resource"]);
if (modelRes == nullptr) {
return false;
}
glm::mat4 modelMatrix = modelRes->m_Matrix;
glm::vec3 mini = glm::vec3(INFINITY, INFINITY, INFINITY);
glm::vec3 maxi = glm::vec3(-INFINITY, -INFINITY, -INFINITY);
for (const auto& v : modelRes->m_Vertices) {
const auto& wPos = modelMatrix * glm::vec4(v.Position.x, v.Position.y, v.Position.z, 1);
maxi.x = std::max(wPos.x, maxi.x);
maxi.y = std::max(wPos.y, maxi.y);
maxi.z = std::max(wPos.z, maxi.z);
mini.x = std::min(wPos.x, mini.x);
mini.y = std::min(wPos.y, mini.y);
mini.z = std::min(wPos.z, mini.z);
}
collision["BoxCenter"] = 0.5f * (maxi + mini);
collision["BoxSize"] = maxi - mini;
return true;
}
bool GetEntityBox(World* world, ComponentWrapper& AABBComponent, AABB& outBox)
{
ComponentWrapper& cTrans = world->GetComponent(AABBComponent.EntityID, "Transform");
ComponentWrapper model = world->GetComponent(AABBComponent.EntityID, "Model");
Model* modelRes = ResourceManager::Load<Model>(model["Resource"]);
outBox.CreateFromCenter(AABBComponent["BoxCenter"], AABBComponent["BoxSize"]);
glm::vec3 mini = outBox.MinCorner();
glm::vec3 maxi = outBox.MaxCorner();
if (modelRes == nullptr) {
return false;
}
glm::mat4 modelMatrix = modelRes->m_Matrix *
glm::translate(glm::mat4(), (glm::vec3)cTrans["Position"]) *
glm::scale((glm::vec3)cTrans["Scale"]);
outBox = AABB(modelMatrix * glm::vec4(mini.x, mini.y, mini.z, 1),
modelMatrix * glm::vec4(maxi.x, maxi.y, maxi.z, 1));
return true;
}
bool GetEntityBox(World* world, EntityID entity, AABB& outBox, bool forceBoxFromModel)
{
if (!world->HasComponent(entity, "AABB")) {
if (forceBoxFromModel) {
if (!attachAABBComponentFromModel(world, entity))
return false;
} else {
return false;
}
}
ComponentWrapper& cBox = world->GetComponent(entity, "AABB");
return GetEntityBox(world, cBox, outBox);
}
}
-40
View File
@@ -1,40 +0,0 @@
#include "Collision/Collision.h"
#include "Collision/CollisionSystem.h"
#include "Core/AABB.h"
void CollisionSystem::UpdateComponent(World * world, ComponentWrapper & cAABB, double dt)
{
//Right now, cAABB is a component attached to any entity that should be collideable.
AABB thisBox;
if (!Collision::GetEntityBox(world, cAABB, thisBox)) {
return;
}
//Press 'Z' to enable/disable collision.
if (zPress) {
return;
}
//Here, mover should be an object that moves, currently only players.
for (auto& mover : *world->GetComponents("Player")) {
if (cAABB.EntityID == mover.EntityID) {
continue;
}
AABB otherBox;
if (!Collision::GetEntityBox(world, mover.EntityID, otherBox)) {
continue;
}
glm::vec3 resolveTranslation;
if (Collision::AABBVsAABB(otherBox, thisBox, resolveTranslation)) {
ComponentWrapper& trans = world->GetComponent(mover.EntityID, "Transform");
//TODO: Special treatment if both are movers.
trans["Position"] = (glm::vec3)trans["Position"] + resolveTranslation;
}
}
}
bool CollisionSystem::OnKeyUp(const Events::KeyUp & event)
{
if (event.KeyCode == GLFW_KEY_Z) {
zPress = !zPress;
}
return false;
}
-81
View File
@@ -1,81 +0,0 @@
#include "Collision/TriggerSystem.h"
#include "Collision/Collision.h"
#include "Core/AABB.h"
#include "Rendering/Model.h"
void TriggerSystem::UpdateComponent(World* world, ComponentWrapper& trigger, double dt)
{
//Currently only players can trigger things.
auto players = world->GetComponents("Player");
if (players == nullptr) {
return;
}
EntityID tId = trigger.EntityID;
AABB triggerBox;
//The trigger *should* have a bounding box, or something, to test against so it can be triggered.
if (!Collision::GetEntityBox(world, tId, triggerBox, true)) {
return;
}
for (auto& pc : *players) {
EntityID pId = pc.EntityID;
AABB playerBox;
//The player can't trigger anything without an AABB.
if (!Collision::GetEntityBox(world, pId, playerBox, true)) {
continue;
}
if (!Collision::AABBVsAABB(triggerBox, playerBox)) {
//Entity is not touching the trigger,
//Throw event if it was previously.
if (throwLeaveIfWasInTrigger(m_EntitiesTouchingTrigger[tId], pId, tId)) {
continue;
}
//This only occurs if the entity was completely inside the trigger one frame,
//then completely outside the trigger, e.g. when dying and respawning.
throwLeaveIfWasInTrigger(m_EntitiesCompletelyInTrigger[tId], pId, tId);
} else {
//Entity is at least touching the trigger.
AABB completelyInsideBox;
completelyInsideBox.CreateFromCenter(triggerBox.Center(), triggerBox.Size() - 2.0f * playerBox.Size());
if (Collision::AABBVsAABB(completelyInsideBox, playerBox) &&
glm::all(glm::greaterThan(triggerBox.Size(), playerBox.Size()))) {
//Entity is completely inside the trigger.
//If it was only touching before, it is erased.
m_EntitiesTouchingTrigger[tId].erase(pId);
std::unordered_set<EntityID>& completeSet = m_EntitiesCompletelyInTrigger[tId];
if (completeSet.count(pId) == 0) {
//If it wasn't completely in the trigger, throw Enter and add to the set.
completeSet.insert(pId);
publish<Events::TriggerEnter>(pId, tId);
}
} else {
//Entity is only touching the trigger.
std::unordered_set<EntityID>& touchSet = m_EntitiesTouchingTrigger[tId];
std::unordered_set<EntityID>& completeSet = m_EntitiesCompletelyInTrigger[tId];
const auto& it = completeSet.find(pId);
//If it was completely inside before.
if (it != completeSet.end()) {
completeSet.erase(it);
touchSet.insert(pId);
//If it was completely outside before.
} else if (touchSet.count(pId) == 0) {
publish<Events::TriggerTouch>(pId, tId);
touchSet.insert(pId);
}
//Else, it was touching the trigger last frame too and nothing is done.
}
}
}
}
bool TriggerSystem::throwLeaveIfWasInTrigger(std::unordered_set<EntityID>& triggerSet, EntityID pId, EntityID tId)
{
const auto& it = triggerSet.find(pId);
if (it != triggerSet.end()) {
//If it was in the trigger, but not anymore, throw leaveEvent and erase from the set.
triggerSet.erase(it);
publish<Events::TriggerLeave>(pId, tId);
return true;
}
return false;
}
-34
View File
@@ -1,34 +0,0 @@
#include "Core/AABB.h"
#include "Common.h"
AABB::AABB(const glm::vec3& minPos, const glm::vec3& maxPos)
: m_MinCorner(minPos)
, m_MaxCorner(maxPos)
, m_Center(0.5f * (maxPos + minPos))
, m_HalfSize(0.5f * (maxPos - minPos))
{
DEBUG_IF(glm::any(glm::lessThan(m_MaxCorner, m_MinCorner))) {
LOG_WARNING("AABB maxCorner coordinates are not greater than minCorner");
m_MaxCorner.x = glm::max(m_MaxCorner.x, m_MinCorner.x);
m_MinCorner.x = glm::min(m_MaxCorner.x, m_MinCorner.x);
m_MaxCorner.y = glm::max(m_MaxCorner.y, m_MinCorner.y);
m_MinCorner.y = glm::min(m_MaxCorner.y, m_MinCorner.y);
m_MaxCorner.z = glm::max(m_MaxCorner.z, m_MinCorner.z);
m_MinCorner.z = glm::min(m_MaxCorner.z, m_MinCorner.z);
}
}
AABB::AABB(const glm::vec4& minPos, const glm::vec4& maxPos)
: AABB(glm::vec3(minPos), glm::vec3(maxPos))
{}
void AABB::CreateFromCenter(const glm::vec3& center, const glm::vec3& size)
{
m_Center = center;
m_HalfSize = 0.5f * size;
m_MinCorner = m_Center - m_HalfSize;
m_MaxCorner = m_Center + m_HalfSize;
}
AABB::~AABB()
{}

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