2024-02-13 13:59:01 +00:00
|
|
|
#include "player_input.hpp"
|
|
|
|
#include "godot_macros.h"
|
|
|
|
#include "godot_cpp/classes/input.hpp"
|
|
|
|
#include "godot_cpp/classes/input_event.hpp"
|
2024-02-13 20:39:50 +00:00
|
|
|
#include "godot_cpp/classes/input_event_mouse_motion.hpp"
|
2024-04-10 10:44:50 +00:00
|
|
|
#include "godot_cpp/variant/callable.hpp"
|
2024-02-13 13:59:01 +00:00
|
|
|
#include <algorithm>
|
2024-02-19 00:04:14 +00:00
|
|
|
#include <optional>
|
2024-02-13 13:59:01 +00:00
|
|
|
|
|
|
|
namespace godot {
|
|
|
|
void PlayerInput::_bind_methods() {}
|
|
|
|
|
2024-02-19 00:04:14 +00:00
|
|
|
Vector2 PlayerInput::lastMouseMotion{0.f, 0.f};
|
|
|
|
bool PlayerInput::primaryExists{false};
|
|
|
|
|
2024-04-10 10:44:50 +00:00
|
|
|
PlayerInput::Listener::Listener(String positive, String negative, Callable callable)
|
2024-02-13 13:59:01 +00:00
|
|
|
: actionNegative{negative}
|
|
|
|
, actionPositive{positive}
|
2024-04-10 10:44:50 +00:00
|
|
|
, callable{callable}
|
2024-02-13 20:39:50 +00:00
|
|
|
, isMouseEvent{positive.begins_with("_mouse_") || negative.begins_with("_mouse_")} {}
|
|
|
|
|
2024-04-10 10:44:50 +00:00
|
|
|
PlayerInput::Listener::Listener(String action, Callable callable)
|
|
|
|
: PlayerInput::Listener::Listener(action, String(), callable) {}
|
2024-02-23 20:50:29 +00:00
|
|
|
|
2024-02-19 00:04:14 +00:00
|
|
|
std::optional<float> PlayerInput::Listener::evaluate_action(String const &action) {
|
2024-02-13 20:39:50 +00:00
|
|
|
Input *input = Input::get_singleton();
|
2024-02-19 00:04:14 +00:00
|
|
|
if(action.begins_with("_mouse_")) {
|
|
|
|
Vector2 vector = PlayerInput::get_last_mouse_motion();
|
|
|
|
if(action.ends_with("_up"))
|
|
|
|
return vector.y > 0.f ? vector.y : 0.f;
|
|
|
|
else if(action.ends_with("_down"))
|
|
|
|
return vector.y < 0.f ? -vector.y : 0.f;
|
|
|
|
else if(action.ends_with("_right"))
|
|
|
|
return vector.x > 0.f ? vector.x : 0.f;
|
|
|
|
else if(action.ends_with("_left"))
|
|
|
|
return vector.x < 0.f ? -vector.x : 0.f;
|
2024-03-20 08:44:25 +00:00
|
|
|
}
|
|
|
|
if(action.is_empty()) {
|
2024-02-19 00:04:14 +00:00
|
|
|
return 0.f;
|
2024-02-13 20:39:50 +00:00
|
|
|
} else {
|
2024-02-19 00:04:14 +00:00
|
|
|
return float(input->is_action_pressed(action));
|
2024-02-13 20:39:50 +00:00
|
|
|
}
|
|
|
|
}
|
2024-02-13 13:59:01 +00:00
|
|
|
|
|
|
|
bool PlayerInput::Listener::has_changed(Ref<InputEvent> const &event) {
|
2024-03-20 08:44:25 +00:00
|
|
|
bool const mouse_changed{this->isMouseEvent && event->is_class("InputEventMouseMotion")};
|
|
|
|
bool const negative_changed{!this->actionNegative.is_empty() && event->is_action(this->actionNegative)};
|
|
|
|
bool const positive_changed{!this->actionPositive.is_empty() && event->is_action(this->actionPositive)};
|
|
|
|
return mouse_changed || negative_changed || positive_changed;
|
2024-02-13 13:59:01 +00:00
|
|
|
}
|
2024-02-13 20:39:50 +00:00
|
|
|
|
2024-02-13 13:59:01 +00:00
|
|
|
float PlayerInput::Listener::evaluate(Ref<InputEvent> const &event) {
|
2024-02-19 00:04:14 +00:00
|
|
|
std::optional<float> positive = PlayerInput::Listener::evaluate_action(this->actionPositive);
|
|
|
|
std::optional<float> negative = PlayerInput::Listener::evaluate_action(this->actionNegative);
|
|
|
|
if(!positive.has_value() || !negative.has_value())
|
|
|
|
return 0.f;
|
|
|
|
float newest = positive.value() - negative.value();
|
|
|
|
if(this->lastCached != newest || this->isMouseEvent)
|
2024-04-10 10:44:50 +00:00
|
|
|
this->callable.call(event, newest);
|
2024-02-19 00:04:14 +00:00
|
|
|
return (this->lastCached = newest);
|
2024-02-13 13:59:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool PlayerInput::Listener::operator==(godot::PlayerInput::Listener const& b) {
|
2024-04-10 10:44:50 +00:00
|
|
|
return this->callable == b.callable
|
2024-02-13 13:59:01 +00:00
|
|
|
&& this->actionNegative == b.actionNegative
|
|
|
|
&& this->actionPositive == b.actionPositive;
|
|
|
|
}
|
|
|
|
|
2024-02-19 00:04:14 +00:00
|
|
|
Vector2 PlayerInput::get_last_mouse_motion() {
|
|
|
|
return PlayerInput::lastMouseMotion;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerInput::_enter_tree() {
|
|
|
|
GDGAMEONLY();
|
|
|
|
if(!PlayerInput::primaryExists) {
|
|
|
|
this->isPrimary = true;
|
|
|
|
PlayerInput::primaryExists = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerInput::_exit_tree() {
|
|
|
|
GDGAMEONLY();
|
|
|
|
if(this->isPrimary) {
|
|
|
|
this->isPrimary = false;
|
|
|
|
PlayerInput::primaryExists = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-13 13:59:01 +00:00
|
|
|
void PlayerInput::_unhandled_input(Ref<InputEvent> const &event) {
|
|
|
|
GDGAMEONLY();
|
2024-02-19 00:04:14 +00:00
|
|
|
if(this->isPrimary && event->is_class("InputEventMouseMotion"))
|
|
|
|
PlayerInput::lastMouseMotion = Object::cast_to<InputEventMouseMotion>(*event)->get_relative();
|
2024-02-13 13:59:01 +00:00
|
|
|
for(Listener& listener: this->listeners) {
|
|
|
|
if(listener.has_changed(event)) {
|
|
|
|
listener.evaluate(event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-19 00:04:14 +00:00
|
|
|
void PlayerInput::_process(double deltaTime) {
|
2024-03-20 08:44:25 +00:00
|
|
|
if(this->isPrimary)
|
|
|
|
PlayerInput::lastMouseMotion = {0.f, 0.f};
|
2024-02-19 00:04:14 +00:00
|
|
|
}
|
|
|
|
|
2024-02-13 13:59:01 +00:00
|
|
|
void PlayerInput::listen_to(Listener const& listener) {
|
|
|
|
this->listeners.push_back(listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerInput::stop_listening(Node *node) {
|
|
|
|
for(size_t i = 0; i < this->listeners.size(); ++i) {
|
|
|
|
Listener& l = this->listeners.at(i);
|
2024-04-10 10:44:50 +00:00
|
|
|
if(l.callable.get_object() == node) {
|
2024-02-13 13:59:01 +00:00
|
|
|
this->listeners.erase(this->listeners.begin() + i);
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlayerInput::stop_listening(Listener const& listener) {
|
|
|
|
std::vector<Listener>::iterator itr = std::find(this->listeners.begin(), this->listeners.end(), listener);
|
|
|
|
if(itr != this->listeners.end())
|
|
|
|
this->listeners.erase(itr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|