diff --git a/CMakeLists.txt b/CMakeLists.txt index 74a506a..2b75b11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ add_executable(${PROJECT_NAME} src/moversine.cpp src/gameplaysceneclassic.cpp src/moverrelative.cpp + src/inputbag.cpp ) target_link_libraries(${PROJECT_NAME} diff --git a/src/inputbag.cpp b/src/inputbag.cpp new file mode 100644 index 0000000..e1cc74f --- /dev/null +++ b/src/inputbag.cpp @@ -0,0 +1,69 @@ +#include "inputbag.hpp" +#include "key.hpp" +#include +#include +#include + +namespace cloonel { + struct Action { + Key key; + const std::string name; + InputBag::ActionStateType state; + }; + + struct InputBag::LocalData { + std::vector actions; + std::map mappings; + }; + + namespace { + ///---------------------------------------------------------------------- + ///When actions vector is reallocated, update pointers in mappings. + ///---------------------------------------------------------------------- + void UpdatePointers (Action* parOldAddrStart, Action* parNewAddress, std::map& parUpdate, int parOffset) { + for (auto itMap : parUpdate) { + if (itMap.second >= parOldAddrStart) { + itMap.second = parNewAddress + (itMap.second - parOldAddrStart) + parOffset; + } + } + } + } //unnamed namespace + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + InputBag::InputBag() : + m_localdata(new LocalData) + { + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + InputBag::~InputBag() { + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + void InputBag::AddAction (int parAction, const Key& parKey, std::string&& parName) { + Action* const oldBuff = m_localdata->actions.data(); + m_localdata->actions.push_back(Action({parKey, parName, ActionState_Released})); + Action* const newBuff = m_localdata->actions.data(); + if (oldBuff != newBuff) { + UpdatePointers(oldBuff, newBuff, m_localdata->mappings, 0); + } + m_localdata->mappings[parAction] = &m_localdata->actions.back(); + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + InputBag::ActionStateType InputBag::ActionState (int parAction) const { + assert(m_localdata->mappings.find(parAction) != m_localdata->mappings.end()); + return m_localdata->mappings[parAction]->state; + } + + ///-------------------------------------------------------------------------- + ///-------------------------------------------------------------------------- + void InputBag::Clear() { + m_localdata->actions.clear(); + m_localdata->mappings.clear(); + } +} //namespace cloonel diff --git a/src/inputbag.hpp b/src/inputbag.hpp new file mode 100644 index 0000000..f1dbed4 --- /dev/null +++ b/src/inputbag.hpp @@ -0,0 +1,32 @@ +#ifndef idF4E67FC292A5480DA4305B806170F520 +#define idF4E67FC292A5480DA4305B806170F520 + +#include + +namespace cloonel { + struct Key; + + class InputBag { + public: + enum ActionStateType { + ActionState_Released, + ActionState_Pressed, + ActionState_JustPressed, + ActionState_JustReleased + }; + + InputBag ( void ); + ~InputBag ( void ) noexcept; + + void AddAction ( int parAction, const Key& parKey, std::string&& parName ); + ActionStateType ActionState ( int parAction ) const; + void Clear ( void ); + + private: + struct LocalData; + + const std::unique_ptr m_localdata; + }; +} //namespace cloonel + +#endif diff --git a/src/key.hpp b/src/key.hpp new file mode 100644 index 0000000..0124df7 --- /dev/null +++ b/src/key.hpp @@ -0,0 +1,40 @@ +#ifndef id8F6145D6CFBA40338C5804DEC032CE16 +#define id8F6145D6CFBA40338C5804DEC032CE16 + +#include + +namespace cloonel { + struct Key { + enum KeyDevice { + KeyDevice_Keyboard + }; + + Key ( void ) = default; + Key ( KeyDevice parDev, int parScancode, const char parLabel[4] ) : + srcdevice(parDev), + scancode(parScancode) + { + label[0] = parLabel[0]; + label[1] = parLabel[1]; + label[2] = parLabel[2]; + label[3] = parLabel[3]; + } + ~Key ( void ) noexcept = default; + + bool operator== ( const Key& parOther ) const { + return srcdevice == parOther.srcdevice and scancode == parOther.srcdevice; + } + bool operator!= ( const Key& parOther ) const { + return not this->operator==(parOther); + } + bool operator< ( const Key& parOther ) const { + return (srcdevice == parOther.srcdevice and scancode < parOther.scancode) or (srcdevice < parOther.srcdevice); + } + + KeyDevice srcdevice; + int scancode; + char label[4]; + }; +} //namespace cloonel + +#endif