Compare commits

..

4 Commits

Author SHA1 Message Date
maqu14 7fc83d1471 Live texturing 2016-03-18 10:14:02 +01:00
maqu14 65e5729118 Added assets 2016-01-27 12:34:24 +01:00
maqu14 26d6f4c7cf Live texturing, fixed so Maya wont crash when the plugin is unloaded and Photoshop not being able to read the file under specific circumstances. 2015-12-16 17:45:20 +01:00
Teejoon e513059522 This is the "working"(little buggy) PhotoShop to Maya connection.
Ask Johan if you want to get this to work, since you need to install zmq, nodeJS, add a line to Maya.env file and som othe stuff for it to work.
2015-12-09 15:11:53 +01:00
342 changed files with 37571 additions and 2516 deletions
+4
View File
@@ -4,3 +4,7 @@ bin/
lib/ lib/
# Because apparently nobody has any self control # Because apparently nobody has any self control
*.orig *.orig
tools/LiveTexturing/mayaPluginRTT/mayaPluginRTT/x64/Debug/
tools/LiveTexturing/mayaPluginRTT/x64/Debug/
*.suo
+1 -1
Submodule assets updated: b37468222e...e4dc9529f2
+9 -9
View File
@@ -1,13 +1,13 @@
# Xerces_FOUND # XERCES_FOUND
# Xerces_INCLUDE_DIRS # XERCES_INCLUDE_DIRS
# Xerces_LIBRARIES # XERCES_LIBRARIES
find_path(Xerces_INCLUDE_DIR xercesc/dom/dom.hpp find_path(XERCES_INCLUDE_DIR xercesc/dom/dom.hpp
/usr/local/include /usr/local/include
/usr/include /usr/include
) )
find_library(Xerces_LIBRARY find_library(XERCES_LIBRARY
NAMES NAMES
xerces-c_3 xerces-c_3
xerces-c_3D xerces-c_3D
@@ -16,8 +16,8 @@ find_library(Xerces_LIBRARY
/usr/lib /usr/lib
) )
set(Xerces_INCLUDE_DIRS ${Xerces_INCLUDE_DIR}) set(XERCES_INCLUDE_DIRS ${XERCES_INCLUDE_DIR})
set(Xerces_LIBRARIES ${Xerces_LIBRARY}) set(XERCES_LIBRARIES ${XERCES_LIBRARY})
find_package_handle_standard_args(Xerces DEFAULT_MSG Xerces_LIBRARY Xerces_INCLUDE_DIR) find_package_handle_standard_args(Xerces DEFAULT_MSG XERCES_LIBRARY XERCES_INCLUDE_DIR)
mark_as_advanced(Xerces_FOUND Xerces_INCLUDE_DIR Xerces_LIBRARY) mark_as_advanced(Xerces_FOUND XERCES_INCLUDE_DIR XERCES_LIBRARY)
+2 -2
View File
@@ -2,7 +2,7 @@
#define ComponentWrapper_h__ #define ComponentWrapper_h__
#include "../Common.h" #include "../Common.h"
#include "Entity.h" #include "EntityWrapper.h"
#include "ComponentInfo.h" #include "ComponentInfo.h"
#include "Util/Any.h" #include "Util/Any.h"
@@ -11,7 +11,7 @@ struct ComponentWrapper
ComponentWrapper(const ComponentInfo& componentInfo, char* data) ComponentWrapper(const ComponentInfo& componentInfo, char* data)
: Info(componentInfo) : Info(componentInfo)
, EntityID(*reinterpret_cast<::EntityID*>(data)) , EntityID(*reinterpret_cast<::EntityID*>(data))
, Data(data + sizeof(::EntityID)) , Data(data + sizeof(EntityID))
{ } { }
const ComponentInfo& Info; const ComponentInfo& Info;
+1 -19
View File
@@ -5,7 +5,6 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp> #include <boost/property_tree/ini_parser.hpp>
#include <boost/lexical_cast.hpp>
#include "../Common.h" #include "../Common.h"
#include "ResourceManager.h" #include "ResourceManager.h"
@@ -20,14 +19,12 @@ private:
public: public:
template <typename T> template <typename T>
T Get(std::string key, T defaultValue); T Get(std::string key, T defaultValue);
template <typename T>
std::vector<std::pair<std::string, T>> GetAll(std::string key);
template <typename T> template <typename T>
void Set(std::string key, T value); void Set(std::string key, T value);
void SaveToDisk(); void SaveToDisk();
private: private:
boost::filesystem::path m_Path; boost::filesystem::path m_Path;
boost::property_tree::ptree m_PTreeDefaults; boost::property_tree::ptree m_PTreeDefaults;
boost::property_tree::ptree m_PTreeOverrides; boost::property_tree::ptree m_PTreeOverrides;
@@ -40,21 +37,6 @@ T ConfigFile::Get(std::string key, T defaultValue)
return m_PTreeMerged.get<T>(key, 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> template <typename T>
void ConfigFile::Set(std::string key, T value) void ConfigFile::Set(std::string key, T value)
{ {
-6
View File
@@ -1,6 +0,0 @@
#ifndef Entity_h__
#define Entity_h__
typedef unsigned int EntityID;
#endif
+12
View File
@@ -0,0 +1,12 @@
#include "ResourceManager.h"
class EntityFile : public Resource
{
friend class ResourceManager;
private:
EntityFile(std::string path);
public:
};
+15
View File
@@ -0,0 +1,15 @@
#ifndef Entity_h__
#define Entity_h__
typedef unsigned int EntityID;
struct EntityWrapper
{
EntityWrapper(EntityID entityID)
: ID(entityID)
{ }
EntityID ID;
};
#endif
-141
View File
@@ -1,141 +0,0 @@
#ifndef EntityXMLFile_h__
#define EntityXMLFile_h__
#include <sstream>
#include "../Common.h"
#include "../GLM.h"
#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMLSInput.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLFloat.hpp>
#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
#include <xercesc/framework/psvi/XSParticle.hpp>
#include <xercesc/framework/psvi/XSModelGroup.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/framework/psvi/XSValue.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include "ResourceManager.h"
#include "Entity.h"
#include "ComponentInfo.h"
class World;
class EntityPreprocessorXMLErrorHandler : public xercesc::DOMErrorHandler
{
public:
bool handleError(const xercesc::DOMError &e) override
{
char* message = xercesc::XMLString::transcode(e.getMessage());
std::cerr << "Preprocessor DOMError: " << message << std::endl;
xercesc::XMLString::release(&message);
return false;
}
};
class EntityParserXMLErrorHandler : public xercesc::ErrorHandler
{
public:
void warning(const xercesc::SAXParseException& e) override
{
reportParseException("Warning", e);
}
void error(const xercesc::SAXParseException& e) override
{
reportParseException("Error", e);
}
void fatalError(const xercesc::SAXParseException& e) override
{
reportParseException("FATAL ERROR", e);
}
void resetErrors() override { }
private:
void reportParseException(std::string type, const xercesc::SAXParseException& e)
{
char* message = xercesc::XMLString::transcode(e.getMessage());
char* systemID = xercesc::XMLString::transcode(e.getSystemId());
std::cerr << systemID << ":" << e.getLineNumber() << ":" << e.getColumnNumber() << std::endl;
std::cerr << type << ": " << message << std::endl;
xercesc::XMLString::release(&systemID);
xercesc::XMLString::release(&message);
}
};
class XSTR
{
public:
XSTR(const XMLCh* const xmlString)
{
m_AsChar = xercesc::XMLString::transcode(xmlString);
}
XSTR(const char* normalString)
{
m_AsXMLCh = xercesc::XMLString::transcode(normalString);
}
~XSTR()
{
if (m_AsChar != nullptr) {
xercesc::XMLString::release(&m_AsChar);
}
if (m_AsXMLCh != nullptr) {
xercesc::XMLString::release(&m_AsXMLCh);
}
}
operator const char*() const { return m_AsChar; }
operator const XMLCh*() const { return m_AsXMLCh; }
private:
char* m_AsChar = nullptr;
XMLCh* m_AsXMLCh = nullptr;
};
class EntityXMLFile : public Resource
{
friend class ResourceManager;
private:
EntityXMLFile(std::string path);
public:
~EntityXMLFile();
void PopulateWorld(World* world);
private:
static unsigned int InstanceCount;
std::string m_EntityFile;
xercesc::XMLGrammarPool* m_GrammarPool = nullptr;
EntityParserXMLErrorHandler* m_ErrorHandler = nullptr;
xercesc::XercesDOMParser* m_DOMParser = nullptr;
xercesc::DOMDocument* m_DOMDocument = nullptr;
std::map<std::string, ComponentInfo> m_ComponentInfo;
// Preprocesses the entity file to insert include-by-copy child entities
// TODO: Make this work in memory instead of saving to file
void preprocess(std::string inPath, std::string outPath);
void parseComponentInfo();
void parseDefaults();
void predictComponentAllocation();
void parseEntityGraph(World* world, xercesc::DOMElement* parent, EntityID parentEntity);
std::size_t getTypeStride(std::string typeName);
float getFloatAttribute(const xercesc::DOMElement* element, const char* attribute) const;
void writeData(const xercesc::DOMElement* element, std::string typeName, char* outData);
};
#endif
+67 -67
View File
@@ -17,119 +17,119 @@ class EventBroker;
class BaseEventRelay class BaseEventRelay
{ {
friend class EventBroker; friend class EventBroker;
protected: protected:
BaseEventRelay(std::string contextTypeName, std::string eventTypeName) BaseEventRelay(std::string contextTypeName, std::string eventTypeName)
: m_ContextTypeName(contextTypeName) : m_ContextTypeName(contextTypeName)
, m_EventTypeName(eventTypeName) , m_EventTypeName(eventTypeName)
, m_Broker(nullptr) , m_Broker(nullptr)
{ } { }
~BaseEventRelay(); ~BaseEventRelay();
public: public:
virtual bool Receive(const std::shared_ptr<Event> event) = 0; virtual bool Receive(const std::shared_ptr<Event> event) = 0;
protected: protected:
std::string m_ContextTypeName; std::string m_ContextTypeName;
std::string m_EventTypeName; std::string m_EventTypeName;
EventBroker* m_Broker; EventBroker* m_Broker;
}; };
template <typename ContextType, typename EventType> template <typename ContextType, typename EventType>
class EventRelay : public BaseEventRelay class EventRelay : public BaseEventRelay
{ {
public: public:
typedef std::function<bool(const EventType&)> CallbackType; typedef std::function<bool(const EventType&)> CallbackType;
EventRelay() EventRelay()
: m_Callback(nullptr) : m_Callback(nullptr)
, BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name()) , BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name())
{ } { }
EventRelay(CallbackType callback) EventRelay(CallbackType callback)
: m_Callback(callback) : m_Callback(callback)
, BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name()) , BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name())
{ } { }
protected: protected:
bool Receive(const std::shared_ptr<Event> event) override; bool Receive(const std::shared_ptr<Event> event) override;
private: private:
CallbackType m_Callback; CallbackType m_Callback;
}; };
template <typename ContextType, typename EventType> template <typename ContextType, typename EventType>
bool EventRelay<ContextType, EventType>::Receive(const std::shared_ptr<Event> event) bool EventRelay<ContextType, EventType>::Receive(const std::shared_ptr<Event> event)
{ {
if (m_Callback != nullptr) { if (m_Callback != nullptr) {
return m_Callback(*static_cast<const EventType*>(event.get())); return m_Callback(*static_cast<const EventType*>(event.get()));
} else { } else {
return false; return false;
} }
} }
class EventBroker class EventBroker
{ {
template <typename ContextType, typename EventType> friend class EventRelay; template <typename ContextType, typename EventType> friend class EventRelay;
public: public:
EventBroker() EventBroker()
{ {
m_EventQueueRead = std::make_shared<EventQueue_t>(); m_EventQueueRead = std::make_shared<EventQueue_t>();
m_EventQueueWrite = std::make_shared<EventQueue_t>(); m_EventQueueWrite = std::make_shared<EventQueue_t>();
} }
void Subscribe(BaseEventRelay &relay); void Subscribe(BaseEventRelay &relay);
template <typename EventType> template <typename EventType>
void Publish(const EventType &event); void Publish(const EventType &event);
/* /*
Process all events in a given context. Process all events in a given context.
Returns: Number of events processed Returns: Number of events processed
*/ */
template <typename ContextType> template <typename ContextType>
int Process(); int Process();
int Process(std::string contextTypeName); int Process(std::string contextTypeName);
void Swap(); void Swap();
void Clear(); void Clear();
void Unsubscribe(BaseEventRelay &relay); void Unsubscribe(BaseEventRelay &relay);
private: private:
bool m_IsProcessing = false; bool m_IsProcessing = false;
typedef std::string ContextTypeName_t; // typeid(ContextType).name() typedef std::string ContextTypeName_t; // typeid(ContextType).name()
typedef std::string EventTypeName_t; // typeid(EventType).name() typedef std::string EventTypeName_t; // typeid(EventType).name()
typedef std::unordered_multimap<EventTypeName_t, BaseEventRelay*> EventRelays_t; typedef std::unordered_multimap<EventTypeName_t, BaseEventRelay*> EventRelays_t;
typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t; typedef std::unordered_map<ContextTypeName_t, EventRelays_t> ContextRelays_t;
ContextRelays_t m_ContextRelays; ContextRelays_t m_ContextRelays;
std::vector<BaseEventRelay*> m_RelaysToSubscribe; std::vector<BaseEventRelay*> m_RelaysToSubscribe;
std::vector<BaseEventRelay*> m_RelaysToUnsubscribe; std::vector<BaseEventRelay*> m_RelaysToUnsubscribe;
typedef std::list<std::pair<EventTypeName_t, std::shared_ptr<Event>>> EventQueue_t; 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_EventQueueRead;
std::shared_ptr<EventQueue_t> m_EventQueueWrite; std::shared_ptr<EventQueue_t> m_EventQueueWrite;
void subscribeImmediate(BaseEventRelay& relay); void subscribeImmediate(BaseEventRelay& relay);
void unsubscribeImmediate(BaseEventRelay& relay); void unsubscribeImmediate(BaseEventRelay& relay);
}; };
template <typename EventType> template <typename EventType>
void EventBroker::Publish(const EventType &event) void EventBroker::Publish(const EventType &event)
{ {
/*auto itpair = m_Subscribers.equal_range(typeid(EventType).name()); /*auto itpair = m_Subscribers.equal_range(typeid(EventType).name());
for (auto it = itpair.first; it != itpair.second; ++it) for (auto it = itpair.first; it != itpair.second; ++it)
{ {
it->second->Receive(event); 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> template <typename ContextType>
int EventBroker::Process() int EventBroker::Process()
{ {
const std::string contextTypeName = typeid(ContextType).name(); const std::string contextTypeName = typeid(ContextType).name();
return Process(contextTypeName); return Process(contextTypeName);
} }
#endif #endif
+7 -4
View File
@@ -11,22 +11,25 @@ template <typename EventContext>
class InputController class InputController
{ {
public: public:
InputController(EventBroker* eventBroker) InputController(std::shared_ptr<dd::EventBroker> eventBroker)
: m_EventBroker(eventBroker) : EventBroker(eventBroker)
{ Initialize(); } { Initialize(); }
virtual void Initialize() virtual void Initialize()
{ {
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &InputController::OnCommand); EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &InputController::OnCommand);
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &InputController::OnMouseMove);
} }
virtual bool OnCommand(const Events::InputCommand& e) { return false; } virtual bool OnCommand(const Events::InputCommand &event) { return false; }
virtual bool OnMouseMove(const Events::MouseMove &event) { return false; }
protected: protected:
EventBroker* m_EventBroker; std::shared_ptr<dd::EventBroker> EventBroker;
private: private:
EventRelay<EventContext, Events::InputCommand> m_EInputCommand; EventRelay<EventContext, Events::InputCommand> m_EInputCommand;
EventRelay<EventContext, Events::MouseMove> m_EMouseMove;
}; };
#endif #endif
+7 -5
View File
@@ -33,6 +33,7 @@ public:
void Initialize(); void Initialize();
static const short MAX_GAMEPADS = 4;
void Update(double dt); void Update(double dt);
@@ -49,6 +50,12 @@ private:
std::array<int, GLFW_KEY_LAST+1> m_LastKeyState; std::array<int, GLFW_KEY_LAST+1> m_LastKeyState;
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_CurrentMouseState; std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_CurrentMouseState;
std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_LastMouseState; std::array<int, GLFW_MOUSE_BUTTON_LAST+1> m_LastMouseState;
typedef std::array<float, static_cast<int>(Gamepad::Axis::LAST) + 1> GamepadAxisState;
std::array<GamepadAxisState, MAX_GAMEPADS> m_CurrentGamepadAxisState;
std::array<GamepadAxisState, MAX_GAMEPADS> m_LastGamepadAxisState;
typedef std::array<bool, static_cast<int>(Gamepad::Button::LAST) + 1> GamepadButtonState;
std::array<GamepadButtonState, MAX_GAMEPADS> m_CurrentGamepadButtonState;
std::array<GamepadButtonState, MAX_GAMEPADS> m_LastGamepadButtonState;
double m_CurrentMouseX, m_CurrentMouseY; double m_CurrentMouseX, m_CurrentMouseY;
double m_LastMouseX, m_LastMouseY; double m_LastMouseX, m_LastMouseY;
@@ -57,11 +64,6 @@ private:
void PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis); void PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis);
void PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button); void PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button);
static void GLFWMouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
LOG_DEBUG("Click! %i %i %i", button, action, mods);
}
}; };
#endif #endif
-2
View File
@@ -81,8 +81,6 @@ public:
@param resourceName Fully qualified name of the resource to reload. @param resourceName Fully qualified name of the resource to reload.
*/ */
static void Reload(std::string resourceName); static void Reload(std::string resourceName);
static void Release(std::string resourceType, std::string resourceName);
static void Update(); static void Update();
-25
View File
@@ -1,25 +0,0 @@
#ifndef System_h__
#define System_h__
#include "EventBroker.h"
#include "World.h"
#include "ComponentWrapper.h"
class System
{
friend class SystemPipeline;
public:
System(EventBroker* eventBroker, std::string componentType)
: m_EventBroker(eventBroker)
, m_ComponentType(componentType)
{ }
virtual void Update(World* world, ComponentWrapper& component, double dt) = 0;
protected:
std::string m_ComponentType;
EventBroker* m_EventBroker;
};
#endif
-58
View File
@@ -1,58 +0,0 @@
#ifndef SystemPipeline_h__
#define SystemPipeline_h__
#include "../Common.h"
#include "EventBroker.h"
#include "System.h"
#include "World.h"
class SystemPipeline
{
public:
SystemPipeline(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{ }
~SystemPipeline()
{
for (auto& pair : m_Systems) {
for (auto& system : pair.second) {
delete system;
}
}
}
template <typename T, typename... Arguments>
void AddSystem(Arguments... args)
{
System* system = new T(m_EventBroker, args...);
if (!system->m_ComponentType.empty()) {
m_Systems[system->m_ComponentType].push_back(system);
} else {
LOG_ERROR("Failed to add system \"%s\": Missing component type!", typeid(T).name());
delete system;
}
}
void Update(World* world, double dt)
{
for (auto& pair : m_Systems) {
const std::string& componentName = pair.first;
auto& systems = pair.second;
const ComponentPool* pool = world->GetComponents(componentName);
if (pool == nullptr) {
continue;
}
for (auto& component : *pool) {
for (auto& system : systems) {
system->Update(world, component, dt);
}
}
}
}
private:
EventBroker* m_EventBroker;
std::unordered_map<std::string, std::vector<System*>> m_Systems;
};
#endif
+3 -6
View File
@@ -2,7 +2,7 @@
#define World_h__ #define World_h__
#include "../Common.h" #include "../Common.h"
#include "Entity.h" #include "EntityWrapper.h"
#include "ObjectPool.h" #include "ObjectPool.h"
#include "ComponentPool.h" #include "ComponentPool.h"
@@ -12,7 +12,6 @@ public:
World() = default; World() = default;
~World(); ~World();
// Create empty entity
EntityID CreateEntity(EntityID parent = 0); EntityID CreateEntity(EntityID parent = 0);
// Register a component type and allocate space for it // Register a component type and allocate space for it
@@ -22,12 +21,10 @@ public:
// Get a component of an entity // Get a component of an entity
ComponentWrapper GetComponent(EntityID entity, std::string componentType); ComponentWrapper GetComponent(EntityID entity, std::string componentType);
// Get all components of the specified type // Get all components of the specified type
const ComponentPool* GetComponents(std::string componentType); const ComponentPool& GetComponents(std::string componentType);
// Get entity parent
EntityID GetParent(EntityID entity);
private: private:
EntityID m_CurrentEntityID = 1; EntityID m_CurrentEntityID = 0;
std::unordered_map<EntityID, EntityID> m_EntityParents; std::unordered_map<EntityID, EntityID> m_EntityParents;
std::unordered_multimap<EntityID, EntityID> m_EntityChildren; std::unordered_multimap<EntityID, EntityID> m_EntityChildren;
+24
View File
@@ -0,0 +1,24 @@
#ifndef Events_BindGamepadAxis_h__
#define Events_BindGamepadAxis_h__
#include "Core/EventBroker.h"
#include "Core/EGamepadAxis.h"
namespace Events
{
/** Called to bind a gamepad axis to an input command. */
struct BindGamepadAxis : Event
{
/** The axis to bind. */
Gamepad::Axis Axis;
/** The command to send. */
std::string Command;
/** The value to send for positive stimulation.
Multiplied by the 0-1 clamped value of the axis.
*/
float Value;
};
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef Events_BindGamepadButton_h__
#define Events_BindGamepadButton_h__
#include "Core/EventBroker.h"
#include "Core/EGamepadButton.h"
namespace Events
{
/** Called to bind a gamepad button to an input command. */
struct BindGamepadButton : Event
{
/** The gamepad button to bind. */
Gamepad::Button Button;
/** The command to send. */
std::string Command;
/** The value to send for positive stimulation.
Multiplied by the 0-1 clamped value of the button.
*/
float Value;
};
}
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef Events_BindKey_h__
#define Events_BindKey_h__
#include "Core/EventBroker.h"
namespace Events
{
/** Called to bind a keyboard key to an input command. */
struct BindKey : Event
{
/** The GLFW key code to bind. */
int KeyCode;
/** The command to send. */
std::string Command;
/** The value to send for positive stimulation.
Multiplied by the 0-1 clamped value of the key.
*/
float Value;
};
}
#endif
+25
View File
@@ -0,0 +1,25 @@
#ifndef Events_BindMouseButton_h__
#define Events_BindMouseButton_h__
#include "Core/EventBroker.h"
namespace Events
{
/** Called to bind a mouse button to an input command. */
struct BindMouseButton : Event
{
/** The GLFW mouse button code to bind. */
int Button;
/** The command to send. */
std::string Command;
/** The value to send for positive stimulation.
Multiplied by the 0-1 clamped value of the button.
*/
float Value;
};
}
#endif
-22
View File
@@ -1,22 +0,0 @@
#ifndef Events_BindOrigin_h__
#define Events_BindOrigin_h__
#include "Core/EventBroker.h"
namespace Events
{
/** Called to bind an input origin to an input command. */
struct BindOrigin : Event
{
/** The input origin to bind. */
std::string Origin;
/** The command to send. */
std::string Command;
/** The value to send for positive stimulation. */
float Value = 1.f;
};
}
#endif
+1 -1
View File
@@ -13,7 +13,7 @@ struct InputCommand : Event
/** The command that was sent. */ /** The command that was sent. */
std::string Command; std::string Command;
/** The value of the command. */ /** The value of the command. */
float Value = 0; float Value;
}; };
} }
@@ -1,70 +0,0 @@
#ifndef FirstPersonInputController_h__
#define FirstPersonInputController_h__
#include "../GLM.h"
#include "../Core/InputController.h"
#include "../Core/ELockMouse.h"
template <typename EventContext>
class FirstPersonInputController : public InputController<EventContext>
{
public:
FirstPersonInputController(EventBroker* eventBroker, unsigned int playerID)
: InputController(eventBroker)
, m_PlayerID(playerID)
{
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &FirstPersonInputController::OnLockMouse);
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &FirstPersonInputController::OnUnlockMouse);
}
const glm::quat Orientation() const { return m_Orientation; }
void LockMouse()
{
Events::LockMouse e;
m_EventBroker->Publish(e);
m_MouseLocked = true;
}
void UnlockMouse()
{
Events::UnlockMouse e;
m_EventBroker->Publish(e);
m_MouseLocked = false;
}
virtual bool OnCommand(const Events::InputCommand& e) override
{
if (m_PlayerID != e.PlayerID) {
return false;
}
if (m_MouseLocked) {
if (e.Command == "Pitch") {
float val = glm::radians(e.Value);
m_Orientation = m_Orientation * glm::angleAxis<float>(-val, glm::vec3(1, 0, 0));
return true;
}
if (e.Command == "Yaw") {
float val = glm::radians(e.Value);
m_Orientation = glm::angleAxis<float>(-val, glm::vec3(0, 1, 0)) * m_Orientation;
return true;
}
}
return false;
}
protected:
const unsigned int m_PlayerID;
glm::quat m_Orientation;
bool m_MouseLocked = false;
EventRelay<EventContext, Events::LockMouse> m_ELockMouse;
bool OnLockMouse(const Events::LockMouse& e) { m_MouseLocked = true; return true; }
EventRelay<EventContext, Events::UnlockMouse> m_EUnlockMouse;
bool OnUnlockMouse(const Events::UnlockMouse& e) { m_MouseLocked = false; return true; }
};
#endif
-25
View File
@@ -1,25 +0,0 @@
#ifndef InputHandler_h__
#define InputHandler_h__
#include "../Common.h"
#include "../Core/EventBroker.h"
#include "InputProxy.h"
class InputHandler
{
public:
InputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
: m_EventBroker(eventBroker)
, m_InputProxy(inputProxy)
{ }
virtual bool BindOrigin(std::string origin, std::string command, float value) = 0;
virtual void Update(double dt) { }
virtual float GetCommandValue(std::string command) = 0;
protected:
EventBroker* m_EventBroker;
InputProxy* m_InputProxy;
};
#endif
-46
View File
@@ -1,46 +0,0 @@
#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
+78
View File
@@ -0,0 +1,78 @@
#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
@@ -1,28 +0,0 @@
#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
-38
View File
@@ -1,38 +0,0 @@
#ifndef MouseInputHandler_h__
#define MouseInputHandler_h__
#include <GLFW/glfw3.h>
#include "InputHandler.h"
#include "Core/EMousePress.h"
#include "Core/EMouseRelease.h"
#include "Core/EMouseMove.h"
class MouseInputHandler : public InputHandler
{
public:
MouseInputHandler(EventBroker* eventBroker, InputProxy* inputProxy);
bool BindOrigin(std::string origin, std::string command, float value) override;
virtual float GetCommandValue(std::string command) override;
private:
std::unordered_map<std::string, int> m_OriginCodes;
std::unordered_map<std::string, char> m_OriginAxes;
std::unordered_map<int, std::tuple<std::string, float>> m_Bindings; // GLFW_MOUSE_BUTTON... -> command string & value
std::unordered_map<char, std::tuple<std::string, float>> m_Axes; // Axis -> command string & value
std::unordered_map<std::string, float> m_CommandValues;
std::unordered_map<std::string, float> m_ContinuousCommandValues;
EventRelay<InputHandler, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<InputHandler, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e);
EventRelay<InputHandler, Events::MouseMove> m_EMouseMove;
bool OnMouseMove(const Events::MouseMove& e);
bool hasOrigin(std::string origin);
};
#endif
@@ -1,40 +0,0 @@
#ifndef XboxControllerInputHandler_h__
#define XboxControllerInputHandler_h__
#include "InputHandler.h"
#include "Core/EKeyDown.h"
#include "Core/EKeyUp.h"
struct _XINPUT_STATE;
typedef _XINPUT_STATE XINPUT_STATE;
class XboxControllerInputHandler : public InputHandler
{
public:
XboxControllerInputHandler(EventBroker* eventBroker, InputProxy* inputProxy);
bool BindOrigin(std::string origin, std::string command, float value) override;
void Update(double dt) override;
virtual float GetCommandValue(std::string command) override;
private:
std::unordered_map<std::string, int> m_OriginButtons;
std::unordered_map<std::string, int> m_OriginAxes;
std::unordered_map<int, std::tuple<std::string, float>> m_ButtonBindings; // GLFW_KEY... -> command string & value
std::unordered_map<int, std::tuple<std::string, float>> m_AxisBindings; // GLFW_KEY... -> command string & value
std::unordered_map<std::string, float> m_CommandValues;
static const short MAX_GAMEPADS = 4;
float getAxisValue(XINPUT_STATE& state, int axis);
//typedef std::array<float, static_cast<int>(Gamepad::Axis::LAST) + 1> GamepadAxisState;
//std::array<GamepadAxisState, MAX_GAMEPADS> m_CurrentGamepadAxisState;
//std::array<GamepadAxisState, MAX_GAMEPADS> m_LastGamepadAxisState;
//typedef std::array<bool, static_cast<int>(Gamepad::Button::LAST) + 1> GamepadButtonState;
//std::array<GamepadButtonState, MAX_GAMEPADS> m_CurrentGamepadButtonState;
//std::array<GamepadButtonState, MAX_GAMEPADS> m_LastGamepadButtonState;
};
#endif
@@ -1,48 +0,0 @@
#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
{
if (e.Command == "PrimaryFire") {
if (e.Value > 0) {
LockMouse();
} else {
UnlockMouse();
}
return false;
}
if (e.Command == "Right") {
float value = std::max(-1.f, std::min(e.Value, 1.f));
m_Velocity.x = value;
}
if (e.Command == "Forward") {
float value = std::max(-1.f, std::min(e.Value, 1.f));
m_Velocity.z = -value;
}
return FirstPersonInputController::OnCommand(e);
}
void Update(double dt)
{
if (glm::length2(m_Velocity) > 0) {
m_Position += (m_Orientation * (m_Velocity * m_BaseSpeed)) * (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;
};
-69
View File
@@ -1,69 +0,0 @@
#ifndef Events_Picking_h__
#define Events_Picking_h__
#include "../OpenGL.h"
#include "../GLM.h"
#include "../Core/EventBroker.h"
#include "Util/ScreenCoords.h"
#include "FrameBuffer.h"
#include "../Core/Entity.h"
#include "Util/UnorderedMapVec2.h"
namespace Events
{
/** Thrown Every frame, use functions to pick*/
struct Picking : Event
{
public:
Picking(FrameBuffer* pickingBuffer, GLuint* depthBuffer, glm::mat4 projectionMatrix, glm::mat4 viewMatrix, Rectangle resolution, const std::unordered_map<glm::vec2, EntityID>* pickingColorsToEntity)
: PickingBuffer(pickingBuffer)
, DepthBuffer(depthBuffer)
, ProjectionMatrix(projectionMatrix)
, ViewMatrix(viewMatrix)
, Resolution(resolution)
, PickingColorsToEntity(pickingColorsToEntity)
{ }
struct PickData
{
//Picked Entity
EntityID Entity;
//World position of the "pick"
glm::vec3 Position;
};
PickData Pick(glm::vec2 screenCoord) const
{
PickData pickData;
ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer);
auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1]));
if (it != PickingColorsToEntity->end()) {
pickData.Entity = it->second;
} else {
pickData.Entity = -1;
}
pickData.Position = ScreenCoords::ToWorldPos(screenCoord.x, Resolution.Width - screenCoord.y, data.Depth, Resolution, ProjectionMatrix, ViewMatrix);
return pickData;
}
private:
FrameBuffer* PickingBuffer;
GLuint* DepthBuffer;
const glm::mat4 ProjectionMatrix;
const glm::mat4 ViewMatrix;
const Rectangle Resolution;
const std::unordered_map<glm::vec2, EntityID>* PickingColorsToEntity;
};
}
#endif
+1 -1
View File
@@ -7,7 +7,7 @@
#include "../Common.h" #include "../Common.h"
#include "../GLM.h" #include "../GLM.h"
#include "../Core/Util/Rectangle.h" #include "../Core/Util/Rectangle.h"
#include "../Core/Entity.h" #include "../Core/EntityWrapper.h"
class Model; class Model;
class Skeleton; class Skeleton;
@@ -22,10 +22,7 @@ private:
void FillLights(World* world, RenderQueue* renderQueue); void FillLights(World* world, RenderQueue* renderQueue);
glm::mat4 ModelMatrix(World* world, EntityID entity); glm::mat4 ModelMatrix(World* world, EntityID entity);
glm::vec3 GetAbsolutePosition(World* world, ComponentWrapper transformComponent);
glm::vec3 AbsolutePosition(World* world, EntityID entity);
glm::quat AbsoluteOrientation(World* world, EntityID entity);
glm::vec3 AbsoluteScale(World* world, EntityID entity);
}; };
#endif #endif
+2 -9
View File
@@ -11,24 +11,15 @@
#include "FrameBuffer.h" #include "FrameBuffer.h"
#include "../Core/World.h" #include "../Core/World.h"
#include "../Core/EventBroker.h"
#include "EPicking.h"
class Renderer : public IRenderer class Renderer : public IRenderer
{ {
public: public:
Renderer(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{ }
virtual void Initialize() override; virtual void Initialize() override;
virtual void Update(double dt) override; virtual void Update(double dt) override;
virtual void Draw(RenderQueueCollection& rq) override; virtual void Draw(RenderQueueCollection& rq) override;
private: private:
//----------------------Variables----------------------// //----------------------Variables----------------------//
EventBroker* m_EventBroker;
Texture* m_ErrorTexture; Texture* m_ErrorTexture;
Texture* m_WhiteTexture; Texture* m_WhiteTexture;
float m_CameraMoveSpeed; float m_CameraMoveSpeed;
@@ -40,6 +31,8 @@ private:
Model* m_UnitQuad; Model* m_UnitQuad;
Model* m_UnitSphere; Model* m_UnitSphere;
std::unordered_map<glm::vec2, EntityID> m_PickingColorsToEntity; std::unordered_map<glm::vec2, EntityID> m_PickingColorsToEntity;
//----------------------Functions----------------------// //----------------------Functions----------------------//
+2 -9
View File
@@ -11,13 +11,6 @@ class ScreenCoords
{ {
public: public:
ScreenCoords() = delete; ScreenCoords() = delete;
struct PixelData
{
int Color[2];
float Depth;
};
//Return world position from given screenspace coordinates and depth value in viewspace. //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(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); static glm::vec3 ToWorldPos(float x, float y, float depth, Rectangle resolution, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat);
@@ -25,8 +18,8 @@ public:
static glm::vec3 ToWorldPos(float x, float y, float depth, float screenWidth, float screenHeight, glm::mat4 cameraProjectionMat, glm::mat4 cameraViewMat); 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. //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 //Data is given as R = x, B = y, and
static PixelData ToPixelData(glm::vec2 screenCoord, FrameBuffer* PickDataBuffer, GLuint DepthBuffer); static glm::vec3 ToPixelData(glm::vec2 screenCoord, FrameBuffer* PickDataBuffer, GLuint DepthBuffer);
static PixelData ToPixelData(float x, float y, FrameBuffer* PickDataBuffer, GLuint DepthBuffer); static glm::vec3 ToPixelData(float x, float y, FrameBuffer* PickDataBuffer, GLuint DepthBuffer);
//Return EntityID of the clicked coordinate in given screenspace coordinates. //Return EntityID of the clicked coordinate in given screenspace coordinates.
//EntityID ScreenCoordsToEntityID(glm::vec2 screenCoord, float depth); //EntityID ScreenCoordsToEntityID(glm::vec2 screenCoord, float depth);
-17
View File
@@ -9,15 +9,6 @@
#include "GUI/Frame.h" #include "GUI/Frame.h"
#include "Core/World.h" #include "Core/World.h"
#include "Rendering/RenderQueueFactory.h" #include "Rendering/RenderQueueFactory.h"
#include "Input/InputProxy.h"
#include "Input/KeyboardInputHandler.h"
#include "Input/MouseInputHandler.h"
#include "Input/XboxControllerInputHandler.h"
#include "Core/EKeyDown.h"
#include "Core/EntityXMLFile.h"
#include "Core/SystemPipeline.h"
#include "RaptorCopterSystem.h"
#include "PlayerSystem.h"
class Game class Game
{ {
@@ -34,17 +25,9 @@ private:
EventBroker* m_EventBroker; EventBroker* m_EventBroker;
IRenderer* m_Renderer; IRenderer* m_Renderer;
InputManager* m_InputManager; InputManager* m_InputManager;
InputProxy* m_InputProxy;
GUI::Frame* m_FrameStack; GUI::Frame* m_FrameStack;
World* m_World; World* m_World;
SystemPipeline* m_SystemPipeline;
RenderQueueFactory* m_RenderQueueFactory; RenderQueueFactory* m_RenderQueueFactory;
EventRelay<Game, Events::InputCommand> m_EInputCommand;
bool debugOnInputCommand(const Events::InputCommand& e);
void debugInitialize();
void debugTick(double dt);
}; };
#endif #endif
+110
View File
@@ -0,0 +1,110 @@
#include <list>
#include <tuple>
#include <boost/any.hpp>
#include "GLM.h"
#include "Core/World.h"
#include "Core/Util/Any.h"
class HardcodedTestWorld : public World
{
public:
HardcodedTestWorld()
: World()
{
registerTestComponents();
createTestEntities();
}
private:
void registerTestComponents()
{
ComponentWrapperFactory f;
f = ComponentWrapperFactory("Test");
f.AddProperty("TestInteger", 1337);
f.AddProperty("TestFloat", 13.37f);
f.AddProperty("TestString", std::string("Carlito"));
RegisterComponent(f);
f = ComponentWrapperFactory("Debug");
f.AddProperty("Name", std::string("Unnamed"));
RegisterComponent(f);
f = ComponentWrapperFactory("Transform");
f.AddProperty("Position", glm::vec3(0.f, 0.f, 0.f));
f.AddProperty("Orientation", glm::quat());
f.AddProperty("Scale", glm::vec3(1.f, 1.f, 1.f));
RegisterComponent(f);
f = ComponentWrapperFactory("Model");
f.AddProperty("Resource", std::string());
f.AddProperty("Color", glm::vec4(1.f, 1.f, 1.f, 1.f));
f.AddProperty("Visible", true);
RegisterComponent(f);
}
void createTestEntities()
{
World& world = *this;
// Create an entity
EntityID e = world.CreateEntity();
// Attach a Debug component
ComponentWrapper debug = world.AttachComponent(e, "Debug");
// Set the Name field of the Debug component using subscript operator
debug["Name"] = "Carlito";
// Attach a Transform component
world.AttachComponent(e, "Transform");
// Fetch the component based on EntityID and component type
ComponentWrapper transform = world.GetComponent(e, "Transform");
// Set the fields of the Transform component
transform["Position"] = glm::vec3(0.f, 0.f, 0.f);
transform["Scale"] = glm::vec3(1.f, 1.f, 1.f);
// Move on the X axis by fetching field as reference
((glm::vec3&)transform["Position"]).x += 10.f;
// Shrink by a factor of 100
((glm::vec3&)transform["Scale"]) /= 100.f;
// Loop through all Transform components and print them
for (auto& transform : world.GetComponents("Transform")) {
glm::vec3 pos = transform["Position"];
std::cout << "Position: " << pos.x << " " << pos.y << " " << pos.z << std::endl;
glm::vec3 scale = transform["Scale"];
std::cout << "Scale: " << scale.x << " " << scale.y << " " << scale.z << std::endl;
// Fetch the Debug component also present in this entity
ComponentWrapper debug = world.GetComponent(transform.EntityID, "Debug");
std::cout << "Name: " << (std::string)debug["Name"] << std::endl;
}
//Create some test widgets
{
EntityID entityScaleWidget = world.CreateEntity();
ComponentWrapper transform = world.AttachComponent(entityScaleWidget, "Transform");
transform["Position"] = glm::vec3(-1.5f, 0.f, 0.f);
ComponentWrapper model = world.AttachComponent(entityScaleWidget, "Model");
model["Resource"] = "Models/ScaleWidget.obj";
}
{
EntityID entityRotationWidget = world.CreateEntity();
ComponentWrapper transform = world.AttachComponent(entityRotationWidget, "Transform");
transform["Position"] = glm::vec3(1.5f, 0.f, 0.f);
ComponentWrapper model = world.AttachComponent(entityRotationWidget, "Model");
model["Resource"] = "Models/RotationWidget.obj";
}
{
EntityID entityDummyScene = world.CreateEntity();
ComponentWrapper transform = world.AttachComponent(entityDummyScene, "Transform");
transform["Position"] = glm::vec3(0, 0.f, 0.f);
ComponentWrapper model = world.AttachComponent(entityDummyScene, "Model");
model["Resource"] = "Models/DummyScene.obj";
}
}
};
-44
View File
@@ -1,44 +0,0 @@
#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 System
{
public:
PlayerSystem(EventBroker* eventBroker)
: System(eventBroker, "Player")
{
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &PlayerSystem::OnKeyDown);
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &PlayerSystem::OnKeyUp);
}
virtual void Update(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
-18
View File
@@ -1,18 +0,0 @@
#include "Common.h"
#include "Core/System.h"
class RaptorCopterSystem : public System
{
public:
RaptorCopterSystem(EventBroker* eventBroker)
: System(eventBroker, "RaptorCopter")
{ }
virtual void Initialize() { }
virtual void Update(World* world, ComponentWrapper& raptorCopter, double dt) override
{
ComponentWrapper& transform = world->GetComponent(raptorCopter.EntityID, "Transform");
(glm::vec3&)transform["Orientation"] += (float)(double)raptorCopter["Speed"] * (float)dt * (glm::vec3)raptorCopter["Axis"];
}
};
-1
View File
@@ -1,6 +1,5 @@
[Debug] [Debug]
LogLevel=1 LogLevel=1
LoadMap=
[Video] [Video]
Fullscreen=false Fullscreen=false
-24
View File
@@ -1,24 +0,0 @@
[Mouse]
Sensitivity=0.5
InvertPitch=false
[Bindings]
MouseLeft=PrimaryFire
MouseX=Yaw
MouseY=Pitch
W=+Forward
S=-Forward
D=+Right
A=-Right
R=Reload
Space=Jump
LeftControl=Crouch
LeftShift=Sprint
GamepadRightTrigger=PrimaryFire
GamepadRightX=Yaw
GamepadRightY=-Pitch
GamepadA=TestGamepadA
GamepadX=TestGamepadX
GamepadLeftX=Right
GamepadLeftY=Forward
-3
View File
@@ -2,8 +2,5 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="components" elementFormDefault="qualified"> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="components" elementFormDefault="qualified">
<xs:include schemaLocation="Components/Transform.xsd"/> <xs:include schemaLocation="Components/Transform.xsd"/>
<xs:include schemaLocation="Components/Model.xsd"/>
<xs:include schemaLocation="Components/Test.xsd"/> <xs:include schemaLocation="Components/Test.xsd"/>
<xs:include schemaLocation="Components/RaptorCopter.xsd"/>
<xs:include schemaLocation="Components/Player.xsd"/>
</xs:schema> </xs:schema>
-5
View File
@@ -1,5 +0,0 @@
<c:Model>
<Resource></Resource>
<Color R="1" G="1" B="1" A="1"/>
<Visible>true</Visible>
</c:Model>
-24
View File
@@ -1,24 +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="Model">
<xs:annotation>
<xs:documentation>A visible model loaded from disk</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Resource" type="t:string" minOccurs="0">
<xs:annotation><xs:documentation>Model file</xs:documentation></xs:annotation>
</xs:element>
<xs:element name="Color" type="t:Color" minOccurs="0">
<xs:annotation><xs:documentation>Color tint</xs:documentation></xs:annotation>
</xs:element>
<xs:element name="Visible" type="t:bool" minOccurs="0">
<xs:annotation><xs:documentation>Wether the model is visible or not</xs:documentation></xs:annotation>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
-3
View File
@@ -1,3 +0,0 @@
<c:Player>
<Velocity X="0" Y="0" Z="0"/>
</c:Player>
-13
View File
@@ -1,13 +0,0 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="Player">
<xs:complexType>
<xs:all>
<xs:element name="Velocity" type="t:Vector" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -1,4 +0,0 @@
<c:RaptorCopter>
<Speed>0</Speed>
<Axis X="0" Y="0" Z="0"/>
</c:RaptorCopter>
@@ -1,14 +0,0 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="RaptorCopter">
<xs:complexType>
<xs:all>
<xs:element name="Speed" type="t:double" minOccurs="0"/>
<xs:element name="Axis" type="t:Vector" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+1 -1
View File
@@ -2,5 +2,5 @@
<Integer>1</Integer> <Integer>1</Integer>
<Float>1.333</Float> <Float>1.333</Float>
<Vector X="1.33333" Y="2.33333" Z="3.33333"/> <Vector X="1.33333" Y="2.33333" Z="3.33333"/>
<Quaternion X="1.33333" Y="2.33333" Z="3.33333" W="4.44444"/> <Quaternion I="1.33333" J="2.33333" K="3.33333"/>
</c:Test> </c:Test>
+3 -3
View File
@@ -1,5 +1,5 @@
<c:Transform> <TransformComponent>
<Position X="0" Y="0" Z="0"/> <Position X="0" Y="0" Z="0"/>
<Orientation X="0" Y="0" Z="0" W="0"/> <Orientation I="0" J="0" K="0"/>
<Scale X="1" Y="1" Z="1"/> <Scale X="1" Y="1" Z="1"/>
</c:Transform> </TransformComponent>
+1 -1
View File
@@ -12,7 +12,7 @@
<xs:element name="Position" type="t:Vector" minOccurs="0"> <xs:element name="Position" type="t:Vector" minOccurs="0">
<xs:annotation><xs:documentation>The position vector</xs:documentation></xs:annotation> <xs:annotation><xs:documentation>The position vector</xs:documentation></xs:annotation>
</xs:element> </xs:element>
<xs:element name="Orientation" type="t:Vector" minOccurs="0"/> <xs:element name="Orientation" type="t:Quaternion" minOccurs="0"/>
<xs:element name="Scale" type="t:Vector" minOccurs="0"/> <xs:element name="Scale" type="t:Vector" minOccurs="0"/>
</xs:all> </xs:all>
</xs:complexType> </xs:complexType>
+10 -107
View File
@@ -3,115 +3,18 @@
<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"> <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> <Components>
<c:Transform> <c:Transform>
<Orientation X="0" Y="0" Z="0"/> <Position X="1.02" Y="3.123123" Z="41.123"/>
<Orientation I="1.234" J="1.234" K="1.234"/>
<Scale X="1.02" Y="3.123123" Z="41.123"/>
</c:Transform> </c:Transform>
<c:Model> <c:Test>
<Resource>Models/DummyScene.obj</Resource> <Integer>12</Integer>
</c:Model> <Double>11.11</Double>
<String>Hello World</String>
</c:Test>
</Components> </Components>
<Children> <Children>
<Entity> <xi:include href="OtherEntity.xml"/>
<Components> <xi:include href="OtherEntity.xml"/>
<c:Transform>
<Position X="-1.5"/>
<Scale X="1" Y="1" Z="1"/>
</c:Transform>
<c:Model>
<Resource>Models/ScaleWidget.obj</Resource>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="1.5"/>
</c:Transform>
<c:Model>
<Resource>Models/RotationWidget.obj</Resource>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c: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>
<Position X="0" Y="-0"/>
<Scale X="1" Y="1" Z="1"/>
</c:Transform>
<!--<c:Move>
<Speed>1</Speed>
<Direction X="-1"/>
<Rotation Y="3.14"/>
</c:Move>-->
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Orientation X="0.0" Y="0" Z="1.0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitRaptor.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="-0.01" Y="0.55"/>
<Orientation X="0" Y="0" Z="-1"/>
</c:Transform>
<c:RaptorCopter>
<Speed>20</Speed>
<Axis Y="1"/>
</c:RaptorCopter>
</Components>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Scale X="1.7" Y="0.03" Z="0.1"/>
<Orientation X="0" Y="0" Z="0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
</Entity>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="0"/>
<Scale X="1.7" Y="0.03" Z="0.1"/>
<Orientation X="0" Y="1.57" Z="0"/>
</c:Transform>
<c:Model>
<Resource>Models/Core/UnitCube.obj</Resource>
<Color R="1" G="0.4" B="0.8"/>
</c:Model>
</Components>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
</Children>
</Entity>
</Children> </Children>
</Entity> </Entity>
-4
View File
@@ -3,10 +3,6 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="types" elementFormDefault="qualified"> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="types" elementFormDefault="qualified">
<xs:include schemaLocation="Types/Quaternion.xsd"/> <xs:include schemaLocation="Types/Quaternion.xsd"/>
<xs:include schemaLocation="Types/Vector.xsd"/> <xs:include schemaLocation="Types/Vector.xsd"/>
<xs:include schemaLocation="Types/Color.xsd"/>
<xs:simpleType name="bool">
<xs:restriction base="xs:boolean"></xs:restriction>
</xs:simpleType>
<xs:simpleType name="int"> <xs:simpleType name="int">
<xs:restriction base="xs:integer"></xs:restriction> <xs:restriction base="xs:integer"></xs:restriction>
</xs:simpleType> </xs:simpleType>
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="types" elementFormDefault="qualified">
<xs:complexType name="Color">
<xs:attribute name="R" type="xs:decimal" default="0.0"/>
<xs:attribute name="G" type="xs:decimal" default="0.0"/>
<xs:attribute name="B" type="xs:decimal" default="0.0"/>
<xs:attribute name="A" type="xs:decimal" default="1.0"/>
</xs:complexType>
</xs:schema>
+1 -4
View File
@@ -7,14 +7,11 @@
<xs:element name="Entity"> <xs:element name="Entity">
<xs:complexType> <xs:complexType>
<xs:all> <xs:all>
<xs:element name="Components" minOccurs="0"> <xs:element name="Components">
<xs:complexType> <xs:complexType>
<xs:all> <xs:all>
<xs:element ref="c:Transform" minOccurs="0"/> <xs:element ref="c:Transform" minOccurs="0"/>
<xs:element ref="c:Model" minOccurs="0"/>
<xs:element ref="c:Test" minOccurs="0"/> <xs:element ref="c:Test" minOccurs="0"/>
<xs:element ref="c:RaptorCopter" minOccurs="0"/>
<xs:element ref="c:Player" minOccurs="0"/>
</xs:all> </xs:all>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
+1 -1
View File
@@ -13,7 +13,7 @@ out vec4 TextureFragment;
void main() void main()
{ {
TextureFragment = vec4(PickingColor/255, 0, 1); TextureFragment = vec4(PickingColor, 0, 1);
} }
+1 -1
View File
@@ -73,7 +73,7 @@ source_group(GUI FILES ${SOURCE_FILES_GUI})
set(SOURCE_FILES set(SOURCE_FILES
${SOURCE_FILES_Core} ${SOURCE_FILES_Core}
${SOURCE_FILES_Core_Util} ${SOURCE_FILES_Core_Util}
${SOURCE_FILES_Input} #${SOURCE_FILES_Input}
${SOURCE_FILES_Network} ${SOURCE_FILES_Network}
${SOURCE_FILES_GUI} ${SOURCE_FILES_GUI}
${SOURCE_FILES_Rendering} ${SOURCE_FILES_Rendering}
+2 -5
View File
@@ -24,11 +24,8 @@ ConfigFile::ConfigFile(std::string path)
if (boost::filesystem::exists(m_Path)) { if (boost::filesystem::exists(m_Path)) {
try { try {
boost::property_tree::ini_parser::read_ini(m_Path.string(), m_PTreeOverrides); boost::property_tree::ini_parser::read_ini(m_Path.string(), m_PTreeOverrides);
for (auto& topLevelNode : m_PTreeOverrides) { for (auto& node : m_PTreeOverrides) {
auto& mergedTopLevelNode = m_PTreeMerged.find(topLevelNode.first); m_PTreeMerged.put_child(node.first, node.second);
for (auto& childOverrideNode : topLevelNode.second) {
mergedTopLevelNode->second.put_child(childOverrideNode.first, childOverrideNode.second);
}
} }
} catch (boost::property_tree::ptree_error& e) { } catch (boost::property_tree::ptree_error& e) {
LOG_ERROR("Failed to parse \"%s\":\n%s", m_Path.filename().string().c_str(), e.what()); LOG_ERROR("Failed to parse \"%s\":\n%s", m_Path.filename().string().c_str(), e.what());
-481
View File
@@ -1,481 +0,0 @@
#include "Core/EntityXMLFile.h"
#include "Core/World.h"
unsigned int EntityXMLFile::InstanceCount = 0;
EntityXMLFile::EntityXMLFile(std::string path)
: m_EntityFile(path)
{
using namespace xercesc;
if (InstanceCount == 0) {
XMLPlatformUtils::Initialize();
}
InstanceCount++;
m_GrammarPool = new XMLGrammarPoolImpl();
m_ErrorHandler = new EntityParserXMLErrorHandler();
m_DOMParser = new XercesDOMParser(nullptr, XMLPlatformUtils::fgMemoryManager, m_GrammarPool);
m_DOMParser->setErrorHandler(m_ErrorHandler);
m_DOMParser->setDoNamespaces(true);
m_DOMParser->setDoXInclude(true);
m_DOMParser->setDoSchema(true);
m_DOMParser->setValidationSchemaFullChecking(true);
m_DOMParser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
m_DOMParser->setValidationSchemaFullChecking(true);
m_DOMParser->setValidationConstraintFatal(false);
m_DOMParser->setIncludeIgnorableWhitespace(false);
// Make sure schema grammar is kept after validation
m_DOMParser->cacheGrammarFromParse(true);
// HACK: Use Sax2 parser instead so the entire DOM doesn't have to reside in memory
m_DOMParser->parse(m_EntityFile.c_str());
m_DOMDocument = m_DOMParser->getDocument();
// 1. Fill in ComponentInfo name, fields, default values and metadata from PSVI
parseComponentInfo();
// 2. Parse default value files for those components
parseDefaults();
// 3. Allocate component structures
predictComponentAllocation();
}
EntityXMLFile::~EntityXMLFile()
{
using namespace xercesc;
if (m_DOMParser != nullptr) {
delete m_DOMParser;
}
if (m_ErrorHandler != nullptr) {
delete m_ErrorHandler;
}
if (m_GrammarPool != nullptr) {
delete m_GrammarPool;
}
InstanceCount--;
if (InstanceCount == 0) {
XMLPlatformUtils::Terminate();
}
}
void EntityXMLFile::PopulateWorld(World* world)
{
for (auto& pair : m_ComponentInfo) {
world->RegisterComponent(pair.second);
}
// 4. Parse entity hierarchy
auto root = m_DOMDocument->getDocumentElement();
parseEntityGraph(world, root, 0);
}
void EntityXMLFile::preprocess(std::string inPath, std::string outPath)
{
using namespace xercesc;
static const XMLCh gLS[] = { 'L', 'S', '\0' };
DOMImplementationLS* di = static_cast<DOMImplementationLS*>(DOMImplementationRegistry::getDOMImplementation(gLS));
// Parse the file
DOMLSParser* parser = di->createLSParser(DOMImplementationLS::MODE_SYNCHRONOUS, nullptr);
DOMConfiguration* config = parser->getDomConfig();
config->setParameter(XMLUni::fgDOMNamespaces, true);
config->setParameter(XMLUni::fgXercesSchema, true);
config->setParameter(XMLUni::fgXercesHandleMultipleImports, true);
config->setParameter(XMLUni::fgXercesSchemaFullChecking, true);
config->setParameter(XMLUni::fgXercesDoXInclude, true);
auto errHandler = new EntityPreprocessorXMLErrorHandler();
config->setParameter(XMLUni::fgDOMErrorHandler, errHandler);
auto source = new LocalFileInputSource(XSTR(inPath.c_str()));
Wrapper4InputSource* domSourceWrapper = new Wrapper4InputSource(source);
DOMDocument* doc = parser->parse(dynamic_cast<DOMLSInput*>(domSourceWrapper));
// Serialize and output the new XML
DOMLSSerializer* writer = di->createLSSerializer();
DOMLSOutput* output = di->createLSOutput();
XMLFormatTarget* formatTarget = new LocalFileFormatTarget(outPath.c_str());
// TODO: MemBufFormatTarget* formatTarget = new MemBufFormatTarget()
output->setByteStream(formatTarget);
writer->write(doc, output);
delete formatTarget;
output->release();
writer->release();
parser->release();
}
void EntityXMLFile::parseComponentInfo()
{
using namespace xercesc;
bool wasChanged;
XSModel* xsModel = m_GrammarPool->getXSModel(wasChanged);
// Find component xsd element declarations
std::cout << "Enumerating components..." << std::endl;
// <xs:element name="ComponentName">
auto topLevelElements = xsModel->getComponents(XSConstants::ELEMENT_DECLARATION);
for (unsigned int i = 0; i < topLevelElements->getLength(); ++i) {
auto element = static_cast<XSElementDeclaration*>(topLevelElements->item(i));
std::string nameSpace(XSTR(element->getNamespace()));
if (nameSpace != "components") {
continue;
}
ComponentInfo compInfo;
// Name
compInfo.Name = XSTR(element->getName());
// Annotation
auto componentAnnotation = element->getAnnotation();
if (componentAnnotation != nullptr) {
// Parse annotation XML
char* annotationString = XMLString::transcode(componentAnnotation->getAnnotationString());
MemBufInputSource annotationInput(reinterpret_cast<const XMLByte*>(annotationString), strlen(annotationString), "MemBuf: Annotation String");
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager, m_GrammarPool);
parser.setErrorHandler(m_ErrorHandler);
parser.parse(annotationInput);
XMLString::release(&annotationString);
auto doc = parser.getDocument();
// Add allocation estimation(s)
auto allocationTags = doc->getElementsByTagName(XSTR("meta:allocation"));
for (int i = 0; i < allocationTags->getLength(); ++i) {
auto allocation = dynamic_cast<DOMElement*>(allocationTags->item(i));
auto child = allocation->getFirstChild();
if (child == nullptr) {
continue;
}
XSValue::Status status;
XSValue* val = XSValue::getActualValue(child->getNodeValue(), XSValue::dt_integer, status);
compInfo.Meta.Allocation += val->fData.fValue.f_int;
}
// Save documentation string
auto documentationTags = doc->getElementsByTagName(XSTR("xs:documentation"));
if (documentationTags->getLength() != 0) {
auto child = documentationTags->item(0)->getFirstChild();
if (child != nullptr) {
compInfo.Meta.Annotation = XSTR(child->getNodeValue());
}
}
// TODO: Parse annotation string XML
// compInfo.Meta.Allocation = ...
} else {
std::cout << "Warning: Component is missing an annotation!" << std::endl;
}
// <xs:complexType>
auto typeDefinition = element->getTypeDefinition();
if (typeDefinition->getTypeCategory() != XSTypeDefinition::COMPLEX_TYPE) {
std::cerr << "Error: Type definition wasn't COMPLEX_TYPE! Skipping." << std::endl;
continue;
}
auto complexTypeDefinition = dynamic_cast<XSComplexTypeDefinition*>(typeDefinition);
// <xs:all>
auto modelGroupParticle = complexTypeDefinition->getParticle();
if (modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
std::cerr << "Error: Model group particle wasn't TERM_MODELGROUP! Skipping." << std::endl;
continue;
}
auto modelGroup = modelGroupParticle->getModelGroupTerm();
// <xs:element...
// <xs:attribute...
unsigned int fieldOffset = 0;
auto particles = modelGroup->getParticles();
for (unsigned int i = 0; i < particles->size(); ++i) {
auto particle = particles->elementAt(i);
if (particle->getTermType() != XSParticle::TERM_ELEMENT) {
std::cerr << "Error: Particle wasn't TERM_ELEMENT! Skipping." << std::endl;
continue;
}
auto elementDeclaration = particle->getElementTerm();
std::string name = XSTR(elementDeclaration->getName());
std::string type = XSTR(elementDeclaration->getTypeDefinition()->getName());
size_t stride = getTypeStride(type);
if (stride == 0) {
std::cout << "Warning: Field \"" << name << "\" in component \"" << compInfo.Name << "\" uses unexpected field type \"" << type << "\". Skipping." << std::endl;
continue;
}
compInfo.FieldTypes[name] = type;
compInfo.FieldOffsets[name] = fieldOffset;
fieldOffset += getTypeStride(type);
}
compInfo.Meta.Stride = fieldOffset;
m_ComponentInfo[compInfo.Name] = compInfo;
}
}
void EntityXMLFile::parseDefaults()
{
using namespace xercesc;
for (auto& ci : m_ComponentInfo) {
// Allocate memory for default values
ci.second.Defaults = std::shared_ptr<char>(new char[ci.second.Meta.Stride]);
memset(ci.second.Defaults.get(), 0, ci.second.Meta.Stride);
XercesDOMParser parser(nullptr, XMLPlatformUtils::fgMemoryManager);
parser.setErrorHandler(m_ErrorHandler);
std::string componentName = ci.first;
LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml";
parser.parse(defaultsFile.string().c_str());
auto doc = parser.getDocument();
if (doc == nullptr) {
LOG_ERROR("%s not found! Skipping.", defaultsFile.string().c_str());
continue;
}
// Find the node in the components namespace matching the component name
std::string tagName = "c:" + componentName;
auto rootNodes = doc->getElementsByTagName(XSTR(tagName.c_str()));
if (rootNodes->getLength() == 0) {
LOG_ERROR("Couldn't find defaults for component \"%s\"! Skipping.", componentName.c_str());
continue;
}
auto componentElement = dynamic_cast<DOMElement*>(rootNodes->item(0));
// Fill the default value buffer with values
for (auto& field : ci.second.FieldOffsets) {
std::string fieldName = field.first;
auto fieldNodes = componentElement->getElementsByTagName(XSTR(fieldName.c_str()));
auto fieldNode = fieldNodes->item(0);
if (fieldNode == nullptr) {
LOG_ERROR("Defaults for component \"%s\" is missing field \"%s\"!", componentName.c_str(), fieldName.c_str());
continue;
}
auto fieldElement = dynamic_cast<DOMElement*>(fieldNode);
std::string fieldType = ci.second.FieldTypes.at(fieldName);
unsigned int fieldOffset = ci.second.FieldOffsets.at(fieldName);
writeData(fieldElement, fieldType, ci.second.Defaults.get() + fieldOffset);
}
}
}
void EntityXMLFile::predictComponentAllocation()
{
using namespace xercesc;
auto root = m_DOMDocument->getDocumentElement();
// Count static instances of components present in entity hierarchy
auto components = m_DOMDocument->getElementsByTagNameNS(XSTR("components"), XSTR("*"));
for (int i = 0; i < components->getLength(); ++i) {
auto component = dynamic_cast<DOMElement*>(components->item(i));
std::string componentName = XSTR(component->getLocalName());
auto& compInfo = m_ComponentInfo.at(componentName);
compInfo.Meta.Allocation += 1;
}
std::cout << "COMPONENT INFO" << std::endl;
for (auto& pair : m_ComponentInfo) {
ComponentInfo& ci = pair.second;
std::cout << "Component: " << ci.Name << " (" << ci.Meta.Annotation << ")" << std::endl;
std::cout << " Allocation: " << ci.Meta.Allocation << std::endl;
std::cout << " Fields:" << std::endl;
// Calculate component size
std::size_t stride = 0;
// Add size of fields
for (auto& field : ci.FieldTypes) {
std::cout << " " << field.second << " " << field.first << " (" << getTypeStride(field.second) << " byte)" << std::endl;
stride += getTypeStride(field.second);
}
std::cout << " Stride: " << ci.Meta.Stride << std::endl;
}
}
void EntityXMLFile::parseEntityGraph(World* world, xercesc::DOMElement* element, EntityID parentEntity)
{
using namespace xercesc;
// Create entity
EntityID entity = world->CreateEntity(parentEntity);
LOG_DEBUG("Created entity %i, parent %i", entity, parentEntity);
// Add components
auto components = m_DOMDocument->evaluate(XSTR("Components/*"), element, nullptr, DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr);
for (int i = 0; i < components->getSnapshotLength(); i++) {
components->snapshotItem(i);
auto componentElement = dynamic_cast<DOMElement*>(components->getNodeValue());
std::string componentName = XSTR(componentElement->getLocalName());
auto& ci = m_ComponentInfo.at(componentName);
// Attach the component
auto c = world->AttachComponent(entity, componentName);
LOG_DEBUG("Attached %s component", componentName.c_str());
// Write field data
auto fields = componentElement->getChildNodes();
for (int j = 0; j < fields->getLength(); ++j) {
auto fieldNode = fields->item(j);
auto nodeType = fieldNode->getNodeType();
if (nodeType != DOMNode::ELEMENT_NODE) {
continue;
}
auto field = dynamic_cast<DOMElement*>(fields->item(j));
//const XMLCh* value = fields->item(j)->getTextContent();
std::string fieldName(XSTR(field->getLocalName()));
if (ci.FieldTypes.find(fieldName) == ci.FieldTypes.end()) {
std::cout << "Warning: Component \"" << componentName << "\" contains invalid field \"" << fieldName << "\". Skipping." << std::endl;
continue;
}
std::string fieldType = ci.FieldTypes.at(fieldName);
unsigned int fieldOffset = ci.FieldOffsets.at(fieldName);
std::string fieldValue(XSTR(field->getTextContent()));
LOG_DEBUG(" %s %s = %s", fieldType.c_str(), fieldName.c_str(), fieldValue.c_str());
writeData(field, fieldType, c.Data + fieldOffset);
}
}
// Recurse children
auto children = m_DOMDocument->evaluate(XSTR("Children/Entity"), element, nullptr, DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr);
for (int i = 0; i < children->getSnapshotLength(); i++) {
children->snapshotItem(i);
parseEntityGraph(world, dynamic_cast<DOMElement*>(children->getNodeValue()), entity);
}
//auto components = m_DOMDocument->getElementsByTagNameNS(XSTR("components"), XSTR("*"));
//for (int i = 0; i < components->getLength(); ++i) {
// auto component = dynamic_cast<DOMElement*>(components->item(i));
// std::string componentName = XSTR(component->getLocalName());
// auto& compStore = m_ComponentStore.at(componentName);
// auto& compInfo = compStore.Info;
// char* data = &compStore.Data[compStore.Size*compStore.Stride];
// compStore.Size += 1;
// auto fields = component->getChildNodes();
// for (int j = 0; j < fields->getLength(); ++j) {
// auto field = fields->item(j);
// auto nodeType = field->getNodeType();
// if (nodeType != DOMNode::ELEMENT_NODE) {
// continue;
// }
// //auto field = dynamic_cast<DOMElement*>(fields->item(j));
// //const XMLCh* value = fields->item(j)->getTextContent();
// std::string fieldName = XSTR(field->getLocalName());
// if (compInfo.FieldTypes.find(fieldName) == compInfo.FieldTypes.end()) {
// std::cout << "Warning: Component \"" << componentName << "\" contains invalid field \"" << fieldName << "\". Skipping." << std::endl;
// continue;
// }
// std::string fieldType = compInfo.FieldTypes.at(fieldName);
// unsigned int fieldOffset = compInfo.FieldOffsets.at(fieldName);
// XSValue::DataType dataType = XSValue::getDataType(XSTR(fieldType.c_str()));
// if (dataType == XSValue::DataType::dt_MAXCOUNT) {
// // TODO:
// continue;
// }
// if (dataType == XSValue::DataType::dt_string) {
// char* str = XMLString::transcode(field->getTextContent());
// std::string standardString(str);
// XMLString::release(&str);
// memcpy(&data[fieldOffset], reinterpret_cast<char*>(&standardString), getTypeStride(fieldType));
// } else {
// XSValue::Status status;
// XSValue* val = XSValue::getActualValue(field->getTextContent(), dataType, status);
// memcpy(&data[fieldOffset], reinterpret_cast<char*>(&val->fData.fValue), getTypeStride(fieldType));
// }
// }
//}
//auto entities = m_DOMDocument->getElementsByTagName(XSTR("Entity"));
//for (int i = 0; i < entities->getLength(); ++i) {
// auto entity = dynamic_cast<DOMElement*>(entities->item(i));
// //entity->setIdAttribute()
// std::cout << "ENTITY " << i + 1 << std::endl;
//}
}
std::size_t EntityXMLFile::getTypeStride(std::string typeName)
{
std::map<std::string, size_t> typeStrides{
{ "bool", sizeof(bool) },
{ "int", sizeof(int) },
{ "double", sizeof(double) },
{ "string", sizeof(std::string) },
{ "Vector", sizeof(glm::vec3) },
{ "Quaternion", sizeof(glm::quat) },
{ "Color", sizeof(glm::vec4) }
};
auto it = typeStrides.find(typeName);
return (it != typeStrides.end()) ? it->second : 0;
}
float EntityXMLFile::getFloatAttribute(const xercesc::DOMElement* element, const char* attribute) const
{
using namespace xercesc;
XSValue::Status status;
XSValue* val = XSValue::getActualValue(element->getAttribute(XSTR(attribute)), xercesc::XSValue::DataType::dt_float, status);
if (val == nullptr) {
LOG_ERROR("Element \"%s\" doesn't have an \"%s\" attribute!", XSTR(element->getTagName()), attribute);
return 0.f;
} else {
return val->fData.fValue.f_float;
}
}
void EntityXMLFile::writeData(const xercesc::DOMElement* element, std::string typeName, char* outData)
{
using namespace xercesc;
XSValue::DataType dataType = XSValue::getDataType(XSTR(typeName.c_str()));
if (dataType == XSValue::DataType::dt_MAXCOUNT) {
if (typeName == "Vector") {
glm::vec3 vec;
vec.x = getFloatAttribute(element, "X");
vec.y = getFloatAttribute(element, "Y");
vec.z = getFloatAttribute(element, "Z");
memcpy(outData, reinterpret_cast<char*>(&vec), getTypeStride(typeName));
} else if (typeName == "Color") {
glm::vec4 vec;
vec.r = getFloatAttribute(element, "R");
vec.g = getFloatAttribute(element, "G");
vec.b = getFloatAttribute(element, "B");
vec.a = getFloatAttribute(element, "A");
memcpy(outData, reinterpret_cast<char*>(&vec), getTypeStride(typeName));
} else if (typeName == "Quaternion") {
glm::quat q;
q.x = getFloatAttribute(element, "X");
q.y = getFloatAttribute(element, "Y");
q.z = getFloatAttribute(element, "Z");
q.w = getFloatAttribute(element, "W");
memcpy(outData, reinterpret_cast<char*>(&q), getTypeStride(typeName));
}
} else if (dataType == XSValue::DataType::dt_string) {
char* str = XMLString::transcode(element->getTextContent());
std::string standardString(str);
new (outData) std::string(str);
XMLString::release(&str);
//memcpy(outData, reinterpret_cast<char*>(&standardString), getTypeStride(typeName));
} else {
XSValue::Status status;
XSValue* val = XSValue::getActualValue(element->getTextContent(), dataType, status);
memcpy(outData, reinterpret_cast<char*>(&val->fData.fValue), getTypeStride(typeName));
}
}
+90 -44
View File
@@ -8,8 +8,6 @@ void InputManager::Initialize()
EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse); EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse);
EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse); EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse);
//glfwSetMouseButtonCallback(m_GLFWWindow, &InputManager::GLFWMouseButtonCallback);
} }
void InputManager::Update(double dt) void InputManager::Update(double dt)
@@ -75,21 +73,6 @@ void InputManager::Update(double dt)
m_EventBroker->Publish(e); m_EventBroker->Publish(e);
} }
// Joysticks
//for (int i = 0; i < GLFW_JOYSTICK_LAST; i++) {
// if (glfwJoystickPresent(i) == GL_FALSE) {
// continue;
// }
// int count;
// const float* axes = glfwGetJoystickAxes(i, &count);
// LOG_DEBUG("Controller %i NumAxes: %i", i, count);
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftX)] = axes[0];
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftY)] = axes[1];
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightX)] = axes[2];
// m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightY)] = axes[3];
//}
// // Lock mouse while holding LMB // // Lock mouse while holding LMB
// if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT]) // if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT])
// { // {
@@ -108,46 +91,109 @@ void InputManager::Update(double dt)
// } // }
// TODO: Xbox360 controller // TODO: Xbox360 controller
/**/ /*DWORD dwResult;
for (int i = 0; i < MAX_GAMEPADS; i++)
{
XINPUT_STATE state = { 0 };
// Simply get the state of the controller from XInput.
dwResult = XInputGetState(i, &state);
if (dwResult == 0)
{
if(std::abs(state.Gamepad.sThumbLX) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
state.Gamepad.sThumbLX = 0;
if(std::abs(state.Gamepad.sThumbLY) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
state.Gamepad.sThumbLY = 0;
if(std::abs(state.Gamepad.sThumbRX) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
state.Gamepad.sThumbRX = 0;
if(std::abs(state.Gamepad.sThumbRY) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
state.Gamepad.sThumbRY = 0;
if(std::abs(state.Gamepad.bLeftTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
state.Gamepad.bLeftTrigger = 0;
if(std::abs(state.Gamepad.bRightTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
state.Gamepad.bRightTrigger = 0;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftX)] = state.Gamepad.sThumbLX / 32767.f;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftY)] = state.Gamepad.sThumbLY / 32767.f;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightX)] = state.Gamepad.sThumbRX / 32767.f;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightY)] = state.Gamepad.sThumbRY / 32767.f;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftTrigger)] = state.Gamepad.bLeftTrigger / 255.f;
m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightTrigger)] = state.Gamepad.bRightTrigger / 255.f;
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftX);
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftY);
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightX);
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightY);
PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftTrigger);
PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightTrigger);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Up)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Down)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Left)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Right)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Start)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_START);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Back)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::A)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_A);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::B)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_B);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::X)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_X);
m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Y)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Up);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Down);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Left);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Right);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Start);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Back);
PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftThumb);
PublishGamepadButtonIfChanged(i, Gamepad::Button::RightThumb);
PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftShoulder);
PublishGamepadButtonIfChanged(i, Gamepad::Button::RightShoulder);
PublishGamepadButtonIfChanged(i, Gamepad::Button::A);
PublishGamepadButtonIfChanged(i, Gamepad::Button::B);
PublishGamepadButtonIfChanged(i, Gamepad::Button::X);
PublishGamepadButtonIfChanged(i, Gamepad::Button::Y);
}
}*/
m_LastKeyState = m_CurrentKeyState; m_LastKeyState = m_CurrentKeyState;
m_LastMouseState = m_CurrentMouseState; m_LastMouseState = m_CurrentMouseState;
m_LastMouseX = m_CurrentMouseX; m_LastMouseX = m_CurrentMouseX;
m_LastMouseY = m_CurrentMouseY; m_LastMouseY = m_CurrentMouseY;
//m_LastGamepadAxisState = m_CurrentGamepadAxisState; m_LastGamepadAxisState = m_CurrentGamepadAxisState;
//m_LastGamepadButtonState = m_CurrentGamepadButtonState; m_LastGamepadButtonState = m_CurrentGamepadButtonState;
} }
void InputManager::PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis) void InputManager::PublishGamepadAxisIfChanged(int gamepadID, Gamepad::Axis axis)
{ {
//float currentValue = m_CurrentGamepadAxisState[gamepadID][static_cast<int>(axis)]; float currentValue = m_CurrentGamepadAxisState[gamepadID][static_cast<int>(axis)];
//float lastValue = m_LastGamepadAxisState[gamepadID][static_cast<int>(axis)]; float lastValue = m_LastGamepadAxisState[gamepadID][static_cast<int>(axis)];
//if (currentValue != lastValue) { if (currentValue != lastValue) {
// Events::GamepadAxis e; Events::GamepadAxis e;
// e.GamepadID = gamepadID; e.GamepadID = gamepadID;
// e.Axis = axis; e.Axis = axis;
// e.Value = currentValue; e.Value = currentValue;
// m_EventBroker->Publish(e); m_EventBroker->Publish(e);
//} }
} }
void InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button) void InputManager::PublishGamepadButtonIfChanged(int gamepadID, Gamepad::Button button)
{ {
//bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast<int>(button)]; bool currentState = m_CurrentGamepadButtonState[gamepadID][static_cast<int>(button)];
//float lastState = m_LastGamepadButtonState[gamepadID][static_cast<int>(button)]; float lastState = m_LastGamepadButtonState[gamepadID][static_cast<int>(button)];
//if (currentState != lastState) { if (currentState != lastState) {
// if (currentState == true) { if (currentState == true) {
// Events::GamepadButtonDown e; Events::GamepadButtonDown e;
// e.GamepadID = gamepadID; e.GamepadID = gamepadID;
// e.Button = button; e.Button = button;
// m_EventBroker->Publish(e); m_EventBroker->Publish(e);
// } else { } else {
// Events::GamepadButtonUp e; Events::GamepadButtonUp e;
// e.GamepadID = gamepadID; e.GamepadID = gamepadID;
// e.Button = button; e.Button = button;
// m_EventBroker->Publish(e); m_EventBroker->Publish(e);
// } }
//} }
} }
bool InputManager::OnLockMouse(const Events::LockMouse &event) bool InputManager::OnLockMouse(const Events::LockMouse &event)
-14
View File
@@ -35,20 +35,6 @@ void ResourceManager::Reload(std::string resourceName)
} }
} }
void ResourceManager::Release(std::string resourceType, std::string resourceName)
{
auto key = std::make_pair(resourceType, resourceName);
if (m_ResourceCache.find(key) == m_ResourceCache.end()) {
return;
}
auto resource = m_ResourceCache.at(key);
m_ResourceCache.erase(key);
m_ResourceFromName.erase(resourceName);
m_ResourceParents.erase(resource);
delete resource;
}
unsigned int ResourceManager::GetNewResourceID(unsigned int typeID) unsigned int ResourceManager::GetNewResourceID(unsigned int typeID)
{ {
return m_ResourceCount[typeID]++; return m_ResourceCount[typeID]++;
+2 -9
View File
@@ -41,16 +41,9 @@ ComponentWrapper World::GetComponent(EntityID entity, std::string componentType)
return pool->GetByEntity(entity); return pool->GetByEntity(entity);
} }
const ComponentPool* World::GetComponents(std::string componentType) const ComponentPool& World::GetComponents(std::string componentType)
{ {
auto it = m_ComponentPools.find(componentType); return *m_ComponentPools.at(componentType);
return (it != m_ComponentPools.end()) ? it->second : nullptr;
}
EntityID World::GetParent(EntityID entity)
{
return m_EntityParents.at(entity);
} }
EntityID World::generateEntityID() EntityID World::generateEntityID()
-112
View File
@@ -1,112 +0,0 @@
#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;
}
+221
View File
@@ -0,0 +1,221 @@
#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);
}
-181
View File
@@ -1,181 +0,0 @@
#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;
}
}
-131
View File
@@ -1,131 +0,0 @@
#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)
{
bool result = false;
auto originCode = m_OriginCodes.find(origin);
if (originCode != m_OriginCodes.end()) {
int code = originCode->second;
m_Bindings[code] = std::make_tuple(command, value);
result = 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);
result = true;
}
return result;
}
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;
}
@@ -1,187 +0,0 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <Xinput.h>
#pragma comment(lib, "Xinput.lib")
#pragma comment(lib, "Xinput9_1_0.lib")
#include "Input/XboxControllerInputHandler.h"
XboxControllerInputHandler::XboxControllerInputHandler(EventBroker* eventBroker, InputProxy* inputProxy)
: InputHandler(eventBroker, inputProxy)
{
m_OriginButtons["GamepadUp"] = XINPUT_GAMEPAD_DPAD_UP;
m_OriginButtons["GamepadDown"] = XINPUT_GAMEPAD_DPAD_DOWN;
m_OriginButtons["GamepadLeft"] = XINPUT_GAMEPAD_DPAD_LEFT;
m_OriginButtons["GamepadRight"] = XINPUT_GAMEPAD_DPAD_RIGHT;
m_OriginButtons["GamepadStart"] = XINPUT_GAMEPAD_START;
m_OriginButtons["GamepadBack"] = XINPUT_GAMEPAD_BACK;
m_OriginButtons["GamepadLeftStick"] = XINPUT_GAMEPAD_LEFT_THUMB;
m_OriginButtons["GamepadRightStick"] = XINPUT_GAMEPAD_RIGHT_THUMB;
m_OriginButtons["GamepadLeftBumper"] = XINPUT_GAMEPAD_LEFT_SHOULDER;
m_OriginButtons["GamepadRightBumper"] = XINPUT_GAMEPAD_RIGHT_SHOULDER;
m_OriginButtons["GamepadA"] = XINPUT_GAMEPAD_A;
m_OriginButtons["GamepadB"] = XINPUT_GAMEPAD_B;
m_OriginButtons["GamepadX"] = XINPUT_GAMEPAD_X;
m_OriginButtons["GamepadY"] = XINPUT_GAMEPAD_Y;
m_OriginAxes["GamepadLeftX"] = 0;
m_OriginAxes["GamepadLeftY"] = 1;
m_OriginAxes["GamepadRightX"] = 2;
m_OriginAxes["GamepadRightY"] = 3;
m_OriginAxes["GamepadLeftTrigger"] = 4;
m_OriginAxes["GamepadRightTrigger"] = 5;
}
bool XboxControllerInputHandler::BindOrigin(std::string origin, std::string command, float value)
{
bool result = false;
auto originIt = m_OriginButtons.find(origin);
if (originIt != m_OriginButtons.end()) {
int button = originIt->second;
m_ButtonBindings[button] = std::make_tuple(command, value);
result = true;
}
auto originAxis = m_OriginAxes.find(origin);
if (originAxis != m_OriginAxes.end()) {
char axis = originAxis->second;
float multiplier = 0.5f;
//// 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_AxisBindings[axis] = std::make_tuple(command, value * multiplier);
result = true;
}
return result;
}
void XboxControllerInputHandler::Update(double dt)
{
DWORD dwResult;
for (int i = 0; i < MAX_GAMEPADS; i++) {
XINPUT_STATE state = { 0 };
// Simply get the state of the controller from XInput.
dwResult = XInputGetState(i, &state);
if (dwResult == 0) {
if (std::abs(state.Gamepad.sThumbLX) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
state.Gamepad.sThumbLX = 0;
if (std::abs(state.Gamepad.sThumbLY) <= XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
state.Gamepad.sThumbLY = 0;
if (std::abs(state.Gamepad.sThumbRX) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
state.Gamepad.sThumbRX = 0;
if (std::abs(state.Gamepad.sThumbRY) <= XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
state.Gamepad.sThumbRY = 0;
if (std::abs(state.Gamepad.bLeftTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
state.Gamepad.bLeftTrigger = 0;
if (std::abs(state.Gamepad.bRightTrigger) <= XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
state.Gamepad.bRightTrigger = 0;
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftX)] = state.Gamepad.sThumbLX / 32767.f;
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftY)] = state.Gamepad.sThumbLY / 32767.f;
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightX)] = state.Gamepad.sThumbRX / 32767.f;
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightY)] = state.Gamepad.sThumbRY / 32767.f;
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::LeftTrigger)] = state.Gamepad.bLeftTrigger / 255.f;
//m_CurrentGamepadAxisState[i][static_cast<int>(Gamepad::Axis::RightTrigger)] = state.Gamepad.bRightTrigger / 255.f;
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftX);
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftY);
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightX);
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightY);
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::LeftTrigger);
//PublishGamepadAxisIfChanged(i, Gamepad::Axis::RightTrigger);
for (auto& pair : m_OriginAxes) {
const std::string& origin = pair.first;
int axis = pair.second;
auto& binding = m_AxisBindings.find(axis);
if (binding == m_AxisBindings.end()) {
continue;
}
std::string command;
float value;
std::tie(command, value) = binding->second;
Events::InputCommand e;
e.PlayerID = -1;
e.Command = command;
e.Value = value * getAxisValue(state, axis);
m_InputProxy->Publish(e);
}
for (auto& pair : m_OriginButtons) {
auto& binding = m_ButtonBindings.find(pair.second);
if (binding == m_ButtonBindings.end()) {
continue;
}
std::string command;
float value;
std::tie(command, value) = binding->second;
bool pressed = static_cast<bool>(state.Gamepad.wButtons & binding->first);
m_CommandValues[command] = (pressed) ? value : 0.f;
}
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Up)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Down)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Left)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Right)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Start)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_START);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Back)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightThumb)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::LeftShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::RightShoulder)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::A)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_A);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::B)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_B);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::X)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_X);
//m_CurrentGamepadButtonState[i][static_cast<int>(Gamepad::Button::Y)] = static_cast<bool>(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Up);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Down);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Left);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Right);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Start);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Back);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftThumb);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::RightThumb);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::LeftShoulder);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::RightShoulder);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::A);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::B);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::X);
//PublishGamepadButtonIfChanged(i, Gamepad::Button::Y);
}
}
}
float XboxControllerInputHandler::GetCommandValue(std::string command)
{
auto it = m_CommandValues.find(command);
if (it != m_CommandValues.end()) {
return m_CommandValues[command];
} else {
return 0.f;
}
}
float XboxControllerInputHandler::getAxisValue(XINPUT_STATE& state, int axis)
{
switch (axis) {
case 0:
return state.Gamepad.sThumbLX / 32767.f;
case 1:
return state.Gamepad.sThumbLY / 32767.f;
case 2:
return state.Gamepad.sThumbRX / 32767.f;
case 3:
return state.Gamepad.sThumbRY / 32767.f;
case 4:
return state.Gamepad.bLeftTrigger / 255.f;
case 5:
return state.Gamepad.bRightTrigger / 255.f;
}
}
+16 -16
View File
@@ -34,10 +34,10 @@ RawModel::RawModel(std::string fileName)
numIndices += face.mNumIndices; numIndices += face.mNumIndices;
} }
} }
//LOG_DEBUG("Vertex count %i", numVertices); LOG_DEBUG("Vertex count %i", numVertices);
//LOG_DEBUG("Index count %i", numIndices); LOG_DEBUG("Index count %i", numIndices);
//LOG_DEBUG("Model has %i embedded textures", scene->mNumTextures); LOG_DEBUG("Model has %i embedded textures", scene->mNumTextures);
std::vector<std::tuple<std::string, glm::mat4>> boneInfo; std::vector<std::tuple<std::string, glm::mat4>> boneInfo;
std::map<std::string, int> boneNameMapping; std::map<std::string, int> boneNameMapping;
@@ -132,35 +132,35 @@ RawModel::RawModel(std::string fileName)
matGroup.EndIndex = m_Indices.size() - 1; matGroup.EndIndex = m_Indices.size() - 1;
// Material shininess // Material shininess
material->Get(AI_MATKEY_SHININESS, matGroup.Shininess); material->Get(AI_MATKEY_SHININESS, matGroup.Shininess);
//LOG_DEBUG("Shininess: %f", matGroup.Shininess); LOG_DEBUG("Shininess: %f", matGroup.Shininess);
// Diffuse texture // Diffuse texture
//LOG_DEBUG("%i diffuse textures found", material->GetTextureCount(aiTextureType_DIFFUSE)); LOG_DEBUG("%i diffuse textures found", material->GetTextureCount(aiTextureType_DIFFUSE));
if (material->GetTextureCount(aiTextureType_DIFFUSE)) { if (material->GetTextureCount(aiTextureType_DIFFUSE)) {
aiString path; aiString path;
aiTextureMapping mapping; aiTextureMapping mapping;
material->GetTexture(aiTextureType_DIFFUSE, 0, &path, &mapping); material->GetTexture(aiTextureType_DIFFUSE, 0, &path, &mapping);
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string(); std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
//LOG_DEBUG("Diffuse texture: %s", absolutePath.c_str()); LOG_DEBUG("Diffuse texture: %s", absolutePath.c_str());
matGroup.Texture = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath)); matGroup.Texture = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
} }
// Normal map // Normal map
//LOG_DEBUG("%i normal maps found", material->GetTextureCount(aiTextureType_HEIGHT)); LOG_DEBUG("%i normal maps found", material->GetTextureCount(aiTextureType_HEIGHT));
if (material->GetTextureCount(aiTextureType_HEIGHT)) { if (material->GetTextureCount(aiTextureType_HEIGHT)) {
aiString path; aiString path;
aiTextureMapping mapping; aiTextureMapping mapping;
material->GetTexture(aiTextureType_HEIGHT, 0, &path, &mapping); material->GetTexture(aiTextureType_HEIGHT, 0, &path, &mapping);
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string(); std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
//LOG_DEBUG("Normal map: %s", absolutePath.c_str()); LOG_DEBUG("Normal map: %s", absolutePath.c_str());
matGroup.NormalMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath)); matGroup.NormalMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
} }
// Specular map // Specular map
//LOG_DEBUG("%i specular maps found", material->GetTextureCount(aiTextureType_SPECULAR)); LOG_DEBUG("%i specular maps found", material->GetTextureCount(aiTextureType_SPECULAR));
if (material->GetTextureCount(aiTextureType_SPECULAR)) { if (material->GetTextureCount(aiTextureType_SPECULAR)) {
aiString path; aiString path;
aiTextureMapping mapping; aiTextureMapping mapping;
material->GetTexture(aiTextureType_SPECULAR, 0, &path, &mapping); material->GetTexture(aiTextureType_SPECULAR, 0, &path, &mapping);
std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string(); std::string absolutePath = (boost::filesystem::path(fileName).branch_path() / path.C_Str()).string();
//LOG_DEBUG("Specular map: %s", absolutePath.c_str()); LOG_DEBUG("Specular map: %s", absolutePath.c_str());
matGroup.SpecularMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath)); matGroup.SpecularMap = std::shared_ptr<Texture>(ResourceManager::Load<Texture>(absolutePath));
} }
TextureGroups.push_back(matGroup); TextureGroups.push_back(matGroup);
@@ -216,20 +216,20 @@ RawModel::RawModel(std::string fileName)
m_Skeleton = new Skeleton(); m_Skeleton = new Skeleton();
CreateSkeleton(boneInfo, boneNameMapping, scene->mRootNode, -1); CreateSkeleton(boneInfo, boneNameMapping, scene->mRootNode, -1);
int numBones = m_Skeleton->Bones.size(); int numBones = m_Skeleton->Bones.size();
//LOG_DEBUG("Bone count: %i", numBones); LOG_DEBUG("Bone count: %i", numBones);
if (numBones > 0) { if (numBones > 0) {
m_Skeleton->PrintSkeleton(); m_Skeleton->PrintSkeleton();
} }
} }
// Animations // Animations
//LOG_DEBUG("Animation count: %i", scene->mNumAnimations); LOG_DEBUG("Animation count: %i", scene->mNumAnimations);
for (int i = 0; i < scene->mNumAnimations; ++i) { for (int i = 0; i < scene->mNumAnimations; ++i) {
auto animation = scene->mAnimations[i]; auto animation = scene->mAnimations[i];
std::string animationName = animation->mName.C_Str(); std::string animationName = animation->mName.C_Str();
//LOG_DEBUG("Animation: %s", animationName.c_str()); LOG_DEBUG("Animation: %s", animationName.c_str());
//LOG_DEBUG("Duration: %f", animation->mDuration); LOG_DEBUG("Duration: %f", animation->mDuration);
//LOG_DEBUG("Ticks per second: %f", animation->mTicksPerSecond); LOG_DEBUG("Ticks per second: %f", animation->mTicksPerSecond);
Skeleton::Animation skelAnim; Skeleton::Animation skelAnim;
skelAnim.Name = animationName; skelAnim.Name = animationName;
@@ -303,7 +303,7 @@ void RawModel::CreateSkeleton(std::vector<std::tuple<std::string, glm::mat4>> &b
// Find the bone by name in the bone info list // Find the bone by name in the bone info list
if (boneNameMapping.find(nodeName) == boneNameMapping.end()) { if (boneNameMapping.find(nodeName) == boneNameMapping.end()) {
//LOG_DEBUG("Node \"%s\" was not a bone", nodeName.c_str()); LOG_DEBUG("Node \"%s\" was not a bone", nodeName.c_str());
} else { } else {
glm::mat4 offsetMatrix; glm::mat4 offsetMatrix;
int ID = boneNameMapping[nodeName]; int ID = boneNameMapping[nodeName];
+31 -69
View File
@@ -15,87 +15,49 @@ void RenderQueueFactory::Update(World* world)
glm::mat4 RenderQueueFactory::ModelMatrix(World* world, EntityID entity) glm::mat4 RenderQueueFactory::ModelMatrix(World* world, EntityID entity)
{ {
glm::vec3 position = AbsolutePosition(world, entity); //should really return absolute model matrix based on parents position, scale and orientation
glm::quat orientation = AbsoluteOrientation(world, entity); //GetAbsolutePosition(World* world, ComponentWrapper transformComponent)
glm::vec3 scale = AbsoluteScale(world, entity);
glm::mat4 modelMatrix = glm::translate(glm::mat4(), position) * glm::toMat4(orientation) * glm::scale(scale); ComponentWrapper transformComponent = world->GetComponent(entity, "Transform");
glm::vec3 position = transformComponent["Position"];
glm::vec3 scale = transformComponent["Scale"];
glm::quat oritentation = transformComponent["Orientation"];
glm::mat4 modelMatrix = glm::translate(glm::mat4(), position) * glm::toMat4(oritentation) * glm::scale(scale);
return modelMatrix; return modelMatrix;
} }
glm::vec3 GetAbsolutePosition(World* world, ComponentWrapper transformComponent)
glm::vec3 RenderQueueFactory::AbsolutePosition(World* world, EntityID entity)
{ {
glm::vec3 position; // positionComponent.EntityID
return glm::vec3();
do {
ComponentWrapper transform = world->GetComponent(entity, "Transform");
position += (glm::vec3)transform["Position"];
entity = world->GetParent(entity);
} while (entity != 0);
return position;
}
glm::quat RenderQueueFactory::AbsoluteOrientation(World* world, EntityID entity)
{
glm::quat orientation;
do {
ComponentWrapper transform = world->GetComponent(entity, "Transform");
orientation = glm::quat((glm::vec3)transform["Orientation"]) * orientation;
entity = world->GetParent(entity);
} while (entity != 0);
return orientation;
}
glm::vec3 RenderQueueFactory::AbsoluteScale(World* world, EntityID entity)
{
ComponentWrapper transform = world->GetComponent(entity, "Transform");
glm::vec3 scale = (glm::vec3)transform["Scale"];
EntityID parent = world->GetParent(entity);
if (parent != 0) {
return AbsoluteScale(world, parent) * scale;
} else {
return scale;
}
} }
void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue) void RenderQueueFactory::FillModels(World* world, RenderQueue* renderQueue)
{ {
auto models = world->GetComponents("Model"); for(auto& modelC : world->GetComponents("Model")) {
if (models == nullptr) { ModelJob job;
return; std::string resource = modelC["Resource"];
} glm::vec4 color = modelC["Color"];
Model* model = ResourceManager::Load<Model>(resource);
for (auto& modelC : *models) { for (auto texGroup : model->TextureGroups) {
std::string resource = modelC["Resource"]; job.TextureID = (texGroup.Texture) ? texGroup.Texture->ResourceID : 0;
if (resource.empty()) { job.DiffuseTexture = texGroup.Texture.get();
continue; job.NormalTexture = texGroup.NormalMap.get();
} job.SpecularTexture = texGroup.SpecularMap.get();
glm::vec4 color = modelC["Color"]; job.Model = model;
Model* model = ResourceManager::Load<Model>(resource); job.StartIndex = texGroup.StartIndex;
job.EndIndex = texGroup.EndIndex;
job.ModelMatrix = model->m_Matrix * ModelMatrix(world, modelC.EntityID);
job.Color = color;
for (auto texGroup : model->TextureGroups) { //TODO: RENDERER: Not sure if the best solution for pickingColor to entity link is this
ModelJob job; job.Entity = modelC.EntityID;
job.TextureID = (texGroup.Texture) ? texGroup.Texture->ResourceID : 0;
job.DiffuseTexture = texGroup.Texture.get();
job.NormalTexture = texGroup.NormalMap.get();
job.SpecularTexture = texGroup.SpecularMap.get();
job.Model = model;
job.StartIndex = texGroup.StartIndex;
job.EndIndex = texGroup.EndIndex;
job.ModelMatrix = model->m_Matrix * ModelMatrix(world, modelC.EntityID);
job.Color = color;
//TODO: RENDERER: Not sure if the best solution for pickingColor to entity link is this renderQueue->Add(job);
job.Entity = modelC.EntityID; }
}
renderQueue->Add(job);
}
}
} }
void RenderQueueFactory::FillLights(World* world, RenderQueue* renderQueue) void RenderQueueFactory::FillLights(World* world, RenderQueue* renderQueue)
+51 -40
View File
@@ -1,9 +1,9 @@
#include "Rendering/Renderer.h" #include "Rendering/Renderer.h"
#include "Rendering/DebugCameraInputController.h"
void Renderer::Initialize() void Renderer::Initialize()
{ {
InitializeWindow(); InitializeWindow();
// Create default camera // Create default camera
m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(45.f), 0.01f, 5000.f); 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)); m_DefaultCamera->SetPosition(glm::vec3(0, 0, 10));
@@ -84,8 +84,6 @@ void Renderer::InitializeShaders()
void Renderer::InputUpdate(double dt) void Renderer::InputUpdate(double dt)
{ {
static DebugCameraInputController<Renderer> firstPersonInputController(m_EventBroker, -1);
glm::vec3 m_Position = m_Camera->Position(); glm::vec3 m_Position = m_Camera->Position();
if (glfwGetKey(m_Window, GLFW_KEY_O) == GLFW_PRESS) if (glfwGetKey(m_Window, GLFW_KEY_O) == GLFW_PRESS)
{ {
@@ -115,15 +113,53 @@ void Renderer::InputUpdate(double dt)
m_CameraMoveSpeed = 0.5f; m_CameraMoveSpeed = 0.5f;
} }
firstPersonInputController.Update(dt);
m_Camera->SetOrientation(firstPersonInputController.Orientation()); static double mousePosX, mousePosY;
m_Camera->SetPosition(firstPersonInputController.Position()); 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);
} }
void Renderer::Update(double dt) void Renderer::Update(double dt)
{ {
m_EventBroker->Process<Renderer>(); InputUpdate(dt);
InputUpdate(dt);
} }
void Renderer::Draw(RenderQueueCollection& rq) void Renderer::Draw(RenderQueueCollection& rq)
@@ -177,12 +213,10 @@ void Renderer::DrawScene(RenderQueueCollection& rq)
continue; continue;
} }
} }
GLERROR("DrawScene Error");
} }
void Renderer::PickingPass(RenderQueueCollection& rq) void Renderer::PickingPass(RenderQueueCollection& rq)
{ {
m_PickingColorsToEntity.clear();
m_PickingBuffer.Bind(); m_PickingBuffer.Bind();
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
@@ -191,7 +225,7 @@ void Renderer::PickingPass(RenderQueueCollection& rq)
glClearColor(0.f, 0.f, 0.f, 1.f); glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
int r = 1; int r = 30;
int g = 0; int g = 0;
//TODO: Render: Add code for more jobs than modeljobs. //TODO: Render: Add code for more jobs than modeljobs.
@@ -203,18 +237,8 @@ void Renderer::PickingPass(RenderQueueCollection& rq)
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job); auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
if (modelJob) { if (modelJob) {
//--------------- glm::vec2 pickColor = glm::vec2(r/255.f, g/255.f);
//TODO: Renderer: IMPORTANT: Fixa detta så det inte loopar igenom listan varje frame. m_PickingColorsToEntity[pickColor] = modelJob->Entity;
//---------------
int pickColor[2] = { r, g };
for (auto i : m_PickingColorsToEntity) {
if(modelJob->Entity == i.second) {
pickColor[0] = i.first.x;
pickColor[1] = i.first.y;
r -= 1;
}
}
m_PickingColorsToEntity[glm::vec2(pickColor[0], pickColor[1])] = modelJob->Entity;
//Render picking stuff //Render picking stuff
@@ -222,32 +246,19 @@ void Renderer::PickingPass(RenderQueueCollection& rq)
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->ModelMatrix)); 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, "V"), 1, GL_FALSE, glm::value_ptr(m_Camera->ViewMatrix()));
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix())); glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Camera->ProjectionMatrix()));
glUniform2fv(glGetUniformLocation(ShaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); glUniform2fv(glGetUniformLocation(ShaderHandle, "PickingColor"), 1, glm::value_ptr(pickColor));
glBindVertexArray(modelJob->Model->VAO); glBindVertexArray(modelJob->Model->VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
r += 1; r+=50;
if(r > 255) { if(r > 255) {
r = 0; r = 0;
g += 1; g+=50;
} }
} }
} }
m_PickingBuffer.Unbind(); m_PickingBuffer.Unbind();
GLERROR("PickingPass Error");
//Publish pick event every frame with the pick data that can be picked by the event
Events::Picking pickEvent = Events::Picking(
&m_PickingBuffer,
&m_DepthBuffer,
m_Camera->ProjectionMatrix(),
m_Camera->ViewMatrix(),
m_Resolution,
&m_PickingColorsToEntity);
m_EventBroker->Publish(pickEvent);
} }
@@ -289,7 +300,7 @@ void Renderer::InitializeTextures()
*/ */
GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR, GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR,
glm::vec2(m_Resolution.Width, m_Resolution.Height), GL_RG8, GL_RG, GL_UNSIGNED_BYTE); 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) void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type)
+5 -14
View File
@@ -29,31 +29,22 @@ glm::vec3 ScreenCoords::ToWorldPos(glm::vec2 screenCoord, float depth, float scr
return ToWorldPos(screenCoord.x, screenCoord.y, depth, screenWidth, screenHeight, cameraProjectionMat, cameraViewMat); return ToWorldPos(screenCoord.x, screenCoord.y, depth, screenWidth, screenHeight, cameraProjectionMat, cameraViewMat);
} }
ScreenCoords::PixelData ScreenCoords::ToPixelData(float x, float y, FrameBuffer* PickDataBuffer, GLuint DepthBuffer) glm::vec3 ScreenCoords::ToPixelData(float x, float y, FrameBuffer* PickDataBuffer, GLuint DepthBuffer)
{ {
PickDataBuffer->Bind(); PickDataBuffer->Bind();
unsigned char pdata[2]; glm::vec2 pixelData;
glReadPixels(x, y, 1, 1, GL_RG, GL_UNSIGNED_BYTE, &pdata); glReadPixels(x, y, 1, 1, GL_RG, GL_FLOAT, &pixelData);
PickDataBuffer->Unbind(); PickDataBuffer->Unbind();
glBindFramebuffer(GL_FRAMEBUFFER, DepthBuffer); glBindFramebuffer(GL_FRAMEBUFFER, DepthBuffer);
float depthData; float depthData;
glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthData); glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depthData);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
PixelData p; return glm::vec3(pixelData, depthData);
p.Color[0] = (int)pdata[0];
p.Color[1] = (int)pdata[1];
p.Depth = depthData;
GLERROR("ScreenCoords::ToPixelData Error");
return p;
} }
ScreenCoords::PixelData ScreenCoords::ToPixelData(glm::vec2 screenCoord, FrameBuffer* PickDataBuffer, GLuint DepthBuffer) glm::vec3 ScreenCoords::ToPixelData(glm::vec2 screenCoord, FrameBuffer* PickDataBuffer, GLuint DepthBuffer)
{ {
return ToPixelData(screenCoord.x, screenCoord.y, PickDataBuffer, DepthBuffer); return ToPixelData(screenCoord.x, screenCoord.y, PickDataBuffer, DepthBuffer);
} }
-1
View File
@@ -19,7 +19,6 @@ file(GLOB SOURCE_FILES
set(SOURCE_FILES set(SOURCE_FILES
${SOURCE_FILES} ${SOURCE_FILES}
"Game.cpp" "Game.cpp"
"PlayerSystem.cpp"
) )
set(LIBRARIES set(LIBRARIES
+42 -96
View File
@@ -1,123 +1,69 @@
#include "Game.h" #include "Game.h"
#include "HardcodedTestWorld.h"
Game::Game(int argc, char* argv[]) Game::Game(int argc, char* argv[])
{ {
ResourceManager::RegisterType<ConfigFile>("ConfigFile"); ResourceManager::RegisterType<ConfigFile>("ConfigFile");
ResourceManager::RegisterType<Model>("Model"); ResourceManager::RegisterType<Model>("Model");
ResourceManager::RegisterType<Texture>("Texture"); ResourceManager::RegisterType<Texture>("Texture");
ResourceManager::RegisterType<EntityXMLFile>("EntityXMLFile");
m_Config = ResourceManager::Load<ConfigFile>("Config.ini"); m_Config = ResourceManager::Load<ConfigFile>("Config.ini");
LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1)); LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get<int>("Debug.LogLevel", 1));
// Create the core event broker // Create the core event broker
m_EventBroker = new EventBroker(); m_EventBroker = new EventBroker();
m_RenderQueueFactory = new RenderQueueFactory(); m_RenderQueueFactory = new RenderQueueFactory();
// Create the renderer // Create the renderer
m_Renderer = new Renderer(m_EventBroker); m_Renderer = new Renderer();
m_Renderer->SetFullscreen(m_Config->Get<bool>("Video.Fullscreen", false)); m_Renderer->SetFullscreen(m_Config->Get<bool>("Video.Fullscreen", false));
m_Renderer->SetVSYNC(m_Config->Get<bool>("Video.VSYNC", false)); m_Renderer->SetVSYNC(m_Config->Get<bool>("Video.VSYNC", false));
m_Renderer->SetResolution(Rectangle( m_Renderer->SetResolution(Rectangle(
0, 0,
0, 0,
m_Config->Get<int>("Video.Width", 1280), m_Config->Get<int>("Video.Width", 1280),
m_Config->Get<int>("Video.Height", 720) m_Config->Get<int>("Video.Height", 720)
)); ));
m_Renderer->Initialize(); m_Renderer->Initialize();
// Create input manager // Create input manager
m_InputManager = new InputManager(m_Renderer->Window(), m_EventBroker); 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->AddHandler<XboxControllerInputHandler>();
m_InputProxy->LoadBindings("Input.ini");
// Create the root level GUI frame // Create the root level GUI frame
m_FrameStack = new GUI::Frame(m_EventBroker); m_FrameStack = new GUI::Frame(m_EventBroker);
m_FrameStack->Width = m_Renderer->Resolution().Width; m_FrameStack->Width = m_Renderer->Resolution().Width;
m_FrameStack->Height = m_Renderer->Resolution().Height; m_FrameStack->Height = m_Renderer->Resolution().Height;
// Create a world // Create a TEST WORLD
m_World = new World(); m_World = new HardcodedTestWorld();
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
if (!mapToLoad.empty()) {
ResourceManager::Load<EntityXMLFile>(mapToLoad)->PopulateWorld(m_World);
}
// Create system pipeline m_LastTime = glfwGetTime();
m_SystemPipeline = new SystemPipeline(m_EventBroker);
m_SystemPipeline->AddSystem<RaptorCopterSystem>();
m_SystemPipeline->AddSystem<PlayerSystem>();
m_LastTime = glfwGetTime();
debugInitialize();
} }
Game::~Game() Game::~Game()
{ {
delete m_FrameStack; delete m_FrameStack;
delete m_EventBroker; delete m_EventBroker;
} }
void Game::Tick() void Game::Tick()
{ {
double currentTime = glfwGetTime(); double currentTime = glfwGetTime();
double dt = currentTime - m_LastTime; double dt = currentTime - m_LastTime;
m_LastTime = currentTime; m_LastTime = currentTime;
// Handle input in a weird looking but responsive way m_EventBroker->Swap();
m_EventBroker->Process<InputManager>(); m_InputManager->Update(dt);
m_EventBroker->Swap(); m_Renderer->Update(dt);
m_InputManager->Update(dt); m_EventBroker->Swap();
m_EventBroker->Swap();
m_InputProxy->Update(dt);
m_EventBroker->Swap();
m_EventBroker->Clear();
m_InputProxy->Process();
m_EventBroker->Swap();
// Iterate through systems and update world!
m_SystemPipeline->Update(m_World, dt);
debugTick(dt);
m_Renderer->Update(dt);
m_RenderQueueFactory->Update(m_World); m_RenderQueueFactory->Update(m_World);
m_Renderer->Draw(m_RenderQueueFactory->RenderQueues());
m_EventBroker->Swap(); m_Renderer->Draw(m_RenderQueueFactory->RenderQueues());
m_EventBroker->Clear();
glfwPollEvents(); m_EventBroker->Swap();
} m_EventBroker->Clear();
glfwPollEvents();
bool Game::debugOnInputCommand(const Events::InputCommand& e)
{
if (e.Command == "DebugReload" && e.Value == 1) {
std::string mapToLoad = m_Config->Get<std::string>("Debug.LoadMap", "");
if (!mapToLoad.empty()) {
delete m_World;
m_World = new World();
ResourceManager::Release("EntityXMLFile", mapToLoad);
ResourceManager::Load<EntityXMLFile>(mapToLoad)->PopulateWorld(m_World);
}
}
return false;
}
void Game::debugInitialize()
{
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Game::debugOnInputCommand);
}
void Game::debugTick(double dt)
{
m_EventBroker->Process<Game>();
} }
-58
View File
@@ -1,58 +0,0 @@
#include "PlayerSystem.h"
void PlayerSystem::Update(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;
}
+135
View File
@@ -0,0 +1,135 @@
/*
* Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
(function () {
"use strict";
var start = 0;
var zmq = require('zmq');
var publisher = zmq.socket('pub');
publisher.bind('tcp://*:5555', function (err) {
if (err) {
console.log(err);
}
else {
console.log("5555");
}
});
process.on('SIGINT', function () {
publisher.close();
});
var PLUGIN_ID = require("./package.json").name,
MENU_ID = "TeamFisk plugins",
MENU_LABEL = "$$$/JavaScripts/Generator/TeamFisk plugins/Menu=Live Texturing RAMDisk";
var _generator = null;
// Initialize script here
function init(generator, config) {
_generator = generator;
_generator.addMenuItem(MENU_ID, MENU_LABEL, true, false)
.then(
function () {
console.log("Menu created", MENU_ID);
}, function () {
console.error("Menu creation failed", MENU_ID);
}
);
_generator.onPhotoshopEvent("imageChanged", handleImageChanged);
}
var lastSent = 0;
var isSaving = false;
function handleImageChanged(document) {
var start = new Date().getTime();
if (start - lastSent > 100 && !isSaving) {
isSaving = true;
//console.log("DOC: " + document.id);
_generator.getDocumentInfo(document.id).then(
function (document) {
// console.log(new Date().getTime() / 1000);
// console.log(stringify(document.timeStamp));
//console.log("HELLO 1");
//lastSent = document.timeStamp
// console.log(stringify(document));
//console.log("Received complete document:", stringify(document));
//var str = 'var options = new PNGSaveOptions(); app.activeDocument.saveAs (new File("D:/HejHej.png"),options, false);';
var str = 'app.activeDocument.save()';
_generator.evaluateJSXString(str).then(function () {
isSaving = false;
//console.log("Save succes");
var size = (4 + document.file.length + 1);
var message = new Buffer(size);
var offset = 0;
//console.log("document.file.length: " + document.file.length);
//console.log("document.fileName: " + document.file);
message.writeInt32LE(document.file.length + 1, offset);
offset += 4;
var fileName = document.file.replace(/\\/g, "/");
message.write(fileName, offset, fileName.length, 'utf8');
offset += fileName.length;
message.writeUInt8(0, offset); //Null byte
offset += 1;
publisher.send(message);
var asd = new Date().getTime();
var time = asd - start;
//console.log(time);
lastSent = new Date().getTime();
//console.log("LastSent: " + lastSent);
},
function () {
console.log("Save Failure");
isSaving = false;
}).done();
});
}
}
function stringify(object) {
try {
return JSON.stringify(object, null, " ");
} catch (e) {
console.error(e);
}
return String(object);
}
//Declare entery function in the script
exports.init = init;
}());
+15
View File
@@ -0,0 +1,15 @@
root = true
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
[*.js]
indent_style = space
indent_size = 2
[*.cc]
indent_style = space
indent_size = 2
+13
View File
@@ -0,0 +1,13 @@
*.swp
*.swo
*.o
build
*.lock*
binding.node
examples/stress-test-client
node_modules
Makefile.gyp
binding.Makefile
binding.target.gyp.mk
gyp-mac-tool
out/
+37
View File
@@ -0,0 +1,37 @@
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
env:
- ZMQ="git://github.com/zeromq/zeromq2-x.git"
- ZMQ="git://github.com/zeromq/zeromq3-x.git -b v3.1.0"
- ZMQ="git://github.com/zeromq/zeromq3-x.git -b v3.2.5"
- ZMQ="git://github.com/zeromq/zeromq4-x.git -b v4.0.5" SODIUM="git://github.com/jedisct1/libsodium.git -b 0.4.5"
before_install:
- export CXX=g++-4.8
- sudo apt-get install uuid-dev
- '[ -z "$SODIUM" ] || git clone --depth 1 $SODIUM libsodium'
- '[ -z "$SODIUM" ] || cd libsodium'
- '[ -z "$SODIUM" ] || ./autogen.sh'
- '[ -z "$SODIUM" ] || ./configure'
- '[ -z "$SODIUM" ] || make'
- '[ -z "$SODIUM" ] || sudo make install'
- '[ -z "$SODIUM" ] || cd ..'
- git clone --depth 1 $ZMQ zmqlib
- cd zmqlib
- ./autogen.sh
- ./configure
- make
- sudo make install
- sudo /sbin/ldconfig
- cd ..
language: node_js
node_js:
- "0.8"
- "0.10"
- "0.12"
- "4"
- "5"
script: travis_retry npm test
+154
View File
@@ -0,0 +1,154 @@
2.14.0 / 2015-11-20
===================
* A socket.read() method was added to retrieve messages while paused [sshutovskyi]
* socket.send() now takes a callback as 3rd argument which is called once the message is sent [ronkorving]
* Now tested on Node.js 0.8, 0.10, 0.12, 4 and 5 [ronkorving]
2.13.0 / 2015-08-26
===================
* io.js 3.x compatible [kkoopa]
* corrections to type casting operations [kkoopa]
* "make clean" now also removes node_modules [reqshark]
2.12.0 / 2015-07-10
===================
* Massive improvements to monitoring code, with new documentation and tests [ValYouW]
* Improved documentation [reqshark]
* Updated bindings from ~1.1.1 to ~1.2.1 [reqshark]
* Test suite improvements [reqshark]
* Updated the Windows bundle to ZeroMQ 4.0.4 [kkoopa]
* License attribute added to package.json [pdehaan]
2.11.1 / 2015-05-21
===================
* io.js 2.x compatible [transcranial]
* replaced asserts with proper exceptions [reqshark]
2.11.0 / 2015-03-31
===================
* Added pause() and resume() APIs on sockets to allow backpressure [philip1986]
* Elegant handling of EINTR return codes [hurricaneLTG]
* Small performance improvements in send() and internal flush methods [ronkorving]
* Updated test suite to cover io.js and Node 0.12 (removed 0.11) [ronkorving]
* Added "make perf" for easy benchmarking [ronkorving]
2.10.0 / 2015-01-22
===================
* Added ZMQ_STREAM socket type [reqshark]
* Update NAN to io.js compatible 1.5.0 [kkoopa]
* Hitting open file descriptor limit now throws an error during zmq.socket() [briansorahan]
* More reliable benchmarking [maxired]
2.9.0 / 2015-01-05
==================
* More unit tests [bluebery and reqshark]
* More reliable testing [f34rdotcom and kkoopa]
* Improved ReadMe [dminkovsky and skibz]
* Support for zmq_proxy sockets [reqshark]
* Removed "docs" and related deps in favor of ReadMe [reqshark]
2.8.0 / 2014-08-27
==================
* Fixed: monitor API would keep CPU busy at 100% [f34rdotcom]
* Fixed: an exception during flush could render a socket unusable [ronkorving]
* Fixed: Travis changed behavior and broke our tests [ronkorving]
* Code cleanup [kkoopa and ronkorving]
* Removed legacy nextTick event emission during flush [utvara and ronkorving]
* Context API added: setMaxThreads, getMaxThreads, setMaxSockets, getMaxSockets [yoneal]
* Changed unit test suite to Mocha [skeggse and yoneal]
* NAN updated to ~1.3.0 [kkoopa]
2.7.0 / 2014-04-24
==================
* Fixed memory leak when closing socket [rasky]
* Fixed high water mark [soplwang, kkoopa]
* Added socket opts for zeromq 4.x security mechanisms [msealand]
* Use MakeCallback [kkoopa]
* Remove useless setImmediate [kkoopa]
* Use `zmq_msg_send` for ZMQ >= 4.0 [kkoopa]
* Expose the Socket class as zmq.Socket [tcr]
2.6.0 / 2014-01-23
==================
* Monitor support [f34rdotcom, dr-fozzy]
* Unbind support [kkoopa]
* Node 0.11.9 compatibility [kkoopa]
* Support for ZMQ 4 [atrniv]
* Fixed memory leak [utvara]
* OSX Homebrew support [jwalton]
* Fix unit tests [ryanlelek]
2.5.1 / 2013-08-28
==================
* Regression fix for IPC socket bind failure [christopherobin]
2.5.0 / 2013-08-20
==================
* Added testing against Node.js v0.11 [AlexeyKupershtokh]
* Add support for Joyent SmartMachines [JonGretar]
* Use pkg-config on OS X too [blalor]
* Patch for Node 0.11.3 [kkoopa]
* Fix for bind / connect / send problem [kkoopa]
* Fixed multiple bugs in perf tests and changed them to push/pull [ronkorving]
* Add definitions for building on openbsd & freebsd [Minjung]
2.4.0 / 2013-04-09
==================
* added: Windows support [mscdex]
* added: support for all options ever [AlexeyKupershtokh]
* fixed: prevent zeromq sockets from being destroyed by GC [AlexeyKupershtokh]
2.3.0 / 2013-03-15
==================
* added: xpub/xsub socket types [xla]
* added: support for zmq_disconnect [matehat]
* added: LAST_ENDPOINT socket option [ronkorving]
* added: local/remote_lat local/remote_thr perf test [wavded]
* fixed: tests improved [qubyte, jeremybarnes, ronkorving]
* fixed: Node v0.9.4+ compatibility [mscdex]
* fixed: SNDHWM and RCVHWM options were given the wrong type [freehaha]
* removed: waf support [mscdex]
2.2.0 / 2012-10-17
==================
* add support for pkg-config
* add libzmq 3.x support [aaudis]
* fix: prevent GC happening too soon for connect/bindSync
2.1.0 / 2012-06-29
==================
* fix require() for 0.8.0
* change: use uv_poll in place of IOWatcher
* remove stupid engines field
2.0.3 / 2012-03-14
==================
* Removed -Wall (libuv unused vars caused the build to fail...)
2.0.2 / 2012-02-16
==================
* Added back `.createSocket()` for BC. Closes #86
2.0.1 / 2012-01-26
==================
* Added `.zmqVersion` [patricklucas]
* Fixed multipart support [joshrtay]
+20
View File
@@ -0,0 +1,20 @@
Copyright (c) 2011 TJ Holowaychuk
Copyright (c) 2010, 2011 Justin Tulloss
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+18
View File
@@ -0,0 +1,18 @@
build/Release/binding.node: binding.cc binding.gyp
npm install
test:
npm test
clean:
rm -fr build node_modules
distclean:
node-gyp clean
perf:
node perf/local_lat.js tcp://127.0.0.1:5555 1 100000& node perf/remote_lat.js tcp://127.0.0.1:5555 1 100000
node perf/local_thr.js tcp://127.0.0.1:5556 1 100000& node perf/remote_thr.js tcp://127.0.0.1:5556 1 100000
.PHONY: test clean distclean perf
+224
View File
@@ -0,0 +1,224 @@
# zmq &nbsp;&nbsp;[![Build Status](https://travis-ci.org/JustinTulloss/zeromq.node.png)](https://travis-ci.org/JustinTulloss/zeromq.node) &nbsp;[![Build status](https://ci.appveyor.com/api/projects/status/n0h0sjs127eadfuo/branch/windowsbuild?svg=true)](https://ci.appveyor.com/project/reqshark/zeromq-node)
[ØMQ](http://www.zeromq.org/) bindings for node.js.
## Installation
### on Windows:
First install [Visual Studio](https://www.visualstudio.com/) and either
[Node.js](https://nodejs.org/download/) or [io.js](https://iojs.org/dist/latest/).
Ensure you're building zmq from a conservative location on disk, one without
unusual characters or spaces, for example somewhere like: `C:\sources\myproject`.
Installing the ZeroMQ library is optional and not required on Windows. We
recommend running `npm install` and node executable commands from a
[github for windows](https://windows.github.com/) shell or similar environment.
### installing on Unix/POSIX (and osx):
First install `pkg-config` and the [ZeroMQ library](http://www.zeromq.org/intro:get-the-software).
This module is compatible with ZeroMQ versions 2, 3 and 4. The installation
process varies by platform, but headers are mandatory. Most Linux distributions
provide these headers with `-devel` packages like `zeromq-devel` or
`zeromq3-devel`. Homebrew for OS X provides versions 4 and 3 with packages
`zeromq` and `zeromq3`, respectively. A
[Chris Lea PPA](https://launchpad.net/~chris-lea/+archive/ubuntu/zeromq)
is available for Debian-like users who want a version newer than currently
provided by their distribution. Windows is supported but not actively
maintained.
Note: For zap support with versions >=4 you need to have libzmq built and linked
against libsodium. Check the [Travis configuration](.travis.yml) for a list of what is tested
and therefore known to work.
#### with your platform-specifics taken care of, install and use this module:
$ npm install zmq
## Examples
### Push/Pull
```js
// producer.js
var zmq = require('zmq')
, sock = zmq.socket('push');
sock.bindSync('tcp://127.0.0.1:3000');
console.log('Producer bound to port 3000');
setInterval(function(){
console.log('sending work');
sock.send('some work');
}, 500);
```
```js
// worker.js
var zmq = require('zmq')
, sock = zmq.socket('pull');
sock.connect('tcp://127.0.0.1:3000');
console.log('Worker connected to port 3000');
sock.on('message', function(msg){
console.log('work: %s', msg.toString());
});
```
### Pub/Sub
```js
// pubber.js
var zmq = require('zmq')
, sock = zmq.socket('pub');
sock.bindSync('tcp://127.0.0.1:3000');
console.log('Publisher bound to port 3000');
setInterval(function(){
console.log('sending a multipart message envelope');
sock.send(['kitty cats', 'meow!']);
}, 500);
```
```js
// subber.js
var zmq = require('zmq')
, sock = zmq.socket('sub');
sock.connect('tcp://127.0.0.1:3000');
sock.subscribe('kitty cats');
console.log('Subscriber connected to port 3000');
sock.on('message', function(topic, message) {
console.log('received a message related to:', topic, 'containing message:', message);
});
```
## Monitoring
You can get socket state changes events by calling to the `monitor` function.
The supported events are (see ZMQ [docs](http://api.zeromq.org/4-2:zmq-socket-monitor) for full description):
* connect - ZMQ_EVENT_CONNECTED
* connect_delay - ZMQ_EVENT_CONNECT_DELAYED
* connect_retry - ZMQ_EVENT_CONNECT_RETRIED
* listen - ZMQ_EVENT_LISTENING
* bind_error - ZMQ_EVENT_BIND_FAILED
* accept - ZMQ_EVENT_ACCEPTED
* accept_error - ZMQ_EVENT_ACCEPT_FAILED
* close - ZMQ_EVENT_CLOSED
* close_error - ZMQ_EVENT_CLOSE_FAILED
* disconnect - ZMQ_EVENT_DISCONNECTED
All events get 2 arguments:
* fd - The file descriptor of the underlying socket (if available)
* endpoint - The underlying socket endpoint
A special `monitor_error` event will be raised when there was an error in the monitoring process, after this event no more
monitoring events will be sent, you can try and call `monitor` again to restart the monitoring process.
### monitor(interval, numOfEvents)
Will create an inproc PAIR socket where zmq will publish socket state changes events, the events from this socket will
be read every `interval` (defaults to 10ms).
By default only 1 message will be read every interval, this can be configured by using the `numOfEvents` parameter,
where passing 0 will read all available messages per interval.
### unmonitor()
Stop the monitoring process
### example
```js
// Create a socket
var zmq = require('zmq');
socket = zmq.socket('req');
// Register to monitoring events
socket.on('connect', function(fd, ep) {console.log('connect, endpoint:', ep);});
socket.on('connect_delay', function(fd, ep) {console.log('connect_delay, endpoint:', ep);});
socket.on('connect_retry', function(fd, ep) {console.log('connect_retry, endpoint:', ep);});
socket.on('listen', function(fd, ep) {console.log('listen, endpoint:', ep);});
socket.on('bind_error', function(fd, ep) {console.log('bind_error, endpoint:', ep);});
socket.on('accept', function(fd, ep) {console.log('accept, endpoint:', ep);});
socket.on('accept_error', function(fd, ep) {console.log('accept_error, endpoint:', ep);});
socket.on('close', function(fd, ep) {console.log('close, endpoint:', ep);});
socket.on('close_error', function(fd, ep) {console.log('close_error, endpoint:', ep);});
socket.on('disconnect', function(fd, ep) {console.log('disconnect, endpoint:', ep);});
// Handle monitor error
socket.on('monitor_error', function(err) {
console.log('Error in monitoring: %s, will restart monitoring in 5 seconds', err);
setTimeout(function() { socket.monitor(500, 0); }, 5000);
});
// Call monitor, check for events every 500ms and get all available events.
console.log('Start monitoring...');
socket.monitor(500, 0);
socket.connect('tcp://127.0.0.1:1234');
setTimeout(function() {
console.log('Stop the monitoring...');
socket.unmonitor();
}, 20000);
```
## Running tests
#### Install dev deps:
```sh
$ git clone https://github.com/JustinTulloss/zeromq.node.git zmq && cd zmq
$ npm i
```
#### Build:
```sh
# on unix:
$ make
# building on windows:
> npm i
```
#### Test:
```sh
# on unix:
$ make test
# testing on windows:
> npm t
```
## Running benchmarks
Benchmarks are available in the `perf` directory, and have been implemented
according to the zmq documentation:
[How to run performance tests](http://www.zeromq.org/results:perf-howto)
In the following examples, the arguments are respectively:
- the host to connect to/bind on
- message size (in bytes)
- message count
You can run a latency benchmark by running these two commands in two separate
shells:
```sh
node ./local_lat.js tcp://127.0.0.1:5555 1 100000
```
```sh
node ./remote_lat.js tcp://127.0.0.1:5555 1 100000
```
And you can run throughput tests by running these two commands in two
separate shells:
```sh
node ./local_thr.js tcp://127.0.0.1:5555 1 100000
```
```sh
node ./remote_thr.js tcp://127.0.0.1:5555 1 100000
```
Running `make perf` will run the commands listed above.
+24
View File
@@ -0,0 +1,24 @@
environment:
matrix:
- nodejs_version: "0.10"
- nodejs_version: "0.12"
- nodejs_version: "2"
#platform:
# - x86
# - x64
install:
- ps: Install-Product node $env:nodejs_version #$env:platform
- npm install
test_script:
- node --version
- npm --version
- npm test
build: off
matrix:
allow_failures:
- nodejs_version: "2"
File diff suppressed because it is too large Load Diff
+76
View File
@@ -0,0 +1,76 @@
{
'targets': [
{
'target_name': 'zmq',
'sources': [ 'binding.cc' ],
'include_dirs' : [
"<!(node -e \"require('nan')\")"
],
'conditions': [
['OS=="win"', {
'win_delay_load_hook': 'true',
'include_dirs': ['windows/include'],
'link_settings': {
'libraries': [
'Delayimp.lib',
],
'conditions': [
['target_arch=="ia32"', {
'libraries': [
'<(PRODUCT_DIR)/../../windows/lib/x86/libzmq-v100-mt-4_0_4.lib',
]
},{
'libraries': [
'<(PRODUCT_DIR)/../../windows/lib/x64/libzmq-v100-mt-4_0_4.lib',
]
}]
],
},
'msvs_settings': {
'VCLinkerTool': {
'DelayLoadDLLs': ['libzmq-v100-mt-4_0_4.dll']
}
},
}, {
'libraries': ['-lzmq'],
'cflags!': ['-fno-exceptions'],
'cflags_cc!': ['-fno-exceptions'],
}],
['OS=="mac" or OS=="solaris"', {
'xcode_settings': {
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES'
},
# add macports include & lib dirs, homebrew include & lib dirs
'include_dirs': [
'<!@(pkg-config libzmq --cflags-only-I | sed s/-I//g)',
'/opt/local/include',
'/usr/local/include',
],
'libraries': [
'<!@(pkg-config libzmq --libs)',
'-L/opt/local/lib',
'-L/usr/local/lib',
]
}],
['OS=="openbsd" or OS=="freebsd"', {
'include_dirs': [
'<!@(pkg-config libzmq --cflags-only-I | sed s/-I//g)',
'/usr/local/include',
],
'libraries': [
'<!@(pkg-config libzmq --libs)',
'-L/usr/local/lib',
]
}],
['OS=="linux"', {
'cflags': [
'<!(pkg-config libzmq --cflags 2>/dev/null || echo "")',
],
'libraries': [
'<!(pkg-config libzmq --libs 2>/dev/null || echo "")',
],
}],
]
}
]
}
@@ -0,0 +1,54 @@
/*
*
* One client two servers (round roobin)
*
*/
var cluster = require('cluster')
, zmq = require('../')
, port = 'tcp://127.0.0.1:12345';
if (cluster.isMaster) {
for (var i = 0; i < 2; i++) cluster.fork();
cluster.on('death', function(worker) {
console.log('worker ' + worker.pid + ' died');
});
//dealer = client
var socket = zmq.socket('dealer');
socket.identity = 'client' + process.pid;
socket.bind(port, function(err) {
if (err) throw err;
console.log('bound!');
setInterval(function() {
var value = Math.floor(Math.random()*100);
console.log(socket.identity + ': asking ' + value);
socket.send(value);
}, 100);
socket.on('message', function(data) {
console.log(socket.identity + ': answer data ' + data);
});
});
} else {
//router = server
var socket = zmq.socket('router');
socket.identity = 'server' + process.pid;
socket.connect(port);
console.log('connected!');
socket.on('message', function(envelope, data) {
console.log(socket.identity + ': received ' + envelope + ' - ' + data.toString());
socket.send([envelope, data * 2]);
});
}
@@ -0,0 +1,69 @@
/*
*
* Forwarder device
*
*/
var zmq = require('../../')
, frontPort = 'tcp://127.0.0.1:12345'
, backPort = 'tcp://127.0.0.1:12346';
function createClient (port) {
var socket = zmq.socket('pub');
socket.identity = 'client' + process.pid;
socket.connect(port);
console.log('client connected!');
setInterval(function() {
var value = Math.floor(Math.random()*100);
console.log(socket.identity + ': broadcasting ' + value);
socket.send(value);
}, 100);
};
function createWorker (port) {
var socket = zmq.socket('sub');
socket.identity = 'worker' + process.pid;
socket.subscribe('');
socket.on('message', function(data) {
console.log(socket.identity + ': got ' + data.toString());
});
socket.connect(port, function(err) {
if (err) throw err;
console.log('worker connected!');
});
};
function createForwarderDevice(frontPort, backPort) {
var frontSocket = zmq.socket('sub'),
backSocket = zmq.socket('pub');
frontSocket.identity = 'sub' + process.pid;
backSocket.identity = 'pub' + process.pid;
frontSocket.subscribe('');
frontSocket.bind(frontPort, function (err) {
console.log('bound', frontPort);
});
frontSocket.on('message', function() {
//pass to back
console.log('forwarder: recasting', arguments[0].toString());
backSocket.send(Array.prototype.slice.call(arguments));
});
backSocket.bind(backPort, function (err) {
console.log('bound', backPort);
});
}
createForwarderDevice(frontPort, backPort);
createClient(frontPort);
createWorker(backPort);
@@ -0,0 +1,78 @@
/*
*
* Queue device
*
*/
var zmq = require('../../')
, frontPort = 'tcp://127.0.0.1:12345'
, backPort = 'tcp://127.0.0.1:12346';
function createClient (port) {
var socket = zmq.socket('req');
socket.identity = 'client' + process.pid;
socket.on('message', function(data) {
console.log(socket.identity + ': answer data ' + data);
});
socket.connect(port);
console.log('client connected!');
setInterval(function() {
var value = Math.floor(Math.random()*100);
console.log(socket.identity + ': asking ' + value);
socket.send(value);
}, 100);
};
function createServer (port) {
var socket = zmq.socket('rep');
socket.identity = 'server' + process.pid;
socket.on('message', function(data) {
console.log(socket.identity + ': received ' + data.toString());
socket.send(data * 2);
});
socket.connect(port, function(err) {
if (err) throw err;
console.log('server connected!');
});
};
function createQueueDevice(frontPort, backPort) {
var frontSocket = zmq.socket('router'),
backSocket = zmq.socket('dealer');
frontSocket.identity = 'router' + process.pid;
backSocket.identity = 'dealer' + process.pid;
frontSocket.bind(frontPort, function (err) {
console.log('bound', frontPort);
});
frontSocket.on('message', function() {
//pass to back
console.log('router: sending to server', arguments[0].toString(), arguments[2].toString());
backSocket.send(Array.prototype.slice.call(arguments));
});
backSocket.bind(backPort, function (err) {
console.log('bound', backPort);
});
backSocket.on('message', function() {
//pass to front
console.log('dealer: sending to client', arguments[0].toString(), arguments[2].toString());
frontSocket.send(Array.prototype.slice.call(arguments));
});
}
createQueueDevice(frontPort, backPort);
createClient(frontPort);
createServer(backPort);
@@ -0,0 +1,67 @@
/*
*
* Forwarder device
*
*/
var zmq = require('../../')
, frontPort = 'tcp://127.0.0.1:12345'
, backPort = 'tcp://127.0.0.1:12346';
function createClient (port) {
var socket = zmq.socket('push');
socket.identity = 'client' + process.pid;
socket.connect(port);
console.log('client connected!');
setInterval(function() {
var value = Math.floor(Math.random()*100);
console.log(socket.identity + ': pushing ' + value);
socket.send(value);
}, 100);
};
function createWorker (port) {
var socket = zmq.socket('pull');
socket.identity = 'worker' + process.pid;
socket.on('message', function(data) {
console.log(socket.identity + ': pulled ' + data.toString());
});
socket.connect(port, function(err) {
if (err) throw err;
console.log('worker connected!');
});
};
function createStreamerDevice(frontPort, backPort) {
var frontSocket = zmq.socket('pull'),
backSocket = zmq.socket('push');
frontSocket.identity = 'sub' + process.pid;
backSocket.identity = 'pub' + process.pid;
frontSocket.bind(frontPort, function (err) {
console.log('bound', frontPort);
});
frontSocket.on('message', function() {
//pass to back
console.log('forwarder: sending downstream', arguments[0].toString());
backSocket.send(Array.prototype.slice.call(arguments));
});
backSocket.bind(backPort, function (err) {
console.log('bound', backPort);
});
}
createStreamerDevice(frontPort, backPort);
createClient(frontPort);
createWorker(backPort);
+55
View File
@@ -0,0 +1,55 @@
/*
*
* Publisher subscriber pattern
*
*/
var cluster = require('cluster')
, zmq = require('../')
, port = 'tcp://127.0.0.1:12345';
if (cluster.isMaster) {
for (var i = 0; i < 2; i++) cluster.fork();
cluster.on('death', function(worker) {
console.log('worker ' + worker.pid + ' died');
});
//publisher = send only
var socket = zmq.socket('pub');
socket.identity = 'publisher' + process.pid;
var stocks = ['AAPL', 'GOOG', 'YHOO', 'MSFT', 'INTC'];
socket.bind(port, function(err) {
if (err) throw err;
console.log('bound!');
setInterval(function() {
var symbol = stocks[Math.floor(Math.random()*stocks.length)]
, value = Math.random()*1000;
console.log(socket.identity + ': sent ' + symbol + ' ' + value);
socket.send(symbol + ' ' + value);
}, 100);
});
} else {
//subscriber = receive only
var socket = zmq.socket('sub');
socket.identity = 'subscriber' + process.pid;
socket.connect(port);
socket.subscribe('AAPL');
socket.subscribe('GOOG');
console.log('connected!');
socket.on('message', function(data) {
console.log(socket.identity + ': received data ' + data.toString());
});
}
@@ -0,0 +1,48 @@
/*
*
* Pipeline
*
*/
var cluster = require('cluster')
, zmq = require('../')
, port = 'tcp://127.0.0.1:12345';
if (cluster.isMaster) {
for (var i = 0; i < 2; i++) cluster.fork();
cluster.on('death', function(worker) {
console.log('worker ' + worker.pid + ' died');
});
//push = upstream
var socket = zmq.socket('push');
socket.identity = 'upstream' + process.pid;
socket.bind(port, function(err) {
if (err) throw err;
console.log('bound!');
setInterval(function() {
var date = new Date();
console.log(socket.identity + ': sending data ' + date.toString());
socket.send(date.toString());
}, 500);
});
} else {
//pull = downstream
var socket = zmq.socket('pull');
socket.identity = 'downstream' + process.pid;
socket.connect(port);
console.log('connected!');
socket.on('message', function(data) {
console.log(socket.identity + ': received data ' + data.toString());
});
}
+53
View File
@@ -0,0 +1,53 @@
/*
*
* One responseder two requesters
*
*/
var cluster = require('cluster')
, zmq = require('../')
, port = 'tcp://127.0.0.1:12345';
if (cluster.isMaster) {
for (var i = 0; i < 2; i++) cluster.fork();
cluster.on('death', function(worker) {
console.log('worker ' + worker.pid + ' died');
});
//responseder = server
var socket = zmq.socket('rep');
socket.identity = 'server' + process.pid;
socket.bind(port, function(err) {
if (err) throw err;
console.log('bound!');
socket.on('message', function(data) {
console.log(socket.identity + ': received ' + data.toString());
socket.send(2 * data);
});
});
} else {
//requester = client
var socket = zmq.socket('req');
socket.identity = 'client' + process.pid;
socket.connect(port);
console.log('connected!');
setInterval(function() {
var value = Math.floor(Math.random()*100);
socket.send(value);
console.log(socket.identity + ': asking ' + value);
}, 100);
socket.on('message', function(data) {
console.log(socket.identity + ': answer data ' + data);
});
}
+57
View File
@@ -0,0 +1,57 @@
/*
*
* One requester two responders (round robin)
*
*/
var cluster = require('cluster')
, zeromq = require('../')
, port = 'tcp://127.0.0.1:12345';
if (cluster.isMaster) {
//Fork servers.
for (var i = 0; i < 2; i++) {
cluster.fork();
}
cluster.on('death', function(worker) {
console.log('worker ' + worker.pid + ' died');
});
//requester = client
var socket = zeromq.socket('req');
socket.identity = 'client' + process.pid;
socket.bind(port, function(err) {
if (err) throw err;
console.log('bound!');
setInterval(function() {
var value = Math.floor(Math.random()*100);
console.log(socket.identity + ': asking ' + value);
socket.send(value);
}, 100);
socket.on('message', function(data) {
console.log(socket.identity + ': answer data ' + data);
});
});
} else {
//responder = server
var socket = zeromq.socket('rep');
socket.identity = 'server' + process.pid;
socket.connect(port);
console.log('connected!');
socket.on('message', function(data) {
console.log(socket.identity + ': received ' + data.toString());
socket.send(data * 2);
});
}
@@ -0,0 +1,53 @@
/*
*
* One server two clients
*
*/
var cluster = require('cluster')
, zeromq = require('../')
, port = 'tcp://127.0.0.1:12345';
if (cluster.isMaster) {
for (var i = 0; i < 2; i++) cluster.fork();
cluster.on('death', function(worker) {
console.log('worker ' + worker.pid + ' died');
});
//router = server
var socket = zeromq.socket('router');
socket.identity = 'server' + process.pid;
socket.bind(port, function(err) {
if (err) throw err;
console.log('bound!');
socket.on('message', function(envelope, data) {
console.log(socket.identity + ': received ' + envelope + ' - ' + data.toString());
socket.send([envelope, data * 2]);
});
});
} else {
//dealer = client
var socket = zeromq.socket('dealer');
socket.identity = 'client' + process.pid;
socket.connect(port);
console.log('connected!');
setInterval(function() {
var value = Math.floor(Math.random()*100);
socket.send(value);
console.log(socket.identity + ': asking ' + value);
}, 100);
socket.on('message', function(data) {
console.log(socket.identity + ': answer data ' + data);
});
}
+17
View File
@@ -0,0 +1,17 @@
/**
* One server two clients
*/
var cluster = require('cluster')
, zmq = require('../')
, port = 'tcp://127.0.0.1:12345';
if (cluster.isMaster) {
for (var i = 0; i < 2; i++) cluster.fork();
} else {
var sock = zmq.socket('dealer');
sock.connect(port);
}
@@ -0,0 +1,11 @@
var zmq = require('../../')
, sock = zmq.socket('push');
sock.bindSync('tcp://127.0.0.1:3000');
console.log('Producer bound to port 3000');
setInterval(function(){
console.log('sending work');
sock.send('some work');
}, 500);
@@ -0,0 +1,10 @@
var zmq = require('../../')
, sock = zmq.socket('pull');
sock.connect('tcp://127.0.0.1:3000');
console.log('Worker connected to port 3000');
sock.on('message', function(msg){
console.log('work: %s', msg.toString());
});
+2
View File
@@ -0,0 +1,2 @@
module.exports = require('./lib');
@@ -0,0 +1,97 @@
node-bindings
=============
### Helper module for loading your native module's .node file
This is a helper module for authors of Node.js native addon modules.
It is basically the "swiss army knife" of `require()`ing your native module's
`.node` file.
Throughout the course of Node's native addon history, addons have ended up being
compiled in a variety of different places, depending on which build tool and which
version of node was used. To make matters worse, now the _gyp_ build tool can
produce either a _Release_ or _Debug_ build, each being built into different
locations.
This module checks _all_ the possible locations that a native addon would be built
at, and returns the first one that loads successfully.
Installation
------------
Install with `npm`:
``` bash
$ npm install bindings
```
Or add it to the `"dependencies"` section of your _package.json_ file.
Example
-------
`require()`ing the proper bindings file for the current node version, platform
and architecture is as simple as:
``` js
var bindings = require('bindings')('binding.node')
// Use your bindings defined in your C files
bindings.your_c_function()
```
Nice Error Output
-----------------
When the `.node` file could not be loaded, `node-bindings` throws an Error with
a nice error message telling you exactly what was tried. You can also check the
`err.tries` Array property.
```
Error: Could not load the bindings file. Tried:
→ /Users/nrajlich/ref/build/binding.node
→ /Users/nrajlich/ref/build/Debug/binding.node
→ /Users/nrajlich/ref/build/Release/binding.node
→ /Users/nrajlich/ref/out/Debug/binding.node
→ /Users/nrajlich/ref/Debug/binding.node
→ /Users/nrajlich/ref/out/Release/binding.node
→ /Users/nrajlich/ref/Release/binding.node
→ /Users/nrajlich/ref/build/default/binding.node
→ /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node
at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13)
at Object.<anonymous> (/Users/nrajlich/ref/lib/ref.js:5:47)
at Module._compile (module.js:449:26)
at Object.Module._extensions..js (module.js:467:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
...
```
License
-------
(The MIT License)
Copyright (c) 2012 Nathan Rajlich &lt;nathan@tootallnate.net&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,166 @@
/**
* Module dependencies.
*/
var fs = require('fs')
, path = require('path')
, join = path.join
, dirname = path.dirname
, exists = fs.existsSync || path.existsSync
, defaults = {
arrow: process.env.NODE_BINDINGS_ARROW || ' → '
, compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled'
, platform: process.platform
, arch: process.arch
, version: process.versions.node
, bindings: 'bindings.node'
, try: [
// node-gyp's linked version in the "build" dir
[ 'module_root', 'build', 'bindings' ]
// node-waf and gyp_addon (a.k.a node-gyp)
, [ 'module_root', 'build', 'Debug', 'bindings' ]
, [ 'module_root', 'build', 'Release', 'bindings' ]
// Debug files, for development (legacy behavior, remove for node v0.9)
, [ 'module_root', 'out', 'Debug', 'bindings' ]
, [ 'module_root', 'Debug', 'bindings' ]
// Release files, but manually compiled (legacy behavior, remove for node v0.9)
, [ 'module_root', 'out', 'Release', 'bindings' ]
, [ 'module_root', 'Release', 'bindings' ]
// Legacy from node-waf, node <= 0.4.x
, [ 'module_root', 'build', 'default', 'bindings' ]
// Production "Release" buildtype binary (meh...)
, [ 'module_root', 'compiled', 'version', 'platform', 'arch', 'bindings' ]
]
}
/**
* The main `bindings()` function loads the compiled bindings for a given module.
* It uses V8's Error API to determine the parent filename that this function is
* being invoked from, which is then used to find the root directory.
*/
function bindings (opts) {
// Argument surgery
if (typeof opts == 'string') {
opts = { bindings: opts }
} else if (!opts) {
opts = {}
}
opts.__proto__ = defaults
// Get the module root
if (!opts.module_root) {
opts.module_root = exports.getRoot(exports.getFileName())
}
// Ensure the given bindings name ends with .node
if (path.extname(opts.bindings) != '.node') {
opts.bindings += '.node'
}
var tries = []
, i = 0
, l = opts.try.length
, n
, b
, err
for (; i<l; i++) {
n = join.apply(null, opts.try[i].map(function (p) {
return opts[p] || p
}))
tries.push(n)
try {
b = opts.path ? require.resolve(n) : require(n)
if (!opts.path) {
b.path = n
}
return b
} catch (e) {
if (!/not find/i.test(e.message)) {
throw e
}
}
}
err = new Error('Could not locate the bindings file. Tried:\n'
+ tries.map(function (a) { return opts.arrow + a }).join('\n'))
err.tries = tries
throw err
}
module.exports = exports = bindings
/**
* Gets the filename of the JavaScript file that invokes this function.
* Used to help find the root directory of a module.
* Optionally accepts an filename argument to skip when searching for the invoking filename
*/
exports.getFileName = function getFileName (calling_file) {
var origPST = Error.prepareStackTrace
, origSTL = Error.stackTraceLimit
, dummy = {}
, fileName
Error.stackTraceLimit = 10
Error.prepareStackTrace = function (e, st) {
for (var i=0, l=st.length; i<l; i++) {
fileName = st[i].getFileName()
if (fileName !== __filename) {
if (calling_file) {
if (fileName !== calling_file) {
return
}
} else {
return
}
}
}
}
// run the 'prepareStackTrace' function above
Error.captureStackTrace(dummy)
dummy.stack
// cleanup
Error.prepareStackTrace = origPST
Error.stackTraceLimit = origSTL
return fileName
}
/**
* Gets the root directory of a module, given an arbitrary filename
* somewhere in the module tree. The "root directory" is the directory
* containing the `package.json` file.
*
* In: /home/nate/node-native-module/lib/index.js
* Out: /home/nate/node-native-module
*/
exports.getRoot = function getRoot (file) {
var dir = dirname(file)
, prev
while (true) {
if (dir === '.') {
// Avoids an infinite loop in rare cases, like the REPL
dir = process.cwd()
}
if (exists(join(dir, 'package.json')) || exists(join(dir, 'node_modules'))) {
// Found the 'package.json' file or 'node_modules' dir; we're done
return dir
}
if (prev === dir) {
// Got to the top
throw new Error('Could not find module root given file: "' + file
+ '". Do you have a `package.json` file? ')
}
// Try the parent dir next
prev = dir
dir = join(dir, '..')
}
}

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