summaryrefslogtreecommitdiff
path: root/core/input/input.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/input/input.cpp')
-rw-r--r--core/input/input.cpp138
1 files changed, 83 insertions, 55 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp
index fa2f00bf8d..4befdfac58 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -72,9 +72,9 @@ Input *Input::singleton = nullptr;
void (*Input::set_mouse_mode_func)(Input::MouseMode) = nullptr;
Input::MouseMode (*Input::get_mouse_mode_func)() = nullptr;
-void (*Input::warp_mouse_func)(const Vector2 &p_to_pos) = nullptr;
+void (*Input::warp_mouse_func)(const Vector2 &p_position) = nullptr;
Input::CursorShape (*Input::get_current_cursor_shape_func)() = nullptr;
-void (*Input::set_custom_mouse_cursor_func)(const RES &, Input::CursorShape, const Vector2 &) = nullptr;
+void (*Input::set_custom_mouse_cursor_func)(const Ref<Resource> &, Input::CursorShape, const Vector2 &) = nullptr;
Input *Input::get_singleton() {
return singleton;
@@ -90,6 +90,7 @@ Input::MouseMode Input::get_mouse_mode() const {
}
void Input::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("is_anything_pressed"), &Input::is_anything_pressed);
ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed);
ClassDB::bind_method(D_METHOD("is_physical_key_pressed", "keycode"), &Input::is_physical_key_pressed);
ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &Input::is_mouse_button_pressed);
@@ -125,7 +126,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &Input::get_mouse_button_mask);
ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &Input::set_mouse_mode);
ClassDB::bind_method(D_METHOD("get_mouse_mode"), &Input::get_mouse_mode);
- ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &Input::warp_mouse_position);
+ ClassDB::bind_method(D_METHOD("warp_mouse", "position"), &Input::warp_mouse);
ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &Input::action_press, DEFVAL(1.f));
ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release);
ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Input::set_default_cursor_shape, DEFVAL(CURSOR_ARROW));
@@ -189,35 +190,53 @@ void Input::VelocityTrack::update(const Vector2 &p_delta_p) {
float delta_t = tdiff / 1000000.0;
last_tick = tick;
+ if (delta_t > max_ref_frame) {
+ // First movement in a long time, reset and start again.
+ velocity = Vector2();
+ accum = p_delta_p;
+ accum_t = 0;
+ return;
+ }
+
accum += p_delta_p;
accum_t += delta_t;
- if (accum_t > max_ref_frame * 10) {
- accum_t = max_ref_frame * 10;
+ if (accum_t < min_ref_frame) {
+ // Not enough time has passed to calculate speed precisely.
+ return;
}
- while (accum_t >= min_ref_frame) {
- float slice_t = min_ref_frame / accum_t;
- Vector2 slice = accum * slice_t;
- accum = accum - slice;
- accum_t -= min_ref_frame;
-
- velocity = (slice / min_ref_frame).lerp(velocity, min_ref_frame / max_ref_frame);
- }
+ velocity = accum / accum_t;
+ accum = Vector2();
+ accum_t = 0;
}
void Input::VelocityTrack::reset() {
last_tick = OS::get_singleton()->get_ticks_usec();
velocity = Vector2();
+ accum = Vector2();
accum_t = 0;
}
Input::VelocityTrack::VelocityTrack() {
min_ref_frame = 0.1;
- max_ref_frame = 0.3;
+ max_ref_frame = 3.0;
reset();
}
+bool Input::is_anything_pressed() const {
+ _THREAD_SAFE_METHOD_
+
+ for (const KeyValue<StringName, Input::Action> &E : action_state) {
+ if (E.value.pressed) {
+ return true;
+ }
+ }
+ return !keys_pressed.is_empty() ||
+ !joy_buttons_pressed.is_empty() ||
+ mouse_button_mask > MouseButton::NONE;
+}
+
bool Input::is_key_pressed(Key p_keycode) const {
_THREAD_SAFE_METHOD_
return keys_pressed.has(p_keycode);
@@ -253,65 +272,65 @@ bool Input::is_action_pressed(const StringName &p_action, bool p_exact) const {
bool Input::is_action_just_pressed(const StringName &p_action, bool p_exact) const {
ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action));
- const Map<StringName, Action>::Element *E = action_state.find(p_action);
+ HashMap<StringName, Action>::ConstIterator E = action_state.find(p_action);
if (!E) {
return false;
}
- if (p_exact && E->get().exact == false) {
+ if (p_exact && E->value.exact == false) {
return false;
}
if (Engine::get_singleton()->is_in_physics_frame()) {
- return E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames();
+ return E->value.pressed && E->value.physics_frame == Engine::get_singleton()->get_physics_frames();
} else {
- return E->get().pressed && E->get().process_frame == Engine::get_singleton()->get_process_frames();
+ return E->value.pressed && E->value.process_frame == Engine::get_singleton()->get_process_frames();
}
}
bool Input::is_action_just_released(const StringName &p_action, bool p_exact) const {
ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action));
- const Map<StringName, Action>::Element *E = action_state.find(p_action);
+ HashMap<StringName, Action>::ConstIterator E = action_state.find(p_action);
if (!E) {
return false;
}
- if (p_exact && E->get().exact == false) {
+ if (p_exact && E->value.exact == false) {
return false;
}
if (Engine::get_singleton()->is_in_physics_frame()) {
- return !E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames();
+ return !E->value.pressed && E->value.physics_frame == Engine::get_singleton()->get_physics_frames();
} else {
- return !E->get().pressed && E->get().process_frame == Engine::get_singleton()->get_process_frames();
+ return !E->value.pressed && E->value.process_frame == Engine::get_singleton()->get_process_frames();
}
}
float Input::get_action_strength(const StringName &p_action, bool p_exact) const {
ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), 0.0, InputMap::get_singleton()->suggest_actions(p_action));
- const Map<StringName, Action>::Element *E = action_state.find(p_action);
+ HashMap<StringName, Action>::ConstIterator E = action_state.find(p_action);
if (!E) {
return 0.0f;
}
- if (p_exact && E->get().exact == false) {
+ if (p_exact && E->value.exact == false) {
return 0.0f;
}
- return E->get().strength;
+ return E->value.strength;
}
float Input::get_action_raw_strength(const StringName &p_action, bool p_exact) const {
- const Map<StringName, Action>::Element *E = action_state.find(p_action);
+ HashMap<StringName, Action>::ConstIterator E = action_state.find(p_action);
if (!E) {
return 0.0f;
}
- if (p_exact && E->get().exact == false) {
+ if (p_exact && E->value.exact == false) {
return 0.0f;
}
- return E->get().raw_strength;
+ return E->value.raw_strength;
}
float Input::get_axis(const StringName &p_negative_action, const StringName &p_positive_action) const {
@@ -504,18 +523,20 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
- Point2 pos = mm->get_global_position();
- if (mouse_pos != pos) {
- set_mouse_position(pos);
+ Point2 position = mm->get_global_position();
+ if (mouse_pos != position) {
+ set_mouse_position(position);
}
+ Vector2 relative = mm->get_relative();
+ mouse_velocity_track.update(relative);
if (event_dispatch_function && emulate_touch_from_mouse && !p_is_emulated && (mm->get_button_mask() & MouseButton::LEFT) != MouseButton::NONE) {
Ref<InputEventScreenDrag> drag_event;
drag_event.instantiate();
- drag_event->set_position(mm->get_position());
- drag_event->set_relative(mm->get_relative());
- drag_event->set_velocity(mm->get_velocity());
+ drag_event->set_position(position);
+ drag_event->set_relative(relative);
+ drag_event->set_velocity(get_last_mouse_velocity());
event_dispatch_function(drag_event);
}
@@ -615,21 +636,21 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
}
}
- for (OrderedHashMap<StringName, InputMap::Action>::ConstElement E = InputMap::get_singleton()->get_action_map().front(); E; E = E.next()) {
- if (InputMap::get_singleton()->event_is_action(p_event, E.key())) {
+ for (const KeyValue<StringName, InputMap::Action> &E : InputMap::get_singleton()->get_action_map()) {
+ if (InputMap::get_singleton()->event_is_action(p_event, E.key)) {
// If not echo and action pressed state has changed
- if (!p_event->is_echo() && is_action_pressed(E.key(), false) != p_event->is_action_pressed(E.key())) {
+ if (!p_event->is_echo() && is_action_pressed(E.key, false) != p_event->is_action_pressed(E.key)) {
Action action;
action.physics_frame = Engine::get_singleton()->get_physics_frames();
action.process_frame = Engine::get_singleton()->get_process_frames();
- action.pressed = p_event->is_action_pressed(E.key());
+ action.pressed = p_event->is_action_pressed(E.key);
action.strength = 0.0f;
action.raw_strength = 0.0f;
- action.exact = InputMap::get_singleton()->event_is_action(p_event, E.key(), true);
- action_state[E.key()] = action;
+ action.exact = InputMap::get_singleton()->event_is_action(p_event, E.key, true);
+ action_state[E.key] = action;
}
- action_state[E.key()].strength = p_event->get_action_strength(E.key());
- action_state[E.key()].raw_strength = p_event->get_action_raw_strength(E.key());
+ action_state[E.key].strength = p_event->get_action_strength(E.key);
+ action_state[E.key].raw_strength = p_event->get_action_raw_strength(E.key);
}
}
@@ -696,7 +717,6 @@ void Input::set_gyroscope(const Vector3 &p_gyroscope) {
}
void Input::set_mouse_position(const Point2 &p_posf) {
- mouse_velocity_track.update(p_posf - mouse_pos);
mouse_pos = p_posf;
}
@@ -704,7 +724,8 @@ Point2 Input::get_mouse_position() const {
return mouse_pos;
}
-Point2 Input::get_last_mouse_velocity() const {
+Point2 Input::get_last_mouse_velocity() {
+ mouse_velocity_track.update(Vector2());
return mouse_velocity_track.velocity;
}
@@ -712,8 +733,8 @@ MouseButton Input::get_mouse_button_mask() const {
return mouse_button_mask; // do not trust OS implementation, should remove it - OS::get_singleton()->get_mouse_button_state();
}
-void Input::warp_mouse_position(const Vector2 &p_to) {
- warp_mouse_func(p_to);
+void Input::warp_mouse(const Vector2 &p_position) {
+ warp_mouse_func(p_position);
}
Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) {
@@ -735,7 +756,7 @@ Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, con
const Point2i pos_local = p_motion->get_global_position() - p_rect.position;
const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y));
if (pos_warped != pos_local) {
- warp_mouse_position(pos_warped + p_rect.position);
+ warp_mouse(pos_warped + p_rect.position);
}
return rel_warped;
@@ -751,6 +772,8 @@ void Input::action_press(const StringName &p_action, float p_strength) {
action.process_frame = Engine::get_singleton()->get_process_frames();
action.pressed = true;
action.strength = p_strength;
+ action.raw_strength = p_strength;
+ action.exact = true;
action_state[p_action] = action;
}
@@ -762,6 +785,8 @@ void Input::action_release(const StringName &p_action) {
action.process_frame = Engine::get_singleton()->get_process_frames();
action.pressed = false;
action.strength = 0.f;
+ action.raw_strength = 0.f;
+ action.exact = true;
action_state[p_action] = action;
}
@@ -825,11 +850,13 @@ Input::CursorShape Input::get_current_cursor_shape() const {
return get_current_cursor_shape_func();
}
-void Input::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+void Input::set_custom_mouse_cursor(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
+ ERR_FAIL_INDEX(p_shape, CursorShape::CURSOR_MAX);
+
set_custom_mouse_cursor_func(p_cursor, p_shape, p_hotspot);
}
@@ -1049,7 +1076,6 @@ void Input::_axis_event(int p_device, JoyAxis p_axis, float p_value) {
Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button) {
JoyEvent event;
- event.type = TYPE_MAX;
for (int i = 0; i < mapping.bindings.size(); i++) {
const JoyBinding binding = mapping.bindings[i];
@@ -1085,7 +1111,6 @@ Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping,
Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, JoyAxis p_axis, float p_value) {
JoyEvent event;
- event.type = TYPE_MAX;
for (int i = 0; i < mapping.bindings.size(); i++) {
const JoyBinding binding = mapping.bindings[i];
@@ -1124,7 +1149,6 @@ Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, J
// It doesn't make sense for a full axis to map to a button,
// but keeping as a default for a trigger with a positive half-axis.
event.value = (shifted_positive_value * 2) - 1;
- ;
break;
}
return event;
@@ -1379,12 +1403,12 @@ String Input::get_joy_guid(int p_device) const {
Array Input::get_connected_joypads() {
Array ret;
- Map<int, Joypad>::Element *elem = joy_names.front();
+ HashMap<int, Joypad>::Iterator elem = joy_names.begin();
while (elem) {
- if (elem->get().connected) {
- ret.push_back(elem->key());
+ if (elem->value.connected) {
+ ret.push_back(elem->key);
}
- elem = elem->next();
+ ++elem;
}
return ret;
}
@@ -1422,4 +1446,8 @@ Input::Input() {
}
}
+Input::~Input() {
+ singleton = nullptr;
+}
+
//////////////////////////////////////////////////////////