Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 589ca45936 | |||
| 0cff07101c |
@@ -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...1b478d3159
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -4,5 +4,4 @@
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Core/Util/Logging.h"
|
||||
#include "Core/Util/IfDebug.h"
|
||||
#include "Core/Util/Logging.h"
|
||||
@@ -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
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
#include <string>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/range/adaptors.hpp>
|
||||
#include <ini_file/ini_file.hpp>
|
||||
|
||||
#include "../Common.h"
|
||||
#include "ResourceManager.h"
|
||||
|
||||
@@ -20,52 +20,46 @@ private:
|
||||
public:
|
||||
template <typename T>
|
||||
T Get(std::string key, T defaultValue);
|
||||
template <typename T>
|
||||
std::vector<std::pair<std::string, T>> GetAll(std::string key);
|
||||
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:
|
||||
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 m_PTreeMerged.get<T>(key, defaultValue);
|
||||
}
|
||||
|
||||
return boost::lexical_cast<T>(param->get_value());
|
||||
template <typename T>
|
||||
std::vector<std::pair<std::string, T>> ConfigFile::GetAll(std::string key)
|
||||
{
|
||||
std::vector<std::pair<std::string, T>> out;
|
||||
auto parent = m_PTreeMerged.find(key);
|
||||
if (parent == m_PTreeMerged.not_found()) {
|
||||
return out;
|
||||
}
|
||||
for (auto& child : parent->second) {
|
||||
T value = boost::lexical_cast<T>(child.second.data());
|
||||
out.push_back(std::make_pair(child.first, value));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef EFileDropped_h__
|
||||
#define EFileDropped_h__
|
||||
|
||||
#include "EventBroker.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct FileDropped : Event
|
||||
{
|
||||
std::string Path;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -2,6 +2,5 @@
|
||||
#define Entity_h__
|
||||
|
||||
typedef unsigned int EntityID;
|
||||
const static unsigned int EntityID_Invalid = -1;
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -13,8 +13,6 @@
|
||||
relay = decltype(relay)(std::bind(handler, this, std::placeholders::_1)); \
|
||||
m_EventBroker->Subscribe(relay);
|
||||
|
||||
typedef unsigned int EventID;
|
||||
|
||||
class EventBroker;
|
||||
|
||||
class BaseEventRelay
|
||||
@@ -33,7 +31,6 @@ public:
|
||||
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;
|
||||
@@ -98,7 +95,6 @@ public:
|
||||
|
||||
private:
|
||||
bool m_IsProcessing = false;
|
||||
EventID m_NextEventID = 0;
|
||||
|
||||
typedef std::string ContextTypeName_t; // typeid(ContextType).name()
|
||||
typedef std::string EventTypeName_t; // typeid(EventType).name()
|
||||
@@ -107,14 +103,14 @@ private:
|
||||
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;
|
||||
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;
|
||||
|
||||
void subscribeImmediate(BaseEventRelay& relay);
|
||||
void unsubscribeImmediate(std::tuple<EventID, ContextTypeName_t, EventTypeName_t> identifier);
|
||||
void unsubscribeImmediate(BaseEventRelay& relay);
|
||||
};
|
||||
|
||||
template <typename EventType>
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -36,7 +33,6 @@ public:
|
||||
|
||||
void Initialize();
|
||||
|
||||
static const short MAX_GAMEPADS = 4;
|
||||
|
||||
void Update(double dt);
|
||||
|
||||
@@ -53,12 +49,6 @@ private:
|
||||
std::array<int, GLFW_KEY_LAST+1> m_LastKeyState;
|
||||
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_CurrentMouseState;
|
||||
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_LastMouseState;
|
||||
typedef std::array<float, static_cast<int>(Gamepad::Axis::LAST) + 1> GamepadAxisState;
|
||||
std::array<GamepadAxisState, MAX_GAMEPADS> m_CurrentGamepadAxisState;
|
||||
std::array<GamepadAxisState, MAX_GAMEPADS> m_LastGamepadAxisState;
|
||||
typedef std::array<bool, static_cast<int>(Gamepad::Button::LAST) + 1> GamepadButtonState;
|
||||
std::array<GamepadButtonState, MAX_GAMEPADS> m_CurrentGamepadButtonState;
|
||||
std::array<GamepadButtonState, MAX_GAMEPADS> m_LastGamepadButtonState;
|
||||
|
||||
double m_CurrentMouseX, m_CurrentMouseY;
|
||||
double m_LastMouseX, m_LastMouseY;
|
||||
@@ -68,12 +58,10 @@ 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[]);
|
||||
static void GLFWMouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
LOG_DEBUG("Click! %i %i %i", button, action, mods);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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++();
|
||||
|
||||
@@ -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
|
||||
@@ -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__
|
||||
@@ -9,42 +9,17 @@ class System
|
||||
{
|
||||
friend class SystemPipeline;
|
||||
|
||||
protected:
|
||||
System(EventBroker* eventBroker)
|
||||
public:
|
||||
System(EventBroker* eventBroker, std::string componentType)
|
||||
: m_EventBroker(eventBroker)
|
||||
, m_ComponentType(componentType)
|
||||
{ }
|
||||
virtual ~System() = default;
|
||||
|
||||
virtual void Update(World* world, ComponentWrapper& component, double dt) = 0;
|
||||
|
||||
protected:
|
||||
std::string m_ComponentType;
|
||||
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 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;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -14,76 +14,45 @@ public:
|
||||
{ }
|
||||
~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;
|
||||
std::unordered_map<std::string, std::vector<System*>> m_Systems;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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__
|
||||
@@ -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
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef XboxControllerInputHandler_h__
|
||||
#define XboxControllerInputHandler_h__
|
||||
|
||||
#include "InputHandler.h"
|
||||
#include "Core/EKeyDown.h"
|
||||
#include "Core/EKeyUp.h"
|
||||
|
||||
struct _XINPUT_STATE;
|
||||
typedef _XINPUT_STATE XINPUT_STATE;
|
||||
|
||||
class XboxControllerInputHandler : public InputHandler
|
||||
{
|
||||
public:
|
||||
XboxControllerInputHandler(EventBroker* eventBroker, InputProxy* inputProxy);
|
||||
|
||||
|
||||
bool BindOrigin(std::string origin, std::string command, float value) override;
|
||||
|
||||
void Update(double dt) override;
|
||||
|
||||
virtual float GetCommandValue(std::string command) override;
|
||||
private:
|
||||
std::unordered_map<std::string, int> m_OriginButtons;
|
||||
std::unordered_map<std::string, int> m_OriginAxes;
|
||||
std::unordered_map<int, std::tuple<std::string, float>> m_ButtonBindings; // GLFW_KEY... -> command string & value
|
||||
std::unordered_map<int, std::tuple<std::string, float>> m_AxisBindings; // GLFW_KEY... -> command string & value
|
||||
std::unordered_map<std::string, float> m_CommandValues;
|
||||
|
||||
static const short MAX_GAMEPADS = 4;
|
||||
|
||||
float getAxisValue(XINPUT_STATE& state, int axis);
|
||||
//typedef std::array<float, static_cast<int>(Gamepad::Axis::LAST) + 1> GamepadAxisState;
|
||||
//std::array<GamepadAxisState, MAX_GAMEPADS> m_CurrentGamepadAxisState;
|
||||
//std::array<GamepadAxisState, MAX_GAMEPADS> m_LastGamepadAxisState;
|
||||
//typedef std::array<bool, static_cast<int>(Gamepad::Button::LAST) + 1> GamepadButtonState;
|
||||
//std::array<GamepadButtonState, MAX_GAMEPADS> m_CurrentGamepadButtonState;
|
||||
//std::array<GamepadButtonState, MAX_GAMEPADS> m_LastGamepadButtonState;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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,4 +1,3 @@
|
||||
#include <imgui/imgui.h>
|
||||
#include "../Input/FirstPersonInputController.h"
|
||||
|
||||
template <typename EventContext>
|
||||
@@ -14,35 +13,22 @@ public:
|
||||
|
||||
virtual bool OnCommand(const Events::InputCommand& e) override
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
if (e.Command == "PrimaryFire") {
|
||||
if (e.Value > 0) {
|
||||
if (!io.WantCaptureMouse) {
|
||||
LockMouse();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
return FirstPersonInputController::OnCommand(e);
|
||||
@@ -51,7 +37,7 @@ public:
|
||||
void Update(double dt)
|
||||
{
|
||||
if (glm::length2(m_Velocity) > 0) {
|
||||
m_Position += m_Orientation * (glm::normalize(m_Velocity) * m_Speed * (float)dt);
|
||||
m_Position += (m_Orientation * (m_Velocity * m_BaseSpeed)) * (float)dt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,5 +45,4 @@ protected:
|
||||
glm::vec3 m_Position = glm::vec3(0, 0, 0);
|
||||
glm::vec3 m_Velocity = glm::vec3(0, 0, 0);
|
||||
float m_BaseSpeed = 2.0f;
|
||||
float m_Speed = m_BaseSpeed;
|
||||
};
|
||||
@@ -1,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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+2
-20
@@ -12,21 +12,12 @@
|
||||
#include "Input/InputProxy.h"
|
||||
#include "Input/KeyboardInputHandler.h"
|
||||
#include "Input/MouseInputHandler.h"
|
||||
#include "Input/XboxControllerInputHandler.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 +39,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;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
+24
-13
@@ -6,28 +6,39 @@
|
||||
|
||||
#include "Common.h"
|
||||
#include "Core/System.h"
|
||||
#include "Collision/ETrigger.h"
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Core/EKeyDown.h"
|
||||
#include "Core/EKeyUp.h"
|
||||
|
||||
class PlayerSystem : public PureSystem
|
||||
struct KeyInput
|
||||
{
|
||||
bool Forward = false;
|
||||
bool Left = false;
|
||||
bool Back = false;
|
||||
bool Right = false;
|
||||
};
|
||||
|
||||
class PlayerSystem : public System
|
||||
{
|
||||
public:
|
||||
PlayerSystem(EventBroker* eventBroker)
|
||||
: PureSystem(eventBroker, "Player")
|
||||
: System(eventBroker, "Player")
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ETouch, &PlayerSystem::OnTouch);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EEnter, &PlayerSystem::OnEnter);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ELeave, &PlayerSystem::OnLeave);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &PlayerSystem::OnKeyDown);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &PlayerSystem::OnKeyUp);
|
||||
}
|
||||
|
||||
virtual void UpdateComponent(World* world, ComponentWrapper& player, double dt) override;
|
||||
virtual void Update(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);
|
||||
glm::vec3 m_Direction;
|
||||
KeyInput input;
|
||||
|
||||
EventRelay<PlayerSystem, Events::KeyDown> m_EKeyDown;
|
||||
bool OnKeyDown(const Events::KeyDown &event);
|
||||
EventRelay<PlayerSystem, Events::KeyUp> m_EKeyUp;
|
||||
bool OnKeyUp(const Events::KeyUp &event);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,14 +1,16 @@
|
||||
#include "Common.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
class RaptorCopterSystem : public PureSystem
|
||||
class RaptorCopterSystem : public System
|
||||
{
|
||||
public:
|
||||
RaptorCopterSystem(EventBroker* eventBroker)
|
||||
: PureSystem(eventBroker, "RaptorCopter")
|
||||
: System(eventBroker, "RaptorCopter")
|
||||
{ }
|
||||
|
||||
virtual void UpdateComponent(World* world, ComponentWrapper& raptorCopter, double dt) override
|
||||
virtual void Initialize() { }
|
||||
|
||||
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,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
|
||||
@@ -14,11 +14,11 @@ R=Reload
|
||||
Space=Jump
|
||||
LeftControl=Crouch
|
||||
LeftShift=Sprint
|
||||
F1=ToggleEditor
|
||||
1=EditorToolMove
|
||||
2=EditorToolRotate
|
||||
3=EditorToolScale
|
||||
X=EditorToggleTransformSpace
|
||||
C=ConnectToServer
|
||||
N=SwitchToServer
|
||||
M=SwitchToClient
|
||||
|
||||
GamepadRightTrigger=PrimaryFire
|
||||
GamepadRightX=Yaw
|
||||
GamepadRightY=-Pitch
|
||||
GamepadA=TestGamepadA
|
||||
GamepadX=TestGamepadX
|
||||
GamepadLeftX=Right
|
||||
GamepadLeftY=Forward
|
||||
@@ -6,7 +6,4 @@
|
||||
<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>
|
||||
@@ -1,4 +0,0 @@
|
||||
<c:AABB>
|
||||
<BoxCenter X="0" Y="0" Z="0"/>
|
||||
<BoxSize X="1" Y="1" Z="1"/>
|
||||
</c:AABB>
|
||||
@@ -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>
|
||||
@@ -1,4 +0,0 @@
|
||||
<c:Health>
|
||||
<Health>100</Health>
|
||||
<MaxHealth>100</MaxHealth>
|
||||
</c:Health>
|
||||
@@ -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>
|
||||
@@ -1,7 +1,3 @@
|
||||
<c:Player>
|
||||
<Velocity X="0" Y="0" Z="0"/>
|
||||
<Forward>false</Forward>
|
||||
<Left>false</Left>
|
||||
<Back>false</Back>
|
||||
<Right>false</Right>
|
||||
</c:Player>
|
||||
@@ -7,10 +7,6 @@
|
||||
<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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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,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>
|
||||
@@ -1,2 +0,0 @@
|
||||
<c:Trigger>
|
||||
</c:Trigger>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -25,16 +25,13 @@
|
||||
<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>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Player>
|
||||
<Velocity X="0" Y="0" Z="0"/>
|
||||
@@ -45,10 +42,8 @@
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitCube.obj</Resource>
|
||||
</c:Model>
|
||||
<c:AABB>
|
||||
</c:AABB>
|
||||
</Components>
|
||||
</Entity>-->
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
<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 +23,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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{}
|
||||
@@ -19,7 +19,7 @@ bool ComponentPoolForwardIterator::operator!=(const ComponentPoolForwardIterator
|
||||
return m_MemoryPoolIterator != other.m_MemoryPoolIterator;
|
||||
}
|
||||
|
||||
ComponentPoolForwardIterator ComponentPoolForwardIterator::operator++(int)
|
||||
ComponentPoolForwardIterator& ComponentPoolForwardIterator::operator++(int)
|
||||
{
|
||||
ComponentPoolForwardIterator copyIter(*this);
|
||||
operator++();
|
||||
@@ -50,16 +50,10 @@ ComponentWrapper ComponentPool::GetByEntity(EntityID ent)
|
||||
return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent));
|
||||
}
|
||||
|
||||
|
||||
bool ComponentPool::KnowsEntity(EntityID ent)
|
||||
{
|
||||
return m_EntityToComponent.find(ent) != m_EntityToComponent.end();
|
||||
}
|
||||
|
||||
void ComponentPool::Delete(ComponentWrapper& wrapper)
|
||||
{
|
||||
m_EntityToComponent.erase(wrapper.EntityID);
|
||||
m_Pool.Free(wrapper.Data - sizeof(EntityID));
|
||||
m_Pool.Free(wrapper.Data);
|
||||
}
|
||||
|
||||
ComponentPool::iterator ComponentPool::begin() const
|
||||
|
||||
@@ -7,110 +7,36 @@ ConfigFile::ConfigFile(std::string path)
|
||||
boost::filesystem::path defaultFile;
|
||||
defaultFile = m_Path.parent_path() / ("Default" + m_Path.filename().string());
|
||||
|
||||
std::fstream file;
|
||||
// Read defaults
|
||||
file.open(defaultFile.string());
|
||||
if (file) {
|
||||
if (boost::filesystem::exists(defaultFile)) {
|
||||
try {
|
||||
file >> m_Defaults;
|
||||
} catch (ini_file::ini_exceptions::ini_file_exception& e) {
|
||||
LOG_ERROR("Failed to parse \"%s\":\n%s", defaultFile.string().c_str(), "ini_file_exception");
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("Failed to find \"%s\"! Relying on hardcoded default values!", defaultFile.string().c_str());
|
||||
}
|
||||
file.close();
|
||||
|
||||
// Read overrides
|
||||
file.open(m_Path.string());
|
||||
if (file) {
|
||||
try {
|
||||
file >> m_Overrides;
|
||||
} catch (ini_file::ini_exceptions::ini_file_exception& e) {
|
||||
LOG_ERROR("Failed to parse \"%s\":\n%s", defaultFile.string().c_str(), "ini_file_exception");
|
||||
boost::property_tree::ini_parser::read_ini(defaultFile.string(), m_PTreeDefaults);
|
||||
} catch (boost::property_tree::ptree_error& e) {
|
||||
LOG_ERROR("Failed to parse \"%s\":\n%s", defaultFile.string().c_str(), e.what());
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("Failed to find \"%s\"! Relying on hardcoded default values!", defaultFile.string().c_str());
|
||||
}
|
||||
file.close();
|
||||
|
||||
// Merge
|
||||
mergeINI(m_Merged, m_Defaults);
|
||||
mergeINI(m_Merged, m_Overrides);
|
||||
}
|
||||
m_PTreeMerged = m_PTreeDefaults;
|
||||
|
||||
const ini_file::section* ConfigFile::GetSection(std::string section)
|
||||
{
|
||||
auto sectionIt = m_Merged.find(section);
|
||||
if (sectionIt == m_Merged.end()) {
|
||||
LOG_WARNING("%s: Unknown section \"%s\"", m_Path.string().c_str(), section.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sectionIt->second.get();
|
||||
}
|
||||
|
||||
const ini_file::param* ConfigFile::GetParam(std::string key)
|
||||
{
|
||||
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 nullptr;
|
||||
}
|
||||
|
||||
auto sectionIt = m_Merged.find(section);
|
||||
if (sectionIt == m_Merged.end()) {
|
||||
LOG_WARNING("%s: Unknown section \"%s\"", m_Path.string().c_str(), section.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto paramIt = sectionIt->second->find(param);
|
||||
if (paramIt == sectionIt->second->end()) {
|
||||
LOG_WARNING("%s: Unknown section param \"%s\"", m_Path.string().c_str(), key.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return paramIt->second.get();
|
||||
}
|
||||
|
||||
void ConfigFile::SaveToDisk()
|
||||
{
|
||||
std::ofstream file(m_Path.string());
|
||||
file << m_Overrides;
|
||||
file.close();
|
||||
}
|
||||
|
||||
void ConfigFile::mergeINI(ini_file::section_map& to, const ini_file::section_map& from)
|
||||
{
|
||||
for (auto& section : from) {
|
||||
for (auto& param : *section.second) {
|
||||
auto& p = to[section.first][param.first];
|
||||
if (!param.second->get_comment().empty()) {
|
||||
p.set_comment(param.second->get_comment());
|
||||
// Read overrides
|
||||
if (boost::filesystem::exists(m_Path)) {
|
||||
try {
|
||||
boost::property_tree::ini_parser::read_ini(m_Path.string(), m_PTreeOverrides);
|
||||
for (auto& topLevelNode : m_PTreeOverrides) {
|
||||
auto& mergedTopLevelNode = m_PTreeMerged.find(topLevelNode.first);
|
||||
for (auto& childOverrideNode : topLevelNode.second) {
|
||||
mergedTopLevelNode->second.put_child(childOverrideNode.first, childOverrideNode.second);
|
||||
}
|
||||
}
|
||||
p.set_value(param.second->get_value());
|
||||
} catch (boost::property_tree::ptree_error& e) {
|
||||
LOG_ERROR("Failed to parse \"%s\":\n%s", m_Path.filename().string().c_str(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::optional<std::pair<std::string, std::string>> ConfigFile::tokenizeKey(std::string key)
|
||||
void ConfigFile::SaveToDisk()
|
||||
{
|
||||
std::size_t delimiter = key.find_last_of('.');
|
||||
if (delimiter == std::string::npos) {
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
std::string section = key.substr(0, delimiter);
|
||||
if (section.empty()) {
|
||||
return boost::none;
|
||||
}
|
||||
std::string param = key.substr(delimiter + 1);
|
||||
if (param.empty()) {
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
return std::make_pair(section, param);
|
||||
}
|
||||
boost::property_tree::ini_parser::write_ini(m_Path.string(), m_PTreeOverrides);
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#include "Core/DeveloperConsole.h"
|
||||
|
||||
std::map<std::string, std::function<void(std::string)>> DeveloperConsole::m_VariableBindingSetters;
|
||||
std::map<std::string, std::function<std::string()>> DeveloperConsole::m_VariableBindingGetters;
|
||||
@@ -1,95 +0,0 @@
|
||||
#include "Core/EntityFile.h"
|
||||
|
||||
EntityFile::EntityFile(boost::filesystem::path path)
|
||||
: m_FilePath(path)
|
||||
{
|
||||
using namespace xercesc;
|
||||
XMLPlatformUtils::Initialize();
|
||||
m_GrammarPool = new XMLGrammarPoolImpl();
|
||||
m_SAX2XMLReader = XMLReaderFactory::createXMLReader(XMLPlatformUtils::fgMemoryManager, m_GrammarPool);
|
||||
}
|
||||
|
||||
EntityFile::~EntityFile()
|
||||
{
|
||||
delete m_SAX2XMLReader;
|
||||
delete m_GrammarPool;
|
||||
xercesc::XMLPlatformUtils::Terminate();
|
||||
}
|
||||
|
||||
void EntityFile::Parse(const EntityFileHandler* handler) const
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
EntityFileSAXHandler saxHandler(handler, nullptr);
|
||||
m_SAX2XMLReader->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true);
|
||||
m_SAX2XMLReader->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);
|
||||
m_SAX2XMLReader->setContentHandler(&saxHandler);
|
||||
m_SAX2XMLReader->setErrorHandler(&saxHandler);
|
||||
m_SAX2XMLReader->setDeclarationHandler(&saxHandler);
|
||||
m_SAX2XMLReader->parse(m_FilePath.string().c_str());
|
||||
}
|
||||
|
||||
std::size_t EntityFile::GetTypeStride(std::string typeName)
|
||||
{
|
||||
std::map<std::string, size_t> typeStrides{
|
||||
{ "bool", sizeof(bool) },
|
||||
{ "int", sizeof(int) },
|
||||
{ "float", sizeof(float) },
|
||||
{ "double", sizeof(double) },
|
||||
{ "string", sizeof(std::string) },
|
||||
{ "Vector", sizeof(glm::vec3) },
|
||||
{ "Quaternion", sizeof(glm::quat) },
|
||||
{ "Color", sizeof(glm::vec4) }
|
||||
};
|
||||
|
||||
auto it = typeStrides.find(typeName);
|
||||
return (it != typeStrides.end()) ? it->second : 0;
|
||||
}
|
||||
|
||||
void EntityFile::WriteAttributeData(char* outData, const ComponentInfo::Field_t& field, const std::map<std::string, std::string>& attributes)
|
||||
{
|
||||
if (field.Type == "Vector") {
|
||||
glm::vec3 vec;
|
||||
vec.x = boost::lexical_cast<float>(attributes.at("X"));
|
||||
vec.y = boost::lexical_cast<float>(attributes.at("Y"));
|
||||
vec.z = boost::lexical_cast<float>(attributes.at("Z"));
|
||||
memcpy(outData, reinterpret_cast<char*>(&vec), field.Stride);
|
||||
} else if (field.Type == "Color") {
|
||||
glm::vec4 vec;
|
||||
vec.r = boost::lexical_cast<float>(attributes.at("R"));
|
||||
vec.g = boost::lexical_cast<float>(attributes.at("G"));
|
||||
vec.b = boost::lexical_cast<float>(attributes.at("B"));
|
||||
vec.a = boost::lexical_cast<float>(attributes.at("A"));
|
||||
memcpy(outData, reinterpret_cast<char*>(&vec), field.Stride);
|
||||
} else if (field.Type == "Quaternion") {
|
||||
glm::quat q;
|
||||
q.x = boost::lexical_cast<float>(attributes.at("X"));
|
||||
q.y = boost::lexical_cast<float>(attributes.at("Y"));
|
||||
q.z = boost::lexical_cast<float>(attributes.at("Z"));
|
||||
q.w = boost::lexical_cast<float>(attributes.at("W"));
|
||||
memcpy(outData, reinterpret_cast<char*>(&q), field.Stride);
|
||||
} else if (!attributes.empty()) {
|
||||
LOG_WARNING("%i attributes not handled by any type conversion!", attributes.size());
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData)
|
||||
{
|
||||
if (field.Type == "int") {
|
||||
int value = boost::lexical_cast<int>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "float") {
|
||||
float value = boost::lexical_cast<float>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "double") {
|
||||
double value = boost::lexical_cast<double>(valueData);
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "bool") {
|
||||
bool value = (valueData[0] == 't'); // Lazy bool evaluation
|
||||
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
|
||||
} else if (field.Type == "string") {
|
||||
new (outData) std::string(valueData);
|
||||
} else {
|
||||
LOG_WARNING("Unknown value data type: %s", field.Type.c_str());
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
#include "Core/EntityFileParser.h"
|
||||
|
||||
EntityFileParser::EntityFileParser(const EntityFile* entityFile)
|
||||
: m_EntityFile(entityFile)
|
||||
{
|
||||
m_Handler.SetStartEntityCallback(std::bind(&EntityFileParser::onStartEntity, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
m_Handler.SetStartComponentCallback(std::bind(&EntityFileParser::onStartComponent, this, std::placeholders::_1, std::placeholders::_2));
|
||||
m_Handler.SetStartFieldCallback(std::bind(&EntityFileParser::onStartComponentField, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
m_Handler.SetStartFieldDataCallback(std::bind(&EntityFileParser::onFieldData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||
}
|
||||
|
||||
void EntityFileParser::MergeEntities(World* world)
|
||||
{
|
||||
m_World = world;
|
||||
m_EntityIDMapper[0] = 0;
|
||||
m_EntityFile->Parse(&m_Handler);
|
||||
}
|
||||
|
||||
void EntityFileParser::onStartEntity(EntityID entity, EntityID parent, const std::string& name)
|
||||
{
|
||||
EntityID realParent = m_EntityIDMapper.at(parent);
|
||||
EntityID realEntity = m_World->CreateEntity(realParent);
|
||||
if (!name.empty()) {
|
||||
m_World->SetName(realEntity, name);
|
||||
}
|
||||
m_EntityIDMapper[entity] = realEntity;
|
||||
LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent);
|
||||
}
|
||||
|
||||
void EntityFileParser::onStartComponent(EntityID entity, const std::string& component)
|
||||
{
|
||||
EntityID realEntity = m_EntityIDMapper.at(entity);
|
||||
m_World->AttachComponent(realEntity, component);
|
||||
LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity);
|
||||
}
|
||||
|
||||
void EntityFileParser::onStartComponentField(EntityID entity, const std::string& componentType, const std::string& fieldName, const std::map<std::string, std::string>& attributes)
|
||||
{
|
||||
EntityID realEntity = m_EntityIDMapper.at(entity);
|
||||
ComponentWrapper component = m_World->GetComponent(realEntity, componentType);
|
||||
auto& field = component.Info.Fields.at(fieldName);
|
||||
|
||||
LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), field.Type.c_str());
|
||||
LOG_DEBUG("Attributes:");
|
||||
for (auto& kv : attributes) {
|
||||
LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str());
|
||||
}
|
||||
|
||||
char* data = component.Data + field.Offset;
|
||||
EntityFile::WriteAttributeData(data, field, attributes);
|
||||
}
|
||||
|
||||
void EntityFileParser::onFieldData(EntityID entity, const std::string& componentType, const std::string& fieldName, const char* fieldData)
|
||||
{
|
||||
EntityID realEntity = m_EntityIDMapper.at(entity);
|
||||
ComponentWrapper component = m_World->GetComponent(realEntity, componentType);
|
||||
auto& field = component.Info.Fields.at(fieldName);
|
||||
|
||||
char* data = component.Data + field.Offset;
|
||||
EntityFile::WriteValueData(data, field, fieldData);
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
#include "Core/EntityFilePreprocessor.h"
|
||||
|
||||
EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile)
|
||||
: m_EntityFile(entityFile)
|
||||
{
|
||||
EntityFileHandler handler;
|
||||
handler.SetStartComponentCallback(std::bind(&EntityFilePreprocessor::onStartComponent, this, std::placeholders::_1, std::placeholders::_2));
|
||||
m_EntityFile->Parse(&handler);
|
||||
|
||||
LOG_DEBUG("___ COMPONENT DEFINITIONS ___");
|
||||
for (auto& kv : m_ComponentCounts) {
|
||||
LOG_DEBUG("%s: %i", kv.first.c_str(), kv.second);
|
||||
}
|
||||
|
||||
parseComponentInfo();
|
||||
|
||||
for (auto& kv : m_ComponentInfo) {
|
||||
auto& info = kv.second;
|
||||
LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta.Annotation.c_str());
|
||||
LOG_DEBUG("Stride: %i", info.Meta.Stride);
|
||||
LOG_DEBUG("Allocation: %i", info.Meta.Allocation);
|
||||
for (auto& kv : info.Fields) {
|
||||
auto& field = kv.second;
|
||||
LOG_DEBUG("\t%i\t%s %s", field.Offset, field.Type, kv.first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
parseDefaults();
|
||||
}
|
||||
|
||||
void EntityFilePreprocessor::RegisterComponents(World* world)
|
||||
{
|
||||
for (auto& kv : m_ComponentInfo) {
|
||||
world->RegisterComponent(kv.second);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFilePreprocessor::onStartComponent(EntityID entity, std::string type)
|
||||
{
|
||||
//LOG_DEBUG("Component: %s", type.c_str());
|
||||
m_ComponentCounts[type]++;
|
||||
}
|
||||
|
||||
void EntityFilePreprocessor::parseComponentInfo()
|
||||
{
|
||||
using namespace xercesc;
|
||||
EntityFileXMLErrorHandler errorHandler;
|
||||
auto grammarPool = m_EntityFile->GrammarPool();
|
||||
bool whateverTheFuckThisIs;
|
||||
auto xsModel = grammarPool->getXSModel(whateverTheFuckThisIs);
|
||||
|
||||
// Find component xsd element declarations
|
||||
std::cout << "Enumerating components..." << std::endl;
|
||||
// <xs:element name="ComponentName">
|
||||
auto topLevelElements = xsModel->getComponents(XSConstants::ELEMENT_DECLARATION);
|
||||
for (unsigned int i = 0; i < topLevelElements->getLength(); ++i) {
|
||||
auto element = static_cast<XSElementDeclaration*>(topLevelElements->item(i));
|
||||
|
||||
std::string nameSpace = XS::ToString(element->getNamespace());
|
||||
if (nameSpace != "components") {
|
||||
continue;
|
||||
}
|
||||
|
||||
ComponentInfo compInfo;
|
||||
|
||||
// Name
|
||||
compInfo.Name = XS::ToString(element->getName());
|
||||
// Known allocation
|
||||
compInfo.Meta.Allocation = m_ComponentCounts[compInfo.Name];
|
||||
// Annotation
|
||||
auto componentAnnotation = element->getAnnotation();
|
||||
if (componentAnnotation != nullptr) {
|
||||
// Parse annotation XML
|
||||
char* annotationString = XMLString::transcode(componentAnnotation->getAnnotationString());
|
||||
MemBufInputSource annotationInput(reinterpret_cast<const XMLByte*>(annotationString), strlen(annotationString), "MemBuf: Annotation String");
|
||||
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager, grammarPool);
|
||||
parser.setErrorHandler(&errorHandler);
|
||||
parser.parse(annotationInput);
|
||||
XMLString::release(&annotationString);
|
||||
auto doc = parser.getDocument();
|
||||
|
||||
// TODO: Add allocation estimations from external file on map-to-map basis
|
||||
// Add allocation estimation(s)
|
||||
//auto allocationTags = doc->getElementsByTagName(XSTR("meta:allocation"));
|
||||
//for (int i = 0; i < allocationTags->getLength(); ++i) {
|
||||
// auto allocation = dynamic_cast<DOMElement*>(allocationTags->item(i));
|
||||
// auto child = allocation->getFirstChild();
|
||||
// if (child == nullptr) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// XSValue::Status status;
|
||||
// XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, status);
|
||||
// compInfo.Meta.Allocation += val->fData.fValue.f_int;
|
||||
//}
|
||||
|
||||
// Save documentation string
|
||||
auto documentationTags = doc->getElementsByTagName(XS::ToXMLCh("xs:documentation"));
|
||||
if (documentationTags->getLength() != 0) {
|
||||
auto child = documentationTags->item(0)->getFirstChild();
|
||||
if (child != nullptr) {
|
||||
compInfo.Meta.Annotation = XS::ToString(child->getNodeValue());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_WARNING("Component is missing an annotation!");
|
||||
}
|
||||
|
||||
// <xs:complexType>
|
||||
auto typeDefinition = element->getTypeDefinition();
|
||||
if (typeDefinition->getTypeCategory() != XSTypeDefinition::COMPLEX_TYPE) {
|
||||
LOG_ERROR("Type definition wasn't COMPLEX_TYPE! Skipping.");
|
||||
continue;
|
||||
}
|
||||
auto complexTypeDefinition = dynamic_cast<XSComplexTypeDefinition*>(typeDefinition);
|
||||
|
||||
// <xs:all>
|
||||
auto modelGroupParticle = complexTypeDefinition->getParticle();
|
||||
if (modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
|
||||
LOG_ERROR("Model group particle wasn't TERM_MODELGROUP! Skipping.");
|
||||
continue;
|
||||
}
|
||||
auto modelGroup = modelGroupParticle->getModelGroupTerm();
|
||||
|
||||
// <xs:element...
|
||||
// <xs:attribute...
|
||||
unsigned int fieldOffset = 0;
|
||||
auto particles = modelGroup->getParticles();
|
||||
for (unsigned int i = 0; i < particles->size(); ++i) {
|
||||
auto particle = particles->elementAt(i);
|
||||
if (particle->getTermType() != XSParticle::TERM_ELEMENT) {
|
||||
LOG_ERROR("Particle wasn't TERM_ELEMENT! Skipping.");
|
||||
continue;
|
||||
}
|
||||
auto elementDeclaration = particle->getElementTerm();
|
||||
|
||||
std::string name = XS::ToString(elementDeclaration->getName());
|
||||
std::string type = XS::ToString(elementDeclaration->getTypeDefinition()->getName());
|
||||
|
||||
size_t stride = EntityFile::GetTypeStride(type);
|
||||
if (stride == 0) {
|
||||
std::cout << "Warning: Field \"" << name << "\" in component \"" << compInfo.Name << "\" uses unexpected field type \"" << type << "\". Skipping." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& field = compInfo.Fields[name];
|
||||
field.Type = type;
|
||||
field.Offset = fieldOffset;
|
||||
field.Stride = stride;
|
||||
compInfo.FieldsInOrder.push_back(&field);
|
||||
|
||||
fieldOffset += stride;
|
||||
}
|
||||
|
||||
compInfo.Meta.Stride = fieldOffset;
|
||||
m_ComponentInfo[compInfo.Name] = compInfo;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFilePreprocessor::parseDefaults()
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
EntityFileXMLErrorHandler errorHandler;
|
||||
|
||||
for (auto& ci : m_ComponentInfo) {
|
||||
// Allocate memory for default values
|
||||
ci.second.Defaults = std::shared_ptr<char>(new char[ci.second.Meta.Stride]);
|
||||
memset(ci.second.Defaults.get(), 0, ci.second.Meta.Stride);
|
||||
|
||||
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager);
|
||||
parser.setErrorHandler(&errorHandler);
|
||||
|
||||
std::string componentName = ci.first;
|
||||
LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
|
||||
boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml";
|
||||
|
||||
parser.parse(defaultsFile.string().c_str());
|
||||
auto doc = parser.getDocument();
|
||||
if (doc == nullptr) {
|
||||
LOG_ERROR("%s not found! Skipping.", defaultsFile.string().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the node in the components namespace matching the component name
|
||||
std::string tagName = "c:" + componentName;
|
||||
auto rootNodes = doc->getElementsByTagName(XS::ToXMLCh(tagName));
|
||||
if (rootNodes->getLength() == 0) {
|
||||
LOG_ERROR("Couldn't find defaults for component \"%s\"! Skipping.", componentName.c_str());
|
||||
continue;
|
||||
}
|
||||
auto componentElement = dynamic_cast<DOMElement*>(rootNodes->item(0));
|
||||
|
||||
// Fill the default value buffer with values
|
||||
for (auto& kv : ci.second.Fields) {
|
||||
std::string fieldName = kv.first;
|
||||
auto& field = kv.second;
|
||||
auto fieldNodes = componentElement->getElementsByTagName(XS::ToXMLCh(fieldName));
|
||||
auto fieldNode = fieldNodes->item(0);
|
||||
if (fieldNode == nullptr) {
|
||||
LOG_ERROR("Defaults for component \"%s\" is missing field \"%s\"!", componentName.c_str(), fieldName.c_str());
|
||||
continue;
|
||||
}
|
||||
auto fieldElement = dynamic_cast<DOMElement*>(fieldNode);
|
||||
|
||||
char* data = ci.second.Defaults.get() + field.Offset;
|
||||
|
||||
// Handle potential field attributes
|
||||
if (fieldElement->hasAttributes()) {
|
||||
std::map<std::string, std::string> attributes;
|
||||
auto attributeMap = fieldElement->getAttributes();
|
||||
for (int i = 0; i < attributeMap->getLength(); ++i) {
|
||||
auto attribItem = attributeMap->item(i);
|
||||
attributes[XS::ToString(attribItem->getNodeName())] = XS::ToString(attribItem->getNodeValue());
|
||||
}
|
||||
EntityFile::WriteAttributeData(data, field, attributes);
|
||||
}
|
||||
|
||||
// Handle potential field values
|
||||
auto childNode = fieldElement->getFirstChild();
|
||||
if (childNode != nullptr && childNode->getNodeType() == DOMNode::TEXT_NODE) {
|
||||
char* cstrValue = XMLString::transcode(childNode->getNodeValue());
|
||||
EntityFile::WriteValueData(data, field, cstrValue);
|
||||
XMLString::release(&cstrValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
#include "Core/EntityFileWriter.h"
|
||||
|
||||
#define X(str) XS::ToXMLCh(str)
|
||||
|
||||
void EntityFileWriter::WriteWorld(World* world)
|
||||
{
|
||||
WriteEntity(world, 0);
|
||||
}
|
||||
|
||||
void EntityFileWriter::WriteEntity(World* world, EntityID entity)
|
||||
{
|
||||
using namespace xercesc;
|
||||
DOMDocument* doc = m_DOMImplementation->createDocument(nullptr, X("Entity"), nullptr);
|
||||
DOMElement* root = doc->getDocumentElement();
|
||||
root->setAttribute(X("xmlns:xsi"), X("http://www.w3.org/2001/XMLSchema-instance"));
|
||||
root->setAttribute(X("xsi:noNamespaceSchemaLocation"), X("../Types/Entity.xsd"));
|
||||
root->setAttribute(X("xmlns:c"), X("components"));
|
||||
const std::string& name = world->GetName(entity);
|
||||
if (!name.empty()) {
|
||||
root->setAttribute(X("name"), X(name));
|
||||
}
|
||||
|
||||
DOMElement* componentsElement = doc->createElement(X("Components"));
|
||||
root->appendChild(componentsElement);
|
||||
appentEntityComponents(componentsElement, world, entity);
|
||||
|
||||
DOMElement* childrenElement = doc->createElement(X("Children"));
|
||||
root->appendChild(childrenElement);
|
||||
appendEntityChildren(childrenElement, world, entity);
|
||||
|
||||
try {
|
||||
LocalFileFormatTarget* target = new LocalFileFormatTarget(X(m_FilePath.string()));
|
||||
DOMLSOutput* output = static_cast<DOMImplementationLS*>(m_DOMImplementation)->createLSOutput();
|
||||
output->setByteStream(target);
|
||||
m_DOMLSSerializer->write(doc, output);
|
||||
delete target;
|
||||
} catch (const std::runtime_error& e) {
|
||||
LOG_ERROR("Failed to save \"%s\": %s", m_FilePath.c_str(), e.what());
|
||||
}
|
||||
|
||||
doc->release();
|
||||
}
|
||||
|
||||
void EntityFileWriter::appendEntityChildren(xercesc::DOMElement* parentElement, const World* world, EntityID entity)
|
||||
{
|
||||
using namespace xercesc;
|
||||
DOMDocument* doc = parentElement->getOwnerDocument();
|
||||
|
||||
auto childrenRange = world->GetEntityChildren().equal_range(entity);
|
||||
for (auto it = childrenRange.first; it != childrenRange.second; ++it) {
|
||||
EntityID childEntity = it->second;
|
||||
|
||||
DOMElement* entityElement = doc->createElement(X("Entity"));
|
||||
const std::string& name = world->GetName(childEntity);
|
||||
if (!name.empty()) {
|
||||
entityElement->setAttribute(X("name"), X(name));
|
||||
}
|
||||
parentElement->appendChild(entityElement);
|
||||
|
||||
DOMElement* componentsElement = doc->createElement(X("Components"));
|
||||
entityElement->appendChild(componentsElement);
|
||||
appentEntityComponents(componentsElement, world, childEntity);
|
||||
|
||||
DOMElement* childrenElement = doc->createElement(X("Children"));
|
||||
entityElement->appendChild(childrenElement);
|
||||
appendEntityChildren(childrenElement, world, childEntity);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement, const World* world, EntityID entity)
|
||||
{
|
||||
using namespace xercesc;
|
||||
DOMDocument* doc = parentElement->getOwnerDocument();
|
||||
auto& componentPools = world->GetComponentPools();
|
||||
|
||||
// Step through all component pools to get an entity's components
|
||||
// HACK: This is sloooow.
|
||||
for (auto& kv : componentPools) {
|
||||
const std::string& componentName = kv.first;
|
||||
if (!world->HasComponent(entity, componentName)) {
|
||||
continue;
|
||||
}
|
||||
std::string qualifiedComponentName = "c:" + componentName;
|
||||
DOMElement* componentElement = doc->createElement(X(qualifiedComponentName));
|
||||
parentElement->appendChild(componentElement);
|
||||
ComponentWrapper c = kv.second->GetByEntity(entity);
|
||||
for (auto& kv : c.Info.Fields) {
|
||||
std::string fieldName = kv.first;
|
||||
auto& field = kv.second;
|
||||
|
||||
// Ignore fields that are equal to the default
|
||||
// HACK: This is probably sloooooow, but it's okay.
|
||||
if (memcmp(c.Data + field.Offset, c.Info.Defaults.get() + field.Offset, field.Stride) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DOMElement* fieldElement = doc->createElement(X(fieldName));
|
||||
componentElement->appendChild(fieldElement);
|
||||
|
||||
if (field.Type == "Vector") {
|
||||
const glm::vec3& vec = c[fieldName];
|
||||
fieldElement->setAttribute(X("X"), X(boost::lexical_cast<std::string>(vec.x)));
|
||||
fieldElement->setAttribute(X("Y"), X(boost::lexical_cast<std::string>(vec.y)));
|
||||
fieldElement->setAttribute(X("Z"), X(boost::lexical_cast<std::string>(vec.z)));
|
||||
} else if (field.Type == "Color") {
|
||||
const glm::vec4& vec = c[fieldName];
|
||||
fieldElement->setAttribute(X("R"), X(boost::lexical_cast<std::string>(vec.r)));
|
||||
fieldElement->setAttribute(X("G"), X(boost::lexical_cast<std::string>(vec.g)));
|
||||
fieldElement->setAttribute(X("B"), X(boost::lexical_cast<std::string>(vec.b)));
|
||||
fieldElement->setAttribute(X("A"), X(boost::lexical_cast<std::string>(vec.a)));
|
||||
} else if (field.Type == "Quaternion") {
|
||||
const glm::quat& q = c[fieldName];
|
||||
fieldElement->setAttribute(X("X"), X(boost::lexical_cast<std::string>(q.x)));
|
||||
fieldElement->setAttribute(X("Y"), X(boost::lexical_cast<std::string>(q.y)));
|
||||
fieldElement->setAttribute(X("Z"), X(boost::lexical_cast<std::string>(q.z)));
|
||||
fieldElement->setAttribute(X("W"), X(boost::lexical_cast<std::string>(q.w)));
|
||||
} else if (field.Type == "int") {
|
||||
const int& value = c[fieldName];
|
||||
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
|
||||
} else if (field.Type == "float") {
|
||||
const float& value = c[fieldName];
|
||||
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
|
||||
} else if (field.Type == "double") {
|
||||
const double& value = c[fieldName];
|
||||
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
|
||||
} else if (field.Type == "bool") {
|
||||
const bool& value = c[fieldName];
|
||||
if (value) {
|
||||
fieldElement->appendChild(doc->createTextNode(X("true")));
|
||||
} else {
|
||||
fieldElement->appendChild(doc->createTextNode(X("false")));
|
||||
}
|
||||
} else if (field.Type == "string") {
|
||||
const std::string& value = c[fieldName];
|
||||
fieldElement->appendChild(doc->createTextNode(X(value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
#include "Core/EntityXMLFile.h"
|
||||
#include "Core/World.h"
|
||||
|
||||
unsigned int EntityXMLFile::InstanceCount = 0;
|
||||
|
||||
EntityXMLFile::EntityXMLFile(std::string path)
|
||||
: m_EntityFile(path)
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
if (InstanceCount == 0) {
|
||||
XMLPlatformUtils::Initialize();
|
||||
}
|
||||
InstanceCount++;
|
||||
|
||||
m_GrammarPool = new XMLGrammarPoolImpl();
|
||||
m_ErrorHandler = new EntityParserXMLErrorHandler();
|
||||
m_DOMParser = new XercesDOMParser(nullptr, XMLPlatformUtils::fgMemoryManager, m_GrammarPool);
|
||||
m_DOMParser->setErrorHandler(m_ErrorHandler);
|
||||
m_DOMParser->setDoNamespaces(true);
|
||||
m_DOMParser->setDoXInclude(true);
|
||||
m_DOMParser->setDoSchema(true);
|
||||
m_DOMParser->setValidationSchemaFullChecking(true);
|
||||
m_DOMParser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
|
||||
m_DOMParser->setValidationSchemaFullChecking(true);
|
||||
m_DOMParser->setValidationConstraintFatal(false);
|
||||
m_DOMParser->setIncludeIgnorableWhitespace(false);
|
||||
// Make sure schema grammar is kept after validation
|
||||
m_DOMParser->cacheGrammarFromParse(true);
|
||||
|
||||
// HACK: Use Sax2 parser instead so the entire DOM doesn't have to reside in memory
|
||||
m_DOMParser->parse(m_EntityFile.c_str());
|
||||
m_DOMDocument = m_DOMParser->getDocument();
|
||||
|
||||
// 1. Fill in ComponentInfo name, fields, default values and metadata from PSVI
|
||||
parseComponentInfo();
|
||||
// 2. Parse default value files for those components
|
||||
parseDefaults();
|
||||
// 3. Allocate component structures
|
||||
predictComponentAllocation();
|
||||
}
|
||||
|
||||
EntityXMLFile::~EntityXMLFile()
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
if (m_DOMParser != nullptr) {
|
||||
delete m_DOMParser;
|
||||
}
|
||||
if (m_ErrorHandler != nullptr) {
|
||||
delete m_ErrorHandler;
|
||||
}
|
||||
if (m_GrammarPool != nullptr) {
|
||||
delete m_GrammarPool;
|
||||
}
|
||||
|
||||
InstanceCount--;
|
||||
if (InstanceCount == 0) {
|
||||
XMLPlatformUtils::Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityXMLFile::PopulateWorld(World* world)
|
||||
{
|
||||
for (auto& pair : m_ComponentInfo) {
|
||||
world->RegisterComponent(pair.second);
|
||||
}
|
||||
|
||||
// 4. Parse entity hierarchy
|
||||
auto root = m_DOMDocument->getDocumentElement();
|
||||
parseEntityGraph(world, root, 0);
|
||||
}
|
||||
|
||||
|
||||
void EntityXMLFile::preprocess(std::string inPath, std::string outPath)
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
static const XMLCh gLS[] = { 'L', 'S', '\0' };
|
||||
DOMImplementationLS* di = static_cast<DOMImplementationLS*>(DOMImplementationRegistry::getDOMImplementation(gLS));
|
||||
|
||||
// Parse the file
|
||||
DOMLSParser* parser = di->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, nullptr);
|
||||
DOMConfiguration* config = parser->getDomConfig();
|
||||
config->setParameter(XMLUni::fgDOMNamespaces, true);
|
||||
config->setParameter(XMLUni::fgXercesSchema, true);
|
||||
config->setParameter(XMLUni::fgXercesHandleMultipleImports, true);
|
||||
config->setParameter(XMLUni::fgXercesSchemaFullChecking, true);
|
||||
config->setParameter(XMLUni::fgXercesDoXInclude, true);
|
||||
auto errHandler = new EntityPreprocessorXMLErrorHandler();
|
||||
config->setParameter(XMLUni::fgDOMErrorHandler, errHandler);
|
||||
|
||||
auto source = new LocalFileInputSource(XSTR(inPath.c_str()));
|
||||
Wrapper4InputSource* domSourceWrapper = new Wrapper4InputSource(source);
|
||||
DOMDocument* doc = parser->parse(dynamic_cast<DOMLSInput*>(domSourceWrapper));
|
||||
|
||||
// Serialize and output the new XML
|
||||
DOMLSSerializer* writer = di->createLSSerializer();
|
||||
DOMLSOutput* output = di->createLSOutput();
|
||||
XMLFormatTarget* formatTarget = new LocalFileFormatTarget(outPath.c_str());
|
||||
// TODO: MemBufFormatTarget* formatTarget = new MemBufFormatTarget()
|
||||
output->setByteStream(formatTarget);
|
||||
writer->write(doc, output);
|
||||
|
||||
delete formatTarget;
|
||||
output->release();
|
||||
writer->release();
|
||||
parser->release();
|
||||
}
|
||||
|
||||
void EntityXMLFile::parseComponentInfo()
|
||||
{
|
||||
using namespace xercesc;
|
||||
bool wasChanged;
|
||||
XSModel* xsModel = m_GrammarPool->getXSModel(wasChanged);
|
||||
|
||||
// Find component xsd element declarations
|
||||
std::cout << "Enumerating components..." << std::endl;
|
||||
// <xs:element name="ComponentName">
|
||||
auto topLevelElements = xsModel->getComponents(XSConstants::ELEMENT_DECLARATION);
|
||||
for (unsigned int i = 0; i < topLevelElements->getLength(); ++i) {
|
||||
auto element = static_cast<XSElementDeclaration*>(topLevelElements->item(i));
|
||||
|
||||
std::string nameSpace(XSTR(element->getNamespace()));
|
||||
if (nameSpace != "components") {
|
||||
continue;
|
||||
}
|
||||
|
||||
ComponentInfo compInfo;
|
||||
|
||||
// Name
|
||||
compInfo.Name = XSTR(element->getName());
|
||||
// Annotation
|
||||
auto componentAnnotation = element->getAnnotation();
|
||||
if (componentAnnotation != nullptr) {
|
||||
// Parse annotation XML
|
||||
char* annotationString = XMLString::transcode(componentAnnotation->getAnnotationString());
|
||||
MemBufInputSource annotationInput(reinterpret_cast<const XMLByte*>(annotationString), strlen(annotationString), "MemBuf: Annotation String");
|
||||
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager, m_GrammarPool);
|
||||
parser.setErrorHandler(m_ErrorHandler);
|
||||
parser.parse(annotationInput);
|
||||
XMLString::release(&annotationString);
|
||||
auto doc = parser.getDocument();
|
||||
|
||||
// Add allocation estimation(s)
|
||||
auto allocationTags = doc->getElementsByTagName(XSTR("meta:allocation"));
|
||||
for (int i = 0; i < allocationTags->getLength(); ++i) {
|
||||
auto allocation = dynamic_cast<DOMElement*>(allocationTags->item(i));
|
||||
auto child = allocation->getFirstChild();
|
||||
if (child == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
XSValue::Status status;
|
||||
XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, status);
|
||||
compInfo.Meta.Allocation += val->fData.fValue.f_int;
|
||||
}
|
||||
|
||||
// Save documentation string
|
||||
auto documentationTags = doc->getElementsByTagName(XSTR("xs:documentation"));
|
||||
if (documentationTags->getLength() != 0) {
|
||||
auto child = documentationTags->item(0)->getFirstChild();
|
||||
if (child != nullptr) {
|
||||
compInfo.Meta.Annotation = XSTR(child->getNodeValue());
|
||||
}
|
||||
}
|
||||
// TODO: Parse annotation string XML
|
||||
// compInfo.Meta.Allocation = ...
|
||||
} else {
|
||||
std::cout << "Warning: Component is missing an annotation!" << std::endl;
|
||||
}
|
||||
|
||||
// <xs:complexType>
|
||||
auto typeDefinition = element->getTypeDefinition();
|
||||
if (typeDefinition->getTypeCategory() != XSTypeDefinition::COMPLEX_TYPE) {
|
||||
std::cerr << "Error: Type definition wasn't COMPLEX_TYPE! Skipping." << std::endl;
|
||||
continue;
|
||||
}
|
||||
auto complexTypeDefinition = dynamic_cast<XSComplexTypeDefinition*>(typeDefinition);
|
||||
|
||||
// <xs:all>
|
||||
auto modelGroupParticle = complexTypeDefinition->getParticle();
|
||||
if (modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
|
||||
std::cerr << "Error: Model group particle wasn't TERM_MODELGROUP! Skipping." << std::endl;
|
||||
continue;
|
||||
}
|
||||
auto modelGroup = modelGroupParticle->getModelGroupTerm();
|
||||
|
||||
// <xs:element...
|
||||
// <xs:attribute...
|
||||
unsigned int fieldOffset = 0;
|
||||
auto particles = modelGroup->getParticles();
|
||||
for (unsigned int i = 0; i < particles->size(); ++i) {
|
||||
auto particle = particles->elementAt(i);
|
||||
if (particle->getTermType() != XSParticle::TERM_ELEMENT) {
|
||||
std::cerr << "Error: Particle wasn't TERM_ELEMENT! Skipping." << std::endl;
|
||||
continue;
|
||||
}
|
||||
auto elementDeclaration = particle->getElementTerm();
|
||||
|
||||
std::string name = XSTR(elementDeclaration->getName());
|
||||
std::string type = XSTR(elementDeclaration->getTypeDefinition()->getName());
|
||||
|
||||
size_t stride = getTypeStride(type);
|
||||
if (stride == 0) {
|
||||
std::cout << "Warning: Field \"" << name << "\" in component \"" << compInfo.Name << "\" uses unexpected field type \"" << type << "\". Skipping." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
compInfo.FieldTypes[name] = type;
|
||||
compInfo.FieldOffsets[name] = fieldOffset;
|
||||
fieldOffset += getTypeStride(type);
|
||||
}
|
||||
|
||||
compInfo.Meta.Stride = fieldOffset;
|
||||
m_ComponentInfo[compInfo.Name] = compInfo;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityXMLFile::parseDefaults()
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
for (auto& ci : m_ComponentInfo) {
|
||||
// Allocate memory for default values
|
||||
ci.second.Defaults = std::shared_ptr<char>(new char[ci.second.Meta.Stride]);
|
||||
memset(ci.second.Defaults.get(), 0, ci.second.Meta.Stride);
|
||||
|
||||
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager);
|
||||
parser.setErrorHandler(m_ErrorHandler);
|
||||
|
||||
std::string componentName = ci.first;
|
||||
LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
|
||||
boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml";
|
||||
|
||||
parser.parse(defaultsFile.string().c_str());
|
||||
auto doc = parser.getDocument();
|
||||
if (doc == nullptr) {
|
||||
LOG_ERROR("%s not found! Skipping.", defaultsFile.string().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the node in the components namespace matching the component name
|
||||
std::string tagName = "c:" + componentName;
|
||||
auto rootNodes = doc->getElementsByTagName(XSTR(tagName.c_str()));
|
||||
if (rootNodes->getLength() == 0) {
|
||||
LOG_ERROR("Couldn't find defaults for component \"%s\"! Skipping.", componentName.c_str());
|
||||
continue;
|
||||
}
|
||||
auto componentElement = dynamic_cast<DOMElement*>(rootNodes->item(0));
|
||||
|
||||
// Fill the default value buffer with values
|
||||
for (auto& field : ci.second.FieldOffsets) {
|
||||
std::string fieldName = field.first;
|
||||
auto fieldNodes = componentElement->getElementsByTagName(XSTR(fieldName.c_str()));
|
||||
auto fieldNode = fieldNodes->item(0);
|
||||
if (fieldNode == nullptr) {
|
||||
LOG_ERROR("Defaults for component \"%s\" is missing field \"%s\"!", componentName.c_str(), fieldName.c_str());
|
||||
continue;
|
||||
}
|
||||
auto fieldElement = dynamic_cast<DOMElement*>(fieldNode);
|
||||
|
||||
std::string fieldType = ci.second.FieldTypes.at(fieldName);
|
||||
unsigned int fieldOffset = ci.second.FieldOffsets.at(fieldName);
|
||||
writeData(fieldElement, fieldType, ci.second.Defaults.get() + fieldOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EntityXMLFile::predictComponentAllocation()
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
auto root = m_DOMDocument->getDocumentElement();
|
||||
|
||||
// Count static instances of components present in entity hierarchy
|
||||
auto components = m_DOMDocument->getElementsByTagNameNS(XSTR("components"), XSTR("*"));
|
||||
for (int i = 0; i < components->getLength(); ++i) {
|
||||
auto component = dynamic_cast<DOMElement*>(components->item(i));
|
||||
|
||||
std::string componentName = XSTR(component->getLocalName());
|
||||
auto& compInfo = m_ComponentInfo.at(componentName);
|
||||
compInfo.Meta.Allocation += 1;
|
||||
}
|
||||
|
||||
std::cout << "COMPONENT INFO" << std::endl;
|
||||
for (auto& pair : m_ComponentInfo) {
|
||||
ComponentInfo& ci = pair.second;
|
||||
std::cout << "Component: " << ci.Name << " (" << ci.Meta.Annotation << ")" << std::endl;
|
||||
std::cout << " Allocation: " << ci.Meta.Allocation << std::endl;
|
||||
std::cout << " Fields:" << std::endl;
|
||||
|
||||
// Calculate component size
|
||||
std::size_t stride = 0;
|
||||
// Add size of fields
|
||||
for (auto& field : ci.FieldTypes) {
|
||||
std::cout << " " << field.second << " " << field.first << " (" << getTypeStride(field.second) << " byte)" << std::endl;
|
||||
stride += getTypeStride(field.second);
|
||||
}
|
||||
std::cout << " Stride: " << ci.Meta.Stride << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityXMLFile::parseEntityGraph(World* world, xercesc::DOMElement* element, EntityID parentEntity)
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
// Create entity
|
||||
EntityID entity = world->CreateEntity(parentEntity);
|
||||
LOG_DEBUG("Created entity %i, parent %i", entity, parentEntity);
|
||||
|
||||
// Add components
|
||||
auto components = m_DOMDocument->evaluate(XSTR("Components/*"), element, nullptr, DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr);
|
||||
for (int i = 0; i < components->getSnapshotLength(); i++) {
|
||||
components->snapshotItem(i);
|
||||
auto componentElement = dynamic_cast<DOMElement*>(components->getNodeValue());
|
||||
std::string componentName = XSTR(componentElement->getLocalName());
|
||||
auto& ci = m_ComponentInfo.at(componentName);
|
||||
|
||||
// Attach the component
|
||||
auto c = world->AttachComponent(entity, componentName);
|
||||
LOG_DEBUG("Attached %s component", componentName.c_str());
|
||||
|
||||
// Write field data
|
||||
auto fields = componentElement->getChildNodes();
|
||||
for (int j = 0; j < fields->getLength(); ++j) {
|
||||
auto fieldNode = fields->item(j);
|
||||
auto nodeType = fieldNode->getNodeType();
|
||||
if (nodeType != DOMNode::ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
auto field = dynamic_cast<DOMElement*>(fields->item(j));
|
||||
//const XMLCh* value = fields->item(j)->getTextContent();
|
||||
std::string fieldName(XSTR(field->getLocalName()));
|
||||
if (ci.FieldTypes.find(fieldName) == ci.FieldTypes.end()) {
|
||||
std::cout << "Warning: Component \"" << componentName << "\" contains invalid field \"" << fieldName << "\". Skipping." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string fieldType = ci.FieldTypes.at(fieldName);
|
||||
unsigned int fieldOffset = ci.FieldOffsets.at(fieldName);
|
||||
std::string fieldValue(XSTR(field->getTextContent()));
|
||||
LOG_DEBUG(" %s %s = %s", fieldType.c_str(), fieldName.c_str(), fieldValue.c_str());
|
||||
writeData(field, fieldType, c.Data + fieldOffset);
|
||||
}
|
||||
}
|
||||
|
||||
// Recurse children
|
||||
auto children = m_DOMDocument->evaluate(XSTR("Children/Entity"), element, nullptr, DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr);
|
||||
for (int i = 0; i < children->getSnapshotLength(); i++) {
|
||||
children->snapshotItem(i);
|
||||
parseEntityGraph(world, dynamic_cast<DOMElement*>(children->getNodeValue()), entity);
|
||||
}
|
||||
|
||||
//auto components = m_DOMDocument->getElementsByTagNameNS(XSTR("components"), XSTR("*"));
|
||||
//for (int i = 0; i < components->getLength(); ++i) {
|
||||
// auto component = dynamic_cast<DOMElement*>(components->item(i));
|
||||
|
||||
// std::string componentName = XSTR(component->getLocalName());
|
||||
// auto& compStore = m_ComponentStore.at(componentName);
|
||||
// auto& compInfo = compStore.Info;
|
||||
|
||||
// char* data = &compStore.Data[compStore.Size*compStore.Stride];
|
||||
// compStore.Size += 1;
|
||||
|
||||
// auto fields = component->getChildNodes();
|
||||
// for (int j = 0; j < fields->getLength(); ++j) {
|
||||
// auto field = fields->item(j);
|
||||
// auto nodeType = field->getNodeType();
|
||||
// if (nodeType != DOMNode::ELEMENT_NODE) {
|
||||
// continue;
|
||||
// }
|
||||
// //auto field = dynamic_cast<DOMElement*>(fields->item(j));
|
||||
// //const XMLCh* value = fields->item(j)->getTextContent();
|
||||
// std::string fieldName = XSTR(field->getLocalName());
|
||||
// if (compInfo.FieldTypes.find(fieldName) == compInfo.FieldTypes.end()) {
|
||||
// std::cout << "Warning: Component \"" << componentName << "\" contains invalid field \"" << fieldName << "\". Skipping." << std::endl;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// std::string fieldType = compInfo.FieldTypes.at(fieldName);
|
||||
// unsigned int fieldOffset = compInfo.FieldOffsets.at(fieldName);
|
||||
|
||||
// XSValue::DataType dataType = XSValue::getDataType(XSTR(fieldType.c_str()));
|
||||
// if (dataType == XSValue::DataType::dt_MAXCOUNT) {
|
||||
// // TODO:
|
||||
// continue;
|
||||
// }
|
||||
// if (dataType == XSValue::DataType::dt_string) {
|
||||
// char* str = XMLString::transcode(field->getTextContent());
|
||||
// std::string standardString(str);
|
||||
// XMLString::release(&str);
|
||||
// memcpy(&data[fieldOffset], reinterpret_cast<char*>(&standardString), getTypeStride(fieldType));
|
||||
// } else {
|
||||
// XSValue::Status status;
|
||||
// XSValue* val = XSValue::getActualValue(field->getTextContent(), dataType, status);
|
||||
// memcpy(&data[fieldOffset], reinterpret_cast<char*>(&val->fData.fValue), getTypeStride(fieldType));
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//auto entities = m_DOMDocument->getElementsByTagName(XSTR("Entity"));
|
||||
//for (int i = 0; i < entities->getLength(); ++i) {
|
||||
// auto entity = dynamic_cast<DOMElement*>(entities->item(i));
|
||||
|
||||
|
||||
// //entity->setIdAttribute()
|
||||
|
||||
// std::cout << "ENTITY " << i + 1 << std::endl;
|
||||
//}
|
||||
}
|
||||
|
||||
std::size_t EntityXMLFile::getTypeStride(std::string typeName)
|
||||
{
|
||||
std::map<std::string, size_t> typeStrides{
|
||||
{ "bool", sizeof(bool) },
|
||||
{ "int", sizeof(int) },
|
||||
{ "double", sizeof(double) },
|
||||
{ "string", sizeof(std::string) },
|
||||
{ "Vector", sizeof(glm::vec3) },
|
||||
{ "Quaternion", sizeof(glm::quat) },
|
||||
{ "Color", sizeof(glm::vec4) }
|
||||
};
|
||||
|
||||
auto it = typeStrides.find(typeName);
|
||||
return (it != typeStrides.end()) ? it->second : 0;
|
||||
}
|
||||
|
||||
float EntityXMLFile::getFloatAttribute(const xercesc::DOMElement* element, const char* attribute) const
|
||||
{
|
||||
using namespace xercesc;
|
||||
XSValue::Status status;
|
||||
XSValue* val = XSValue::getActualValue(element->getAttribute(XSTR(attribute)), xercesc::XSValue::DataType::dt_float, status);
|
||||
if (val == nullptr) {
|
||||
LOG_ERROR("Element \"%s\" doesn't have an \"%s\" attribute!", XSTR(element->getTagName()), attribute);
|
||||
return 0.f;
|
||||
} else {
|
||||
return val->fData.fValue.f_float;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityXMLFile::writeData(const xercesc::DOMElement* element, std::string typeName, char* outData)
|
||||
{
|
||||
using namespace xercesc;
|
||||
|
||||
XSValue::DataType dataType = XSValue::getDataType(XSTR(typeName.c_str()));
|
||||
if (dataType == XSValue::DataType::dt_MAXCOUNT) {
|
||||
if (typeName == "Vector") {
|
||||
glm::vec3 vec;
|
||||
vec.x = getFloatAttribute(element, "X");
|
||||
vec.y = getFloatAttribute(element, "Y");
|
||||
vec.z = getFloatAttribute(element, "Z");
|
||||
memcpy(outData, reinterpret_cast<char*>(&vec), getTypeStride(typeName));
|
||||
} else if (typeName == "Color") {
|
||||
glm::vec4 vec;
|
||||
vec.r = getFloatAttribute(element, "R");
|
||||
vec.g = getFloatAttribute(element, "G");
|
||||
vec.b = getFloatAttribute(element, "B");
|
||||
vec.a = getFloatAttribute(element, "A");
|
||||
memcpy(outData, reinterpret_cast<char*>(&vec), getTypeStride(typeName));
|
||||
} else if (typeName == "Quaternion") {
|
||||
glm::quat q;
|
||||
q.x = getFloatAttribute(element, "X");
|
||||
q.y = getFloatAttribute(element, "Y");
|
||||
q.z = getFloatAttribute(element, "Z");
|
||||
q.w = getFloatAttribute(element, "W");
|
||||
memcpy(outData, reinterpret_cast<char*>(&q), getTypeStride(typeName));
|
||||
}
|
||||
} else if (dataType == XSValue::DataType::dt_string) {
|
||||
char* str = XMLString::transcode(element->getTextContent());
|
||||
std::string standardString(str);
|
||||
new (outData) std::string(str);
|
||||
XMLString::release(&str);
|
||||
//memcpy(outData, reinterpret_cast<char*>(&standardString), getTypeStride(typeName));
|
||||
} else {
|
||||
XSValue::Status status;
|
||||
XSValue* val = XSValue::getActualValue(element->getTextContent(), dataType, status);
|
||||
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue), getTypeStride(typeName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,21 @@
|
||||
|
||||
BaseEventRelay::~BaseEventRelay()
|
||||
{
|
||||
if (m_Broker != nullptr) {
|
||||
if (m_Broker != nullptr) {
|
||||
m_Broker->Unsubscribe(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventBroker::Unsubscribe(BaseEventRelay& relay) // ?
|
||||
void EventBroker::Unsubscribe(BaseEventRelay &relay) // ?
|
||||
{
|
||||
auto identifier = std::make_tuple(relay.m_EventID, relay.m_ContextTypeName, relay.m_EventTypeName);
|
||||
|
||||
relay.m_Broker = nullptr;
|
||||
if (m_IsProcessing) {
|
||||
m_RelaysToUnsubscribe.push_back(identifier);
|
||||
} else {
|
||||
unsubscribeImmediate(identifier);
|
||||
}
|
||||
if (m_IsProcessing) {
|
||||
m_RelaysToUnsubscribe.push_back(&relay);
|
||||
} else {
|
||||
unsubscribeImmediate(relay);
|
||||
}
|
||||
}
|
||||
|
||||
void EventBroker::Subscribe(BaseEventRelay& relay)
|
||||
void EventBroker::Subscribe(BaseEventRelay &relay)
|
||||
{
|
||||
if (m_IsProcessing) {
|
||||
m_RelaysToSubscribe.push_back(&relay);
|
||||
@@ -41,11 +38,12 @@ int EventBroker::Process(std::string contextTypeName)
|
||||
|
||||
int eventsProcessed = 0;
|
||||
for (auto &pair : *m_EventQueueRead) {
|
||||
std::string& eventTypeName = pair.first;
|
||||
std::string &eventTypeName = pair.first;
|
||||
std::shared_ptr<Event> event = pair.second;
|
||||
|
||||
auto itpair = relays.equal_range(eventTypeName);
|
||||
for (auto it2 = itpair.first; it2 != itpair.second; it2++) {
|
||||
for (auto it2 = itpair.first; it2 != itpair.second; it2++)
|
||||
{
|
||||
std::string name = it2->first;
|
||||
BaseEventRelay* relay = it2->second;
|
||||
relay->Receive(event);
|
||||
@@ -62,8 +60,8 @@ int EventBroker::Process(std::string contextTypeName)
|
||||
m_RelaysToSubscribe.clear();
|
||||
|
||||
// Process pending unsubscriptions
|
||||
for (auto& identifier : m_RelaysToUnsubscribe) {
|
||||
unsubscribeImmediate(identifier);
|
||||
for (auto& r : m_RelaysToUnsubscribe) {
|
||||
unsubscribeImmediate(*r);
|
||||
}
|
||||
m_RelaysToUnsubscribe.clear();
|
||||
|
||||
@@ -83,26 +81,21 @@ void EventBroker::Clear()
|
||||
void EventBroker::subscribeImmediate(BaseEventRelay& relay)
|
||||
{
|
||||
relay.m_Broker = this;
|
||||
relay.m_EventID = m_NextEventID++;
|
||||
m_ContextRelays[relay.m_ContextTypeName].insert(std::make_pair(relay.m_EventTypeName, &relay));
|
||||
}
|
||||
|
||||
void EventBroker::unsubscribeImmediate(std::tuple<EventID, ContextTypeName_t, EventTypeName_t> identifier)
|
||||
void EventBroker::unsubscribeImmediate(BaseEventRelay& relay)
|
||||
{
|
||||
EventID eventID;
|
||||
ContextTypeName_t contextTypeName;
|
||||
EventTypeName_t eventTypeName;
|
||||
std::tie(eventID, contextTypeName, eventTypeName) = identifier;
|
||||
|
||||
auto contextIt = m_ContextRelays.find(contextTypeName);
|
||||
auto contextIt = m_ContextRelays.find(relay.m_ContextTypeName);
|
||||
if (contextIt == m_ContextRelays.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto eventRelays = contextIt->second;
|
||||
auto itpair = eventRelays.equal_range(eventTypeName);
|
||||
auto itpair = eventRelays.equal_range(relay.m_EventTypeName);
|
||||
for (auto it = itpair.first; it != itpair.second; ++it) {
|
||||
if (it->second->m_EventID == eventID) {
|
||||
if (it->second == &relay) {
|
||||
relay.m_Broker = nullptr;
|
||||
eventRelays.erase(it);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
#include "Core/InputManager.h"
|
||||
|
||||
std::vector<unsigned int> InputManager::GLFWCharCallbackQueue;
|
||||
std::vector<std::pair<double, double>> InputManager::GLFWScrollCallbackQueue;
|
||||
std::vector<std::string> InputManager::GLFWDropCallbackQueue;
|
||||
|
||||
void InputManager::Initialize()
|
||||
{
|
||||
// TODO: Gamepad
|
||||
//m_LastGamepadAxisState = std::array<GamepadAxisState, XUSER_MAX_COUNT>();
|
||||
//m_LastGamepadButtonState = std::array<GamepadButtonState, XUSER_MAX_COUNT>();
|
||||
glfwSetCharCallback(m_GLFWWindow, &InputManager::GLFWCharCallback);
|
||||
glfwSetScrollCallback(m_GLFWWindow, &InputManager::GLFWScrollCallback);
|
||||
glfwSetDropCallback(m_GLFWWindow, &InputManager::GLFWDropCallback);
|
||||
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse);
|
||||
|
||||
//glfwSetMouseButtonCallback(m_GLFWWindow, &InputManager::GLFWMouseButtonCallback);
|
||||
}
|
||||
|
||||
void InputManager::Update(double dt)
|
||||
@@ -43,15 +38,6 @@ void InputManager::Update(double dt)
|
||||
}
|
||||
}
|
||||
|
||||
// Keyboard text input
|
||||
for (unsigned int& c : GLFWCharCallbackQueue) {
|
||||
Events::KeyboardChar e;
|
||||
e.Timestamp = glfwGetTime();
|
||||
e.Char = c;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
GLFWCharCallbackQueue.clear();
|
||||
|
||||
// Mouse buttons
|
||||
for (int i = 0; i <= GLFW_MOUSE_BUTTON_LAST; ++i) {
|
||||
m_CurrentMouseState[i] = glfwGetMouseButton(m_GLFWWindow, i);
|
||||
@@ -89,21 +75,20 @@ void InputManager::Update(double dt)
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
|
||||
// Mouse scroll
|
||||
for (auto& pair : GLFWScrollCallbackQueue) {
|
||||
Events::MouseScroll e;
|
||||
std::tie(e.DeltaX, e.DeltaY) = pair;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
GLFWScrollCallbackQueue.clear();
|
||||
// Joysticks
|
||||
//for (int i = 0; i < GLFW_JOYSTICK_LAST; i++) {
|
||||
// if (glfwJoystickPresent(i) == GL_FALSE) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// File drop
|
||||
for (auto& path : GLFWDropCallbackQueue) {
|
||||
Events::FileDropped e;
|
||||
e.Path = path;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
GLFWDropCallbackQueue.clear();
|
||||
// int count;
|
||||
// const float* axes = glfwGetJoystickAxes(i, &count);
|
||||
// LOG_DEBUG("Controller %i NumAxes: %i", i, count);
|
||||
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftX)] = axes[0];
|
||||
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftY)] = axes[1];
|
||||
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightX)] = axes[2];
|
||||
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightY)] = axes[3];
|
||||
//}
|
||||
|
||||
// // Lock mouse while holding LMB
|
||||
// if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT])
|
||||
@@ -123,128 +108,46 @@ void InputManager::Update(double dt)
|
||||
// }
|
||||
|
||||
// TODO: Xbox360 controller
|
||||
/*DWORD dwResult;
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++)
|
||||
{
|
||||
XINPUT_STATE state = { 0 };
|
||||
// Simply get the state of the controller from XInput.
|
||||
dwResult = XInputGetState(i, &state);
|
||||
if (dwResult == 0)
|
||||
{
|
||||
if(std::abs(state.Gamepad.sThumbLX) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||
state.Gamepad.sThumbLX = 0;
|
||||
if(std::abs(state.Gamepad.sThumbLY) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||
state.Gamepad.sThumbLY = 0;
|
||||
if(std::abs(state.Gamepad.sThumbRX) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||
state.Gamepad.sThumbRX = 0;
|
||||
if(std::abs(state.Gamepad.sThumbRY) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||
state.Gamepad.sThumbRY = 0;
|
||||
if(std::abs(state.Gamepad.bLeftTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
state.Gamepad.bLeftTrigger = 0;
|
||||
if(std::abs(state.Gamepad.bRightTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
state.Gamepad.bRightTrigger = 0;
|
||||
|
||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftX)] = state.Gamepad.sThumbLX / 32767.f;
|
||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftY)] = state.Gamepad.sThumbLY / 32767.f;
|
||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightX)] = state.Gamepad.sThumbRX / 32767.f;
|
||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightY)] = state.Gamepad.sThumbRY / 32767.f;
|
||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftTrigger)] = state.Gamepad.bLeftTrigger / 255.f;
|
||||
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightTrigger)] = state.Gamepad.bRightTrigger / 255.f;
|
||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftX);
|
||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftY);
|
||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightX);
|
||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightY);
|
||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftTrigger);
|
||||
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightTrigger);
|
||||
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Up)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Down)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Left)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Right)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Start)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_START);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Back)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::A)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_A);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::B)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_B);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::X)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_X);
|
||||
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Y)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Up);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Down);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Left);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Right);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Start);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Back);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftThumb);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::RightThumb);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftShoulder);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::RightShoulder);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::A);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::B);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::X);
|
||||
PublishGamepadButtonIfChanged(i, Gamepad::Button::Y);
|
||||
}
|
||||
}*/
|
||||
/**/
|
||||
|
||||
m_LastKeyState = m_CurrentKeyState;
|
||||
m_LastMouseState = m_CurrentMouseState;
|
||||
m_LastMouseX = m_CurrentMouseX;
|
||||
m_LastMouseY = m_CurrentMouseY;
|
||||
m_LastGamepadAxisState = m_CurrentGamepadAxisState;
|
||||
m_LastGamepadButtonState = m_CurrentGamepadButtonState;
|
||||
//m_LastGamepadAxisState = m_CurrentGamepadAxisState;
|
||||
//m_LastGamepadButtonState = m_CurrentGamepadButtonState;
|
||||
}
|
||||
|
||||
void InputManager::PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis)
|
||||
{
|
||||
float currentValue = m_CurrentGamepadAxisState[gamepadID][static_cast<int>(axis)];
|
||||
float lastValue = m_LastGamepadAxisState[gamepadID][static_cast<int>(axis)];
|
||||
if (currentValue != lastValue) {
|
||||
Events::GamepadAxis e;
|
||||
e.GamepadID = gamepadID;
|
||||
e.Axis = axis;
|
||||
e.Value = currentValue;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
//float currentValue = m_CurrentGamepadAxisState[gamepadID][static_cast<int>(axis)];
|
||||
//float lastValue = m_LastGamepadAxisState[gamepadID][static_cast<int>(axis)];
|
||||
//if (currentValue != lastValue) {
|
||||
// Events::GamepadAxis e;
|
||||
// e.GamepadID = gamepadID;
|
||||
// e.Axis = axis;
|
||||
// e.Value = currentValue;
|
||||
// m_EventBroker->Publish(e);
|
||||
//}
|
||||
}
|
||||
|
||||
void InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button)
|
||||
{
|
||||
bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast<int>(button)];
|
||||
float lastState = m_LastGamepadButtonState[gamepadID][static_cast<int>(button)];
|
||||
if (currentState != lastState) {
|
||||
if (currentState == true) {
|
||||
Events::GamepadButtonDown e;
|
||||
e.GamepadID = gamepadID;
|
||||
e.Button = button;
|
||||
m_EventBroker->Publish(e);
|
||||
} else {
|
||||
Events::GamepadButtonUp e;
|
||||
e.GamepadID = gamepadID;
|
||||
e.Button = button;
|
||||
m_EventBroker->Publish(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::GLFWCharCallback(GLFWwindow* window, unsigned int c)
|
||||
{
|
||||
GLFWCharCallbackQueue.push_back(c);
|
||||
}
|
||||
|
||||
|
||||
void InputManager::GLFWScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
GLFWScrollCallbackQueue.push_back(std::make_pair(xoffset, yoffset));
|
||||
}
|
||||
|
||||
|
||||
void InputManager::GLFWDropCallback(GLFWwindow* window, int count, const char* paths[])
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
GLFWDropCallbackQueue.push_back(std::string(paths[i]));
|
||||
}
|
||||
//bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast<int>(button)];
|
||||
//float lastState = m_LastGamepadButtonState[gamepadID][static_cast<int>(button)];
|
||||
//if (currentState != lastState) {
|
||||
// if (currentState == true) {
|
||||
// Events::GamepadButtonDown e;
|
||||
// e.GamepadID = gamepadID;
|
||||
// e.Button = button;
|
||||
// m_EventBroker->Publish(e);
|
||||
// } else {
|
||||
// Events::GamepadButtonUp e;
|
||||
// e.GamepadID = gamepadID;
|
||||
// e.Button = button;
|
||||
// m_EventBroker->Publish(e);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
bool InputManager::OnLockMouse(const Events::LockMouse &event)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user