Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/StarInput.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/game/StarInput.hpp')
-rw-r--r--source/game/StarInput.hpp160
1 files changed, 160 insertions, 0 deletions
diff --git a/source/game/StarInput.hpp b/source/game/StarInput.hpp
new file mode 100644
index 0000000..f329cc2
--- /dev/null
+++ b/source/game/StarInput.hpp
@@ -0,0 +1,160 @@
+#ifndef STAR_INPUT_HPP
+#define STAR_INPUT_HPP
+
+#include "StarInputEvent.hpp"
+#include "StarJson.hpp"
+#include "StarListener.hpp"
+#include "StarHash.hpp"
+
+namespace Star {
+
+ STAR_CLASS(Input);
+ STAR_EXCEPTION(InputException, StarException);
+
+ typedef Variant<Key, MouseButton, ControllerButton> InputVariant;
+
+ template <>
+ struct hash<InputVariant> {
+ size_t operator()(InputVariant const& v) const;
+ };
+
+ class Input {
+ public:
+ struct NoBind {
+ String error;
+
+ NoBind(String err);
+ };
+
+ struct KeyBind {
+ Key key = Key::Zero;
+ KeyMod mods = KeyMod::NoMod;
+ uint8_t priority = 0;
+
+ inline bool operator<(KeyBind const& rhs) const {
+ return priority < rhs.priority;
+ }
+
+ inline bool operator>(KeyBind const& rhs) const {
+ return priority > rhs.priority;
+ }
+ };
+
+ struct MouseBind {
+ MouseButton button = MouseButton::Left;
+ KeyMod mods = KeyMod::NoMod;
+ uint8_t priority = 0;
+ };
+
+ struct ControllerBind {
+ unsigned int controller = 0;
+ ControllerButton button = ControllerButton::Invalid;
+ };
+
+ typedef Variant<NoBind, KeyBind, MouseBind, ControllerBind> Bind;
+
+ static Bind bindFromJson(Json const& json);
+ static Json bindToJson(Bind const& bind);
+
+ struct Category;
+
+ struct BindEntry {
+ // The internal ID of this entry.
+ String id;
+ // The category this entry belongs to.
+ String category;
+ // The user-facing name of this entry.
+ String name;
+
+ // The default binds.
+ List<Bind> defaultBinds;
+ // The user-configured binds.
+ List<Bind> customBinds;
+
+ BindEntry(Json const& config, Category const& category);
+ };
+
+ struct BindRef {
+ KeyMod mods;
+ uint8_t priority;
+
+ // Invalidated on reload, careful!
+ BindEntry* entry;
+ };
+
+ struct BindRefSorter {
+ inline bool operator() (BindRef const& a, BindRef const& b) {
+ return a.priority > b.priority;
+ }
+ };
+
+ struct BindCategory {
+ String id;
+ String name;
+ Json meta;
+
+ StringMap<BindEntry> entries;
+
+ BindCategory(Json const& data);
+ };
+
+ struct InputState {
+ size_t presses = 0;
+ size_t releases = 0;
+
+ // Calls the passed functions for each press and release.
+ template <typename PressFunction, typename ReleaseFunction>
+ void forEach(PressFunction&& pressed, ReleaseFunction&& released) {
+ for (size_t i = 0; i != releases; ++i) {
+ pressed();
+ released();
+ }
+ }
+
+ constexpr bool held() {
+ return presses < releases;
+ }
+ };
+
+ // Get pointer to the singleton root instance, if it exists. Otherwise,
+ // returns nullptr.
+ static Input* singletonPtr();
+
+ // Gets reference to GuiContext singleton, throws GuiContextException if root
+ // is not initialized.
+ static Input& singleton();
+
+ Input();
+ ~Input();
+
+ Input(Input const&) = delete;
+ Input& operator=(Input const&) = delete;
+
+ // Clears input state. Should be done at the end of the client loop.
+ void reset();
+
+ // Handles an input event.
+ bool handleInput(InputEvent const& event);
+
+ // Loads input categories and their binds from Assets.
+ void reload();
+ private:
+ static Input* s_singleton;
+
+ // Regenerated on reload.
+ StringMap<BindCategory> m_bindCategories;
+ // Contains raw pointers to bind entries in categories, so also regenerated on reload.
+ HashMap<InputVariant, List<BindRef>> m_inputsToBinds;
+
+ ListenerPtr m_rootReloadListener;
+
+ // Per-frame input state maps.
+
+ //Raw input state
+ HashMap<InputVariant, InputState> m_inputStates;
+ //Bind input state
+ HashMap<BindEntry*, InputState> m_bindStates;
+ };
+}
+
+#endif \ No newline at end of file