Merge remote-tracking branch 'origin/master' into AndersTest
# Conflicts: # include/Engine/Core/InputController.h # include/Game/Game.h
This commit is contained in:
@@ -10,6 +10,7 @@ Libraries bundled along with binaries for Windows (MSVC14), available as a submo
|
||||
| **[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) |
|
||||
|
||||
#### External libraries
|
||||
Libraries that are too big to be bundled with the project.
|
||||
|
||||
+1
-1
Submodule assets updated: b37468222e...95823e122a
+1
-1
Submodule deps updated: 1b478d3159...f20b9cc13b
@@ -54,6 +54,8 @@ 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);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "../Common.h"
|
||||
#include "ResourceManager.h"
|
||||
@@ -19,12 +20,14 @@ 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);
|
||||
|
||||
void SaveToDisk();
|
||||
|
||||
private:
|
||||
private:
|
||||
boost::filesystem::path m_Path;
|
||||
boost::property_tree::ptree m_PTreeDefaults;
|
||||
boost::property_tree::ptree m_PTreeOverrides;
|
||||
@@ -37,6 +40,21 @@ T ConfigFile::Get(std::string key, T defaultValue)
|
||||
return m_PTreeMerged.get<T>(key, defaultValue);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#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
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef Events_MouseScroll_h__
|
||||
#define Events_MouseScroll_h__
|
||||
|
||||
#include "EventBroker.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
struct MouseScroll : Event
|
||||
{
|
||||
double DeltaX;
|
||||
double DeltaY;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -17,119 +17,119 @@ class EventBroker;
|
||||
|
||||
class BaseEventRelay
|
||||
{
|
||||
friend class EventBroker;
|
||||
friend class EventBroker;
|
||||
|
||||
protected:
|
||||
BaseEventRelay(std::string contextTypeName, std::string eventTypeName)
|
||||
: m_ContextTypeName(contextTypeName)
|
||||
, m_EventTypeName(eventTypeName)
|
||||
, m_Broker(nullptr)
|
||||
{ }
|
||||
~BaseEventRelay();
|
||||
BaseEventRelay(std::string contextTypeName, std::string eventTypeName)
|
||||
: m_ContextTypeName(contextTypeName)
|
||||
, m_EventTypeName(eventTypeName)
|
||||
, m_Broker(nullptr)
|
||||
{ }
|
||||
~BaseEventRelay();
|
||||
|
||||
public:
|
||||
virtual bool Receive(const std::shared_ptr<Event> event) = 0;
|
||||
virtual bool Receive(const std::shared_ptr<Event> event) = 0;
|
||||
|
||||
protected:
|
||||
std::string m_ContextTypeName;
|
||||
std::string m_EventTypeName;
|
||||
EventBroker* m_Broker;
|
||||
std::string m_ContextTypeName;
|
||||
std::string m_EventTypeName;
|
||||
EventBroker* m_Broker;
|
||||
};
|
||||
|
||||
template <typename ContextType, typename EventType>
|
||||
class EventRelay : public BaseEventRelay
|
||||
{
|
||||
public:
|
||||
typedef std::function<bool(const EventType&)> CallbackType;
|
||||
typedef std::function<bool(const EventType&)> CallbackType;
|
||||
|
||||
EventRelay()
|
||||
: m_Callback(nullptr)
|
||||
, BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name())
|
||||
{ }
|
||||
EventRelay(CallbackType callback)
|
||||
: m_Callback(callback)
|
||||
, BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name())
|
||||
{ }
|
||||
EventRelay()
|
||||
: m_Callback(nullptr)
|
||||
, BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name())
|
||||
{ }
|
||||
EventRelay(CallbackType callback)
|
||||
: m_Callback(callback)
|
||||
, BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name())
|
||||
{ }
|
||||
|
||||
protected:
|
||||
bool Receive(const std::shared_ptr<Event> event) override;
|
||||
bool Receive(const std::shared_ptr<Event> event) override;
|
||||
|
||||
private:
|
||||
CallbackType m_Callback;
|
||||
CallbackType m_Callback;
|
||||
};
|
||||
|
||||
template <typename ContextType, typename EventType>
|
||||
bool EventRelay<ContextType, EventType>::Receive(const std::shared_ptr<Event> event)
|
||||
{
|
||||
if (m_Callback != nullptr) {
|
||||
return m_Callback(*static_cast<const EventType*>(event.get()));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (m_Callback != nullptr) {
|
||||
return m_Callback(*static_cast<const EventType*>(event.get()));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class EventBroker
|
||||
{
|
||||
template <typename ContextType, typename EventType> friend class EventRelay;
|
||||
template <typename ContextType, typename EventType> friend class EventRelay;
|
||||
|
||||
public:
|
||||
EventBroker()
|
||||
{
|
||||
m_EventQueueRead = std::make_shared<EventQueue_t>();
|
||||
m_EventQueueWrite = std::make_shared<EventQueue_t>();
|
||||
}
|
||||
EventBroker()
|
||||
{
|
||||
m_EventQueueRead = std::make_shared<EventQueue_t>();
|
||||
m_EventQueueWrite = std::make_shared<EventQueue_t>();
|
||||
}
|
||||
|
||||
void Subscribe(BaseEventRelay &relay);
|
||||
template <typename EventType>
|
||||
void Publish(const EventType &event);
|
||||
/*
|
||||
Process all events in a given context.
|
||||
Returns: Number of events processed
|
||||
*/
|
||||
template <typename ContextType>
|
||||
int Process();
|
||||
int Process(std::string contextTypeName);
|
||||
void Swap();
|
||||
void Clear();
|
||||
void Unsubscribe(BaseEventRelay &relay);
|
||||
void Subscribe(BaseEventRelay &relay);
|
||||
template <typename EventType>
|
||||
void Publish(const EventType &event);
|
||||
/*
|
||||
Process all events in a given context.
|
||||
Returns: Number of events processed
|
||||
*/
|
||||
template <typename ContextType>
|
||||
int Process();
|
||||
int Process(std::string contextTypeName);
|
||||
void Swap();
|
||||
void Clear();
|
||||
void Unsubscribe(BaseEventRelay &relay);
|
||||
|
||||
private:
|
||||
bool m_IsProcessing = false;
|
||||
bool m_IsProcessing = false;
|
||||
|
||||
typedef std::string ContextTypeName_t; // typeid(ContextType).name()
|
||||
typedef std::string EventTypeName_t; // typeid(EventType).name()
|
||||
typedef std::string ContextTypeName_t; // typeid(ContextType).name()
|
||||
typedef std::string EventTypeName_t; // typeid(EventType).name()
|
||||
|
||||
typedef std::unordered_multimap<EventTypeName_t, BaseEventRelay*> EventRelays_t;
|
||||
typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t;
|
||||
ContextRelays_t m_ContextRelays;
|
||||
std::vector<BaseEventRelay*> m_RelaysToSubscribe;
|
||||
std::vector<BaseEventRelay*> m_RelaysToUnsubscribe;
|
||||
typedef std::unordered_multimap<EventTypeName_t, BaseEventRelay*> EventRelays_t;
|
||||
typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t;
|
||||
ContextRelays_t m_ContextRelays;
|
||||
std::vector<BaseEventRelay*> m_RelaysToSubscribe;
|
||||
std::vector<BaseEventRelay*> m_RelaysToUnsubscribe;
|
||||
|
||||
typedef std::list<std::pair<EventTypeName_t, std::shared_ptr<Event>>> EventQueue_t;
|
||||
std::shared_ptr<EventQueue_t> m_EventQueueRead;
|
||||
std::shared_ptr<EventQueue_t> m_EventQueueWrite;
|
||||
typedef std::list<std::pair<EventTypeName_t, std::shared_ptr<Event>>> EventQueue_t;
|
||||
std::shared_ptr<EventQueue_t> m_EventQueueRead;
|
||||
std::shared_ptr<EventQueue_t> m_EventQueueWrite;
|
||||
|
||||
void subscribeImmediate(BaseEventRelay& relay);
|
||||
void unsubscribeImmediate(BaseEventRelay& relay);
|
||||
void subscribeImmediate(BaseEventRelay& relay);
|
||||
void unsubscribeImmediate(BaseEventRelay& relay);
|
||||
};
|
||||
|
||||
template <typename EventType>
|
||||
void EventBroker::Publish(const EventType &event)
|
||||
{
|
||||
/*auto itpair = m_Subscribers.equal_range(typeid(EventType).name());
|
||||
for (auto it = itpair.first; it != itpair.second; ++it)
|
||||
{
|
||||
it->second->Receive(event);
|
||||
}*/
|
||||
/*auto itpair = m_Subscribers.equal_range(typeid(EventType).name());
|
||||
for (auto it = itpair.first; it != itpair.second; ++it)
|
||||
{
|
||||
it->second->Receive(event);
|
||||
}*/
|
||||
|
||||
m_EventQueueWrite->push_back(std::make_pair(typeid(EventType).name(), std::shared_ptr<EventType>(new EventType(event))));
|
||||
m_EventQueueWrite->push_back(std::make_pair(typeid(EventType).name(), std::shared_ptr<EventType>(new EventType(event))));
|
||||
}
|
||||
|
||||
template <typename ContextType>
|
||||
int EventBroker::Process()
|
||||
{
|
||||
const std::string contextTypeName = typeid(ContextType).name();
|
||||
return Process(contextTypeName);
|
||||
const std::string contextTypeName = typeid(ContextType).name();
|
||||
return Process(contextTypeName);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,26 +11,23 @@ template <typename EventContext>
|
||||
class InputController
|
||||
{
|
||||
public:
|
||||
InputController(std::shared_ptr<dd::EventBroker> eventBroker)
|
||||
: EventBroker(eventBroker)
|
||||
InputController(EventBroker* eventBroker)
|
||||
: m_EventBroker(eventBroker)
|
||||
{ Initialize(); }
|
||||
|
||||
virtual void Initialize()
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(
|
||||
_EInputCommand, &InputController::OnCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &InputController::OnMouseMove);
|
||||
}
|
||||
|
||||
virtual bool OnCommand(const Events::InputCommand &event) { return false; }
|
||||
virtual bool OnMouseMove(const Events::MouseMove &event) { return false; }
|
||||
virtual bool OnCommand(const Events::InputCommand& e) { return false; }
|
||||
|
||||
protected:
|
||||
std::shared_ptr<dd::EventBroker> EventBroker;
|
||||
EventBroker* m_EventBroker;
|
||||
|
||||
private:
|
||||
EventRelay<EventContext, Events::InputCommand> m_EInputCommand;
|
||||
EventRelay<EventContext, Events::MouseMove> m_EMouseMove;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
#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"
|
||||
@@ -64,6 +66,11 @@ 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);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,20 +6,40 @@
|
||||
#include "ComponentWrapper.h"
|
||||
|
||||
class System
|
||||
{
|
||||
protected:
|
||||
System(EventBroker* eventBroker)
|
||||
: m_EventBroker(eventBroker)
|
||||
{ }
|
||||
|
||||
EventBroker* m_EventBroker;
|
||||
};
|
||||
|
||||
class PureSystem : public System
|
||||
{
|
||||
friend class SystemPipeline;
|
||||
|
||||
public:
|
||||
System(const EventBroker* eventBroker, std::string componentType)
|
||||
: m_EventBroker(eventBroker)
|
||||
protected:
|
||||
PureSystem(EventBroker* eventBroker, std::string componentType)
|
||||
: System(eventBroker)
|
||||
, m_ComponentType(componentType)
|
||||
{ }
|
||||
|
||||
virtual void Update(World* world, ComponentWrapper& component, double dt) = 0;
|
||||
const std::string m_ComponentType;
|
||||
|
||||
private:
|
||||
const EventBroker* m_EventBroker;
|
||||
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 void Update(World* world, double dt) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,12 +9,12 @@
|
||||
class SystemPipeline
|
||||
{
|
||||
public:
|
||||
SystemPipeline(const EventBroker* eventBroker)
|
||||
SystemPipeline(EventBroker* eventBroker)
|
||||
: m_EventBroker(eventBroker)
|
||||
{ }
|
||||
~SystemPipeline()
|
||||
{
|
||||
for (auto& pair : m_Systems) {
|
||||
for (auto& pair : m_PureSystems) {
|
||||
for (auto& system : pair.second) {
|
||||
delete system;
|
||||
}
|
||||
@@ -25,17 +25,32 @@ public:
|
||||
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;
|
||||
m_Systems[typeid(T).name()] = system;
|
||||
|
||||
if (std::is_base_of<PureSystem, T>::value) {
|
||||
PureSystem* pureSystem = static_cast<PureSystem*>(system);
|
||||
if (!pureSystem->m_ComponentType.empty()) {
|
||||
m_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);
|
||||
m_ImpureSystems.push_back(impureSystem);
|
||||
}
|
||||
}
|
||||
|
||||
void Update(World* world, double dt)
|
||||
{
|
||||
// Process events
|
||||
for (auto& pair : m_Systems) {
|
||||
m_EventBroker->Process(pair.first);
|
||||
}
|
||||
|
||||
// Update
|
||||
for (auto& pair : m_PureSystems) {
|
||||
const std::string& componentName = pair.first;
|
||||
auto& systems = pair.second;
|
||||
const ComponentPool* pool = world->GetComponents(componentName);
|
||||
@@ -44,15 +59,20 @@ public:
|
||||
}
|
||||
for (auto& component : *pool) {
|
||||
for (auto& system : systems) {
|
||||
system->Update(world, component, dt);
|
||||
system->UpdateComponent(world, component, dt);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& system : m_ImpureSystems) {
|
||||
system->Update(world, dt);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const EventBroker* m_EventBroker;
|
||||
std::unordered_map<std::string, std::vector<System*>> m_Systems;
|
||||
EventBroker* m_EventBroker;
|
||||
std::map<std::string, System*> m_Systems;
|
||||
std::map<std::string, std::vector<PureSystem*>> m_PureSystems;
|
||||
std::vector<ImpureSystem*> m_ImpureSystems;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -14,17 +14,27 @@ public:
|
||||
|
||||
// Create empty entity
|
||||
EntityID CreateEntity(EntityID parent = 0);
|
||||
// Delete entity and all components within
|
||||
void DeleteEntity(EntityID entity);
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
// 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; }
|
||||
|
||||
private:
|
||||
EntityID m_CurrentEntityID = 1;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <imgui/imgui.h>
|
||||
#include <glm/gtx/common.hpp>
|
||||
#include "../Core/System.h"
|
||||
#include "../Core/EMousePress.h"
|
||||
#include "../Core/ConfigFile.h"
|
||||
#include "../Input/EInputCommand.h"
|
||||
#include "../Rendering/EPicking.h"
|
||||
#include "../Rendering/RenderQueueFactory.h"
|
||||
|
||||
class EditorSystem : public ImpureSystem
|
||||
{
|
||||
public:
|
||||
EditorSystem(EventBroker* eventBroker);
|
||||
|
||||
virtual void Update(World* world, double dt) override;
|
||||
|
||||
private:
|
||||
bool m_Enabled;
|
||||
bool m_Visible;
|
||||
std::vector<glm::vec2> m_PickingQueue;
|
||||
EntityID m_Widget = 0;
|
||||
EntityID m_Selection = 0;
|
||||
EntityID m_LastSelection = 0;
|
||||
glm::vec3 m_Position;
|
||||
|
||||
EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand;
|
||||
bool OnInputCommand(const Events::InputCommand& e);
|
||||
EventRelay<EditorSystem, Events::MousePress> m_EMousePress;
|
||||
bool OnMousePress(const Events::MousePress& e);
|
||||
EventRelay<EditorSystem, Events::Picking> m_EPicking;
|
||||
bool OnPicking(const Events::Picking& e);
|
||||
|
||||
void drawUI(World* world, double dt);
|
||||
bool createDeleteButton(std::string componentType);
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
#ifndef Events_BindGamepadAxis_h__
|
||||
#define Events_BindGamepadAxis_h__
|
||||
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Core/EGamepadAxis.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
/** Called to bind a gamepad axis to an input command. */
|
||||
struct BindGamepadAxis : Event
|
||||
{
|
||||
/** The axis to bind. */
|
||||
Gamepad::Axis Axis;
|
||||
/** The command to send. */
|
||||
std::string Command;
|
||||
/** The value to send for positive stimulation.
|
||||
|
||||
Multiplied by the 0-1 clamped value of the axis.
|
||||
*/
|
||||
float Value;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#ifndef Events_BindGamepadButton_h__
|
||||
#define Events_BindGamepadButton_h__
|
||||
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Core/EGamepadButton.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
/** Called to bind a gamepad button to an input command. */
|
||||
struct BindGamepadButton : Event
|
||||
{
|
||||
/** The gamepad button to bind. */
|
||||
Gamepad::Button Button;
|
||||
/** The command to send. */
|
||||
std::string Command;
|
||||
/** The value to send for positive stimulation.
|
||||
|
||||
Multiplied by the 0-1 clamped value of the button.
|
||||
*/
|
||||
float Value;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef Events_BindKey_h__
|
||||
#define Events_BindKey_h__
|
||||
|
||||
#include "Core/EventBroker.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
/** Called to bind a keyboard key to an input command. */
|
||||
struct BindKey : Event
|
||||
{
|
||||
/** The GLFW key code to bind. */
|
||||
int KeyCode;
|
||||
/** The command to send. */
|
||||
std::string Command;
|
||||
/** The value to send for positive stimulation.
|
||||
|
||||
Multiplied by the 0-1 clamped value of the key.
|
||||
*/
|
||||
float Value;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef Events_BindMouseButton_h__
|
||||
#define Events_BindMouseButton_h__
|
||||
|
||||
#include "Core/EventBroker.h"
|
||||
|
||||
namespace Events
|
||||
{
|
||||
|
||||
/** Called to bind a mouse button to an input command. */
|
||||
struct BindMouseButton : Event
|
||||
{
|
||||
/** The GLFW mouse button code to bind. */
|
||||
int Button;
|
||||
/** The command to send. */
|
||||
std::string Command;
|
||||
/** The value to send for positive stimulation.
|
||||
|
||||
Multiplied by the 0-1 clamped value of the button.
|
||||
*/
|
||||
float Value;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef FirstPersonInputController_h__
|
||||
#define FirstPersonInputController_h__
|
||||
|
||||
#include "../GLM.h"
|
||||
#include "../Core/InputController.h"
|
||||
#include "../Core/ELockMouse.h"
|
||||
|
||||
template <typename EventContext>
|
||||
class FirstPersonInputController : public InputController<EventContext>
|
||||
{
|
||||
public:
|
||||
FirstPersonInputController(EventBroker* eventBroker, unsigned int playerID)
|
||||
: InputController(eventBroker)
|
||||
, m_PlayerID(playerID)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &FirstPersonInputController::OnLockMouse);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &FirstPersonInputController::OnUnlockMouse);
|
||||
}
|
||||
|
||||
const glm::quat Orientation() const { return m_Orientation; }
|
||||
|
||||
void LockMouse()
|
||||
{
|
||||
Events::LockMouse e;
|
||||
m_EventBroker->Publish(e);
|
||||
m_MouseLocked = true;
|
||||
}
|
||||
|
||||
void UnlockMouse()
|
||||
{
|
||||
Events::UnlockMouse e;
|
||||
m_EventBroker->Publish(e);
|
||||
m_MouseLocked = false;
|
||||
}
|
||||
|
||||
virtual bool OnCommand(const Events::InputCommand& e) override
|
||||
{
|
||||
if (m_PlayerID != e.PlayerID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_MouseLocked) {
|
||||
if (e.Command == "Pitch") {
|
||||
float val = glm::radians(e.Value);
|
||||
m_Orientation = m_Orientation * glm::angleAxis<float>(-val, glm::vec3(1, 0, 0));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (e.Command == "Yaw") {
|
||||
float val = glm::radians(e.Value);
|
||||
m_Orientation = glm::angleAxis<float>(-val, glm::vec3(0, 1, 0)) * m_Orientation;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
const unsigned int m_PlayerID;
|
||||
glm::quat m_Orientation;
|
||||
bool m_MouseLocked = false;
|
||||
|
||||
EventRelay<EventContext, Events::LockMouse> m_ELockMouse;
|
||||
bool OnLockMouse(const Events::LockMouse& e) { m_MouseLocked = true; return true; }
|
||||
EventRelay<EventContext, Events::UnlockMouse> m_EUnlockMouse;
|
||||
bool OnUnlockMouse(const Events::UnlockMouse& e) { m_MouseLocked = false; return true; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef InputHandler_h__
|
||||
#define InputHandler_h__
|
||||
|
||||
#include "../Common.h"
|
||||
#include "../Core/EventBroker.h"
|
||||
#include "InputProxy.h"
|
||||
|
||||
class InputHandler
|
||||
{
|
||||
public:
|
||||
InputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
|
||||
: m_EventBroker(eventBroker)
|
||||
, m_InputProxy(inputProxy)
|
||||
{ }
|
||||
|
||||
virtual bool BindOrigin(std::string origin, std::string command, float value) = 0;
|
||||
virtual void Update(double dt) { }
|
||||
virtual float GetCommandValue(std::string command) = 0;
|
||||
|
||||
protected:
|
||||
EventBroker* m_EventBroker;
|
||||
InputProxy* m_InputProxy;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef InputProxy_h__
|
||||
#define InputProxy_h__
|
||||
|
||||
#include "../Common.h"
|
||||
#include "../Core/ResourceManager.h"
|
||||
#include "../Core/ConfigFile.h"
|
||||
#include "EInputCommand.h"
|
||||
#include "EBindOrigin.h"
|
||||
|
||||
class InputHandler;
|
||||
|
||||
class InputProxy
|
||||
{
|
||||
public:
|
||||
InputProxy(EventBroker* eventBroker);
|
||||
~InputProxy();
|
||||
|
||||
void LoadBindings(std::string file);
|
||||
void Update(double dt);
|
||||
void Process();
|
||||
template <typename T>
|
||||
void AddHandler();
|
||||
void Publish(const Events::InputCommand& e);
|
||||
|
||||
protected:
|
||||
EventBroker* m_EventBroker;
|
||||
std::vector<InputHandler*> m_Handlers;
|
||||
std::map<std::string, std::set<InputHandler*>> m_CommandHandlers;
|
||||
|
||||
// Represents every unique command (has of PlayerID & Command) and all values reported for that command this frame
|
||||
std::map<std::pair<unsigned int, std::string>, std::vector<float>> m_CommandQueue;
|
||||
|
||||
std::map<std::string, float> m_CurrentCommandValues;
|
||||
std::map<std::string, float> m_LastCommandValues;
|
||||
|
||||
EventRelay<InputProxy, Events::BindOrigin> m_EBindOrigin;
|
||||
bool OnBindOrigin(const Events::BindOrigin& e);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void InputProxy::AddHandler()
|
||||
{
|
||||
m_Handlers.push_back(new T(m_EventBroker, this));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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,28 @@
|
||||
#ifndef KeyboardInputHandler_h__
|
||||
#define KeyboardInputHandler_h__
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "InputHandler.h"
|
||||
#include "Core/EKeyDown.h"
|
||||
#include "Core/EKeyUp.h"
|
||||
|
||||
class KeyboardInputHandler : public InputHandler
|
||||
{
|
||||
public:
|
||||
KeyboardInputHandler(EventBroker* eventBroker, InputProxy* inputProxy);
|
||||
|
||||
bool BindOrigin(std::string origin, std::string command, float value) override;
|
||||
virtual float GetCommandValue(std::string command) override;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, int> m_OriginKeyCodes;
|
||||
std::unordered_map<int, std::tuple<std::string, float>> m_KeyBindings; // GLFW_KEY... -> command string & value
|
||||
std::unordered_map<std::string, float> m_CommandValues;
|
||||
|
||||
EventRelay<InputHandler, Events::KeyDown> m_EKeyDown;
|
||||
bool OnKeyDown(const Events::KeyDown& e);
|
||||
EventRelay<InputHandler, Events::KeyUp> m_EKeyUp;
|
||||
bool OnKeyUp(const Events::KeyUp& e);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef MouseInputHandler_h__
|
||||
#define MouseInputHandler_h__
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "InputHandler.h"
|
||||
#include "Core/EMousePress.h"
|
||||
#include "Core/EMouseRelease.h"
|
||||
#include "Core/EMouseMove.h"
|
||||
|
||||
class MouseInputHandler : public InputHandler
|
||||
{
|
||||
public:
|
||||
MouseInputHandler(EventBroker* eventBroker, InputProxy* inputProxy);
|
||||
|
||||
bool BindOrigin(std::string origin, std::string command, float value) override;
|
||||
virtual float GetCommandValue(std::string command) override;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, int> m_OriginCodes;
|
||||
std::unordered_map<std::string, char> m_OriginAxes;
|
||||
std::unordered_map<int, std::tuple<std::string, float>> m_Bindings; // GLFW_MOUSE_BUTTON... -> command string & value
|
||||
std::unordered_map<char, std::tuple<std::string, float>> m_Axes; // Axis -> command string & value
|
||||
std::unordered_map<std::string, float> m_CommandValues;
|
||||
std::unordered_map<std::string, float> m_ContinuousCommandValues;
|
||||
|
||||
EventRelay<InputHandler, Events::MousePress> m_EMousePress;
|
||||
bool OnMousePress(const Events::MousePress& e);
|
||||
EventRelay<InputHandler, Events::MouseRelease> m_EMouseRelease;
|
||||
bool OnMouseRelease(const Events::MouseRelease& e);
|
||||
EventRelay<InputHandler, Events::MouseMove> m_EMouseMove;
|
||||
bool OnMouseMove(const Events::MouseMove& e);
|
||||
|
||||
bool hasOrigin(std::string origin);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
#include <imgui/imgui.h>
|
||||
#include "../Input/FirstPersonInputController.h"
|
||||
|
||||
template <typename EventContext>
|
||||
class DebugCameraInputController : public FirstPersonInputController<EventContext>
|
||||
{
|
||||
public:
|
||||
DebugCameraInputController(EventBroker* eventBroker, unsigned int playerID)
|
||||
: FirstPersonInputController(eventBroker, playerID)
|
||||
{ }
|
||||
|
||||
const glm::vec3 Position() const { return m_Position; }
|
||||
void SetBaseSpeed(float speed) { m_BaseSpeed = speed; }
|
||||
|
||||
virtual bool OnCommand(const Events::InputCommand& e) override
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
if (e.Command == "PrimaryFire") {
|
||||
if (e.Value > 0) {
|
||||
if (!io.WantCaptureMouse) {
|
||||
LockMouse();
|
||||
}
|
||||
} else {
|
||||
UnlockMouse();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!io.WantCaptureKeyboard) {
|
||||
if (e.Command == "Right") {
|
||||
float value = std::max(-1.f, std::min(e.Value, 1.f));
|
||||
m_Velocity.x = value;
|
||||
}
|
||||
if (e.Command == "Forward") {
|
||||
float value = std::max(-1.f, std::min(e.Value, 1.f));
|
||||
m_Velocity.z = -value;
|
||||
}
|
||||
if (e.Command == "Sprint") {
|
||||
if (e.Value > 0.f) {
|
||||
m_Speed = m_BaseSpeed * 2.f * (e.Value);
|
||||
} else {
|
||||
m_Speed = m_BaseSpeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FirstPersonInputController::OnCommand(e);
|
||||
}
|
||||
|
||||
void Update(double dt)
|
||||
{
|
||||
if (glm::length2(m_Velocity) > 0) {
|
||||
m_Position += m_Orientation * (glm::normalize(m_Velocity) * m_Speed * (float)dt);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
glm::vec3 m_Position = glm::vec3(0, 0, 0);
|
||||
glm::vec3 m_Velocity = glm::vec3(0, 0, 0);
|
||||
float m_BaseSpeed = 2.0f;
|
||||
float m_Speed = m_BaseSpeed;
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef DrawScenePass_h__
|
||||
#define DrawScenePass_h__
|
||||
|
||||
#include "IRenderer.h"
|
||||
#include "DrawScenePassState.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "Util/UnorderedMapVec2.h"
|
||||
#include "Texture.h"
|
||||
|
||||
class DrawScenePass
|
||||
{
|
||||
public:
|
||||
DrawScenePass(IRenderer* renderer);
|
||||
~DrawScenePass() { }
|
||||
void InitializeTextures();
|
||||
void InitializeFrameBuffers();
|
||||
void InitializeShaderPrograms();
|
||||
|
||||
void Draw(RenderQueueCollection& rq);
|
||||
|
||||
//Getters
|
||||
|
||||
|
||||
private:
|
||||
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
|
||||
|
||||
Texture* m_WhiteTexture;
|
||||
|
||||
const IRenderer* m_Renderer;
|
||||
|
||||
ShaderProgram* m_BasicForwardProgram;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef DrawScenePassState_h__
|
||||
#define DrawScenePassState_h__
|
||||
|
||||
#include "Rendering/RenderState.h"
|
||||
|
||||
class DrawScenePassState : public RenderState
|
||||
{
|
||||
public:
|
||||
DrawScenePassState();
|
||||
~DrawScenePassState();
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
#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;
|
||||
|
||||
// Invert screen y coordinate
|
||||
screenCoord.y = Resolution.Height - screenCoord.y;
|
||||
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 = 0;
|
||||
}
|
||||
pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix);
|
||||
|
||||
return pickData;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
FrameBuffer* PickingBuffer;
|
||||
GLuint* DepthBuffer;
|
||||
const glm::mat4 ProjectionMatrix;
|
||||
const glm::mat4 ViewMatrix;
|
||||
const Rectangle Resolution;
|
||||
const std::unordered_map<glm::vec2, EntityID>* PickingColorsToEntity;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
#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();
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
#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
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef PickingPassState_h__
|
||||
#define PickingPassState_h__
|
||||
|
||||
#include "Rendering/RenderState.h"
|
||||
|
||||
class PickingPassState : public RenderState
|
||||
{
|
||||
public:
|
||||
PickingPassState(GLuint frameBuffer);
|
||||
~PickingPassState();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -13,8 +13,12 @@ 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;
|
||||
|
||||
@@ -22,10 +26,6 @@ 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
|
||||
@@ -0,0 +1,27 @@
|
||||
#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,48 +10,115 @@
|
||||
#include "Util/UnorderedMapVec2.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "../Core/World.h"
|
||||
#include "PickingPass.h"
|
||||
#include "DrawScenePass.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
|
||||
{
|
||||
public:
|
||||
virtual void Initialize() override;
|
||||
virtual void Update(double dt) override;
|
||||
virtual void Draw(RenderQueueCollection& rq) override;
|
||||
Renderer(EventBroker* eventBroker)
|
||||
: m_EventBroker(eventBroker)
|
||||
{ }
|
||||
|
||||
virtual void Initialize() override;
|
||||
virtual void Update(double dt) override;
|
||||
virtual void Draw(RenderQueueCollection& rq) override;
|
||||
|
||||
private:
|
||||
//----------------------Variables----------------------//
|
||||
Texture* m_ErrorTexture;
|
||||
Texture* m_WhiteTexture;
|
||||
float m_CameraMoveSpeed;
|
||||
FrameBuffer m_PickingBuffer;
|
||||
GLuint m_PickingTexture;
|
||||
GLuint m_DepthBuffer;
|
||||
//----------------------Variables----------------------//
|
||||
EventBroker* m_EventBroker;
|
||||
|
||||
Texture* m_ErrorTexture;
|
||||
Texture* m_WhiteTexture;
|
||||
float m_CameraMoveSpeed;
|
||||
|
||||
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 InitializeFrameBuffers();
|
||||
void InitializeSSBOs();
|
||||
void InitializeRenderPasses();
|
||||
//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_PickingProgram;
|
||||
ShaderProgram m_DrawScreenQuadProgram;
|
||||
ShaderProgram* m_BasicForwardProgram;
|
||||
ShaderProgram* m_DrawScreenQuadProgram;
|
||||
ShaderProgram* m_CalculateFrustumProgram;
|
||||
ShaderProgram* m_LightCullProgram;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,9 @@
|
||||
#ifndef ShaderProgram_h__
|
||||
#define ShaderProgram_h__
|
||||
|
||||
#include "../Common.h"
|
||||
#include "../OpenGL.h"
|
||||
#include "../Core/ResourceManager.h"
|
||||
#include <fstream>
|
||||
|
||||
class Shader
|
||||
@@ -60,11 +63,13 @@ public:
|
||||
: ShaderType(fileName) { }
|
||||
};
|
||||
|
||||
class ShaderProgram
|
||||
class ShaderProgram : public Resource
|
||||
{
|
||||
public:
|
||||
ShaderProgram()
|
||||
friend class ResourceManager;
|
||||
private:
|
||||
ShaderProgram(std::string)
|
||||
: m_ShaderProgramHandle(0) { }
|
||||
public:
|
||||
~ShaderProgram();
|
||||
|
||||
void AddShader(std::shared_ptr<Shader> shader);
|
||||
@@ -79,3 +84,5 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+10
-4
@@ -9,10 +9,15 @@
|
||||
#include "GUI/Frame.h"
|
||||
#include "Core/World.h"
|
||||
#include "Rendering/RenderQueueFactory.h"
|
||||
#include "Input/InputProxy.h"
|
||||
#include "Input/KeyboardInputHandler.h"
|
||||
#include "Input/MouseInputHandler.h"
|
||||
#include "Core/EKeyDown.h"
|
||||
#include "Core/EntityXMLFile.h"
|
||||
#include "Core/SystemPipeline.h"
|
||||
#include "RaptorCopterSystem.h"
|
||||
#include "PlayerSystem.h"
|
||||
#include "Editor/EditorSystem.h"
|
||||
|
||||
class OctTree;
|
||||
|
||||
@@ -31,16 +36,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;
|
||||
OctTree* m_OctTree;
|
||||
EventRelay<Game, Events::KeyUp> m_EKeyUp;
|
||||
bool testOnKeyUp(const Events::KeyUp& e);
|
||||
EventRelay<Game, Events::InputCommand> m_EInputCommand;
|
||||
bool debugOnInputCommand(const Events::InputCommand& e);
|
||||
|
||||
void testIntialize();
|
||||
void testTick(double dt);
|
||||
void debugInitialize();
|
||||
void debugTick(double dt);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef PlayerSystem_h__
|
||||
#define PlayerSystem_h__
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glm/common.hpp>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/EventBroker.h"
|
||||
#include "Core/EKeyDown.h"
|
||||
#include "Core/EKeyUp.h"
|
||||
|
||||
struct KeyInput
|
||||
{
|
||||
bool Forward = false;
|
||||
bool Left = false;
|
||||
bool Back = false;
|
||||
bool Right = false;
|
||||
};
|
||||
|
||||
class PlayerSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
PlayerSystem(EventBroker* eventBroker)
|
||||
: PureSystem(eventBroker, "Player")
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &PlayerSystem::OnKeyDown);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &PlayerSystem::OnKeyUp);
|
||||
}
|
||||
|
||||
virtual void UpdateComponent(World* world, ComponentWrapper& player, double dt) override;
|
||||
|
||||
private:
|
||||
float m_Speed = 5;
|
||||
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,14 @@
|
||||
#include "Common.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
class RaptorCopterSystem : public System
|
||||
class RaptorCopterSystem : public PureSystem
|
||||
{
|
||||
public:
|
||||
RaptorCopterSystem(const EventBroker* eventBroker)
|
||||
: System(eventBroker, "RaptorCopter")
|
||||
RaptorCopterSystem(EventBroker* eventBroker)
|
||||
: PureSystem(eventBroker, "RaptorCopter")
|
||||
{ }
|
||||
|
||||
virtual void Update(World* world, ComponentWrapper& raptorCopter, double dt) override
|
||||
virtual void UpdateComponent(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"];
|
||||
|
||||
@@ -6,4 +6,5 @@ LoadMap=
|
||||
Fullscreen=false
|
||||
VSYNC=false
|
||||
Width=1280
|
||||
Height=720
|
||||
Height=720
|
||||
FOV=45
|
||||
@@ -0,0 +1,16 @@
|
||||
[Mouse]
|
||||
Sensitivity=0.5
|
||||
InvertPitch=false
|
||||
|
||||
[Bindings]
|
||||
MouseLeft=PrimaryFire
|
||||
MouseX=Yaw
|
||||
MouseY=Pitch
|
||||
W=+Forward
|
||||
S=-Forward
|
||||
D=+Right
|
||||
A=-Right
|
||||
R=Reload
|
||||
Space=Jump
|
||||
LeftControl=Crouch
|
||||
LeftShift=Sprint
|
||||
@@ -5,4 +5,5 @@
|
||||
<xs:include schemaLocation="Components/Model.xsd"/>
|
||||
<xs:include schemaLocation="Components/Test.xsd"/>
|
||||
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
|
||||
<xs:include schemaLocation="Components/Player.xsd"/>
|
||||
</xs:schema>
|
||||
@@ -0,0 +1,3 @@
|
||||
<c:Player>
|
||||
<Velocity X="0" Y="0" Z="0"/>
|
||||
</c:Player>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
|
||||
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
|
||||
|
||||
<xs:element name="Player">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Velocity" type="t:Vector" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -1,6 +0,0 @@
|
||||
<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>
|
||||
@@ -1,20 +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="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>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?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></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="0" Y="1" Z="0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>An error</Resource>
|
||||
</c:Model>
|
||||
</Components>
|
||||
</Entity>
|
||||
</Children>
|
||||
</Entity>
|
||||
@@ -31,6 +31,19 @@
|
||||
</c:Model>
|
||||
</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>
|
||||
</Components>
|
||||
</Entity>
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
@@ -48,7 +61,7 @@
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0"/>
|
||||
<Orientation X="0.0" Y="0" Z="0.0"/>
|
||||
<Orientation X="0.0" Y="0" Z="1.0"/>
|
||||
</c:Transform>
|
||||
<c:Model>
|
||||
<Resource>Models/Core/UnitRaptor.obj</Resource>
|
||||
@@ -59,8 +72,8 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0"/>
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
<Position X="-0.01" Y="0.55"/>
|
||||
<Orientation X="0" Y="0" Z="-1"/>
|
||||
</c:Transform>
|
||||
<c:RaptorCopter>
|
||||
<Speed>20</Speed>
|
||||
@@ -71,19 +84,7 @@
|
||||
<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"/>
|
||||
<Position X="0" Y="0"/>
|
||||
<Scale X="1.7" Y="0.03" Z="0.1"/>
|
||||
<Orientation X="0" Y="0" Z="0"/>
|
||||
</c:Transform>
|
||||
@@ -96,7 +97,7 @@
|
||||
<Entity>
|
||||
<Components>
|
||||
<c:Transform>
|
||||
<Position X="0" Y="0.6"/>
|
||||
<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>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<xs:element ref="c:Model" minOccurs="0"/>
|
||||
<xs:element ref="c:Test" minOccurs="0"/>
|
||||
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
|
||||
<xs:element ref="c:Player" minOccurs="0"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ out vec4 TextureFragment;
|
||||
|
||||
void main()
|
||||
{
|
||||
TextureFragment = vec4(PickingColor, 0, 1);
|
||||
TextureFragment = vec4(PickingColor/255, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#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,7 +60,6 @@ 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})
|
||||
|
||||
@@ -70,14 +69,24 @@ file(GLOB SOURCE_FILES_GUI
|
||||
)
|
||||
source_group(GUI FILES ${SOURCE_FILES_GUI})
|
||||
|
||||
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}
|
||||
#${SOURCE_FILES_Input}
|
||||
${SOURCE_FILES_Input}
|
||||
${SOURCE_FILES_Network}
|
||||
${SOURCE_FILES_GUI}
|
||||
${SOURCE_FILES_Rendering}
|
||||
${SOURCE_FILES_Rendering_Util}
|
||||
${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
|
||||
${SOURCE_FILES_Editor}
|
||||
)
|
||||
|
||||
set(LIBRARIES
|
||||
@@ -103,4 +112,4 @@ target_link_libraries(Engine
|
||||
${LIBRARIES}
|
||||
)
|
||||
#set_target_properties(Engine PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${INCLUDE_PATH}/PrecompiledHeader.h")
|
||||
#cotire(Engine)
|
||||
#cotire(Engine)
|
||||
|
||||
@@ -50,10 +50,16 @@ 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);
|
||||
m_Pool.Free(wrapper.Data - sizeof(EntityID));
|
||||
}
|
||||
|
||||
ComponentPool::iterator ComponentPool::begin() const
|
||||
|
||||
@@ -24,8 +24,11 @@ ConfigFile::ConfigFile(std::string path)
|
||||
if (boost::filesystem::exists(m_Path)) {
|
||||
try {
|
||||
boost::property_tree::ini_parser::read_ini(m_Path.string(), m_PTreeOverrides);
|
||||
for (auto& node : m_PTreeOverrides) {
|
||||
m_PTreeMerged.put_child(node.first, node.second);
|
||||
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);
|
||||
}
|
||||
}
|
||||
} catch (boost::property_tree::ptree_error& e) {
|
||||
LOG_ERROR("Failed to parse \"%s\":\n%s", m_Path.filename().string().c_str(), e.what());
|
||||
|
||||
@@ -415,6 +415,7 @@ std::size_t EntityXMLFile::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) },
|
||||
@@ -443,39 +444,52 @@ void EntityXMLFile::writeData(const xercesc::DOMElement* element, std::string ty
|
||||
{
|
||||
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 {
|
||||
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 (typeName == "float") {
|
||||
XSValue::Status status;
|
||||
XSValue* val = XSValue::getActualValue(element->getTextContent(), dataType, status);
|
||||
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue), getTypeStride(typeName));
|
||||
XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_float, status);
|
||||
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue.f_float), getTypeStride(typeName));
|
||||
} else if (typeName == "double") {
|
||||
XSValue::Status status;
|
||||
XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_double, status);
|
||||
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue.f_double), getTypeStride(typeName));
|
||||
} else if (typeName == "bool") {
|
||||
XSValue::Status status;
|
||||
XSValue* val = XSValue::getActualValue(element->getTextContent(), xercesc::XSValue::DataType::dt_boolean, status);
|
||||
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue.f_bool), getTypeStride(typeName));
|
||||
} else {
|
||||
XSValue::DataType dataType = XSValue::getDataType(XSTR(typeName.c_str()));
|
||||
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));
|
||||
LOG_WARNING("Unknown native data type: %s", typeName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
#include "Core/InputManager.h"
|
||||
|
||||
std::vector<unsigned int> InputManager::GLFWCharCallbackQueue;
|
||||
std::vector<std::pair<double, double>> InputManager::GLFWScrollCallbackQueue;
|
||||
|
||||
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);
|
||||
|
||||
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse);
|
||||
@@ -36,6 +41,15 @@ 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);
|
||||
@@ -73,6 +87,14 @@ 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();
|
||||
|
||||
// // Lock mouse while holding LMB
|
||||
// if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT])
|
||||
// {
|
||||
@@ -196,6 +218,17 @@ void InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
bool InputManager::OnLockMouse(const Events::LockMouse &event)
|
||||
{
|
||||
m_MouseLocked = true;
|
||||
|
||||
@@ -100,7 +100,7 @@ Resource* ResourceManager::Load(std::string resourceType, std::string resourceNa
|
||||
LOG_WARNING("Hot-loading resource \"%s\"", resourceName.c_str());
|
||||
}
|
||||
|
||||
return CreateResource(resourceType, resourceName, parent);
|
||||
return CreateResource(resourceType, resourceName, parent);
|
||||
}
|
||||
|
||||
Resource* ResourceManager::CreateResource(std::string resourceType, std::string resourceName, Resource* parent)
|
||||
@@ -112,10 +112,16 @@ Resource* ResourceManager::CreateResource(std::string resourceType, std::string
|
||||
}
|
||||
|
||||
// Call the factory function
|
||||
Resource* resource = facIt->second(resourceName);
|
||||
// Store IDs
|
||||
resource->TypeID = GetTypeID(resourceType);
|
||||
resource->ResourceID = GetNewResourceID(resource->TypeID);
|
||||
Resource* resource;
|
||||
try {
|
||||
resource = facIt->second(resourceName);
|
||||
// Store IDs
|
||||
resource->TypeID = GetTypeID(resourceType);
|
||||
resource->ResourceID = GetNewResourceID(resource->TypeID);
|
||||
} catch (const std::exception& e) {
|
||||
resource = nullptr;
|
||||
LOG_ERROR("Failed to load resource \"%s\" of type \"%s\": %s", resourceName.c_str(), resourceType.c_str(), e.what());
|
||||
}
|
||||
// Cache
|
||||
m_ResourceCache[std::make_pair(resourceType, resourceName)] = resource;
|
||||
m_ResourceFromName[resourceName] = resource;
|
||||
|
||||
@@ -11,12 +11,43 @@ EntityID World::CreateEntity(EntityID parent /*= 0*/)
|
||||
{
|
||||
EntityID newEntity = generateEntityID();
|
||||
m_EntityParents[newEntity] = parent;
|
||||
if (parent != 0) {
|
||||
m_EntityChildren.insert(std::make_pair(parent, newEntity));
|
||||
}
|
||||
m_EntityChildren.insert(std::make_pair(parent, newEntity));
|
||||
return newEntity;
|
||||
}
|
||||
|
||||
|
||||
void World::DeleteEntity(EntityID entity)
|
||||
{
|
||||
// Delete components
|
||||
for (auto& pair : m_ComponentPools) {
|
||||
auto& pool = pair.second;
|
||||
if (pool->KnowsEntity(entity)) {
|
||||
auto& c = pool->GetByEntity(entity);
|
||||
pool->Delete(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through children
|
||||
std::vector<EntityID> childrenToDelete;
|
||||
auto children = m_EntityChildren.equal_range(entity);
|
||||
for (auto it = children.first; it != children.second; ++it) {
|
||||
childrenToDelete.push_back(it->second);
|
||||
}
|
||||
for (auto& child : childrenToDelete) {
|
||||
DeleteEntity(child);
|
||||
}
|
||||
|
||||
EntityID parent = m_EntityParents.at(entity);
|
||||
m_EntityParents.erase(entity);
|
||||
auto parentChildren = m_EntityChildren.equal_range(parent);
|
||||
for (auto it = parentChildren.first; it != parentChildren.second; ++it) {
|
||||
if (it->second == entity) {
|
||||
m_EntityChildren.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void World::RegisterComponent(ComponentInfo& ci)
|
||||
{
|
||||
m_ComponentPools[ci.Name] = new ComponentPool(ci);
|
||||
@@ -35,12 +66,27 @@ ComponentWrapper World::AttachComponent(EntityID entity, std::string componentTy
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
bool World::HasComponent(EntityID entity, std::string componentType)
|
||||
{
|
||||
ComponentPool* pool = m_ComponentPools.at(componentType);
|
||||
return pool->KnowsEntity(entity);
|
||||
}
|
||||
|
||||
ComponentWrapper World::GetComponent(EntityID entity, std::string componentType)
|
||||
{
|
||||
ComponentPool* pool = m_ComponentPools.at(componentType);
|
||||
return pool->GetByEntity(entity);
|
||||
}
|
||||
|
||||
|
||||
void World::DeleteComponent(EntityID entity, std::string componentType)
|
||||
{
|
||||
ComponentPool* pool = m_ComponentPools.at(componentType);
|
||||
ComponentWrapper c = pool->GetByEntity(entity);
|
||||
return pool->Delete(c);
|
||||
}
|
||||
|
||||
const ComponentPool* World::GetComponents(std::string componentType)
|
||||
{
|
||||
auto it = m_ComponentPools.find(componentType);
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
#include "Editor/EditorSystem.h"
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include <imgui/imgui_internal.h>
|
||||
|
||||
EditorSystem::EditorSystem(EventBroker* eventBroker)
|
||||
: ImpureSystem(eventBroker)
|
||||
{
|
||||
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
m_Enabled = config->Get<bool>("Debug.EditorEnabled", false);
|
||||
m_Visible = m_Enabled;
|
||||
|
||||
if (!m_Enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystem::OnInputCommand);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EPicking, &EditorSystem::OnPicking);
|
||||
}
|
||||
|
||||
void EditorSystem::Update(World* world, double dt)
|
||||
{
|
||||
if (!m_Enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Widget == 0) {
|
||||
m_Widget = world->CreateEntity();
|
||||
world->AttachComponent(m_Widget, "Transform");
|
||||
auto& model = world->AttachComponent(m_Widget, "Model");
|
||||
model["Resource"] = "Models/TranslationWidget.obj";
|
||||
}
|
||||
|
||||
if (m_Selection != m_LastSelection) {
|
||||
|
||||
}
|
||||
|
||||
auto& widgetModel = world->GetComponent(m_Widget, "Model");
|
||||
widgetModel["Visible"] = m_Visible;
|
||||
if (m_Selection != 0) {
|
||||
if (world->HasComponent(m_Selection, "Transform")) {
|
||||
glm::vec3 pos = RenderQueueFactory::AbsolutePosition(world, m_Selection);
|
||||
auto widgetTransform = world->GetComponent(m_Widget, "Transform");
|
||||
widgetTransform["Position"] = pos;
|
||||
} else {
|
||||
m_Selection = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_Visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
drawUI(world, dt);
|
||||
}
|
||||
|
||||
|
||||
bool EditorSystem::OnInputCommand(const Events::InputCommand& e)
|
||||
{
|
||||
if (e.Command == "ToggleEditor" && e.Value > 0) {
|
||||
m_Visible = !m_Visible;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorSystem::OnMousePress(const Events::MousePress& e)
|
||||
{
|
||||
if (e.Button == GLFW_MOUSE_BUTTON_RIGHT) {
|
||||
m_PickingQueue.push_back(glm::vec2((int)e.X, (int)e.Y));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EditorSystem::OnPicking(const Events::Picking& e)
|
||||
{
|
||||
for (auto& pos : m_PickingQueue) {
|
||||
auto result = e.Pick(pos);
|
||||
LOG_INFO("Selected %i", result.Entity);
|
||||
m_Selection = result.Entity;
|
||||
}
|
||||
m_PickingQueue.clear();
|
||||
return true;
|
||||
};
|
||||
|
||||
void EditorSystem::drawUI(World* world, double dt)
|
||||
{
|
||||
ImGui::ShowTestWindow();
|
||||
//ImGui::ShowStyleEditor();
|
||||
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
|
||||
if (ImGui::MenuItem("New")) { }
|
||||
if (ImGui::MenuItem("Open", "Ctrl+O")) { }
|
||||
if (ImGui::MenuItem("Save", "Ctrl+S")) { }
|
||||
if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) { }
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Close Editor", "F1")) { }
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Move")) {
|
||||
auto& model = world->GetComponent(m_Widget, "Model");
|
||||
model["Resource"] = "Models/TranslationWidget.obj";
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Rotate")) {
|
||||
auto& model = world->GetComponent(m_Widget, "Model");
|
||||
model["Resource"] = "Models/RotationWidget.obj";
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Scale")) {
|
||||
auto& model = world->GetComponent(m_Widget, "Model");
|
||||
model["Resource"] = "Models/ScaleWidget.obj";
|
||||
}
|
||||
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
|
||||
if (ImGui::Begin("Components")) {
|
||||
if (m_Selection != 0) {
|
||||
auto& pools = world->GetComponentPools();
|
||||
|
||||
std::vector<const char*> componentTypes;
|
||||
for (auto& pair : pools) {
|
||||
// Only add components the entity doesn't already have
|
||||
if (!pair.second->KnowsEntity(m_Selection)) {
|
||||
componentTypes.push_back(pair.first.c_str());
|
||||
}
|
||||
}
|
||||
int item = -1;
|
||||
ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth() - 5.f);
|
||||
if (ImGui::Combo("", &item, componentTypes.data(), componentTypes.size())) {
|
||||
if (item != -1) {
|
||||
std::string chosenType = std::string(componentTypes.at(item));
|
||||
world->AttachComponent(m_Selection, chosenType);
|
||||
}
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
for (auto& pair : pools) {
|
||||
const std::string& componentType = pair.first;
|
||||
auto pool = pair.second;
|
||||
if (!pool->KnowsEntity(m_Selection)) {
|
||||
continue;
|
||||
}
|
||||
auto& ci = pool->ComponentInfo();
|
||||
|
||||
bool deletePressed = createDeleteButton(componentType);
|
||||
if (deletePressed) {
|
||||
world->DeleteComponent(m_Selection, componentType);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader(componentType.c_str())) {
|
||||
if (!ci.Meta.Annotation.empty()) {
|
||||
ImGui::Text(ci.Meta.Annotation.c_str());
|
||||
}
|
||||
|
||||
auto& component = world->GetComponent(m_Selection, componentType);
|
||||
for (auto& pair : ci.FieldTypes) {
|
||||
const std::string& field = pair.first;
|
||||
const std::string& type = pair.second;
|
||||
|
||||
if (type == "Vector") {
|
||||
auto& val = component.Property<glm::vec3>(field);
|
||||
if (field == "Scale") {
|
||||
ImGui::DragFloat3(field.c_str(), glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
|
||||
} else if (field == "Orientation") {
|
||||
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
|
||||
if (ImGui::SliderFloat3(field.c_str(), glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
|
||||
val = tempVal;
|
||||
}
|
||||
} else {
|
||||
ImGui::DragFloat3(field.c_str(), glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
|
||||
}
|
||||
} else if (type == "Color") {
|
||||
auto& val = component.Property<glm::vec4>(field);
|
||||
ImGui::ColorEdit4(field.c_str(), glm::value_ptr(val), true);
|
||||
} else if (type == "string") {
|
||||
std::string& val = component.Property<std::string>(field);
|
||||
char tempString[1024];
|
||||
memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString)));
|
||||
if (ImGui::InputText(field.c_str(), tempString, sizeof(tempString))) {
|
||||
val = std::string(tempString);
|
||||
LOG_DEBUG("%s::%s changed!", componentType.c_str(), field.c_str());
|
||||
}
|
||||
} else if (type == "double") {
|
||||
float tempVal = static_cast<float>(component.Property<double>(field));
|
||||
if (ImGui::InputFloat(field.c_str(), &tempVal, 0.01f, 1.f)) {
|
||||
component.SetProperty(field, static_cast<double>(tempVal));
|
||||
}
|
||||
} else if (type == "bool") {
|
||||
auto& val = component.Property<bool>(field);
|
||||
ImGui::Checkbox(field.c_str(), &val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
if (ImGui::Begin("Entitites")) {
|
||||
auto entityChildren = world->GetEntityChildren();
|
||||
std::function<void(EntityID)> recurse = [&](EntityID parent) {
|
||||
auto range = entityChildren.equal_range(parent);
|
||||
for (auto it = range.first; it != range.second; it++) {
|
||||
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once);
|
||||
if (ImGui::TreeNode((std::string("#") + std::to_string(it->second)).c_str())) {
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(0)) {
|
||||
m_Selection = it->second;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Add")) {
|
||||
EntityID entity = world->CreateEntity(it->second);
|
||||
world->AttachComponent(entity, "Transform");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Delete")) {
|
||||
world->DeleteEntity(it->second);
|
||||
}
|
||||
recurse(it->second);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
};
|
||||
recurse(0);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
bool EditorSystem::createDeleteButton(std::string componentType)
|
||||
{
|
||||
float width = ImGui::GetContentRegionAvailWidth();
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
auto pos = ImGui::GetCursorScreenPos() + ImVec2(width - 14.f, 1);
|
||||
ImRect bb = ImRect(pos, pos + ImVec2(14.f, 14.f));
|
||||
std::string idString = "#DELETE";
|
||||
idString += componentType;
|
||||
ImGuiID id = window->GetID(idString.c_str());
|
||||
bool hovered;
|
||||
bool held;
|
||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held);
|
||||
//ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton);
|
||||
ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||
window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16);
|
||||
return pressed;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
#include "Input/InputProxy.h"
|
||||
#include "Input/InputHandler.h"
|
||||
|
||||
InputProxy::InputProxy(EventBroker* eventBroker)
|
||||
: m_EventBroker(eventBroker)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EBindOrigin, &InputProxy::OnBindOrigin);
|
||||
}
|
||||
|
||||
InputProxy::~InputProxy()
|
||||
{
|
||||
for (auto& handler : m_Handlers) {
|
||||
delete handler;
|
||||
}
|
||||
}
|
||||
|
||||
void InputProxy::LoadBindings(std::string file)
|
||||
{
|
||||
auto config = ResourceManager::Load<ConfigFile>(file);
|
||||
for (auto& origin : config->GetAll<std::string>("Bindings")) {
|
||||
Events::BindOrigin e;
|
||||
e.Origin = origin.first;
|
||||
e.Command = origin.second;
|
||||
e.Value = 1.f;
|
||||
if (!e.Command.empty()) {
|
||||
char prefix = e.Command.at(0);
|
||||
if (prefix == '+' || prefix == '-') {
|
||||
e.Command = e.Command.substr(1);
|
||||
if (prefix == '-') {
|
||||
e.Value *= -1.f;
|
||||
}
|
||||
}
|
||||
OnBindOrigin(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputProxy::Update(double dt)
|
||||
{
|
||||
m_EventBroker->Process<InputProxy>();
|
||||
m_EventBroker->Process<InputHandler>();
|
||||
for (auto& handler : m_Handlers) {
|
||||
handler->Update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
void InputProxy::Process()
|
||||
{
|
||||
for (auto& pair : m_CommandHandlers) {
|
||||
const std::string& command = pair.first;
|
||||
auto handlers = pair.second;
|
||||
m_CurrentCommandValues[command] = 0.f;
|
||||
for (auto& handler : handlers) {
|
||||
m_CurrentCommandValues[command] += handler->GetCommandValue(command);
|
||||
}
|
||||
|
||||
auto last = m_LastCommandValues.find(command);
|
||||
float currentValue = m_CurrentCommandValues[command];
|
||||
if (last == m_LastCommandValues.end() || last->second != currentValue) {
|
||||
Events::InputCommand e;
|
||||
e.PlayerID = -1;
|
||||
e.Command = command;
|
||||
e.Value = currentValue;
|
||||
m_EventBroker->Publish(e);
|
||||
LOG_DEBUG("Input: Published command %s=%f for player %i", e.Command.c_str(), e.Value, e.PlayerID);
|
||||
m_LastCommandValues[command] = currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
void InputProxy::Publish(const Events::InputCommand& e)
|
||||
{
|
||||
auto key = std::make_pair(e.PlayerID, e.Command);
|
||||
m_CommandQueue[key].push_back(e.Value);
|
||||
}
|
||||
|
||||
bool InputProxy::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) {
|
||||
m_CommandHandlers[e.Command].insert(handler);
|
||||
m_LastCommandValues[e.Command] = 0.f;
|
||||
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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
#include "Input/KeyboardInputHandler.h"
|
||||
|
||||
KeyboardInputHandler::KeyboardInputHandler(EventBroker* eventBroker, InputProxy* inputProxy) : InputHandler(eventBroker, inputProxy)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &KeyboardInputHandler::OnKeyDown);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &KeyboardInputHandler::OnKeyUp);
|
||||
|
||||
m_OriginKeyCodes["Space"] = GLFW_KEY_SPACE;
|
||||
m_OriginKeyCodes["Apostrophe"] = GLFW_KEY_APOSTROPHE;
|
||||
m_OriginKeyCodes["Comma"] = GLFW_KEY_COMMA;
|
||||
m_OriginKeyCodes["Minus"] = GLFW_KEY_MINUS;
|
||||
m_OriginKeyCodes["Period"] = GLFW_KEY_PERIOD;
|
||||
m_OriginKeyCodes["Slash"] = GLFW_KEY_SLASH;
|
||||
m_OriginKeyCodes["0"] = GLFW_KEY_0;
|
||||
m_OriginKeyCodes["1"] = GLFW_KEY_1;
|
||||
m_OriginKeyCodes["2"] = GLFW_KEY_2;
|
||||
m_OriginKeyCodes["3"] = GLFW_KEY_3;
|
||||
m_OriginKeyCodes["4"] = GLFW_KEY_4;
|
||||
m_OriginKeyCodes["5"] = GLFW_KEY_5;
|
||||
m_OriginKeyCodes["6"] = GLFW_KEY_6;
|
||||
m_OriginKeyCodes["7"] = GLFW_KEY_7;
|
||||
m_OriginKeyCodes["8"] = GLFW_KEY_8;
|
||||
m_OriginKeyCodes["9"] = GLFW_KEY_9;
|
||||
m_OriginKeyCodes["Semicolon"] = GLFW_KEY_SEMICOLON;
|
||||
m_OriginKeyCodes["Equal"] = GLFW_KEY_EQUAL;
|
||||
m_OriginKeyCodes["A"] = GLFW_KEY_A;
|
||||
m_OriginKeyCodes["B"] = GLFW_KEY_B;
|
||||
m_OriginKeyCodes["C"] = GLFW_KEY_C;
|
||||
m_OriginKeyCodes["D"] = GLFW_KEY_D;
|
||||
m_OriginKeyCodes["E"] = GLFW_KEY_E;
|
||||
m_OriginKeyCodes["F"] = GLFW_KEY_F;
|
||||
m_OriginKeyCodes["G"] = GLFW_KEY_G;
|
||||
m_OriginKeyCodes["H"] = GLFW_KEY_H;
|
||||
m_OriginKeyCodes["I"] = GLFW_KEY_I;
|
||||
m_OriginKeyCodes["J"] = GLFW_KEY_J;
|
||||
m_OriginKeyCodes["K"] = GLFW_KEY_K;
|
||||
m_OriginKeyCodes["L"] = GLFW_KEY_L;
|
||||
m_OriginKeyCodes["M"] = GLFW_KEY_M;
|
||||
m_OriginKeyCodes["N"] = GLFW_KEY_N;
|
||||
m_OriginKeyCodes["O"] = GLFW_KEY_O;
|
||||
m_OriginKeyCodes["P"] = GLFW_KEY_P;
|
||||
m_OriginKeyCodes["Q"] = GLFW_KEY_Q;
|
||||
m_OriginKeyCodes["R"] = GLFW_KEY_R;
|
||||
m_OriginKeyCodes["S"] = GLFW_KEY_S;
|
||||
m_OriginKeyCodes["T"] = GLFW_KEY_T;
|
||||
m_OriginKeyCodes["U"] = GLFW_KEY_U;
|
||||
m_OriginKeyCodes["V"] = GLFW_KEY_V;
|
||||
m_OriginKeyCodes["W"] = GLFW_KEY_W;
|
||||
m_OriginKeyCodes["X"] = GLFW_KEY_X;
|
||||
m_OriginKeyCodes["Y"] = GLFW_KEY_Y;
|
||||
m_OriginKeyCodes["Z"] = GLFW_KEY_Z;
|
||||
m_OriginKeyCodes["LeftBracket"] = GLFW_KEY_LEFT_BRACKET;
|
||||
m_OriginKeyCodes["Backslash"] = GLFW_KEY_BACKSLASH;
|
||||
m_OriginKeyCodes["RightBracket"] = GLFW_KEY_RIGHT_BRACKET;
|
||||
m_OriginKeyCodes["Accent"] = GLFW_KEY_GRAVE_ACCENT;
|
||||
m_OriginKeyCodes["W1"] = GLFW_KEY_WORLD_1;
|
||||
m_OriginKeyCodes["W2"] = GLFW_KEY_WORLD_2;
|
||||
m_OriginKeyCodes["Escape"] = GLFW_KEY_ESCAPE;
|
||||
m_OriginKeyCodes["Enter"] = GLFW_KEY_ENTER;
|
||||
m_OriginKeyCodes["Tab"] = GLFW_KEY_TAB;
|
||||
m_OriginKeyCodes["Backspace"] = GLFW_KEY_BACKSPACE;
|
||||
m_OriginKeyCodes["Insert"] = GLFW_KEY_INSERT;
|
||||
m_OriginKeyCodes["Delete"] = GLFW_KEY_DELETE;
|
||||
m_OriginKeyCodes["Right"] = GLFW_KEY_RIGHT;
|
||||
m_OriginKeyCodes["Left"] = GLFW_KEY_LEFT;
|
||||
m_OriginKeyCodes["Down"] = GLFW_KEY_DOWN;
|
||||
m_OriginKeyCodes["Up"] = GLFW_KEY_UP;
|
||||
m_OriginKeyCodes["PgUp"] = GLFW_KEY_PAGE_UP;
|
||||
m_OriginKeyCodes["PgDn"] = GLFW_KEY_PAGE_DOWN;
|
||||
m_OriginKeyCodes["Home"] = GLFW_KEY_HOME;
|
||||
m_OriginKeyCodes["End"] = GLFW_KEY_END;
|
||||
m_OriginKeyCodes["CapsLock"] = GLFW_KEY_CAPS_LOCK;
|
||||
m_OriginKeyCodes["ScrollLock"] = GLFW_KEY_SCROLL_LOCK;
|
||||
m_OriginKeyCodes["NumLock"] = GLFW_KEY_NUM_LOCK;
|
||||
m_OriginKeyCodes["PrintScreen"] = GLFW_KEY_PRINT_SCREEN;
|
||||
m_OriginKeyCodes["Pause"] = GLFW_KEY_PAUSE;
|
||||
m_OriginKeyCodes["F1"] = GLFW_KEY_F1;
|
||||
m_OriginKeyCodes["F2"] = GLFW_KEY_F2;
|
||||
m_OriginKeyCodes["F3"] = GLFW_KEY_F3;
|
||||
m_OriginKeyCodes["F4"] = GLFW_KEY_F4;
|
||||
m_OriginKeyCodes["F5"] = GLFW_KEY_F5;
|
||||
m_OriginKeyCodes["F6"] = GLFW_KEY_F6;
|
||||
m_OriginKeyCodes["F7"] = GLFW_KEY_F7;
|
||||
m_OriginKeyCodes["F8"] = GLFW_KEY_F8;
|
||||
m_OriginKeyCodes["F9"] = GLFW_KEY_F9;
|
||||
m_OriginKeyCodes["F10"] = GLFW_KEY_F10;
|
||||
m_OriginKeyCodes["F11"] = GLFW_KEY_F11;
|
||||
m_OriginKeyCodes["F12"] = GLFW_KEY_F12;
|
||||
m_OriginKeyCodes["F13"] = GLFW_KEY_F13;
|
||||
m_OriginKeyCodes["F14"] = GLFW_KEY_F14;
|
||||
m_OriginKeyCodes["F15"] = GLFW_KEY_F15;
|
||||
m_OriginKeyCodes["F16"] = GLFW_KEY_F16;
|
||||
m_OriginKeyCodes["F17"] = GLFW_KEY_F17;
|
||||
m_OriginKeyCodes["F18"] = GLFW_KEY_F18;
|
||||
m_OriginKeyCodes["F19"] = GLFW_KEY_F19;
|
||||
m_OriginKeyCodes["F20"] = GLFW_KEY_F20;
|
||||
m_OriginKeyCodes["F21"] = GLFW_KEY_F21;
|
||||
m_OriginKeyCodes["F22"] = GLFW_KEY_F22;
|
||||
m_OriginKeyCodes["F23"] = GLFW_KEY_F23;
|
||||
m_OriginKeyCodes["F24"] = GLFW_KEY_F24;
|
||||
m_OriginKeyCodes["F25"] = GLFW_KEY_F25;
|
||||
m_OriginKeyCodes["KP0"] = GLFW_KEY_KP_0;
|
||||
m_OriginKeyCodes["KP1"] = GLFW_KEY_KP_1;
|
||||
m_OriginKeyCodes["KP2"] = GLFW_KEY_KP_2;
|
||||
m_OriginKeyCodes["KP3"] = GLFW_KEY_KP_3;
|
||||
m_OriginKeyCodes["KP4"] = GLFW_KEY_KP_4;
|
||||
m_OriginKeyCodes["KP5"] = GLFW_KEY_KP_5;
|
||||
m_OriginKeyCodes["KP6"] = GLFW_KEY_KP_6;
|
||||
m_OriginKeyCodes["KP7"] = GLFW_KEY_KP_7;
|
||||
m_OriginKeyCodes["KP8"] = GLFW_KEY_KP_8;
|
||||
m_OriginKeyCodes["KP9"] = GLFW_KEY_KP_9;
|
||||
m_OriginKeyCodes["KPDecimal"] = GLFW_KEY_KP_DECIMAL;
|
||||
m_OriginKeyCodes["KPDivide"] = GLFW_KEY_KP_DIVIDE;
|
||||
m_OriginKeyCodes["KPMultiply"] = GLFW_KEY_KP_MULTIPLY;
|
||||
m_OriginKeyCodes["KPSubtract"] = GLFW_KEY_KP_SUBTRACT;
|
||||
m_OriginKeyCodes["KPAdd"] = GLFW_KEY_KP_ADD;
|
||||
m_OriginKeyCodes["KPEnter"] = GLFW_KEY_KP_ENTER;
|
||||
m_OriginKeyCodes["KPEqual"] = GLFW_KEY_KP_EQUAL;
|
||||
m_OriginKeyCodes["LeftShift"] = GLFW_KEY_LEFT_SHIFT;
|
||||
m_OriginKeyCodes["LeftControl"] = GLFW_KEY_LEFT_CONTROL;
|
||||
m_OriginKeyCodes["LeftAlt"] = GLFW_KEY_LEFT_ALT;
|
||||
m_OriginKeyCodes["LeftSuper"] = GLFW_KEY_LEFT_SUPER;
|
||||
m_OriginKeyCodes["RightShift"] = GLFW_KEY_RIGHT_SHIFT;
|
||||
m_OriginKeyCodes["RightControl"] = GLFW_KEY_RIGHT_CONTROL;
|
||||
m_OriginKeyCodes["RightAlt"] = GLFW_KEY_RIGHT_ALT;
|
||||
m_OriginKeyCodes["RightSuper"] = GLFW_KEY_RIGHT_SUPER;
|
||||
m_OriginKeyCodes["Menu"] = GLFW_KEY_MENU;
|
||||
}
|
||||
|
||||
bool KeyboardInputHandler::BindOrigin(std::string origin, std::string command, float value)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
bool KeyboardInputHandler::OnKeyDown(const Events::KeyDown& e)
|
||||
{
|
||||
auto it = m_KeyBindings.find(e.KeyCode);
|
||||
if (it == m_KeyBindings.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string command;
|
||||
float value;
|
||||
std::tie(command, value) = it->second;
|
||||
m_CommandValues[command] += value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KeyboardInputHandler::OnKeyUp(const Events::KeyUp& e)
|
||||
{
|
||||
auto it = m_KeyBindings.find(e.KeyCode);
|
||||
if (it == m_KeyBindings.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string command;
|
||||
float value;
|
||||
std::tie(command, value) = it->second;
|
||||
m_CommandValues[command] -= value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float KeyboardInputHandler::GetCommandValue(std::string command)
|
||||
{
|
||||
auto it = m_CommandValues.find(command);
|
||||
if (it != m_CommandValues.end()) {
|
||||
return m_CommandValues[command];
|
||||
} else {
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
#include "Input/MouseInputHandler.h"
|
||||
|
||||
MouseInputHandler::MouseInputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
|
||||
: InputHandler(eventBroker, inputProxy)
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &MouseInputHandler::OnMousePress);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &MouseInputHandler::OnMouseRelease);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &MouseInputHandler::OnMouseMove);
|
||||
|
||||
m_OriginCodes["Mouse1"] = GLFW_MOUSE_BUTTON_1;
|
||||
m_OriginCodes["MouseLeft"] = GLFW_MOUSE_BUTTON_LEFT;
|
||||
m_OriginCodes["Mouse2"] = GLFW_MOUSE_BUTTON_2;
|
||||
m_OriginCodes["MouseRight"] = GLFW_MOUSE_BUTTON_RIGHT;
|
||||
m_OriginCodes["Mouse3"] = GLFW_MOUSE_BUTTON_3;
|
||||
m_OriginCodes["MouseMiddle"] = GLFW_MOUSE_BUTTON_MIDDLE;
|
||||
m_OriginCodes["Mouse4"] = GLFW_MOUSE_BUTTON_4;
|
||||
m_OriginCodes["Mouse5"] = GLFW_MOUSE_BUTTON_5;
|
||||
m_OriginCodes["Mouse6"] = GLFW_MOUSE_BUTTON_6;
|
||||
m_OriginCodes["Mouse7"] = GLFW_MOUSE_BUTTON_7;
|
||||
m_OriginCodes["Mouse8"] = GLFW_MOUSE_BUTTON_8;
|
||||
|
||||
m_OriginAxes["MouseX"] = 'X';
|
||||
m_OriginAxes["MouseY"] = 'Y';
|
||||
}
|
||||
|
||||
bool MouseInputHandler::BindOrigin(std::string origin, std::string command, float value)
|
||||
{
|
||||
auto originCode = m_OriginCodes.find(origin);
|
||||
if (originCode != m_OriginCodes.end()) {
|
||||
int code = originCode->second;
|
||||
m_Bindings[code] = std::make_tuple(command, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto originAxis = m_OriginAxes.find(origin);
|
||||
if (originAxis != m_OriginAxes.end()) {
|
||||
char axis = originAxis->second;
|
||||
float multiplier = 1.f;
|
||||
// Sensitivity
|
||||
multiplier *= ResourceManager::Load<ConfigFile>("Input.ini")->Get<float>("Mouse.Sensitivity", 1.f);
|
||||
if (axis == 'Y') {
|
||||
if (ResourceManager::Load<ConfigFile>("Input.ini")->Get<bool>("Mouse.InvertPitch", false)) {
|
||||
multiplier *= -1.f;
|
||||
}
|
||||
}
|
||||
m_Axes[axis] = std::make_tuple(command, value * multiplier);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float MouseInputHandler::GetCommandValue(std::string command)
|
||||
{
|
||||
auto it = m_CommandValues.find(command);
|
||||
if (it != m_CommandValues.end()) {
|
||||
return m_CommandValues[command];
|
||||
} else {
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
bool MouseInputHandler::OnMousePress(const Events::MousePress& e)
|
||||
{
|
||||
auto it = m_Bindings.find(e.Button);
|
||||
if (it == m_Bindings.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string command;
|
||||
float value;
|
||||
std::tie(command, value) = it->second;
|
||||
m_CommandValues[command] += value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MouseInputHandler::OnMouseRelease(const Events::MouseRelease& e)
|
||||
{
|
||||
auto it = m_Bindings.find(e.Button);
|
||||
if (it == m_Bindings.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string command;
|
||||
float value;
|
||||
std::tie(command, value) = it->second;
|
||||
m_CommandValues[command] -= value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MouseInputHandler::OnMouseMove(const Events::MouseMove& e)
|
||||
{
|
||||
if (std::abs(e.DeltaX) > 0) {
|
||||
auto it = m_Axes.find('X');
|
||||
if (it != m_Axes.end()) {
|
||||
Events::InputCommand ic;
|
||||
ic.PlayerID = -1;
|
||||
std::tie(ic.Command, ic.Value) = it->second;
|
||||
ic.Value *= e.DeltaX;
|
||||
m_InputProxy->Publish(ic);
|
||||
}
|
||||
}
|
||||
|
||||
if (std::abs(e.DeltaY) > 0) {
|
||||
auto it = m_Axes.find('Y');
|
||||
if (it != m_Axes.end()) {
|
||||
Events::InputCommand ic;
|
||||
ic.PlayerID = -1;
|
||||
std::tie(ic.Command, ic.Value) = it->second;
|
||||
ic.Value *= e.DeltaY;
|
||||
m_InputProxy->Publish(ic);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MouseInputHandler::hasOrigin(std::string origin)
|
||||
{
|
||||
if (m_OriginCodes.find(origin) == m_OriginCodes.end()) {
|
||||
return false;
|
||||
}
|
||||
if (m_OriginAxes.find(origin) == m_OriginAxes.end()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "Rendering/DrawScenePass.h"
|
||||
|
||||
DrawScenePass::DrawScenePass(IRenderer* renderer)
|
||||
{
|
||||
m_Renderer = renderer;
|
||||
InitializeTextures();
|
||||
InitializeShaderPrograms();
|
||||
}
|
||||
|
||||
void DrawScenePass::InitializeTextures()
|
||||
{
|
||||
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
||||
}
|
||||
|
||||
void DrawScenePass::InitializeShaderPrograms()
|
||||
{
|
||||
//Gör så att shaders är en resource, tex som texture classen. Konstruktorn måste vara privat.
|
||||
m_BasicForwardProgram = ResourceManager::Load<ShaderProgram>("#BasicForwardProgram");
|
||||
|
||||
m_BasicForwardProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/BasicForward.vert.glsl")));
|
||||
m_BasicForwardProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/BasicForward.frag.glsl")));
|
||||
m_BasicForwardProgram->Compile();
|
||||
m_BasicForwardProgram->Link();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void DrawScenePass::Draw(RenderQueueCollection& rq)
|
||||
{
|
||||
//glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
GLERROR("Renderer::Draw PickingPass");
|
||||
|
||||
DrawScenePassState state;
|
||||
|
||||
|
||||
//TODO: Render: Add code for more jobs than modeljobs.
|
||||
for (auto &job : rq.Forward) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
if (modelJob) {
|
||||
GLuint ShaderHandle = m_BasicForwardProgram->GetHandle();
|
||||
|
||||
m_BasicForwardProgram->Bind();
|
||||
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix()));
|
||||
glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
|
||||
|
||||
//TODO: Renderer: bättre textur felhantering samt fler texturer stöd
|
||||
if (modelJob->DiffuseTexture != nullptr) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture);
|
||||
} else {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
GLERROR("DrawScene Error");
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "Rendering/DrawScenePassState.h"
|
||||
|
||||
|
||||
DrawScenePassState::DrawScenePassState()
|
||||
{
|
||||
GLERROR("---");
|
||||
BindFramebuffer(0);
|
||||
GLERROR("---");
|
||||
Enable(GL_DEPTH_TEST);
|
||||
Enable(GL_CULL_FACE);
|
||||
ClearColor(glm::vec4(255.f / 255, 163.f / 255, 176.f / 255, 0.f));
|
||||
Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
DrawScenePassState::~DrawScenePassState()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -48,13 +48,21 @@ void FrameBuffer::Generate()
|
||||
switch ((*it)->m_ResourceType) {
|
||||
case GL_TEXTURE_2D:
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle, 0);
|
||||
GLERROR("FrameBuffer generate: glFramebufferTexture2D");
|
||||
|
||||
break;
|
||||
case GL_RENDERBUFFER:
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle);
|
||||
GLERROR("FrameBuffer generate: glFramebufferRenderbuffer");
|
||||
if ( (*it)->m_Attachment != GL_COLOR_ATTACHMENT0 ||
|
||||
(*it)->m_Attachment != GL_DEPTH_ATTACHMENT ||
|
||||
(*it)->m_Attachment != GL_STENCIL_ATTACHMENT)
|
||||
{
|
||||
LOG_ERROR("RenderBuffer Attachment not valid.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
GLERROR("FrameBuffer generate");
|
||||
|
||||
if ((*it)->m_Attachment != GL_DEPTH_ATTACHMENT) {
|
||||
attachments.push_back((*it)->m_Attachment);
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
#include "Rendering/ImGuiRenderPass.h"
|
||||
|
||||
ImGuiRenderPass::ImGuiRenderPass(IRenderer* renderer, EventBroker* eventBroker)
|
||||
: m_Renderer(renderer)
|
||||
, m_EventBroker(eventBroker)
|
||||
{
|
||||
g_Window = renderer->Window();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
|
||||
io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
|
||||
io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
|
||||
io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
|
||||
io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
|
||||
io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
|
||||
io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
|
||||
io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE;
|
||||
io.KeyMap[ImGuiKey_A] = GLFW_KEY_A;
|
||||
io.KeyMap[ImGuiKey_C] = GLFW_KEY_C;
|
||||
io.KeyMap[ImGuiKey_V] = GLFW_KEY_V;
|
||||
io.KeyMap[ImGuiKey_X] = GLFW_KEY_X;
|
||||
io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y;
|
||||
io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z;
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.Alpha = 1.f;
|
||||
style.WindowPadding = ImVec2(8.f, 7.f);
|
||||
style.WindowRounding = 4.f;
|
||||
style.ChildWindowRounding = 0.f;
|
||||
style.FramePadding = ImVec2(4.f, 2.f);
|
||||
style.FrameRounding = 2.f;
|
||||
style.ItemSpacing = ImVec2(6.f, 2.f);
|
||||
style.ItemInnerSpacing = ImVec2(3.f, 4.f);
|
||||
style.IndentSpacing = 16.f;
|
||||
style.ScrollbarSize = 12;
|
||||
style.ScrollbarRounding = 2.f;
|
||||
style.GrabMinSize = 13.f;
|
||||
style.GrabRounding = 3.f;
|
||||
|
||||
createDeviceObjects();
|
||||
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &ImGuiRenderPass::OnMousePress);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &ImGuiRenderPass::OnMouseRelease);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &ImGuiRenderPass::OnMouseMove);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EMouseScroll, &ImGuiRenderPass::OnMouseScroll);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &ImGuiRenderPass::OnKeyDown);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &ImGuiRenderPass::OnKeyUp);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyboardChar, &ImGuiRenderPass::OnKeyboardChar);
|
||||
|
||||
// Prime the first frame
|
||||
newFrame();
|
||||
}
|
||||
|
||||
void ImGuiRenderPass::Update(double dt)
|
||||
{
|
||||
g_DeltaTime = dt;
|
||||
}
|
||||
|
||||
void ImGuiRenderPass::Draw()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
|
||||
// Set up render state
|
||||
ImGuiRenderState state;
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays)
|
||||
float fb_height = io.DisplaySize.y * io.DisplayFramebufferScale.y;
|
||||
draw_data->ScaleClipRects(io.DisplayFramebufferScale);
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
glViewport(0, 0, (GLsizei)io.DisplaySize.x, (GLsizei)io.DisplaySize.y);
|
||||
const float ortho_projection[4][4] =
|
||||
{
|
||||
{ 2.0f/io.DisplaySize.x, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/-io.DisplaySize.y, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||
{ -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
};
|
||||
glUseProgram(g_ShaderHandle);
|
||||
glUniform1i(g_AttribLocationTex, 0);
|
||||
glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
glBindVertexArray(g_VaoHandle);
|
||||
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++) {
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawIdx* idx_buffer_offset = 0;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.size() * sizeof(ImDrawVert), (GLvoid*)&cmd_list->VtxBuffer.front(), GL_STREAM_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx), (GLvoid*)&cmd_list->IdxBuffer.front(), GL_STREAM_DRAW);
|
||||
|
||||
for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) {
|
||||
if (pcmd->UserCallback) {
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
}
|
||||
idx_buffer_offset += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Start next frame
|
||||
newFrame();
|
||||
}
|
||||
|
||||
bool ImGuiRenderPass::OnMousePress(const Events::MousePress& e)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MouseDown[e.Button] = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ImGuiRenderPass::OnMouseRelease(const Events::MouseRelease& e)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MouseDown[e.Button] = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ImGuiRenderPass::OnMouseMove(const Events::MouseMove& e)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MousePos.x = e.X;
|
||||
io.MousePos.y = e.Y;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGuiRenderPass::OnMouseScroll(const Events::MouseScroll& e)
|
||||
{
|
||||
g_MouseWheel += (float)e.DeltaY;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGuiRenderPass::OnKeyDown(const Events::KeyDown& e)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeysDown[e.KeyCode] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGuiRenderPass::OnKeyUp(const Events::KeyUp& e)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.KeysDown[e.KeyCode] = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGuiRenderPass::OnKeyboardChar(const Events::KeyboardChar& e)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (e.Char > 0 && e.Char < 0x10000) {
|
||||
io.AddInputCharacter((unsigned short)e.Char);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGuiRenderPass::createDeviceObjects()
|
||||
{
|
||||
// Backup GL state
|
||||
GLint last_texture, last_array_buffer, last_vertex_array;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
|
||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
|
||||
|
||||
const GLchar *vertex_shader =
|
||||
"#version 330\n"
|
||||
"uniform mat4 ProjMtx;\n"
|
||||
"in vec2 Position;\n"
|
||||
"in vec2 UV;\n"
|
||||
"in vec4 Color;\n"
|
||||
"out vec2 Frag_UV;\n"
|
||||
"out vec4 Frag_Color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Frag_UV = UV;\n"
|
||||
" Frag_Color = Color;\n"
|
||||
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||
"}\n";
|
||||
|
||||
const GLchar* fragment_shader =
|
||||
"#version 330\n"
|
||||
"uniform sampler2D Texture;\n"
|
||||
"in vec2 Frag_UV;\n"
|
||||
"in vec4 Frag_Color;\n"
|
||||
"out vec4 Out_Color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
|
||||
"}\n";
|
||||
|
||||
g_ShaderHandle = glCreateProgram();
|
||||
g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
|
||||
g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(g_VertHandle, 1, &vertex_shader, 0);
|
||||
glShaderSource(g_FragHandle, 1, &fragment_shader, 0);
|
||||
glCompileShader(g_VertHandle);
|
||||
glCompileShader(g_FragHandle);
|
||||
glAttachShader(g_ShaderHandle, g_VertHandle);
|
||||
glAttachShader(g_ShaderHandle, g_FragHandle);
|
||||
glLinkProgram(g_ShaderHandle);
|
||||
|
||||
g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
|
||||
g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
|
||||
g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
|
||||
g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
|
||||
g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
|
||||
|
||||
glGenBuffers(1, &g_VboHandle);
|
||||
glGenBuffers(1, &g_ElementsHandle);
|
||||
|
||||
glGenVertexArrays(1, &g_VaoHandle);
|
||||
glBindVertexArray(g_VaoHandle);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
|
||||
glEnableVertexAttribArray(g_AttribLocationPosition);
|
||||
glEnableVertexAttribArray(g_AttribLocationUV);
|
||||
glEnableVertexAttribArray(g_AttribLocationColor);
|
||||
|
||||
#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT))
|
||||
glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos));
|
||||
glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv));
|
||||
glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col));
|
||||
#undef OFFSETOF
|
||||
|
||||
createFontsTexture();
|
||||
|
||||
// Restore modified GL state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
|
||||
glBindVertexArray(last_vertex_array);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGuiRenderPass::createFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
io.Fonts->AddFontFromFileTTF("Fonts/DroidSans.ttf", 13.f);
|
||||
//io.Fonts->AddFontFromFileTTF("Fonts/ProggyClean.ttf", 13.f);
|
||||
//io.Fonts->AddFontFromFileTTF("Fonts/ProggyTiny.ttf", 10.f);
|
||||
//io.Fonts->AddFontFromFileTTF("Fonts/Karla-Regular.ttf", 15.0f);
|
||||
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader.
|
||||
|
||||
// Upload texture to graphics system
|
||||
GLint last_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
|
||||
glGenTextures(1, &g_FontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, g_FontTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
|
||||
|
||||
// Restore state
|
||||
glBindTexture(GL_TEXTURE_2D, last_texture);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGuiRenderPass::newFrame()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
int w, h;
|
||||
int display_w, display_h;
|
||||
glfwGetWindowSize(g_Window, &w, &h);
|
||||
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
|
||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||
io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
|
||||
|
||||
io.DeltaTime = g_DeltaTime;
|
||||
|
||||
io.KeyCtrl = glfwGetKey(g_Window, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(g_Window, GLFW_KEY_RIGHT_CONTROL);
|
||||
io.KeyShift = glfwGetKey(g_Window, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(g_Window, GLFW_KEY_RIGHT_SHIFT);
|
||||
io.KeyAlt = glfwGetKey(g_Window, GLFW_KEY_LEFT_ALT) || glfwGetKey(g_Window, GLFW_KEY_RIGHT_ALT);
|
||||
|
||||
io.MouseWheel = g_MouseWheel;
|
||||
g_MouseWheel = 0;
|
||||
|
||||
m_EventBroker->Process<ImGuiRenderPass>();
|
||||
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
#include "Rendering/PickingPass.h"
|
||||
|
||||
PickingPass::PickingPass(IRenderer* renderer, EventBroker* eb)
|
||||
{
|
||||
m_Renderer = renderer;
|
||||
m_EventBroker = eb;
|
||||
|
||||
InitializeTextures();
|
||||
InitializeFrameBuffers();
|
||||
InitializeShaderPrograms();
|
||||
}
|
||||
|
||||
PickingPass::~PickingPass()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PickingPass::InitializeTextures()
|
||||
{
|
||||
GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR,
|
||||
glm::vec2(m_Renderer->Resolution().Width, m_Renderer->Resolution().Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
|
||||
}
|
||||
|
||||
void PickingPass::InitializeFrameBuffers()
|
||||
{
|
||||
glGenRenderbuffers(1, &m_DepthBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
|
||||
|
||||
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT)));
|
||||
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0)));
|
||||
m_PickingBuffer.Generate();
|
||||
}
|
||||
|
||||
void PickingPass::InitializeShaderPrograms()
|
||||
{
|
||||
m_PickingProgram = ResourceManager::Load<ShaderProgram>("#PickingProgram");
|
||||
|
||||
m_PickingProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Picking.vert.glsl")));
|
||||
m_PickingProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Picking.frag.glsl")));
|
||||
m_PickingProgram->Compile();
|
||||
m_PickingProgram->BindFragDataLocation(0, "TextureFragment");
|
||||
m_PickingProgram->Link();
|
||||
}
|
||||
|
||||
void PickingPass::Draw(RenderQueueCollection& rq)
|
||||
{
|
||||
m_PickingColorsToEntity.clear();
|
||||
PickingPassState* state = new PickingPassState(m_PickingBuffer.GetHandle());
|
||||
|
||||
int r = 0;
|
||||
int g = 0;
|
||||
//TODO: Render: Add code for more jobs than modeljobs.
|
||||
|
||||
GLuint ShaderHandle = m_PickingProgram->GetHandle();
|
||||
m_PickingProgram->Bind();
|
||||
|
||||
std::map<EntityID, glm::vec2> entityColors;
|
||||
|
||||
for (auto &job : rq.Forward) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
|
||||
if (modelJob) {
|
||||
int pickColor[2] = { r, g };
|
||||
auto color = entityColors.find(modelJob->Entity);
|
||||
if (color != entityColors.end()) {
|
||||
pickColor[0] = color->second[0];
|
||||
pickColor[1] = color->second[1];
|
||||
} else {
|
||||
entityColors[modelJob->Entity] = glm::vec2(pickColor[0], pickColor[1]);
|
||||
if (r + 10 > 255) {
|
||||
r = 0;
|
||||
g += 1;
|
||||
} else {
|
||||
r += 1;
|
||||
}
|
||||
}
|
||||
m_PickingColorsToEntity[glm::vec2(pickColor[0], pickColor[1])] = modelJob->Entity;
|
||||
|
||||
//Render picking stuff
|
||||
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix));
|
||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix()));
|
||||
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix()));
|
||||
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, nullptr, modelJob->StartIndex);
|
||||
}
|
||||
}
|
||||
m_PickingBuffer.Unbind();
|
||||
GLERROR("PickingPass Error");
|
||||
|
||||
//Publish pick event every frame with the pick data that can be picked by the event
|
||||
int fbWidth;
|
||||
int fbHeight;
|
||||
glfwGetFramebufferSize(m_Renderer->Window(), &fbWidth, &fbHeight);
|
||||
Events::Picking pickEvent = Events::Picking(
|
||||
&m_PickingBuffer,
|
||||
&m_DepthBuffer,
|
||||
m_Renderer->Camera()->ProjectionMatrix(),
|
||||
m_Renderer->Camera()->ViewMatrix(),
|
||||
Rectangle(fbWidth, fbHeight),
|
||||
&m_PickingColorsToEntity);
|
||||
|
||||
m_EventBroker->Publish(pickEvent);
|
||||
|
||||
delete state;
|
||||
}
|
||||
|
||||
void PickingPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const
|
||||
{
|
||||
//TODO: Renderer: Make this in a sparate class
|
||||
glGenTextures(1, texture);
|
||||
glBindTexture(GL_TEXTURE_2D, *texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, dimensions.x, dimensions.y, 0, format, type, nullptr);//TODO: Renderer: Fix the precision and Resolution
|
||||
GLERROR("Texture initialization failed");
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "Rendering/PickingPassState.h"
|
||||
|
||||
|
||||
PickingPassState::PickingPassState(GLuint frameBuffer)
|
||||
{
|
||||
GLERROR("---2");
|
||||
BindFramebuffer(frameBuffer);
|
||||
GLERROR("---3");
|
||||
Enable(GL_DEPTH_TEST);
|
||||
Enable(GL_CULL_FACE);
|
||||
|
||||
glm::vec4 clearColor = glm::vec4(0.f);
|
||||
ClearColor(clearColor);
|
||||
Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
PickingPassState::~PickingPassState()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@ RawModel::RawModel(std::string fileName)
|
||||
if (scene == nullptr) {
|
||||
LOG_ERROR("Failed to load model \"%s\"", fileName.c_str());
|
||||
LOG_ERROR("Assimp error: %s", importer.GetErrorString());
|
||||
return;
|
||||
throw std::runtime_error("Failed to open model file.");
|
||||
}
|
||||
|
||||
auto m = scene->mRootNode->mTransformation;
|
||||
|
||||
@@ -23,15 +23,19 @@ glm::mat4 RenderQueueFactory::ModelMatrix(World* world, EntityID entity)
|
||||
return modelMatrix;
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 RenderQueueFactory::AbsolutePosition(World* world, EntityID entity)
|
||||
{
|
||||
glm::vec3 position;
|
||||
|
||||
do {
|
||||
ComponentWrapper transform = world->GetComponent(entity, "Transform");
|
||||
position += AbsoluteOrientation(world, entity) * (glm::vec3)transform["Position"];
|
||||
entity = world->GetParent(entity);
|
||||
EntityID parent = world->GetParent(entity);
|
||||
if (parent != 0) {
|
||||
position += AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"];
|
||||
} else {
|
||||
position += (glm::vec3)transform["Position"];
|
||||
}
|
||||
entity = parent;
|
||||
} while (entity != 0);
|
||||
|
||||
return position;
|
||||
@@ -52,15 +56,15 @@ glm::quat RenderQueueFactory::AbsoluteOrientation(World* world, EntityID entity)
|
||||
|
||||
glm::vec3 RenderQueueFactory::AbsoluteScale(World* world, EntityID entity)
|
||||
{
|
||||
ComponentWrapper transform = world->GetComponent(entity, "Transform");
|
||||
glm::vec3 scale = (glm::vec3)transform["Scale"];
|
||||
glm::vec3 scale(1.f);
|
||||
|
||||
EntityID parent = world->GetParent(entity);
|
||||
if (parent != 0) {
|
||||
return AbsoluteScale(world, parent) * scale;
|
||||
} else {
|
||||
return scale;
|
||||
}
|
||||
do {
|
||||
ComponentWrapper transform = world->GetComponent(entity, "Transform");
|
||||
scale *= (glm::vec3)transform["Scale"];
|
||||
entity = world->GetParent(entity);
|
||||
} while (entity != 0);
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue)
|
||||
@@ -71,12 +75,19 @@ void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue)
|
||||
}
|
||||
|
||||
for (auto& modelC : *models) {
|
||||
bool visible = modelC["Visible"];
|
||||
if (!visible) {
|
||||
continue;
|
||||
}
|
||||
std::string resource = modelC["Resource"];
|
||||
if (resource.empty()) {
|
||||
continue;
|
||||
}
|
||||
glm::vec4 color = modelC["Color"];
|
||||
Model* model = ResourceManager::Load<Model>(resource);
|
||||
if (model == nullptr) {
|
||||
model = ResourceManager::Load<Model>("Models/Core/Error.obj");
|
||||
}
|
||||
|
||||
for (auto texGroup : model->TextureGroups) {
|
||||
ModelJob job;
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
#include "Rendering/RenderState.h"
|
||||
|
||||
bool RenderState::Enable(GLenum cap)
|
||||
{
|
||||
if (glIsEnabled(cap)) {
|
||||
return false;
|
||||
}
|
||||
m_ResetFunctions.push_back(std::bind(glDisable, cap));
|
||||
glEnable(cap);
|
||||
return !GLERROR("RenderState::Enable");
|
||||
}
|
||||
|
||||
bool RenderState::Disable(GLenum cap)
|
||||
{
|
||||
if (!glIsEnabled(cap)) {
|
||||
return false;
|
||||
}
|
||||
m_ResetFunctions.push_back(std::bind(glEnable, cap));
|
||||
glDisable(cap);
|
||||
return !GLERROR("RenderState::Disable");
|
||||
}
|
||||
|
||||
bool RenderState::CullFace(GLenum mode)
|
||||
{
|
||||
if (!glIsEnabled(GL_CULL_FACE)) {
|
||||
LOG_ERROR("Setting GL_CULL_FACE without enabling it.");
|
||||
return false;
|
||||
}
|
||||
|
||||
GLint original;
|
||||
glGetIntegerv(GL_CULL_FACE_MODE, &original);
|
||||
m_ResetFunctions.push_back(std::bind(glCullFace, original));
|
||||
glCullFace(mode);
|
||||
return !GLERROR("RenderState::CullFace");
|
||||
}
|
||||
|
||||
bool RenderState::ClearColor(glm::vec4 color)
|
||||
{
|
||||
GLfloat original[4];
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, &original[0]);
|
||||
m_ResetFunctions.push_back(std::bind(glClearColor, original[0], original[1], original[2], original[3]));
|
||||
glClearColor(color.r, color.g, color.b, color.a);
|
||||
return !GLERROR("RenderState::ClearColor");
|
||||
}
|
||||
|
||||
bool RenderState::Clear(GLbitfield mask)
|
||||
{
|
||||
glClear(mask);
|
||||
return !GLERROR("RenderState::Clear");
|
||||
}
|
||||
|
||||
bool RenderState::BindFramebuffer(GLint framebuffer)
|
||||
{
|
||||
GLint originalRead;
|
||||
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &originalRead);
|
||||
GLint originalDraw;
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &originalDraw);
|
||||
m_ResetFunctions.push_back([originalRead, originalDraw]() {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, originalRead);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, originalDraw);
|
||||
});
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
return !GLERROR("RenderState::BindBuffer");
|
||||
}
|
||||
|
||||
|
||||
bool RenderState::BlendEquation(GLenum mode)
|
||||
{
|
||||
GLint originalRGB;
|
||||
glGetIntegerv(GL_BLEND_EQUATION_RGB, &originalRGB);
|
||||
GLint originalAlpha;
|
||||
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &originalAlpha);
|
||||
m_ResetFunctions.push_back(std::bind(glBlendEquationSeparate, originalRGB, originalAlpha));
|
||||
glBlendEquation(mode);
|
||||
return !GLERROR("RenderState::BlendEquation");
|
||||
}
|
||||
|
||||
bool RenderState::BlendFunc(GLenum sfactor, GLenum dfactor)
|
||||
{
|
||||
GLint originalSrcRGB;
|
||||
glGetIntegerv(GL_BLEND_SRC_RGB, &originalSrcRGB);
|
||||
GLint originalSrcAlpha;
|
||||
glGetIntegerv(GL_BLEND_SRC_ALPHA, &originalSrcAlpha);
|
||||
GLint originalDestRGB;
|
||||
glGetIntegerv(GL_BLEND_DST_RGB, &originalDestRGB);
|
||||
GLint originalDestAlpha;
|
||||
glGetIntegerv(GL_BLEND_DST_ALPHA, &originalDestAlpha);
|
||||
m_ResetFunctions.push_back(std::bind(glBlendFuncSeparate, originalSrcRGB, originalSrcAlpha, originalDestRGB, originalDestAlpha));
|
||||
glBlendFunc(sfactor, dfactor);
|
||||
return !GLERROR("RenderState::BlendFunc");
|
||||
}
|
||||
|
||||
RenderState::~RenderState()
|
||||
{
|
||||
for (auto& f : m_ResetFunctions) {
|
||||
f();
|
||||
}
|
||||
}
|
||||
|
||||
+130
-178
@@ -1,25 +1,29 @@
|
||||
#include "Rendering/Renderer.h"
|
||||
#include "Rendering/DebugCameraInputController.h"
|
||||
|
||||
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));
|
||||
if (m_Camera == nullptr) {
|
||||
m_Camera = m_DefaultCamera;
|
||||
}
|
||||
TEMPCreateLights();
|
||||
InitializeRenderPasses();
|
||||
|
||||
glfwSwapInterval(m_VSYNC);
|
||||
InitializeShaders();
|
||||
InitializeTextures();
|
||||
InitializeFrameBuffers();
|
||||
|
||||
InitializeSSBOs();
|
||||
//CalculateFrustum();
|
||||
|
||||
m_ScreenQuad = ResourceManager::Load<Model>("Models/Core/ScreenQuad.obj");
|
||||
m_UnitQuad = ResourceManager::Load<Model>("Models/Core/UnitQuad.obj");
|
||||
m_UnitSphere = ResourceManager::Load<Model>("Models/Core/UnitSphere.obj");
|
||||
|
||||
m_ImGuiRenderPass = new ImGuiRenderPass(this, m_EventBroker);
|
||||
}
|
||||
|
||||
void Renderer::InitializeWindow()
|
||||
@@ -64,26 +68,29 @@ void Renderer::InitializeWindow()
|
||||
|
||||
void Renderer::InitializeShaders()
|
||||
{
|
||||
m_BasicForwardProgram.AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/BasicForward.vert.glsl")));
|
||||
m_BasicForwardProgram.AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/BasicForward.frag.glsl")));
|
||||
m_BasicForwardProgram.Compile();
|
||||
m_BasicForwardProgram.Link();
|
||||
m_BasicForwardProgram = ResourceManager::Load<ShaderProgram>("#m_BasicForwardProgram");
|
||||
|
||||
m_PickingProgram.AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/Picking.vert.glsl")));
|
||||
m_PickingProgram.AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/Picking.frag.glsl")));
|
||||
m_PickingProgram.Compile();
|
||||
m_PickingProgram.BindFragDataLocation(0, "TextureFragment");
|
||||
m_PickingProgram.Link();
|
||||
m_DrawScreenQuadProgram = ResourceManager::Load<ShaderProgram>("#DrawScreenQuadProgram");
|
||||
m_DrawScreenQuadProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/DrawScreenQuad.vert.glsl")));
|
||||
m_DrawScreenQuadProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/DrawScreenQuad.frag.glsl")));
|
||||
m_DrawScreenQuadProgram->Compile();
|
||||
m_DrawScreenQuadProgram->Link();
|
||||
|
||||
m_DrawScreenQuadProgram.AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/DrawScreenQuad.vert.glsl")));
|
||||
m_DrawScreenQuadProgram.AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/DrawScreenQuad.frag.glsl")));
|
||||
m_DrawScreenQuadProgram.Compile();
|
||||
m_DrawScreenQuadProgram.Link();
|
||||
//m_CalculateFrustumProgram = ResourceManager::Load<ShaderProgram>("#CalculateFrustumProgram");
|
||||
//m_CalculateFrustumProgram.AddShader(std::shared_ptr<Shader>(new ComputeShader("Shaders/GridFrustum.comp.glsl")));
|
||||
//m_CalculateFrustumProgram.Compile();
|
||||
//m_CalculateFrustumProgram.Link();
|
||||
|
||||
//m_LightCullProgram = ResourceManager::Load<ShaderProgram>("#LightCullProgram");
|
||||
//m_LightCullProgram.AddShader(std::shared_ptr<Shader>(new ComputeShader("Shaders/cullLights.comp.glsl")));
|
||||
//m_LightCullProgram.Compile();
|
||||
//m_LightCullProgram.Link();
|
||||
}
|
||||
|
||||
void Renderer::InputUpdate(double dt)
|
||||
{
|
||||
static DebugCameraInputController<Renderer> firstPersonInputController(m_EventBroker, -1);
|
||||
|
||||
glm::vec3 m_Position = m_Camera->Position();
|
||||
if (glfwGetKey(m_Window, GLFW_KEY_O) == GLFW_PRESS)
|
||||
{
|
||||
@@ -113,155 +120,34 @@ void Renderer::InputUpdate(double dt)
|
||||
m_CameraMoveSpeed = 0.5f;
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
|
||||
|
||||
double deltaX, deltaY;
|
||||
deltaX = mousePosX - (float)Resolution().Width / 2;
|
||||
deltaY = mousePosY - (float)Resolution().Height / 2;
|
||||
|
||||
float rotationY = -deltaY / 300.f;
|
||||
float rotationX = -deltaX / 300.f;
|
||||
glm::quat orientation = m_Camera->Orientation();
|
||||
|
||||
|
||||
orientation = orientation * glm::angleAxis<float>(rotationY, glm::vec3(1, 0, 0));
|
||||
orientation = glm::angleAxis<float>(rotationX, glm::vec3(0, 1, 0)) * orientation;
|
||||
|
||||
m_Camera->SetOrientation(orientation);
|
||||
|
||||
glfwSetCursorPos(m_Window, Resolution().Width / 2, Resolution().Height / 2);
|
||||
}
|
||||
m_Camera->SetPosition(m_Position);
|
||||
firstPersonInputController.Update(dt);
|
||||
m_Camera->SetOrientation(firstPersonInputController.Orientation());
|
||||
m_Camera->SetPosition(firstPersonInputController.Position());
|
||||
}
|
||||
|
||||
void Renderer::Update(double dt)
|
||||
{
|
||||
InputUpdate(dt);
|
||||
|
||||
m_EventBroker->Process<Renderer>();
|
||||
InputUpdate(dt);
|
||||
m_ImGuiRenderPass->Update(dt);
|
||||
}
|
||||
|
||||
void Renderer::Draw(RenderQueueCollection& rq)
|
||||
{
|
||||
//TODO: Renderer: Kanske borde vara längst upp i update.
|
||||
PickingPass(rq);
|
||||
DrawScreenQuad(m_PickingTexture);
|
||||
m_PickingPass->Draw(rq);
|
||||
//DrawScreenQuad(m_PickingPass->PickingTexture());
|
||||
//CullLights();
|
||||
|
||||
DrawScene(rq);
|
||||
glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 1.f);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
m_DrawScenePass->Draw(rq);
|
||||
GLERROR("Renderer::Draw m_DrawScenePass->Draw");
|
||||
m_ImGuiRenderPass->Draw();
|
||||
glfwSwapBuffers(m_Window);
|
||||
}
|
||||
|
||||
void Renderer::DrawScene(RenderQueueCollection& rq)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
//TODO: Render: Clean up draw code
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
//TODO: Render: Add code for more jobs than modeljobs.
|
||||
for (auto &job : rq.Forward) {
|
||||
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
|
||||
if (modelJob) {
|
||||
GLuint ShaderHandle = m_BasicForwardProgram.GetHandle();
|
||||
|
||||
m_BasicForwardProgram.Bind();
|
||||
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
||||
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()));
|
||||
glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
|
||||
|
||||
//TODO: Renderer: bättre textur felhantering samt fler texturer stöd
|
||||
if (modelJob->DiffuseTexture != nullptr) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture);
|
||||
} else {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::PickingPass(RenderQueueCollection& rq)
|
||||
{
|
||||
m_PickingBuffer.Bind();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
int r = 30;
|
||||
int g = 0;
|
||||
//TODO: Render: Add code for more jobs than modeljobs.
|
||||
|
||||
|
||||
GLuint ShaderHandle = m_PickingProgram.GetHandle();
|
||||
m_PickingProgram.Bind();
|
||||
|
||||
for (auto &job : rq.Forward) {
|
||||
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;
|
||||
|
||||
|
||||
//Render picking stuff
|
||||
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
|
||||
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));
|
||||
|
||||
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;
|
||||
if(r > 255) {
|
||||
r = 0;
|
||||
g+=50;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_PickingBuffer.Unbind();
|
||||
}
|
||||
|
||||
|
||||
void Renderer::DrawScreenQuad(GLuint textureToDraw)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
@@ -273,7 +159,7 @@ void Renderer::DrawScreenQuad(GLuint textureToDraw)
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
|
||||
m_DrawScreenQuadProgram.Bind();
|
||||
m_DrawScreenQuadProgram->Bind();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, textureToDraw);
|
||||
|
||||
@@ -283,24 +169,10 @@ void Renderer::DrawScreenQuad(GLuint textureToDraw)
|
||||
, GL_UNSIGNED_INT, 0, m_ScreenQuad->TextureGroups[0].StartIndex);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::InitializeTextures()
|
||||
{
|
||||
m_ErrorTexture=ResourceManager::Load<Texture>("Textures/Core/ErrorTexture.png");
|
||||
m_WhiteTexture=ResourceManager::Load<Texture>("Textures/Core/Blank.png");
|
||||
/*
|
||||
glGenTextures(1, &m_PickingTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_PickingTexture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, m_Resolution.Width, m_Resolution.Height, 0, GL_RG, GL_FLOAT, NULL);//TODO: Renderer: Fix the precision and Resolution
|
||||
GLERROR("m_PickingTexture initialization failed");
|
||||
*/
|
||||
|
||||
GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR,
|
||||
glm::vec2(m_Resolution.Width, m_Resolution.Height), GL_RG8, GL_RG, GL_FLOAT);
|
||||
}
|
||||
|
||||
void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type)
|
||||
@@ -315,15 +187,95 @@ void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filterin
|
||||
GLERROR("Texture initialization failed");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Renderer::InitializeFrameBuffers()//TODO: Renderer: Get this to a better location, as its really big
|
||||
void Renderer::InitializeSSBOs()
|
||||
{
|
||||
glGenRenderbuffers(1, &m_DepthBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Resolution.Width, m_Resolution.Height);
|
||||
printf("Size: %i\n", sizeof(m_Frustums));
|
||||
glGenBuffers(1, &m_FrustumSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_Frustums), &m_Frustums, GL_DYNAMIC_COPY);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLERROR("m_FrustumSSBO");
|
||||
|
||||
glGenBuffers(1, &m_LightSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_PointLights), &m_PointLights, GL_DYNAMIC_COPY);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLERROR("m_LightSSBO");
|
||||
|
||||
|
||||
glGenBuffers(1, &m_LightGridSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightGrid), &m_LightGrid, GL_DYNAMIC_COPY);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLERROR("m_LightGridSSBO");
|
||||
|
||||
|
||||
glGenBuffers(1, &m_LightOffsetSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLERROR("m_LightOffsetSSBO");
|
||||
|
||||
|
||||
glGenBuffers(1, &m_LightIndexSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightIndex), &m_LightIndex, GL_DYNAMIC_COPY);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
|
||||
GLERROR("m_LightIndexSSBO");
|
||||
|
||||
}
|
||||
|
||||
void Renderer::InitializeRenderPasses()
|
||||
{
|
||||
m_DrawScenePass = new DrawScenePass(this);
|
||||
m_PickingPass = new PickingPass(this, m_EventBroker);
|
||||
}
|
||||
|
||||
void Renderer::CalculateFrustum()
|
||||
{
|
||||
GLERROR("CalculateFrustum Error-1");
|
||||
m_CalculateFrustumProgram->Bind();
|
||||
|
||||
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new RenderBuffer(&m_DepthBuffer, GL_DEPTH_ATTACHMENT)));
|
||||
m_PickingBuffer.AddResource(std::shared_ptr<BufferResource>(new Texture2D(&m_PickingTexture, GL_COLOR_ATTACHMENT0)));
|
||||
m_PickingBuffer.Generate();
|
||||
}
|
||||
GLERROR("CalculateFrustum Error1");
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
GLERROR("CalculateFrustum Error2");
|
||||
glUniformMatrix4fv(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "P"), 1, false, glm::value_ptr(m_Camera->ProjectionMatrix()));
|
||||
GLERROR("CalculateFrustum Error3");
|
||||
glUniform2f(glGetUniformLocation(m_CalculateFrustumProgram->GetHandle(), "ScreenDimensions"), m_Resolution.Width, m_Resolution.Height);
|
||||
GLERROR("CalculateFrustum Error4");
|
||||
glDispatchCompute(5, 3, 1);
|
||||
GLERROR("CalculateFrustum Error5");
|
||||
|
||||
}
|
||||
|
||||
void Renderer::TEMPCreateLights()
|
||||
{
|
||||
for (int i = 0; i < NUM_LIGHTS; i++) {
|
||||
m_PointLights[i].Position = glm::vec4(i, 0.f, 0.f, 0.f);
|
||||
m_PointLights[i].Color = glm::vec4(1.f, 0.5f, 0.f + i*0.1f, 1.f);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CullLights()
|
||||
{
|
||||
m_LightCullProgram->Bind();
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_FrustumSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightGridSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_LightOffsetSSBO);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightIndexSSBO);
|
||||
glDispatchCompute(m_Resolution.Width / TILE_SIZE, m_Resolution.Height / TILE_SIZE, 1);
|
||||
GLERROR("CullLights Error");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ 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[3];
|
||||
glReadPixels(x, y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pdata);
|
||||
PickDataBuffer->Unbind();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, DepthBuffer);
|
||||
@@ -41,10 +41,18 @@ glm::vec3 ScreenCoords::ToPixelData(float x, float y, FrameBuffer* PickDataBuffe
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ file(GLOB SOURCE_FILES
|
||||
set(SOURCE_FILES
|
||||
${SOURCE_FILES}
|
||||
"Game.cpp"
|
||||
"PlayerSystem.cpp"
|
||||
)
|
||||
|
||||
set(LIBRARIES
|
||||
|
||||
+63
-48
@@ -2,38 +2,44 @@
|
||||
|
||||
Game::Game(int argc, char* argv[])
|
||||
{
|
||||
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
|
||||
ResourceManager::RegisterType<Model>("Model");
|
||||
ResourceManager::RegisterType<Texture>("Texture");
|
||||
ResourceManager::RegisterType<ConfigFile>("ConfigFile");
|
||||
ResourceManager::RegisterType<Model>("Model");
|
||||
ResourceManager::RegisterType<Texture>("Texture");
|
||||
ResourceManager::RegisterType<EntityXMLFile>("EntityXMLFile");
|
||||
ResourceManager::RegisterType<ShaderProgram>("ShaderProgram");
|
||||
|
||||
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
|
||||
m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
|
||||
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
|
||||
|
||||
// Create the core event broker
|
||||
m_EventBroker = new EventBroker();
|
||||
// Create the core event broker
|
||||
m_EventBroker = new EventBroker();
|
||||
|
||||
m_RenderQueueFactory = new RenderQueueFactory();
|
||||
|
||||
// Create the renderer
|
||||
m_Renderer = new Renderer();
|
||||
m_Renderer->SetFullscreen(m_Config->Get<bool>("Video.Fullscreen", false));
|
||||
m_Renderer->SetVSYNC(m_Config->Get<bool>("Video.VSYNC", false));
|
||||
m_Renderer->SetResolution(Rectangle(
|
||||
0,
|
||||
0,
|
||||
m_Config->Get<int>("Video.Width", 1280),
|
||||
m_Config->Get<int>("Video.Height", 720)
|
||||
));
|
||||
m_Renderer->Initialize();
|
||||
// Create the 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(
|
||||
0,
|
||||
0,
|
||||
m_Config->Get<int>("Video.Width", 1280),
|
||||
m_Config->Get<int>("Video.Height", 720)
|
||||
));
|
||||
m_Renderer->Initialize();
|
||||
m_Renderer->Camera()->SetFOV(glm::radians(m_Config->Get<float>("Video.FOV", 90.f)));
|
||||
|
||||
// Create input manager
|
||||
m_InputManager = new InputManager(m_Renderer->Window(), m_EventBroker);
|
||||
// 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<MouseInputHandler>();
|
||||
m_InputProxy->LoadBindings("Input.ini");
|
||||
|
||||
// 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 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 world
|
||||
m_World = new World();
|
||||
@@ -41,50 +47,59 @@ Game::Game(int argc, char* argv[])
|
||||
if (!mapToLoad.empty()) {
|
||||
ResourceManager::Load<EntityXMLFile>(mapToLoad)->PopulateWorld(m_World);
|
||||
}
|
||||
|
||||
|
||||
// Create system pipeline
|
||||
m_SystemPipeline = new SystemPipeline(m_EventBroker);
|
||||
m_SystemPipeline->AddSystem<RaptorCopterSystem>();
|
||||
m_SystemPipeline->AddSystem<PlayerSystem>();
|
||||
m_SystemPipeline->AddSystem<EditorSystem>();
|
||||
|
||||
m_LastTime = glfwGetTime();
|
||||
m_LastTime = glfwGetTime();
|
||||
|
||||
testIntialize();
|
||||
debugInitialize();
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
{
|
||||
delete m_FrameStack;
|
||||
delete m_EventBroker;
|
||||
delete m_FrameStack;
|
||||
delete m_EventBroker;
|
||||
}
|
||||
|
||||
void Game::Tick()
|
||||
{
|
||||
double currentTime = glfwGetTime();
|
||||
double dt = currentTime - m_LastTime;
|
||||
m_LastTime = currentTime;
|
||||
glfwPollEvents();
|
||||
|
||||
m_EventBroker->Swap();
|
||||
m_InputManager->Update(dt);
|
||||
m_Renderer->Update(dt);
|
||||
m_EventBroker->Swap();
|
||||
double currentTime = glfwGetTime();
|
||||
double dt = currentTime - m_LastTime;
|
||||
m_LastTime = currentTime;
|
||||
|
||||
// Handle input in a weird looking but responsive way
|
||||
m_EventBroker->Process<InputManager>();
|
||||
m_EventBroker->Swap();
|
||||
m_InputManager->Update(dt);
|
||||
m_EventBroker->Swap();
|
||||
m_InputProxy->Update(dt);
|
||||
m_EventBroker->Swap();
|
||||
m_InputProxy->Process();
|
||||
m_EventBroker->Swap();
|
||||
|
||||
// Iterate through systems and update world!
|
||||
m_SystemPipeline->Update(m_World, dt);
|
||||
testTick(dt);
|
||||
debugTick(dt);
|
||||
m_Renderer->Update(dt);
|
||||
|
||||
m_RenderQueueFactory->Update(m_World);
|
||||
m_Renderer->Draw(m_RenderQueueFactory->RenderQueues());
|
||||
|
||||
m_EventBroker->Swap();
|
||||
m_EventBroker->Clear();
|
||||
|
||||
glfwPollEvents();
|
||||
GLERROR("Game::Tick m_RenderQueueFactory->Update");
|
||||
m_Renderer->Draw(m_RenderQueueFactory->RenderQueues());
|
||||
GLERROR("Game::Tick m_Renderer->Draw");
|
||||
m_EventBroker->Swap();
|
||||
m_EventBroker->Clear();
|
||||
}
|
||||
|
||||
|
||||
bool Game::testOnKeyUp(const Events::KeyUp& e)
|
||||
bool Game::debugOnInputCommand(const Events::InputCommand& e)
|
||||
{
|
||||
if (e.KeyCode == GLFW_KEY_R) {
|
||||
if (e.Command == "DebugReload" && e.Value == 1) {
|
||||
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
|
||||
if (!mapToLoad.empty()) {
|
||||
delete m_World;
|
||||
@@ -97,12 +112,12 @@ bool Game::testOnKeyUp(const Events::KeyUp& e)
|
||||
return false;
|
||||
}
|
||||
|
||||
void Game::testIntialize()
|
||||
void Game::debugInitialize()
|
||||
{
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &Game::testOnKeyUp);
|
||||
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Game::debugOnInputCommand);
|
||||
}
|
||||
|
||||
void Game::testTick(double dt)
|
||||
void Game::debugTick(double dt)
|
||||
{
|
||||
m_EventBroker->Process<Game>();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "PlayerSystem.h"
|
||||
|
||||
void PlayerSystem::UpdateComponent(World * world, ComponentWrapper & player, double dt)
|
||||
{
|
||||
if (input.Forward) {
|
||||
m_Direction.z = -1;
|
||||
} else if (input.Back) {
|
||||
m_Direction.z = 1;
|
||||
} else {
|
||||
m_Direction.z = 0;
|
||||
}
|
||||
if (input.Left) {
|
||||
m_Direction.x = -1;
|
||||
} else if (input.Right) {
|
||||
m_Direction.x = 1;
|
||||
} else {
|
||||
m_Direction.x = 0;
|
||||
}
|
||||
m_EventBroker->Process<PlayerSystem>();
|
||||
ComponentWrapper& transform = world->GetComponent(player.EntityID, "Transform");
|
||||
(glm::vec3&)player["Velocity"] = m_Speed * float(dt) * m_Direction;
|
||||
(glm::vec3&)transform["Position"] += (glm::vec3)player["Velocity"];
|
||||
}
|
||||
|
||||
bool PlayerSystem::OnKeyDown(const Events::KeyDown & event)
|
||||
{
|
||||
if (event.KeyCode == GLFW_KEY_W) {
|
||||
input.Forward = true;
|
||||
}
|
||||
if (event.KeyCode == GLFW_KEY_A) {
|
||||
input.Left = true;
|
||||
}
|
||||
if (event.KeyCode == GLFW_KEY_S) {
|
||||
input.Back = true;
|
||||
}
|
||||
if (event.KeyCode == GLFW_KEY_D) {
|
||||
input.Right = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlayerSystem::OnKeyUp(const Events::KeyUp & event)
|
||||
{
|
||||
if (event.KeyCode == GLFW_KEY_W) {
|
||||
input.Forward = false;
|
||||
}
|
||||
if (event.KeyCode == GLFW_KEY_A) {
|
||||
input.Left = false;
|
||||
}
|
||||
if (event.KeyCode == GLFW_KEY_S) {
|
||||
input.Back = false;
|
||||
}
|
||||
if (event.KeyCode == GLFW_KEY_D) {
|
||||
input.Right = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -11,6 +11,8 @@ RMDIR "%DeployLocation%\Textures"
|
||||
MKLINK "%DeployLocation%\Textures\" "assets\Textures\" /J
|
||||
RMDIR "%DeployLocation%\Audio"
|
||||
MKLINK "%DeployLocation%\Audio\" "assets\Audio\" /J
|
||||
RMDIR "%DeployLocation%\Fonts"
|
||||
MKLINK "%DeployLocation%\Fonts\" "assets\Fonts\" /J
|
||||
|
||||
ECHO Deploying resources to %DeployLocation%
|
||||
:: Schemas
|
||||
@@ -21,6 +23,7 @@ RMDIR /S /Q "%DeployLocation%\Shaders"
|
||||
MKLINK "%DeployLocation%\Shaders\" "resources\Shaders" /J
|
||||
:: Configuration files
|
||||
MKLINK "%DeployLocation%\DefaultConfig.ini" "resources\DefaultConfig.ini" /H
|
||||
MKLINK "%DeployLocation%\DefaultInput.ini" "resources\DefaultInput.ini" /H
|
||||
|
||||
:: Platform specific binaries
|
||||
IF "%~1"=="" GOTO :EOF
|
||||
|
||||
Reference in New Issue
Block a user