Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7fc83d1471 | |||
| 65e5729118 | |||
| 26d6f4c7cf | |||
| e513059522 |
@@ -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
@@ -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,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;
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#ifndef Entity_h__
|
|
||||||
#define Entity_h__
|
|
||||||
|
|
||||||
typedef unsigned int EntityID;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#include "ResourceManager.h"
|
||||||
|
|
||||||
|
class EntityFile : public Resource
|
||||||
|
{
|
||||||
|
friend class ResourceManager;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EntityFile(std::string path);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef Entity_h__
|
||||||
|
#define Entity_h__
|
||||||
|
|
||||||
|
typedef unsigned int EntityID;
|
||||||
|
|
||||||
|
struct EntityWrapper
|
||||||
|
{
|
||||||
|
EntityWrapper(EntityID entityID)
|
||||||
|
: ID(entityID)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
EntityID ID;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef Events_BindMouseButton_h__
|
||||||
|
#define Events_BindMouseButton_h__
|
||||||
|
|
||||||
|
#include "Core/EventBroker.h"
|
||||||
|
|
||||||
|
namespace Events
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Called to bind a mouse button to an input command. */
|
||||||
|
struct BindMouseButton : Event
|
||||||
|
{
|
||||||
|
/** The GLFW mouse button code to bind. */
|
||||||
|
int Button;
|
||||||
|
/** The command to send. */
|
||||||
|
std::string Command;
|
||||||
|
/** The value to send for positive stimulation.
|
||||||
|
|
||||||
|
Multiplied by the 0-1 clamped value of the button.
|
||||||
|
*/
|
||||||
|
float Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
};
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
||||||
@@ -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----------------------//
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -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
|
|
||||||
@@ -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,6 +1,5 @@
|
|||||||
[Debug]
|
[Debug]
|
||||||
LogLevel=1
|
LogLevel=1
|
||||||
LoadMap=
|
|
||||||
|
|
||||||
[Video]
|
[Video]
|
||||||
Fullscreen=false
|
Fullscreen=false
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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>
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<c:Model>
|
|
||||||
<Resource></Resource>
|
|
||||||
<Color R="1" G="1" B="1" A="1"/>
|
|
||||||
<Visible>true</Visible>
|
|
||||||
</c:Model>
|
|
||||||
@@ -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>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<c:Player>
|
|
||||||
<Velocity X="0" Y="0" Z="0"/>
|
|
||||||
</c:Player>
|
|
||||||
@@ -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>
|
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ out vec4 TextureFragment;
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
TextureFragment = vec4(PickingColor/255, 0, 1);
|
TextureFragment = vec4(PickingColor, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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]++;
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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];
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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>();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,224 @@
|
|||||||
|
# zmq [](https://travis-ci.org/JustinTulloss/zeromq.node) [](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
@@ -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"
|
||||||
+1393
File diff suppressed because it is too large
Load Diff
+76
@@ -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 "")',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+54
@@ -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]);
|
||||||
|
});
|
||||||
|
}
|
||||||
+69
@@ -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);
|
||||||
+78
@@ -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);
|
||||||
+67
@@ -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
@@ -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());
|
||||||
|
});
|
||||||
|
}
|
||||||
+48
@@ -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
@@ -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
@@ -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);
|
||||||
|
});
|
||||||
|
}
|
||||||
+53
@@ -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
@@ -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);
|
||||||
|
}
|
||||||
+11
@@ -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);
|
||||||
+10
@@ -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
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
module.exports = require('./lib');
|
||||||
Generated
Vendored
+97
@@ -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 <nathan@tootallnate.net>
|
||||||
|
|
||||||
|
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.
|
||||||
Generated
Vendored
+166
@@ -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
Reference in New Issue
Block a user