#ifndef PLAYER_INPUT_HPP #define PLAYER_INPUT_HPP #include #include #include "godot_cpp/classes/input.hpp" #include "godot_cpp/classes/input_event.hpp" #include "godot_cpp/classes/node.hpp" namespace godot { class PlayerInput : public Node { GDCLASS(PlayerInput, Node) static void _bind_methods(); public: // a listener is a combination of a positive and negative action and a listener function. // listener functions use godot's Object::call function. // So they require a Node instance and a function name. // The expected signature is void(Ref, float) // actions can also be "special" actions prefixed with _. // special actions include _mouse_up, _mouse_down, _mouse_left and _mouse_right // which rather than checking action_is_down, // will use PlayerInput::get_last_mouse_motion() to poll the current state. struct Listener { friend class PlayerInput; private: // the two actions, evaluated as positive - negative String actionNegative{""}; String actionPositive{""}; // the last cached action, if the newest result matches this, the event will be considered // duplicate and ignored (not passed to listener) float lastCached{0.f}; // name of the method to call, expected signature is void(Ref, float) String methodName{""}; // pointer to the node to call methodName on Node *object{nullptr}; // if either actionNegative or actionPositive is a _mouse_ event this will be true bool isMouseEvent{false}; public: Listener(String positive, String negative, Node *object, String method); Listener(String action, Node *object, String method); // evaluate the current state of an action. static std::optional evaluate_action(String const &action); // check if this event has any chance to result in a trigger, does not evaluate the event or // poll current input state bool has_changed(Ref const &event); // evaluate the event for changes to either actionPositive or actionNegative float evaluate(Ref const &event); bool operator==(godot::PlayerInput::Listener const& b); }; private: // the last mouse motion, updated by the primary instance static Vector2 lastMouseMotion; // does a primary instance exist static bool primaryExists; // is this the primary instance // the primary instance is responsible for updating static // variables like lastMouseMotion bool isPrimary{false}; // current listeners for this instance std::vector listeners{}; public: static Vector2 get_last_mouse_motion(); virtual void _enter_tree() override; virtual void _exit_tree() override; virtual void _unhandled_input(Ref const &event) override; virtual void _process(double deltaTime) override; void listen_to(Listener const& listener); void stop_listening(Node *node); void stop_listening(Listener const& listener); }; } #endif // !PLAYER_INPUT_HPP