Compare commits

...

24 Commits

Author SHA1 Message Date
Jace 13a6cf5a9b Groundwork for Steam Controller support 2015-12-11 00:41:51 +01:00
Jace b4df0c49ae Groundwork for input command proxy 2015-12-11 00:37:48 +01:00
Jace 6326a60a79 Merge pull request #11 from teamfisk/Picking
Picking
2015-12-10 17:24:12 +01:00
viktorljung bb900c5110 Added picking event 2015-12-10 16:33:33 +01:00
viktorljung aa805f9a41 Merge remote-tracking branch 'origin/master' into Picking 2015-12-10 11:38:35 +01:00
Jace dc4f5ad26e Merge pull request #9 from teamfisk/ecs-systems
ECS Systems
2015-12-10 10:42:37 +01:00
Viktor Ljung eaca1c4dd1 Merge pull request #7 from teamfisk/ecs
Entity loading from schema
2015-12-10 10:32:00 +01:00
sippeangelo 0367826f16 Added RaptorCopter example system 2015-12-10 10:17:18 +01:00
sippeangelo 352074da04 Created base for systems 2015-12-10 10:17:08 +01:00
sippeangelo 53ef749736 Fixed absoute positioning, I think... 2015-12-10 10:16:03 +01:00
sippeangelo 90a79c702f Added crude absolute positioning when rendering 2015-12-09 15:26:49 +01:00
sippeangelo 578018607a Moved decision of which map to load to Config.ini 2015-12-09 14:32:34 +01:00
sippeangelo 58d827f7d0 Moved world definition to Schema/Entities/Test.xml and removed HardcodedTestWorld 2015-12-09 14:25:41 +01:00
sippeangelo 3085ccdfbf Added temporary Release function to resource manager to be able to reload a resource 2015-12-09 14:23:49 +01:00
sippeangelo c9b140bd6b Semi-working entity loading from XML files! 2015-12-09 12:29:32 +01:00
sippeangelo c9d1ba6cae EntityIDs should start at 1, because 0 is world 2015-12-09 11:07:46 +01:00
Tleety eb9c217eb4 3D picking float value error fixed. 2015-12-09 10:44:06 +01:00
Jace d597c7e60e Cleaned up custom type conversion code 2015-12-08 22:51:35 +01:00
Jace 0dbe0fe48e Component definitions and default values loading from schema 2015-12-08 21:38:52 +01:00
sippeangelo 1e1ce4e127 Added Model component to schema 2015-12-08 18:21:24 +01:00
sippeangelo 9fbea18330 fixup! Merge remote-tracking branch 'origin/master' into ecs 2015-12-08 18:20:42 +01:00
sippeangelo f337305dee Merge remote-tracking branch 'origin/master' into ecs 2015-12-08 18:07:42 +01:00
sippeangelo d7de4fc694 Component definitions now loaded from schema. No default values yet. 2015-12-08 18:07:32 +01:00
sippeangelo 03bbe25a1e Fixed FindXerces.cmake 2015-12-08 17:42:59 +01:00
51 changed files with 1825 additions and 563 deletions
+1 -1
Submodule assets updated: 4bd902b697...b37468222e
+9 -9
View File
@@ -1,13 +1,13 @@
# XERCES_FOUND
# XERCES_INCLUDE_DIRS
# XERCES_LIBRARIES
# Xerces_FOUND
# Xerces_INCLUDE_DIRS
# Xerces_LIBRARIES
find_path(XERCES_INCLUDE_DIR xercesc/dom/dom.hpp
find_path(Xerces_INCLUDE_DIR xercesc/dom/dom.hpp
/usr/local/include
/usr/include
)
find_library(XERCES_LIBRARY
find_library(Xerces_LIBRARY
NAMES
xerces-c_3
xerces-c_3D
@@ -16,8 +16,8 @@ find_library(XERCES_LIBRARY
/usr/lib
)
set(XERCES_INCLUDE_DIRS ${XERCES_INCLUDE_DIR})
set(XERCES_LIBRARIES ${XERCES_LIBRARY})
set(Xerces_INCLUDE_DIRS ${Xerces_INCLUDE_DIR})
set(Xerces_LIBRARIES ${Xerces_LIBRARY})
find_package_handle_standard_args(Xerces DEFAULT_MSG XERCES_LIBRARY XERCES_INCLUDE_DIR)
mark_as_advanced(Xerces_FOUND XERCES_INCLUDE_DIR XERCES_LIBRARY)
find_package_handle_standard_args(Xerces DEFAULT_MSG Xerces_LIBRARY Xerces_INCLUDE_DIR)
mark_as_advanced(Xerces_FOUND Xerces_INCLUDE_DIR Xerces_LIBRARY)
+1 -1
Submodule deps updated: 1b478d3159...9861acd762
+2 -2
View File
@@ -2,7 +2,7 @@
#define ComponentWrapper_h__
#include "../Common.h"
#include "EntityWrapper.h"
#include "Entity.h"
#include "ComponentInfo.h"
#include "Util/Any.h"
@@ -11,7 +11,7 @@ struct ComponentWrapper
ComponentWrapper(const ComponentInfo& componentInfo, char* data)
: Info(componentInfo)
, EntityID(*reinterpret_cast<::EntityID*>(data))
, Data(data + sizeof(EntityID))
, Data(data + sizeof(::EntityID))
{ }
const ComponentInfo& Info;
+6
View File
@@ -0,0 +1,6 @@
#ifndef Entity_h__
#define Entity_h__
typedef unsigned int EntityID;
#endif
-12
View File
@@ -1,12 +0,0 @@
#include "ResourceManager.h"
class EntityFile : public Resource
{
friend class ResourceManager;
private:
EntityFile(std::string path);
public:
};
-15
View File
@@ -1,15 +0,0 @@
#ifndef Entity_h__
#define Entity_h__
typedef unsigned int EntityID;
struct EntityWrapper
{
EntityWrapper(EntityID entityID)
: ID(entityID)
{ }
EntityID ID;
};
#endif
+141
View File
@@ -0,0 +1,141 @@
#ifndef EntityXMLFile_h__
#define EntityXMLFile_h__
#include <sstream>
#include "../Common.h"
#include "../GLM.h"
#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMLSInput.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLFloat.hpp>
#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp>
#include <xercesc/framework/psvi/XSModelGroup.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include "ResourceManager.h"
#include "Entity.h"
#include "ComponentInfo.h"
class World;
class EntityPreprocessorXMLErrorHandler : public xercesc::DOMErrorHandler
{
public:
bool handleError(const xercesc::DOMError &e) override
{
char* message = xercesc::XMLString::transcode(e.getMessage());
std::cerr << "Preprocessor DOMError: " << message << std::endl;
xercesc::XMLString::release(&message);
return false;
}
};
class EntityParserXMLErrorHandler : public xercesc::ErrorHandler
{
public:
void warning(const xercesc::SAXParseException& e) override
{
reportParseException("Warning", e);
}
void error(const xercesc::SAXParseException& e) override
{
reportParseException("Error", e);
}
void fatalError(const xercesc::SAXParseException& e) override
{
reportParseException("FATAL ERROR", e);
}
void resetErrors() override { }
private:
void reportParseException(std::string type, const xercesc::SAXParseException& e)
{
char* message = xercesc::XMLString::transcode(e.getMessage());
char* systemID = xercesc::XMLString::transcode(e.getSystemId());
std::cerr << systemID << ":" << e.getLineNumber() << ":" << e.getColumnNumber() << std::endl;
std::cerr << type << ": " << message << std::endl;
xercesc::XMLString::release(&systemID);
xercesc::XMLString::release(&message);
}
};
class XSTR
{
public:
XSTR(const XMLCh* const xmlString)
{
m_AsChar = xercesc::XMLString::transcode(xmlString);
}
XSTR(const char* normalString)
{
m_AsXMLCh = xercesc::XMLString::transcode(normalString);
}
~XSTR()
{
if (m_AsChar != nullptr) {
xercesc::XMLString::release(&m_AsChar);
}
if (m_AsXMLCh != nullptr) {
xercesc::XMLString::release(&m_AsXMLCh);
}
}
operator const char*() const { return m_AsChar; }
operator const XMLCh*() const { return m_AsXMLCh; }
private:
char* m_AsChar = nullptr;
XMLCh* m_AsXMLCh = nullptr;
};
class EntityXMLFile : public Resource
{
friend class ResourceManager;
private:
EntityXMLFile(std::string path);
public:
~EntityXMLFile();
void PopulateWorld(World* world);
private:
static unsigned int InstanceCount;
std::string m_EntityFile;
xercesc::XMLGrammarPool* m_GrammarPool = nullptr;
EntityParserXMLErrorHandler* m_ErrorHandler = nullptr;
xercesc::XercesDOMParser* m_DOMParser = nullptr;
xercesc::DOMDocument* m_DOMDocument = nullptr;
std::map<std::string, ComponentInfo> m_ComponentInfo;
// Preprocesses the entity file to insert include-by-copy child entities
// TODO: Make this work in memory instead of saving to file
void preprocess(std::string inPath, std::string outPath);
void parseComponentInfo();
void parseDefaults();
void predictComponentAllocation();
void parseEntityGraph(World* world, xercesc::DOMElement* parent, EntityID parentEntity);
std::size_t getTypeStride(std::string typeName);
float getFloatAttribute(const xercesc::DOMElement* element, const char* attribute) const;
void writeData(const xercesc::DOMElement* element, std::string typeName, char* outData);
};
#endif
+2
View File
@@ -81,6 +81,8 @@ public:
@param resourceName Fully qualified name of the resource to reload.
*/
static void Reload(std::string resourceName);
static void Release(std::string resourceType, std::string resourceName);
static void Update();
+25
View File
@@ -0,0 +1,25 @@
#ifndef System_h__
#define System_h__
#include "EventBroker.h"
#include "World.h"
#include "ComponentWrapper.h"
class System
{
friend class SystemPipeline;
public:
System(const EventBroker* eventBroker, std::string componentType)
: m_EventBroker(eventBroker)
, m_ComponentType(componentType)
{ }
virtual void Update(World* world, ComponentWrapper& component, double dt) = 0;
private:
const EventBroker* m_EventBroker;
std::string m_ComponentType;
};
#endif
+58
View File
@@ -0,0 +1,58 @@
#ifndef SystemPipeline_h__
#define SystemPipeline_h__
#include "../Common.h"
#include "EventBroker.h"
#include "System.h"
#include "World.h"
class SystemPipeline
{
public:
SystemPipeline(const EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{ }
~SystemPipeline()
{
for (auto& pair : m_Systems) {
for (auto& system : pair.second) {
delete system;
}
}
}
template <typename T, typename... Arguments>
void AddSystem(Arguments... args)
{
System* system = new T(m_EventBroker, args...);
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 (auto& pair : m_Systems) {
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);
}
}
}
}
private:
const EventBroker* m_EventBroker;
std::unordered_map<std::string, std::vector<System*>> m_Systems;
};
#endif
+6 -3
View File
@@ -2,7 +2,7 @@
#define World_h__
#include "../Common.h"
#include "EntityWrapper.h"
#include "Entity.h"
#include "ObjectPool.h"
#include "ComponentPool.h"
@@ -12,6 +12,7 @@ public:
World() = default;
~World();
// Create empty entity
EntityID CreateEntity(EntityID parent = 0);
// Register a component type and allocate space for it
@@ -21,10 +22,12 @@ public:
// Get a component of an entity
ComponentWrapper GetComponent(EntityID entity, std::string componentType);
// Get all components of the specified type
const ComponentPool& GetComponents(std::string componentType);
const ComponentPool* GetComponents(std::string componentType);
// Get entity parent
EntityID GetParent(EntityID entity);
private:
EntityID m_CurrentEntityID = 0;
EntityID m_CurrentEntityID = 1;
std::unordered_map<EntityID, EntityID> m_EntityParents;
std::unordered_multimap<EntityID, EntityID> m_EntityChildren;
+22
View File
@@ -0,0 +1,22 @@
#ifndef Events_BindOrigin_h__
#define Events_BindOrigin_h__
#include "Core/EventBroker.h"
namespace Events
{
/** Called to bind an input origin to an input command. */
struct BindOrigin : Event
{
/** The input origin to bind. */
std::string Origin;
/** The command to send. */
std::string Command;
/** The value to send for positive stimulation. */
float Value = 1.f;
};
}
#endif
+1 -1
View File
@@ -13,7 +13,7 @@ struct InputCommand : Event
/** The command that was sent. */
std::string Command;
/** The value of the command. */
float Value;
float Value = 0;
};
}
+146
View File
@@ -0,0 +1,146 @@
#ifndef InputSystem_h__
#define InputSystem_h__
#include <array>
#include <unordered_map>
#include <steam/steam_api.h>
#include "Core/EKeyUp.h"
#include "Core/EKeyDown.h"
#include "Core/EMousePress.h"
#include "Core/EMouseRelease.h"
#include "Core/EGamepadAxis.h"
#include "Core/EGamepadButton.h"
#include "Core/Util/EnumClassHash.h"
#include "EBindKey.h"
#include "EBindMouseButton.h"
#include "EBindGamepadAxis.h"
#include "EBindGamepadButton.h"
#include "EInputCommand.h"
#include "EBindOrigin.h"
class InputProxy;
class InputHandler
{
public:
InputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
: m_EventBroker(eventBroker)
, m_InputProxy(inputProxy)
{ }
virtual void Update(double dt) { }
virtual bool BindOrigin(std::string origin, std::string command, float value) = 0;
protected:
EventBroker* m_EventBroker;
InputProxy* m_InputProxy;
};
class InputProxy
{
public:
InputProxy(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_EBindOrigin, &InputProxy::OnBindOrigin);
}
void Update(double dt)
{
m_EventBroker->Process<InputProxy>();
m_EventBroker->Process<InputHandler>();
for (auto& handler : m_Handlers) {
handler->Update(dt);
}
}
void Process()
{
// Accumulate the input values of all unique commands published by input handlers
for (auto& pair : m_CommandQueue) {
Events::InputCommand e;
e.PlayerID = pair.first.first;
e.Command = pair.first.second;
e.Value = 0;
for (auto& value : pair.second) {
e.Value += value;
}
e.Value = std::max(-1.f, std::min(e.Value, 1.f));
m_EventBroker->Publish(e);
LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID);
}
m_CommandQueue.clear();
}
template <typename T>
void AddHandler()
{
m_Handlers.push_back(new T(m_EventBroker, this));
}
void Publish(const Events::InputCommand& e)
{
auto key = std::make_pair(e.PlayerID, e.Command);
m_CommandQueue[key].push_back(e.Value);
}
protected:
EventBroker* m_EventBroker;
std::vector<InputHandler*> m_Handlers;
// Represents every unique command (has of PlayerID & Command) and all values reported for that command
std::map<std::pair<unsigned int, std::string>, std::vector<float>> m_CommandQueue;
EventRelay<InputProxy, Events::BindOrigin> m_EBindOrigin;
bool OnBindOrigin(const Events::BindOrigin& e)
{
bool originBound = false;
for (auto& handler : m_Handlers) {
bool result = handler->BindOrigin(e.Origin, e.Command, e.Value);
if (result) {
if (originBound) {
LOG_WARNING("Multiple handlers responded to binding input origin \"%s\"!", e.Origin.c_str());
}
originBound = true;
}
}
if (!originBound) {
LOG_ERROR("No input handler responded to binding input origin \"%s\"!", e.Origin.c_str());
}
return originBound;
}
//std::unordered_map<std::string, std::unordered_map<int, float>> m_CommandMouseButtonValues; // command string -> mouse button value for command
//std::unordered_map<std::string, std::unordered_map<Gamepad::Axis, float, EnumClassHash>> m_CommandGamepadAxisValues; // command string -> gamepad axis value for command
//std::unordered_map<std::string, std::unordered_map<Gamepad::Button, float, EnumClassHash>> m_CommandGamepadButtonValues; // command string -> gamepad button value for command
//// Input binding tables
//std::unordered_multimap<int, std::tuple<std::string, float>> m_MouseButtonBindings; // GLFW_MOUSE_BUTTON... -> command string
//std::unordered_multimap<Gamepad::Axis, std::tuple<std::string, float>, EnumClassHash> m_GamepadAxisBindings; // Gamepad::Axis -> command string & value
//std::unordered_multimap<Gamepad::Button, std::tuple<std::string, float>, EnumClassHash> m_GamepadButtonBindings; // Gamepad::Button -> command string
//// Input events
//EventRelay<InputProxy, Events::MousePress> m_EMousePress;
//bool OnMousePress(const Events::MousePress &event);
//EventRelay<InputProxy, Events::MouseRelease> m_EMouseRelease;
//bool OnMouseRelease(const Events::MouseRelease &event);
//EventRelay<InputProxy, Events::GamepadAxis> m_EGamepadAxis;
//bool OnGamepadAxis(const Events::GamepadAxis &event);
//EventRelay<InputProxy, Events::GamepadButtonDown> m_EGamepadButtonDown;
//bool OnGamepadButtonDown(const Events::GamepadButtonDown &event);
//EventRelay<InputProxy, Events::GamepadButtonUp> m_EGamepadButtonUp;
//bool OnGamepadButtonUp(const Events::GamepadButtonUp &event);
//// Input binding events
//EventRelay<InputProxy, Events::BindMouseButton> m_EBindMouseButton;
//bool OnBindMouseButton(const Events::BindMouseButton &event);
//EventRelay<InputProxy, Events::BindGamepadAxis> m_EBindGamepadAxis;
//bool OnBindGamepadAxis(const Events::BindGamepadAxis &event);
//EventRelay<InputProxy, Events::BindGamepadButton> m_EBindGamepadButton;
//bool OnBindGamepadButton(const Events::BindGamepadButton &event);
//float GetCommandTotalValue(std::string command);
//void PublishCommand(int playerID, std::string command, float value);
};
#endif
-78
View File
@@ -1,78 +0,0 @@
#ifndef InputSystem_h__
#define InputSystem_h__
#include <array>
#include <unordered_map>
#include "Core/System.h"
#include "Core/EKeyUp.h"
#include "Core/EKeyDown.h"
#include "Core/EMousePress.h"
#include "Core/EMouseRelease.h"
#include "Core/EGamepadAxis.h"
#include "Core/EGamepadButton.h"
#include "Core/Util/EnumClassHash.h"
#include "EBindKey.h"
#include "EBindMouseButton.h"
#include "EBindGamepadAxis.h"
#include "EBindGamepadButton.h"
#include "EInputCommand.h"
namespace Systems
{
class InputSystem : public System
{
public:
InputSystem(World* world, std::shared_ptr<dd::EventBroker> eventBroker)
: System(world, eventBroker)
{ }
void RegisterComponents(ComponentFactory* cf) override;
void Initialize() override;
void Update(double dt) override;
private:
std::unordered_map<std::string, std::unordered_map<int, float>> m_CommandKeyboardValues; // command string -> keyboard key value for command
std::unordered_map<std::string, std::unordered_map<int, float>> m_CommandMouseButtonValues; // command string -> mouse button value for command
std::unordered_map<std::string, std::unordered_map<Gamepad::Axis, float, EnumClassHash>> m_CommandGamepadAxisValues; // command string -> gamepad axis value for command
std::unordered_map<std::string, std::unordered_map<Gamepad::Button, float, EnumClassHash>> m_CommandGamepadButtonValues; // command string -> gamepad button value for command
// Input binding tables
std::unordered_multimap<int, std::tuple<std::string, float>> m_KeyBindings; // GLFW_KEY... -> command string & value
std::unordered_multimap<int, std::tuple<std::string, float>> m_MouseButtonBindings; // GLFW_MOUSE_BUTTON... -> command string
std::unordered_multimap<Gamepad::Axis, std::tuple<std::string, float>, EnumClassHash> m_GamepadAxisBindings; // Gamepad::Axis -> command string & value
std::unordered_multimap<Gamepad::Button, std::tuple<std::string, float>, EnumClassHash> m_GamepadButtonBindings; // Gamepad::Button -> command string
// Input events
EventRelay<InputSystem, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown &event);
EventRelay<InputSystem, Events::KeyUp> m_EKeyUp;
bool OnKeyUp(const Events::KeyUp &event);
EventRelay<InputSystem, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress &event);
EventRelay<InputSystem, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease &event);
EventRelay<InputSystem, Events::GamepadAxis> m_EGamepadAxis;
bool OnGamepadAxis(const Events::GamepadAxis &event);
EventRelay<InputSystem, Events::GamepadButtonDown> m_EGamepadButtonDown;
bool OnGamepadButtonDown(const Events::GamepadButtonDown &event);
EventRelay<InputSystem, Events::GamepadButtonUp> m_EGamepadButtonUp;
bool OnGamepadButtonUp(const Events::GamepadButtonUp &event);
// Input binding events
EventRelay<InputSystem, Events::BindKey> m_EBindKey;
bool OnBindKey(const Events::BindKey &event);
EventRelay<InputSystem, Events::BindMouseButton> m_EBindMouseButton;
bool OnBindMouseButton(const Events::BindMouseButton &event);
EventRelay<InputSystem, Events::BindGamepadAxis> m_EBindGamepadAxis;
bool OnBindGamepadAxis(const Events::BindGamepadAxis &event);
EventRelay<InputSystem, Events::BindGamepadButton> m_EBindGamepadButton;
bool OnBindGamepadButton(const Events::BindGamepadButton &event);
float GetCommandTotalValue(std::string command);
void PublishCommand(int playerID, std::string command, float value);
};
}
#endif
@@ -0,0 +1,67 @@
#include <GLFW/glfw3.h>
#include "InputProxy.h"
#include "Core/EKeyDown.h"
#include "Core/EKeyUp.h"
class KeyboardInputHandler : public InputHandler
{
public:
KeyboardInputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
: InputHandler(eventBroker, inputProxy)
{
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &KeyboardInputHandler::OnKeyDown);
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &KeyboardInputHandler::OnKeyUp);
m_OriginKeyCodes["R"] = GLFW_KEY_R;
}
bool BindOrigin(std::string origin, std::string command, float value) override
{
auto originIt = m_OriginKeyCodes.find(origin);
if (originIt == m_OriginKeyCodes.end()) {
return false;
}
int keyCode = originIt->second;
m_KeyBindings[keyCode] = std::make_tuple(command, value);
return true;
}
private:
std::unordered_map<std::string, int> m_OriginKeyCodes;
std::unordered_map<int, std::tuple<std::string, float>> m_KeyBindings; // GLFW_KEY... -> command string & value
EventRelay<InputHandler, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown& e)
{
auto it = m_KeyBindings.find(e.KeyCode);
if (it == m_KeyBindings.end()) {
return false;
}
Events::InputCommand ic;
ic.PlayerID = 0;
std::tie(ic.Command, ic.Value) = it->second;
m_InputProxy->Publish(ic);
return true;
}
EventRelay<InputHandler, Events::KeyUp> m_EKeyUp;
bool OnKeyUp(const Events::KeyUp& e)
{
auto it = m_KeyBindings.find(e.KeyCode);
if (it == m_KeyBindings.end()) {
return false;
}
Events::InputCommand ic;
ic.PlayerID = 0;
std::tie(ic.Command, std::ignore) = it->second;
ic.Value = 0;
m_InputProxy->Publish(ic);
return true;
}
};
@@ -0,0 +1,98 @@
#include <steam/steam_api.h>
#include "InputProxy.h"
class SteamControllerInputHandler : public InputHandler
{
public:
SteamControllerInputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
: InputHandler(eventBroker, inputProxy)
{
SteamController()->Init();
}
~SteamControllerInputHandler()
{
SteamController()->Shutdown();
}
void Update(double dt) override
{
std::array<ControllerHandle_t, STEAM_CONTROLLER_MAX_COUNT> controllers;
int numControllers = SteamController()->GetConnectedControllers(controllers.data());
for (int i = 0; i < numControllers; i++) {
auto controllerHandle = controllers.at(i);
auto actionSetHandle = SteamController()->GetActionSetHandle("InGameControls");
//SteamController()->ShowBindingPanel(controllerHandle);
SteamController()->ActivateActionSet(controllerHandle, actionSetHandle);
for (auto& command : m_Commands) {
Events::InputCommand ic;
ic.PlayerID = i + 1;
ic.Command = command.first;
auto digitalActionHandle = m_DigitalActionHandles.at(ic.Command);
auto handle = SteamController()->GetDigitalActionHandle("DebugReload");
auto data = SteamController()->GetDigitalActionData(controllerHandle, handle);
LOG_DEBUG("Controller %i, active %i, value %i", i, data.bActive, data.bState);
if (data.bState) {
ic.Value = command.second;
} else {
ic.Value = 0.f;
}
//m_InputProxy->Publish(ic);
}
}
}
bool BindOrigin(std::string origin, std::string command, float value) override
{
if (origin != "SteamController") {
return false;
}
m_Commands[command] = value;
m_DigitalActionHandles[command] = SteamController()->GetDigitalActionHandle(command.c_str());
return true;
}
private:
std::map<std::string, float> m_Commands;
std::map<std::string, ControllerDigitalActionHandle_t> m_DigitalActionHandles;
//std::unordered_map<std::string, std::unordered_map<int, float>> m_CommandKeyboardValues; // command string -> keyboard key value for command
std::unordered_map<int, std::tuple<std::string, float>> m_KeyBindings; // GLFW_KEY... -> command string & value
EventRelay<InputHandler, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown& e)
{
auto it = m_KeyBindings.find(e.KeyCode);
if (it == m_KeyBindings.end()) {
return false;
}
Events::InputCommand ic;
ic.PlayerID = 0;
std::tie(ic.Command, ic.Value) = it->second;
m_InputProxy->Publish(ic);
return true;
}
EventRelay<InputHandler, Events::KeyUp> m_EKeyUp;
bool OnKeyUp(const Events::KeyUp& e)
{
auto it = m_KeyBindings.find(e.KeyCode);
if (it == m_KeyBindings.end()) {
return false;
}
Events::InputCommand ic;
ic.PlayerID = 0;
std::tie(ic.Command, std::ignore) = it->second;
ic.Value = 0;
m_InputProxy->Publish(ic);
return true;
}
};
+69
View File
@@ -0,0 +1,69 @@
#ifndef Events_Picking_h__
#define Events_Picking_h__
#include "../OpenGL.h"
#include "../GLM.h"
#include "../Core/EventBroker.h"
#include "Util/ScreenCoords.h"
#include "FrameBuffer.h"
#include "../Core/Entity.h"
#include "Util/UnorderedMapVec2.h"
namespace Events
{
/** Thrown Every frame, use functions to pick*/
struct Picking : Event
{
public:
Picking(FrameBuffer* pickingBuffer, GLuint* depthBuffer, glm::mat4 projectionMatrix, glm::mat4 viewMatrix, Rectangle resolution, const std::unordered_map<glm::vec2, EntityID>* pickingColorsToEntity)
: PickingBuffer(pickingBuffer)
, DepthBuffer(depthBuffer)
, ProjectionMatrix(projectionMatrix)
, ViewMatrix(viewMatrix)
, Resolution(resolution)
, PickingColorsToEntity(pickingColorsToEntity)
{ }
struct PickData
{
//Picked Entity
EntityID Entity;
//World position of the "pick"
glm::vec3 Position;
};
PickData Pick(glm::vec2 screenCoord) const
{
PickData pickData;
ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer);
auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1]));
if (it != PickingColorsToEntity->end()) {
pickData.Entity = it->second;
} else {
pickData.Entity = -1;
}
pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, Resolution.Width - screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix);
return pickData;
}
private:
FrameBuffer* PickingBuffer;
GLuint* DepthBuffer;
const glm::mat4 ProjectionMatrix;
const glm::mat4 ViewMatrix;
const Rectangle Resolution;
const std::unordered_map<glm::vec2, EntityID>* PickingColorsToEntity;
};
}
#endif
+1 -1
View File
@@ -7,7 +7,7 @@
#include "../Common.h"
#include "../GLM.h"
#include "../Core/Util/Rectangle.h"
#include "../Core/EntityWrapper.h"
#include "../Core/Entity.h"
class Model;
class Skeleton;
@@ -22,7 +22,10 @@ private:
void FillLights(World* world, RenderQueue* renderQueue);
glm::mat4 ModelMatrix(World* world, EntityID entity);
glm::vec3 GetAbsolutePosition(World* world, ComponentWrapper transformComponent);
glm::vec3 AbsolutePosition(World* world, EntityID entity);
glm::quat AbsoluteOrientation(World* world, EntityID entity);
glm::vec3 AbsoluteScale(World* world, EntityID entity);
};
#endif
+9 -2
View File
@@ -11,15 +11,24 @@
#include "FrameBuffer.h"
#include "../Core/World.h"
#include "../Core/EventBroker.h"
#include "EPicking.h"
class Renderer : public IRenderer
{
public:
Renderer(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{ }
virtual void Initialize() override;
virtual void Update(double dt) override;
virtual void Draw(RenderQueueCollection& rq) override;
private:
//----------------------Variables----------------------//
EventBroker* m_EventBroker;
Texture* m_ErrorTexture;
Texture* m_WhiteTexture;
float m_CameraMoveSpeed;
@@ -31,8 +40,6 @@ private:
Model* m_UnitQuad;
Model* m_UnitSphere;
std::unordered_map<glm::vec2, EntityID> m_PickingColorsToEntity;
//----------------------Functions----------------------//
+9 -2
View File
@@ -11,6 +11,13 @@ class ScreenCoords
{
public:
ScreenCoords() = delete;
struct PixelData
{
int Color[2];
float Depth;
};
//Return world position from given screenspace coordinates and depth value in viewspace.
static glm::vec3 ToWorldPos(glm::vec2 screenCoord, float depth, Rectangle resolution, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat);
static glm::vec3 ToWorldPos(float x, float y, float depth, Rectangle resolution, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat);
@@ -18,8 +25,8 @@ public:
static glm::vec3 ToWorldPos(float x, float y, float depth, float screenWidth, float screenHeight, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat);
//Return data from the given buffers at the coordinates given in screenspace. Buffer should probably have a texture that covers the screen.
//Data is given as R = x, B = y, and
static glm::vec3 ToPixelData(glm::vec2 screenCoord, FrameBuffer* PickDataBuffer, GLuint DepthBuffer);
static glm::vec3 ToPixelData(float x, float y, FrameBuffer* PickDataBuffer, GLuint DepthBuffer);
static PixelData ToPixelData(glm::vec2 screenCoord, FrameBuffer* PickDataBuffer, GLuint DepthBuffer);
static PixelData ToPixelData(float x, float y, FrameBuffer* PickDataBuffer, GLuint DepthBuffer);
//Return EntityID of the clicked coordinate in given screenspace coordinates.
//EntityID ScreenCoordsToEntityID(glm::vec2 screenCoord, float depth);
+15
View File
@@ -9,6 +9,13 @@
#include "GUI/Frame.h"
#include "Core/World.h"
#include "Rendering/RenderQueueFactory.h"
#include "Input/InputProxy.h"
#include "Input/KeyboardInputHandler.h"
#include "Input/SteamControllerInputHandler.h"
#include "Core/EKeyDown.h"
#include "Core/EntityXMLFile.h"
#include "Core/SystemPipeline.h"
#include "RaptorCopterSystem.h"
class Game
{
@@ -25,9 +32,17 @@ private:
EventBroker* m_EventBroker;
IRenderer* m_Renderer;
InputManager* m_InputManager;
InputProxy* m_InputProxy;
GUI::Frame* m_FrameStack;
World* m_World;
SystemPipeline* m_SystemPipeline;
RenderQueueFactory* m_RenderQueueFactory;
EventRelay<Game, Events::KeyUp> m_EKeyUp;
bool testOnKeyUp(const Events::KeyUp& e);
void testIntialize();
void testTick(double dt);
};
#endif
-110
View File
@@ -1,110 +0,0 @@
#include <list>
#include <tuple>
#include <boost/any.hpp>
#include "GLM.h"
#include "Core/World.h"
#include "Core/Util/Any.h"
class HardcodedTestWorld : public World
{
public:
HardcodedTestWorld()
: World()
{
registerTestComponents();
createTestEntities();
}
private:
void registerTestComponents()
{
ComponentWrapperFactory f;
f = ComponentWrapperFactory("Test");
f.AddProperty("TestInteger", 1337);
f.AddProperty("TestFloat", 13.37f);
f.AddProperty("TestString", std::string("Carlito"));
RegisterComponent(f);
f = ComponentWrapperFactory("Debug");
f.AddProperty("Name", std::string("Unnamed"));
RegisterComponent(f);
f = ComponentWrapperFactory("Transform");
f.AddProperty("Position", glm::vec3(0.f, 0.f, 0.f));
f.AddProperty("Orientation", glm::quat());
f.AddProperty("Scale", glm::vec3(1.f, 1.f, 1.f));
RegisterComponent(f);
f = ComponentWrapperFactory("Model");
f.AddProperty("Resource", std::string());
f.AddProperty("Color", glm::vec4(1.f, 1.f, 1.f, 1.f));
f.AddProperty("Visible", true);
RegisterComponent(f);
}
void createTestEntities()
{
World& world = *this;
// Create an entity
EntityID e = world.CreateEntity();
// Attach a Debug component
ComponentWrapper debug = world.AttachComponent(e, "Debug");
// Set the Name field of the Debug component using subscript operator
debug["Name"] = "Carlito";
// Attach a Transform component
world.AttachComponent(e, "Transform");
// Fetch the component based on EntityID and component type
ComponentWrapper transform = world.GetComponent(e, "Transform");
// Set the fields of the Transform component
transform["Position"] = glm::vec3(0.f, 0.f, 0.f);
transform["Scale"] = glm::vec3(1.f, 1.f, 1.f);
// Move on the X axis by fetching field as reference
((glm::vec3&)transform["Position"]).x += 10.f;
// Shrink by a factor of 100
((glm::vec3&)transform["Scale"]) /= 100.f;
// Loop through all Transform components and print them
for (auto& transform : world.GetComponents("Transform")) {
glm::vec3 pos = transform["Position"];
std::cout << "Position: " << pos.x << " " << pos.y << " " << pos.z << std::endl;
glm::vec3 scale = transform["Scale"];
std::cout << "Scale: " << scale.x << " " << scale.y << " " << scale.z << std::endl;
// Fetch the Debug component also present in this entity
ComponentWrapper debug = world.GetComponent(transform.EntityID, "Debug");
std::cout << "Name: " << (std::string)debug["Name"] << std::endl;
}
//Create some test widgets
{
EntityID entityScaleWidget = world.CreateEntity();
ComponentWrapper transform = world.AttachComponent(entityScaleWidget, "Transform");
transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f);
ComponentWrapper model = world.AttachComponent(entityScaleWidget, "Model");
model["Resource"] = "Models/ScaleWidget.obj";
}
{
EntityID entityRotationWidget = world.CreateEntity();
ComponentWrapper transform = world.AttachComponent(entityRotationWidget, "Transform");
transform["Position"] = glm::vec3(1.5f, 0.f, 0.f);
ComponentWrapper model = world.AttachComponent(entityRotationWidget, "Model");
model["Resource"] = "Models/RotationWidget.obj";
}
{
EntityID entityDummyScene = world.CreateEntity();
ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform");
transform["Position"] = glm::vec3(0, 0.f, 0.f);
ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model");
model["Resource"] = "Models/DummyScene.obj";
}
}
};
+16
View File
@@ -0,0 +1,16 @@
#include "Common.h"
#include "Core/System.h"
class RaptorCopterSystem : public System
{
public:
RaptorCopterSystem(const EventBroker* eventBroker)
: System(eventBroker, "RaptorCopter")
{ }
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
View File
@@ -1,5 +1,6 @@
[Debug]
LogLevel=1
LoadMap=
[Video]
Fullscreen=false
+2
View File
@@ -2,5 +2,7 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="components" elementFormDefault="qualified">
<xs:include schemaLocation="Components/Transform.xsd"/>
<xs:include schemaLocation="Components/Model.xsd"/>
<xs:include schemaLocation="Components/Test.xsd"/>
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
</xs:schema>
+5
View File
@@ -0,0 +1,5 @@
<c:Model>
<Resource></Resource>
<Color R="1" G="1" B="1" A="1"/>
<Visible>true</Visible>
</c:Model>
+24
View File
@@ -0,0 +1,24 @@
<?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="Model">
<xs:annotation>
<xs:documentation>A visible model loaded from disk</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Resource" type="t:string" minOccurs="0">
<xs:annotation><xs:documentation>Model file</xs:documentation></xs:annotation>
</xs:element>
<xs:element name="Color" type="t:Color" minOccurs="0">
<xs:annotation><xs:documentation>Color tint</xs:documentation></xs:annotation>
</xs:element>
<xs:element name="Visible" type="t:bool" minOccurs="0">
<xs:annotation><xs:documentation>Wether the model is visible or not</xs:documentation></xs:annotation>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -0,0 +1,4 @@
<c:RaptorCopter>
<Speed>0</Speed>
<Axis X="0" Y="0" Z="0"/>
</c:RaptorCopter>
@@ -0,0 +1,14 @@
<?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="RaptorCopter">
<xs:complexType>
<xs:all>
<xs:element name="Speed" type="t:double" minOccurs="0"/>
<xs:element name="Axis" type="t:Vector" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+1 -1
View File
@@ -2,5 +2,5 @@
<Integer>1</Integer>
<Float>1.333</Float>
<Vector X="1.33333" Y="2.33333" Z="3.33333"/>
<Quaternion I="1.33333" J="2.33333" K="3.33333"/>
<Quaternion X="1.33333" Y="2.33333" Z="3.33333" W="4.44444"/>
</c:Test>
+3 -3
View File
@@ -1,5 +1,5 @@
<TransformComponent>
<c:Transform>
<Position X="0" Y="0" Z="0"/>
<Orientation I="0" J="0" K="0"/>
<Orientation X="0" Y="0" Z="0" W="0"/>
<Scale X="1" Y="1" Z="1"/>
</TransformComponent>
</c:Transform>
+1 -1
View File
@@ -12,7 +12,7 @@
<xs:element name="Position" type="t:Vector" minOccurs="0">
<xs:annotation><xs:documentation>The position vector</xs:documentation></xs:annotation>
</xs:element>
<xs:element name="Orientation" type="t:Quaternion" minOccurs="0"/>
<xs:element name="Orientation" type="t:Vector" minOccurs="0"/>
<xs:element name="Scale" type="t:Vector" minOccurs="0"/>
</xs:all>
</xs:complexType>
+106 -10
View File
@@ -3,18 +3,114 @@
<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="1.02" Y="3.123123" Z="41.123"/>
<Orientation I="1.234" J="1.234" K="1.234"/>
<Scale X="1.02" Y="3.123123" Z="41.123"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
<c:Test>
<Integer>12</Integer>
<Double>11.11</Double>
<String>Hello World</String>
</c:Test>
<c:Model>
<Resource>Models/DummyScene.obj</Resource>
</c:Model>
</Components>
<Children>
<xi:include href="OtherEntity.xml"/>
<xi:include href="OtherEntity.xml"/>
<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"/>
</c:Transform>
<c:Model>
<Resource>Models/RotationWidget.obj</Resource>
</c:Model>
</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="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>
</Children>
</Entity>
</Children>
</Entity>
+4
View File
@@ -3,6 +3,10 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="types" elementFormDefault="qualified">
<xs:include schemaLocation="Types/Quaternion.xsd"/>
<xs:include schemaLocation="Types/Vector.xsd"/>
<xs:include schemaLocation="Types/Color.xsd"/>
<xs:simpleType name="bool">
<xs:restriction base="xs:boolean"></xs:restriction>
</xs:simpleType>
<xs:simpleType name="int">
<xs:restriction base="xs:integer"></xs:restriction>
</xs:simpleType>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="types" elementFormDefault="qualified">
<xs:complexType name="Color">
<xs:attribute name="R" type="xs:decimal" default="0.0"/>
<xs:attribute name="G" type="xs:decimal" default="0.0"/>
<xs:attribute name="B" type="xs:decimal" default="0.0"/>
<xs:attribute name="A" type="xs:decimal" default="1.0"/>
</xs:complexType>
</xs:schema>
+3 -1
View File
@@ -7,11 +7,13 @@
<xs:element name="Entity">
<xs:complexType>
<xs:all>
<xs:element name="Components">
<xs:element name="Components" minOccurs="0">
<xs:complexType>
<xs:all>
<xs:element ref="c:Transform" minOccurs="0"/>
<xs:element ref="c:Model" minOccurs="0"/>
<xs:element ref="c:Test" minOccurs="0"/>
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
+1 -1
View File
@@ -13,7 +13,7 @@ out vec4 TextureFragment;
void main()
{
TextureFragment = vec4(PickingColor, 0, 1);
TextureFragment = vec4(PickingColor/255, 0, 1);
}
+1 -1
View File
@@ -73,7 +73,7 @@ source_group(GUI FILES ${SOURCE_FILES_GUI})
set(SOURCE_FILES
${SOURCE_FILES_Core}
${SOURCE_FILES_Core_Util}
#${SOURCE_FILES_Input}
${SOURCE_FILES_Input}
${SOURCE_FILES_Network}
${SOURCE_FILES_GUI}
${SOURCE_FILES_Rendering}
+481
View File
@@ -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));
}
}
+14
View File
@@ -35,6 +35,20 @@ void ResourceManager::Reload(std::string resourceName)
}
}
void ResourceManager::Release(std::string resourceType, std::string resourceName)
{
auto key = std::make_pair(resourceType, resourceName);
if (m_ResourceCache.find(key) == m_ResourceCache.end()) {
return;
}
auto resource = m_ResourceCache.at(key);
m_ResourceCache.erase(key);
m_ResourceFromName.erase(resourceName);
m_ResourceParents.erase(resource);
delete resource;
}
unsigned int ResourceManager::GetNewResourceID(unsigned int typeID)
{
return m_ResourceCount[typeID]++;
+9 -2
View File
@@ -41,9 +41,16 @@ ComponentWrapper World::GetComponent(EntityID entity, std::string componentType)
return pool->GetByEntity(entity);
}
const ComponentPool& World::GetComponents(std::string componentType)
const ComponentPool* World::GetComponents(std::string componentType)
{
return *m_ComponentPools.at(componentType);
auto it = m_ComponentPools.find(componentType);
return (it != m_ComponentPools.end()) ? it->second : nullptr;
}
EntityID World::GetParent(EntityID entity)
{
return m_EntityParents.at(entity);
}
EntityID World::generateEntityID()
+221
View File
@@ -0,0 +1,221 @@
#include "Input/InputProxy.h"
#include "Core/World.h"
//InputProxy::InputProxy(EventBroker* eventBroker)
// : m_EventBroker(eventBroker)
//{
// // Subscribe to events
// EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &InputProxy::OnMousePress);
// EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &InputProxy::OnMouseRelease);
// EVENT_SUBSCRIBE_MEMBER(m_EGamepadAxis, &InputProxy::OnGamepadAxis);
// EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonDown, &InputProxy::OnGamepadButtonDown);
// EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonUp, &InputProxy::OnGamepadButtonUp);
// EVENT_SUBSCRIBE_MEMBER(m_EBindKey, &InputProxy::OnBindKey);
// EVENT_SUBSCRIBE_MEMBER(m_EBindMouseButton, &InputProxy::OnBindMouseButton);
// EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadAxis, &InputProxy::OnBindGamepadAxis);
// EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadButton, &InputProxy::OnBindGamepadButton);
//
// SteamController()->Init();
//
//}
//
//void InputProxy::Update(double dt)
//{
// std::array<ControllerHandle_t, STEAM_CONTROLLER_MAX_COUNT> controllers;
// int numControllers = SteamController()->GetConnectedControllers(controllers.data());
//
// ControllerDigitalActionHandle_t debug_reload_handle = SteamController()->GetDigitalActionHandle("debug_reload");
// SteamController()->
//}
//
//bool InputProxy::OnKeyDown(const Events::KeyDown &event)
//{
// auto range = m_KeyBindings.equal_range(event.KeyCode);
// for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
// std::string command;
// float value;
// std::tie(command, value) = bindingIt->second;
// m_CommandKeyboardValues[command][event.KeyCode] = value;
// PublishCommand(1, command, GetCommandTotalValue(command));
// }
//
// return true;
//}
//
//bool InputProxy::OnKeyUp(const Events::KeyUp &event)
//{
// auto range = m_KeyBindings.equal_range(event.KeyCode);
// for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
// std::string command;
// float value;
// std::tie(command, value) = bindingIt->second;
// m_CommandKeyboardValues[command][event.KeyCode] = 0;
// PublishCommand(1, command, GetCommandTotalValue(command));;
// }
//
// return true;
//}
//
//bool InputProxy::OnMousePress(const Events::MousePress &event)
//{
// auto range = m_MouseButtonBindings.equal_range(event.Button);
// for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
// std::string command;
// float value;
// std::tie(command, value) = bindingIt->second;
// m_CommandMouseButtonValues[command][event.Button] = value;
// PublishCommand(1, command, GetCommandTotalValue(command));
// }
//
// return true;
//}
//
//bool InputProxy::OnMouseRelease(const Events::MouseRelease &event)
//{
// auto range = m_MouseButtonBindings.equal_range(event.Button);
// for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
// std::string command;
// float value;
// std::tie(command, value) = bindingIt->second;
// m_CommandMouseButtonValues[command][event.Button] = 0;
// PublishCommand(1, command, GetCommandTotalValue(command));
// }
//
// return true;
//}
//
//bool InputProxy::OnGamepadAxis(const Events::GamepadAxis &event)
//{
// auto range = m_GamepadAxisBindings.equal_range(event.Axis);
// for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
// std::string command;
// float value;
// std::tie(command, value) = bindingIt->second;
// m_CommandGamepadAxisValues[command][event.Axis] = event.Value * value;
// PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command));
// }
//
// return true;
//}
//
//bool InputProxy::OnGamepadButtonDown(const Events::GamepadButtonDown &event)
//{
// auto range = m_GamepadButtonBindings.equal_range(event.Button);
// for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
// std::string command;
// float value;
// std::tie(command, value) = bindingIt->second;
// m_CommandGamepadButtonValues[command][event.Button] = value;
// PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command));
// }
//
// return true;
//}
//
//bool InputProxy::OnGamepadButtonUp(const Events::GamepadButtonUp &event)
//{
// auto range = m_GamepadButtonBindings.equal_range(event.Button);
// for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
// std::string command;
// float value;
// std::tie(command, value) = bindingIt->second;
// m_CommandGamepadButtonValues[command][event.Button] = 0;
// PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command));
// }
//
// return true;
//}
//
//bool InputProxy::OnBindKey(const Events::BindKey &event)
//{
// if (event.Command.empty()) {
// return false;
// }
//
// m_KeyBindings.insert(std::make_pair(event.KeyCode, std::make_tuple(event.Command, event.Value)));
// LOG_DEBUG("Input: Bound key %i to %s", event.KeyCode, event.Command.c_str());
//
// return true;
//}
//
//bool InputProxy::OnBindMouseButton(const Events::BindMouseButton &event)
//{
// if (event.Command.empty()) {
// return false;
// }
//
// m_MouseButtonBindings.insert(std::make_pair(event.Button, std::make_tuple(event.Command, event.Value)));
// LOG_DEBUG("Input: Bound mouse button %i to %s", event.Button, event.Command.c_str());
//
// return true;
//}
//
//bool InputProxy::OnBindGamepadAxis(const Events::BindGamepadAxis &event)
//{
// if (event.Command.empty()) {
// return false;
// }
//
// m_GamepadAxisBindings.insert(std::make_pair(event.Axis, std::make_tuple(event.Command, event.Value)));
// LOG_DEBUG("Input: Bound gamepad axis %i to %s", event.Axis, event.Command.c_str());
//
// return true;
//}
//
//bool InputProxy::OnBindGamepadButton(const Events::BindGamepadButton &event)
//{
// if (event.Command.empty()) {
// return false;
// }
//
// m_GamepadButtonBindings.insert(std::make_pair(event.Button, std::make_tuple(event.Command, event.Value)));
// LOG_DEBUG("Input: Bound gamepad axis %i to %s", event.Button, event.Command.c_str());
//
// return true;
//}
//
//float InputProxy::GetCommandTotalValue(std::string command)
//{
// float value = 0.f;
//
// auto keyboardIt = m_CommandKeyboardValues.find(command);
// if (keyboardIt != m_CommandKeyboardValues.end()) {
// for (auto &key : keyboardIt->second) {
// value += key.second;
// }
// }
//
// auto mouseButtonIt = m_CommandMouseButtonValues.find(command);
// if (mouseButtonIt != m_CommandMouseButtonValues.end()) {
// for (auto &button : mouseButtonIt->second) {
// value += button.second;
// }
// }
//
// auto gamepadAxisIt = m_CommandGamepadAxisValues.find(command);
// if (gamepadAxisIt != m_CommandGamepadAxisValues.end()) {
// for (auto &axis : gamepadAxisIt->second) {
// value += axis.second;
// }
// }
//
// auto gamepadButtonIt = m_CommandGamepadButtonValues.find(command);
// if (gamepadButtonIt != m_CommandGamepadButtonValues.end()) {
// for (auto &button : gamepadButtonIt->second) {
// value += button.second;
// }
// }
//
// return std::max(-1.f, std::min(value, 1.f));
//}
//
//void InputProxy::PublishCommand(int playerID, std::string command, float value)
//{
// Events::InputCommand e;
// e.PlayerID = playerID;
// e.Command = command;
// e.Value = value;
// m_EventBroker->Publish(e);
//
// LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, playerID);
//}
-221
View File
@@ -1,221 +0,0 @@
#include "PrecompiledHeader.h"
#include "Input/InputSystem.h"
#include "Core/World.h"
void Systems::InputSystem::RegisterComponents(ComponentFactory* cf)
{
}
void Systems::InputSystem::Initialize()
{
// Subscribe to events
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &Systems::InputSystem::OnKeyDown);
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &Systems::InputSystem::OnKeyUp);
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &Systems::InputSystem::OnMousePress);
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &Systems::InputSystem::OnMouseRelease);
EVENT_SUBSCRIBE_MEMBER(m_EGamepadAxis, &Systems::InputSystem::OnGamepadAxis);
EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonDown, &Systems::InputSystem::OnGamepadButtonDown);
EVENT_SUBSCRIBE_MEMBER(m_EGamepadButtonUp, &Systems::InputSystem::OnGamepadButtonUp);
EVENT_SUBSCRIBE_MEMBER(m_EBindKey, &Systems::InputSystem::OnBindKey);
EVENT_SUBSCRIBE_MEMBER(m_EBindMouseButton, &Systems::InputSystem::OnBindMouseButton);
EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadAxis, &Systems::InputSystem::OnBindGamepadAxis);
EVENT_SUBSCRIBE_MEMBER(m_EBindGamepadButton, &Systems::InputSystem::OnBindGamepadButton);
}
void Systems::InputSystem::Update(double dt)
{
}
bool Systems::InputSystem::OnKeyDown(const Events::KeyDown &event)
{
auto range = m_KeyBindings.equal_range(event.KeyCode);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandKeyboardValues[command][event.KeyCode] = value;
PublishCommand(1, command, GetCommandTotalValue(command));
}
return true;
}
bool Systems::InputSystem::OnKeyUp(const Events::KeyUp &event)
{
auto range = m_KeyBindings.equal_range(event.KeyCode);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandKeyboardValues[command][event.KeyCode] = 0;
PublishCommand(1, command, GetCommandTotalValue(command));;
}
return true;
}
bool Systems::InputSystem::OnMousePress(const Events::MousePress &event)
{
auto range = m_MouseButtonBindings.equal_range(event.Button);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandMouseButtonValues[command][event.Button] = value;
PublishCommand(1, command, GetCommandTotalValue(command));
}
return true;
}
bool Systems::InputSystem::OnMouseRelease(const Events::MouseRelease &event)
{
auto range = m_MouseButtonBindings.equal_range(event.Button);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandMouseButtonValues[command][event.Button] = 0;
PublishCommand(1, command, GetCommandTotalValue(command));
}
return true;
}
bool Systems::InputSystem::OnGamepadAxis(const Events::GamepadAxis &event)
{
auto range = m_GamepadAxisBindings.equal_range(event.Axis);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandGamepadAxisValues[command][event.Axis] = event.Value * value;
PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command));
}
return true;
}
bool Systems::InputSystem::OnGamepadButtonDown(const Events::GamepadButtonDown &event)
{
auto range = m_GamepadButtonBindings.equal_range(event.Button);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandGamepadButtonValues[command][event.Button] = value;
PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command));
}
return true;
}
bool Systems::InputSystem::OnGamepadButtonUp(const Events::GamepadButtonUp &event)
{
auto range = m_GamepadButtonBindings.equal_range(event.Button);
for (auto bindingIt = range.first; bindingIt != range.second; bindingIt++) {
std::string command;
float value;
std::tie(command, value) = bindingIt->second;
m_CommandGamepadButtonValues[command][event.Button] = 0;
PublishCommand(event.GamepadID + 1, command, GetCommandTotalValue(command));
}
return true;
}
bool Systems::InputSystem::OnBindKey(const Events::BindKey &event)
{
if (event.Command.empty()) {
return false;
}
m_KeyBindings.insert(std::make_pair(event.KeyCode, std::make_tuple(event.Command, event.Value)));
LOG_DEBUG("Input: Bound key %i to %s", event.KeyCode, event.Command.c_str());
return true;
}
bool Systems::InputSystem::OnBindMouseButton(const Events::BindMouseButton &event)
{
if (event.Command.empty()) {
return false;
}
m_MouseButtonBindings.insert(std::make_pair(event.Button, std::make_tuple(event.Command, event.Value)));
LOG_DEBUG("Input: Bound mouse button %i to %s", event.Button, event.Command.c_str());
return true;
}
bool Systems::InputSystem::OnBindGamepadAxis(const Events::BindGamepadAxis &event)
{
if (event.Command.empty()) {
return false;
}
m_GamepadAxisBindings.insert(std::make_pair(event.Axis, std::make_tuple(event.Command, event.Value)));
LOG_DEBUG("Input: Bound gamepad axis %i to %s", event.Axis, event.Command.c_str());
return true;
}
bool Systems::InputSystem::OnBindGamepadButton(const Events::BindGamepadButton &event)
{
if (event.Command.empty()) {
return false;
}
m_GamepadButtonBindings.insert(std::make_pair(event.Button, std::make_tuple(event.Command, event.Value)));
LOG_DEBUG("Input: Bound gamepad axis %i to %s", event.Button, event.Command.c_str());
return true;
}
float Systems::InputSystem::GetCommandTotalValue(std::string command)
{
float value = 0.f;
auto keyboardIt = m_CommandKeyboardValues.find(command);
if (keyboardIt != m_CommandKeyboardValues.end()) {
for (auto &key : keyboardIt->second) {
value += key.second;
}
}
auto mouseButtonIt = m_CommandMouseButtonValues.find(command);
if (mouseButtonIt != m_CommandMouseButtonValues.end()) {
for (auto &button : mouseButtonIt->second) {
value += button.second;
}
}
auto gamepadAxisIt = m_CommandGamepadAxisValues.find(command);
if (gamepadAxisIt != m_CommandGamepadAxisValues.end()) {
for (auto &axis : gamepadAxisIt->second) {
value += axis.second;
}
}
auto gamepadButtonIt = m_CommandGamepadButtonValues.find(command);
if (gamepadButtonIt != m_CommandGamepadButtonValues.end()) {
for (auto &button : gamepadButtonIt->second) {
value += button.second;
}
}
return std::max(-1.f, std::min(value, 1.f));
}
void Systems::InputSystem::PublishCommand(int playerID, std::string command, float value)
{
Events::InputCommand e;
e.PlayerID = playerID;
e.Command = command;
e.Value = value;
EventBroker->Publish(e);
LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, playerID);
}
+16 -16
View File
@@ -34,10 +34,10 @@ RawModel::RawModel(std::string fileName)
numIndices += face.mNumIndices;
}
}
LOG_DEBUG("Vertex count %i", numVertices);
LOG_DEBUG("Index count %i", numIndices);
//LOG_DEBUG("Vertex count %i", numVertices);
//LOG_DEBUG("Index count %i", numIndices);
LOG_DEBUG("Model has %i embedded textures", scene->mNumTextures);
//LOG_DEBUG("Model has %i embedded textures", scene->mNumTextures);
std::vector<std::tuple<std::string, glm::mat4>> boneInfo;
std::map<std::string, int> boneNameMapping;
@@ -132,35 +132,35 @@ RawModel::RawModel(std::string fileName)
matGroup.EndIndex = m_Indices.size() - 1;
// Material shininess
material->Get(AI_MATKEY_SHININESS, matGroup.Shininess);
LOG_DEBUG("Shininess: %f", matGroup.Shininess);
//LOG_DEBUG("Shininess: %f", matGroup.Shininess);
// Diffuse texture
LOG_DEBUG("%i diffuse textures found", material->GetTextureCount(aiTextureType_DIFFUSE));
//LOG_DEBUG("%i diffuse textures found", material->GetTextureCount(aiTextureType_DIFFUSE));
if (material->GetTextureCount(aiTextureType_DIFFUSE)) {
aiString path;
aiTextureMapping mapping;
material->GetTexture(aiTextureType_DIFFUSE, 0, &path, &mapping);
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
LOG_DEBUG("Diffuse texture: %s", absolutePath.c_str());
//LOG_DEBUG("Diffuse texture: %s", absolutePath.c_str());
matGroup.Texture = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
}
// Normal map
LOG_DEBUG("%i normal maps found", material->GetTextureCount(aiTextureType_HEIGHT));
//LOG_DEBUG("%i normal maps found", material->GetTextureCount(aiTextureType_HEIGHT));
if (material->GetTextureCount(aiTextureType_HEIGHT)) {
aiString path;
aiTextureMapping mapping;
material->GetTexture(aiTextureType_HEIGHT, 0, &path, &mapping);
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
LOG_DEBUG("Normal map: %s", absolutePath.c_str());
//LOG_DEBUG("Normal map: %s", absolutePath.c_str());
matGroup.NormalMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
}
// Specular map
LOG_DEBUG("%i specular maps found", material->GetTextureCount(aiTextureType_SPECULAR));
//LOG_DEBUG("%i specular maps found", material->GetTextureCount(aiTextureType_SPECULAR));
if (material->GetTextureCount(aiTextureType_SPECULAR)) {
aiString path;
aiTextureMapping mapping;
material->GetTexture(aiTextureType_SPECULAR, 0, &path, &mapping);
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
LOG_DEBUG("Specular map: %s", absolutePath.c_str());
//LOG_DEBUG("Specular map: %s", absolutePath.c_str());
matGroup.SpecularMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
}
TextureGroups.push_back(matGroup);
@@ -216,20 +216,20 @@ RawModel::RawModel(std::string fileName)
m_Skeleton = new Skeleton();
CreateSkeleton(boneInfo, boneNameMapping, scene->mRootNode, -1);
int numBones = m_Skeleton->Bones.size();
LOG_DEBUG("Bone count: %i", numBones);
//LOG_DEBUG("Bone count: %i", numBones);
if (numBones > 0) {
m_Skeleton->PrintSkeleton();
}
}
// Animations
LOG_DEBUG("Animation count: %i", scene->mNumAnimations);
//LOG_DEBUG("Animation count: %i", scene->mNumAnimations);
for (int i = 0; i < scene->mNumAnimations; ++i) {
auto animation = scene->mAnimations[i];
std::string animationName = animation->mName.C_Str();
LOG_DEBUG("Animation: %s", animationName.c_str());
LOG_DEBUG("Duration: %f", animation->mDuration);
LOG_DEBUG("Ticks per second: %f", animation->mTicksPerSecond);
//LOG_DEBUG("Animation: %s", animationName.c_str());
//LOG_DEBUG("Duration: %f", animation->mDuration);
//LOG_DEBUG("Ticks per second: %f", animation->mTicksPerSecond);
Skeleton::Animation skelAnim;
skelAnim.Name = animationName;
@@ -303,7 +303,7 @@ void RawModel::CreateSkeleton(std::vector<std::tuple<std::string, glm::mat4>> &b
// Find the bone by name in the bone info list
if (boneNameMapping.find(nodeName) == boneNameMapping.end()) {
LOG_DEBUG("Node \"%s\" was not a bone", nodeName.c_str());
//LOG_DEBUG("Node \"%s\" was not a bone", nodeName.c_str());
} else {
glm::mat4 offsetMatrix;
int ID = boneNameMapping[nodeName];
+69 -31
View File
@@ -15,49 +15,87 @@ void RenderQueueFactory::Update(World* world)
glm::mat4 RenderQueueFactory::ModelMatrix(World* world, EntityID entity)
{
//should really return absolute model matrix based on parents position, scale and orientation
//GetAbsolutePosition(World* world, ComponentWrapper transformComponent)
glm::vec3 position = AbsolutePosition(world, entity);
glm::quat orientation = AbsoluteOrientation(world, entity);
glm::vec3 scale = AbsoluteScale(world, entity);
ComponentWrapper transformComponent = world->GetComponent(entity, "Transform");
glm::vec3 position = transformComponent["Position"];
glm::vec3 scale = transformComponent["Scale"];
glm::quat oritentation = transformComponent["Orientation"];
glm::mat4 modelMatrix = glm::translate(glm::mat4(), position) * glm::toMat4(oritentation) * glm::scale(scale);
glm::mat4 modelMatrix = glm::translate(glm::mat4(), position) * glm::toMat4(orientation) * glm::scale(scale);
return modelMatrix;
}
glm::vec3 GetAbsolutePosition(World* world, ComponentWrapper transformComponent)
glm::vec3 RenderQueueFactory::AbsolutePosition(World* world, EntityID entity)
{
// positionComponent.EntityID
return glm::vec3();
glm::vec3 position;
do {
ComponentWrapper transform = world->GetComponent(entity, "Transform");
position += AbsoluteOrientation(world, entity) * (glm::vec3)transform["Position"];
entity = world->GetParent(entity);
} while (entity != 0);
return position;
}
glm::quat RenderQueueFactory::AbsoluteOrientation(World* world, EntityID entity)
{
glm::quat orientation;
do {
ComponentWrapper transform = world->GetComponent(entity, "Transform");
orientation = glm::quat((glm::vec3)transform["Orientation"]) * orientation;
entity = world->GetParent(entity);
} while (entity != 0);
return orientation;
}
glm::vec3 RenderQueueFactory::AbsoluteScale(World* world, EntityID entity)
{
ComponentWrapper transform = world->GetComponent(entity, "Transform");
glm::vec3 scale = (glm::vec3)transform["Scale"];
EntityID parent = world->GetParent(entity);
if (parent != 0) {
return AbsoluteScale(world, parent) * scale;
} else {
return scale;
}
}
void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue)
{
for(auto& modelC : world->GetComponents("Model")) {
ModelJob job;
std::string resource = modelC["Resource"];
glm::vec4 color = modelC["Color"];
Model* model = ResourceManager::Load<Model>(resource);
auto models = world->GetComponents("Model");
if (models == nullptr) {
return;
}
for (auto texGroup : model->TextureGroups) {
job.TextureID = (texGroup.Texture) ? texGroup.Texture->ResourceID : 0;
job.DiffuseTexture = texGroup.Texture.get();
job.NormalTexture = texGroup.NormalMap.get();
job.SpecularTexture = texGroup.SpecularMap.get();
job.Model = model;
job.StartIndex = texGroup.StartIndex;
job.EndIndex = texGroup.EndIndex;
job.ModelMatrix = model->m_Matrix * ModelMatrix(world, modelC.EntityID);
job.Color = color;
for (auto& modelC : *models) {
std::string resource = modelC["Resource"];
if (resource.empty()) {
continue;
}
glm::vec4 color = modelC["Color"];
Model* model = ResourceManager::Load<Model>(resource);
//TODO: RENDERER: Not sure if the best solution for pickingColor to entity link is this
job.Entity = modelC.EntityID;
for (auto texGroup : model->TextureGroups) {
ModelJob job;
job.TextureID = (texGroup.Texture) ? texGroup.Texture->ResourceID : 0;
job.DiffuseTexture = texGroup.Texture.get();
job.NormalTexture = texGroup.NormalMap.get();
job.SpecularTexture = texGroup.SpecularMap.get();
job.Model = model;
job.StartIndex = texGroup.StartIndex;
job.EndIndex = texGroup.EndIndex;
job.ModelMatrix = model->m_Matrix * ModelMatrix(world, modelC.EntityID);
job.Color = color;
renderQueue->Add(job);
}
}
//TODO: RENDERER: Not sure if the best solution for pickingColor to entity link is this
job.Entity = modelC.EntityID;
renderQueue->Add(job);
}
}
}
void RenderQueueFactory::FillLights(World* world, RenderQueue* renderQueue)
+34 -26
View File
@@ -3,7 +3,6 @@
void Renderer::Initialize()
{
InitializeWindow();
// Create default camera
m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(45.f), 0.01f, 5000.f);
m_DefaultCamera->SetPosition(glm::vec3(0, 0, 10));
@@ -116,23 +115,6 @@ void Renderer::InputUpdate(double dt)
static double mousePosX, mousePosY;
glfwGetCursorPos(m_Window, &mousePosX, &mousePosY);
if (glfwGetMouseButton(m_Window, GLFW_MOUSE_BUTTON_1) == GLFW_PRESS) {
glm::vec3 data = ScreenCoords::ToPixelData(mousePosX, m_Resolution.Height - mousePosY, &m_PickingBuffer, m_DepthBuffer);
glm::vec2 color = glm::vec2(data);
float depth = data.z;
glm::vec3 viewPos = ScreenCoords::ToWorldPos(mousePosX, m_Resolution.Height - mousePosY, depth, m_Resolution, m_Camera->ProjectionMatrix(), m_Camera->ViewMatrix());
// glm::vec3 worldPos = glm::vec3(glm::inverse(m_Camera->ViewMatrix()) * glm::vec4(viewPos, 1.f));
//printf("R: %f, G: %f, Depth: %f\n", color.r, color.g, depth);
//printf("view: x: %f, y: %f z: %f, Length: %f\n\n", viewPos.x, viewPos.y, viewPos.z, glm::length(viewPos));
if (color != glm::vec2(0, 0)) {
EntityID pickedEntity = m_PickingColorsToEntity[color];
printf("Picked Entity: %i", pickedEntity);
}
}
if (glfwGetKey(m_Window, GLFW_KEY_SPACE) == GLFW_PRESS) {
@@ -158,7 +140,8 @@ void Renderer::InputUpdate(double dt)
void Renderer::Update(double dt)
{
InputUpdate(dt);
m_EventBroker->Process<Renderer>();
InputUpdate(dt);
}
@@ -213,10 +196,12 @@ void Renderer::DrawScene(RenderQueueCollection& rq)
continue;
}
}
GLERROR("DrawScene Error");
}
void Renderer::PickingPass(RenderQueueCollection& rq)
{
m_PickingColorsToEntity.clear();
m_PickingBuffer.Bind();
glEnable(GL_DEPTH_TEST);
@@ -225,7 +210,7 @@ void Renderer::PickingPass(RenderQueueCollection& rq)
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
int r = 30;
int r = 1;
int g = 0;
//TODO: Render: Add code for more jobs than modeljobs.
@@ -237,8 +222,18 @@ void Renderer::PickingPass(RenderQueueCollection& rq)
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
if (modelJob) {
glm::vec2 pickColor = glm::vec2(r/255.f, g/255.f);
m_PickingColorsToEntity[pickColor] = modelJob->Entity;
//---------------
//TODO: Renderer: IMPORTANT: Fixa detta så det inte loopar igenom listan varje frame.
//---------------
int pickColor[2] = { r, g };
for (auto i : m_PickingColorsToEntity) {
if(modelJob->Entity == i.second) {
pickColor[0] = i.first.x;
pickColor[1] = i.first.y;
r -= 1;
}
}
m_PickingColorsToEntity[glm::vec2(pickColor[0], pickColor[1])] = modelJob->Entity;
//Render picking stuff
@@ -246,19 +241,32 @@ void Renderer::PickingPass(RenderQueueCollection& rq)
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix));
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix()));
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix()));
glUniform2fv(glGetUniformLocation(ShaderHandle, "PickingColor"), 1, glm::value_ptr(pickColor));
glUniform2fv(glGetUniformLocation(ShaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1])));
glBindVertexArray(modelJob->Model->VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
r+=50;
r += 1;
if(r > 255) {
r = 0;
g+=50;
g += 1;
}
}
}
m_PickingBuffer.Unbind();
GLERROR("PickingPass Error");
//Publish pick event every frame with the pick data that can be picked by the event
Events::Picking pickEvent = Events::Picking(
&m_PickingBuffer,
&m_DepthBuffer,
m_Camera->ProjectionMatrix(),
m_Camera->ViewMatrix(),
m_Resolution,
&m_PickingColorsToEntity);
m_EventBroker->Publish(pickEvent);
}
@@ -300,7 +308,7 @@ void Renderer::InitializeTextures()
*/
GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR,
glm::vec2(m_Resolution.Width, m_Resolution.Height), GL_RG8, GL_RG, GL_FLOAT);
glm::vec2(m_Resolution.Width, m_Resolution.Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
}
void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type)
+14 -5
View File
@@ -29,22 +29,31 @@ glm::vec3 ScreenCoords::ToWorldPos(glm::vec2 screenCoord, float depth, float scr
return ToWorldPos(screenCoord.x, screenCoord.y, depth, screenWidth, screenHeight, cameraProjectionMat, cameraViewMat);
}
glm::vec3 ScreenCoords::ToPixelData(float x, float y, FrameBuffer* PickDataBuffer, GLuint DepthBuffer)
ScreenCoords::PixelData ScreenCoords::ToPixelData(float x, float y, FrameBuffer* PickDataBuffer, GLuint DepthBuffer)
{
PickDataBuffer->Bind();
glm::vec2 pixelData;
glReadPixels(x, y, 1, 1, GL_RG, GL_FLOAT, &pixelData);
unsigned char pdata[2];
glReadPixels(x, y, 1, 1, GL_RG, GL_UNSIGNED_BYTE, &pdata);
PickDataBuffer->Unbind();
glBindFramebuffer(GL_FRAMEBUFFER, DepthBuffer);
float depthData;
glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthData);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return glm::vec3(pixelData, depthData);
PixelData p;
p.Color[0] = (int)pdata[0];
p.Color[1] = (int)pdata[1];
p.Depth = depthData;
GLERROR("ScreenCoords::ToPixelData Error");
return p;
}
glm::vec3 ScreenCoords::ToPixelData(glm::vec2 screenCoord, FrameBuffer* PickDataBuffer, GLuint DepthBuffer)
ScreenCoords::PixelData ScreenCoords::ToPixelData(glm::vec2 screenCoord, FrameBuffer* PickDataBuffer, GLuint DepthBuffer)
{
return ToPixelData(screenCoord.x, screenCoord.y, PickDataBuffer, DepthBuffer);
}
+79 -6
View File
@@ -1,11 +1,13 @@
#include "Game.h"
#include "HardcodedTestWorld.h"
Game::Game(int argc, char* argv[])
{
bool steamResult = SteamAPI_Init();
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
ResourceManager::RegisterType<Model>("Model");
ResourceManager::RegisterType<Texture>("Texture");
ResourceManager::RegisterType<EntityXMLFile>("EntityXMLFile");
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
@@ -16,7 +18,7 @@ Game::Game(int argc, char* argv[])
m_RenderQueueFactory = new RenderQueueFactory();
// Create the renderer
m_Renderer = new Renderer();
m_Renderer = new Renderer(m_EventBroker);
m_Renderer->SetFullscreen(m_Config->Get<bool>("Video.Fullscreen", false));
m_Renderer->SetVSYNC(m_Config->Get<bool>("Video.VSYNC", false));
m_Renderer->SetResolution(Rectangle(
@@ -29,16 +31,29 @@ Game::Game(int argc, char* argv[])
// Create input manager
m_InputManager = new InputManager(m_Renderer->Window(), m_EventBroker);
m_InputProxy = new InputProxy(m_EventBroker);
m_InputProxy->AddHandler<KeyboardInputHandler>();
m_InputProxy->AddHandler<SteamControllerInputHandler>();
// Create the root level GUI frame
m_FrameStack = new GUI::Frame(m_EventBroker);
m_FrameStack->Width = m_Renderer->Resolution().Width;
m_FrameStack->Height = m_Renderer->Resolution().Height;
// Create a TEST WORLD
m_World = new HardcodedTestWorld();
// Create a world
m_World = new World();
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
if (!mapToLoad.empty()) {
ResourceManager::Load<EntityXMLFile>(mapToLoad)->PopulateWorld(m_World);
}
// Create system pipeline
m_SystemPipeline = new SystemPipeline(m_EventBroker);
m_SystemPipeline->AddSystem<RaptorCopterSystem>();
m_LastTime = glfwGetTime();
testIntialize();
}
Game::~Game()
@@ -53,13 +68,23 @@ void Game::Tick()
double dt = currentTime - m_LastTime;
m_LastTime = currentTime;
SteamAPI_RunCallbacks();
// Handle input in a weird looking but responsive way
m_EventBroker->Swap();
m_InputManager->Update(dt);
m_Renderer->Update(dt);
m_EventBroker->Swap();
m_InputProxy->Update(dt);
m_EventBroker->Swap();
m_InputProxy->Process();
m_EventBroker->Swap();
m_RenderQueueFactory->Update(m_World);
// Iterate through systems and update world!
m_SystemPipeline->Update(m_World, dt);
testTick(dt);
m_Renderer->Update(dt);
m_RenderQueueFactory->Update(m_World);
m_Renderer->Draw(m_RenderQueueFactory->RenderQueues());
m_EventBroker->Swap();
@@ -67,3 +92,51 @@ void Game::Tick()
glfwPollEvents();
}
bool Game::testOnKeyUp(const Events::KeyUp& e)
{
if (e.KeyCode == GLFW_KEY_R) {
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
if (!mapToLoad.empty()) {
delete m_World;
m_World = new World();
ResourceManager::Release("EntityXMLFile", mapToLoad);
ResourceManager::Load<EntityXMLFile>(mapToLoad)->PopulateWorld(m_World);
}
}
return false;
}
void Game::testIntialize()
{
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &Game::testOnKeyUp);
{
Events::BindOrigin e;
e.Origin = "R";
e.Command = "DebugReload";
e.Value = 1.f;
m_EventBroker->Publish(e);
}
{
Events::BindOrigin e;
e.Origin = "SteamController";
e.Command = "DebugReload";
e.Value = 1.f;
m_EventBroker->Publish(e);
}
{
Events::BindOrigin e;
e.Origin = "X";
e.Command = "DebugReload";
e.Value = 1.f;
m_EventBroker->Publish(e);
}
}
void Game::testTick(double dt)
{
m_EventBroker->Process<Game>();
}