91 lines
3.0 KiB
C++
91 lines
3.0 KiB
C++
#include "player_input.hpp"
|
|
#include "godot_macros.h"
|
|
#include "godot_cpp/classes/input.hpp"
|
|
#include "godot_cpp/classes/input_event.hpp"
|
|
#include "godot_cpp/classes/input_event_mouse_motion.hpp"
|
|
#include <algorithm>
|
|
|
|
namespace godot {
|
|
void PlayerInput::_bind_methods() {}
|
|
|
|
PlayerInput::Listener::Listener(String positive, String negative, Node *object, String method)
|
|
: actionNegative{negative}
|
|
, actionPositive{positive}
|
|
, methodName{method}
|
|
, object{object}
|
|
, isMouseEvent{positive.begins_with("_mouse_") || negative.begins_with("_mouse_")} {}
|
|
|
|
float PlayerInput::Listener::evaluate_event(Ref<InputEvent> const &event, String const &action) {
|
|
Input *input = Input::get_singleton();
|
|
if(!action.begins_with("_mouse_")) {
|
|
return float(input->is_action_pressed(action));
|
|
} else {
|
|
InputEventMouseMotion *motion = Object::cast_to<InputEventMouseMotion>(*event);
|
|
if(motion == nullptr)
|
|
return 0.f;
|
|
if(action.ends_with("_up") || action.ends_with("_right")) {
|
|
return motion->get_relative().x;
|
|
} if(action.ends_with("_right") || action.ends_with("_left")) {
|
|
return motion->get_relative().y;
|
|
}
|
|
}
|
|
return 0.f;
|
|
}
|
|
|
|
bool PlayerInput::Listener::has_changed(Ref<InputEvent> const &event) {
|
|
return (
|
|
(!event->is_class("InputEventMouseMotion") ||
|
|
this->isMouseEvent
|
|
) ||
|
|
event->is_action(this->actionNegative) ||
|
|
event->is_action(this->actionPositive)
|
|
);
|
|
}
|
|
|
|
float PlayerInput::Listener::evaluate(Ref<InputEvent> const &event) {
|
|
float positive = PlayerInput::Listener::evaluate_event(event, this->actionPositive);
|
|
float negative = PlayerInput::Listener::evaluate_event(event, this->actionNegative);
|
|
float newest = positive - negative;
|
|
if(lastCached != newest)
|
|
this->object->call(this->methodName, event, newest);
|
|
return (lastCached = newest);
|
|
}
|
|
|
|
bool PlayerInput::Listener::operator==(godot::PlayerInput::Listener const& b) {
|
|
return this->methodName == b.methodName
|
|
&& this->object == b.object
|
|
&& this->actionNegative == b.actionNegative
|
|
&& this->actionPositive == b.actionPositive;
|
|
}
|
|
|
|
void PlayerInput::_unhandled_input(Ref<InputEvent> const &event) {
|
|
GDGAMEONLY();
|
|
for(Listener& listener: this->listeners) {
|
|
if(listener.has_changed(event)) {
|
|
listener.evaluate(event);
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
if(l.object == node) {
|
|
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);
|
|
}
|
|
}
|
|
|