summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/input/input.cpp43
-rw-r--r--core/input/input.h11
-rw-r--r--core/input/input_event.cpp28
-rw-r--r--core/input/input_event.h10
-rw-r--r--core/input/input_map.cpp22
-rw-r--r--core/input/input_map.h6
-rw-r--r--core/math/vector3.h8
-rw-r--r--core/variant/variant_call.cpp1
8 files changed, 79 insertions, 50 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 047aeb47fd..48e573626d 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -97,11 +97,11 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed);
ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &Input::is_mouse_button_pressed);
ClassDB::bind_method(D_METHOD("is_joy_button_pressed", "device", "button"), &Input::is_joy_button_pressed);
- ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &Input::is_action_pressed);
- ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action"), &Input::is_action_just_pressed);
- ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &Input::is_action_just_released);
- ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &Input::get_action_strength);
- ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action"), &Input::get_action_strength);
+ ClassDB::bind_method(D_METHOD("is_action_pressed", "action", "exact"), &Input::is_action_pressed, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action", "exact"), &Input::is_action_just_pressed, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_action_just_released", "action", "exact"), &Input::is_action_just_released, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_action_strength", "action", "exact"), &Input::get_action_strength, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action", "exact"), &Input::get_action_strength, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_axis", "negative_action", "positive_action"), &Input::get_axis);
ClassDB::bind_method(D_METHOD("get_vector", "negative_x", "positive_x", "negative_y", "positive_y", "deadzone"), &Input::get_vector, DEFVAL(-1.0f));
ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false));
@@ -240,16 +240,20 @@ bool Input::is_joy_button_pressed(int p_device, int p_button) const {
return joy_buttons_pressed.has(_combine_device(p_button, p_device));
}
-bool Input::is_action_pressed(const StringName &p_action) const {
- return action_state.has(p_action) && action_state[p_action].pressed;
+bool Input::is_action_pressed(const StringName &p_action, bool p_exact) const {
+ return action_state.has(p_action) && action_state[p_action].pressed && (p_exact ? action_state[p_action].exact : true);
}
-bool Input::is_action_just_pressed(const StringName &p_action) const {
+bool Input::is_action_just_pressed(const StringName &p_action, bool p_exact) const {
const Map<StringName, Action>::Element *E = action_state.find(p_action);
if (!E) {
return false;
}
+ if (p_exact && E->get().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();
} else {
@@ -257,12 +261,16 @@ bool Input::is_action_just_pressed(const StringName &p_action) const {
}
}
-bool Input::is_action_just_released(const StringName &p_action) const {
+bool Input::is_action_just_released(const StringName &p_action, bool p_exact) const {
const Map<StringName, Action>::Element *E = action_state.find(p_action);
if (!E) {
return false;
}
+ if (p_exact && E->get().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();
} else {
@@ -270,21 +278,29 @@ bool Input::is_action_just_released(const StringName &p_action) const {
}
}
-float Input::get_action_strength(const StringName &p_action) const {
+float Input::get_action_strength(const StringName &p_action, bool p_exact) const {
const Map<StringName, Action>::Element *E = action_state.find(p_action);
if (!E) {
return 0.0f;
}
+ if (p_exact && E->get().exact == false) {
+ return 0.0f;
+ }
+
return E->get().strength;
}
-float Input::get_action_raw_strength(const StringName &p_action) const {
+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);
if (!E) {
return 0.0f;
}
+ if (p_exact && E->get().exact == false) {
+ return 0.0f;
+ }
+
return E->get().raw_strength;
}
@@ -590,14 +606,15 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
for (const Map<StringName, InputMap::Action>::Element *E = InputMap::get_singleton()->get_action_map().front(); E; E = E->next()) {
if (InputMap::get_singleton()->event_is_action(p_event, E->key())) {
- // Save the action's state
- if (!p_event->is_echo() && is_action_pressed(E->key()) != p_event->is_action_pressed(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())) {
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.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_state[E->key()].strength = p_event->get_action_strength(E->key());
diff --git a/core/input/input.h b/core/input/input.h
index 445b7ff0cf..0e3af42381 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -116,6 +116,7 @@ private:
uint64_t physics_frame;
uint64_t process_frame;
bool pressed;
+ bool exact;
float strength;
float raw_strength;
};
@@ -261,11 +262,11 @@ public:
bool is_key_pressed(int p_keycode) const;
bool is_mouse_button_pressed(int p_button) const;
bool is_joy_button_pressed(int p_device, int p_button) const;
- bool is_action_pressed(const StringName &p_action) const;
- bool is_action_just_pressed(const StringName &p_action) const;
- bool is_action_just_released(const StringName &p_action) const;
- float get_action_strength(const StringName &p_action) const;
- float get_action_raw_strength(const StringName &p_action) const;
+ bool is_action_pressed(const StringName &p_action, bool p_exact = false) const;
+ bool is_action_just_pressed(const StringName &p_action, bool p_exact = false) const;
+ bool is_action_just_released(const StringName &p_action, bool p_exact = false) const;
+ float get_action_strength(const StringName &p_action, bool p_exact = false) const;
+ float get_action_raw_strength(const StringName &p_action, bool p_exact = false) const;
float get_axis(const StringName &p_negative_action, const StringName &p_positive_action) const;
Vector2 get_vector(const StringName &p_negative_x, const StringName &p_positive_x, const StringName &p_negative_y, const StringName &p_positive_y, float p_deadzone = -1.0f) const;
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index c91dc4d067..b1c8f1ad66 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -44,31 +44,31 @@ int InputEvent::get_device() const {
return device;
}
-bool InputEvent::is_action(const StringName &p_action) const {
- return InputMap::get_singleton()->event_is_action(Ref<InputEvent>((InputEvent *)this), p_action);
+bool InputEvent::is_action(const StringName &p_action, bool p_exact_match) const {
+ return InputMap::get_singleton()->event_is_action(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match);
}
-bool InputEvent::is_action_pressed(const StringName &p_action, bool p_allow_echo) const {
+bool InputEvent::is_action_pressed(const StringName &p_action, bool p_allow_echo, bool p_exact_match) const {
bool pressed;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, &pressed, nullptr, nullptr);
return valid && pressed && (p_allow_echo || !is_echo());
}
-bool InputEvent::is_action_released(const StringName &p_action) const {
+bool InputEvent::is_action_released(const StringName &p_action, bool p_exact_match) const {
bool pressed;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, &pressed, nullptr, nullptr);
return valid && !pressed;
}
-float InputEvent::get_action_strength(const StringName &p_action) const {
+float InputEvent::get_action_strength(const StringName &p_action, bool p_exact_match) const {
float strength;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, nullptr, &strength);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, nullptr, &strength, nullptr);
return valid ? strength : 0.0f;
}
-float InputEvent::get_action_raw_strength(const StringName &p_action) const {
+float InputEvent::get_action_raw_strength(const StringName &p_action, bool p_exact_match) const {
float raw_strength;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, nullptr, nullptr, &raw_strength);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, p_exact_match, nullptr, nullptr, &raw_strength);
return valid ? raw_strength : 0.0f;
}
@@ -100,10 +100,10 @@ void InputEvent::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_device", "device"), &InputEvent::set_device);
ClassDB::bind_method(D_METHOD("get_device"), &InputEvent::get_device);
- ClassDB::bind_method(D_METHOD("is_action", "action"), &InputEvent::is_action);
- ClassDB::bind_method(D_METHOD("is_action_pressed", "action", "allow_echo"), &InputEvent::is_action_pressed, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("is_action_released", "action"), &InputEvent::is_action_released);
- ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &InputEvent::get_action_strength);
+ ClassDB::bind_method(D_METHOD("is_action", "action", "exact_match"), &InputEvent::is_action, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_action_pressed", "action", "allow_echo", "exact_match"), &InputEvent::is_action_pressed, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("is_action_released", "action", "exact_match"), &InputEvent::is_action_released, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_action_strength", "action", "exact_match"), &InputEvent::get_action_strength, DEFVAL(false));
ClassDB::bind_method(D_METHOD("is_pressed"), &InputEvent::is_pressed);
ClassDB::bind_method(D_METHOD("is_echo"), &InputEvent::is_echo);
diff --git a/core/input/input_event.h b/core/input/input_event.h
index a354119cf9..1ce1fad9c2 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -128,11 +128,11 @@ public:
void set_device(int p_device);
int get_device() const;
- bool is_action(const StringName &p_action) const;
- bool is_action_pressed(const StringName &p_action, bool p_allow_echo = false) const;
- bool is_action_released(const StringName &p_action) const;
- float get_action_strength(const StringName &p_action) const;
- float get_action_raw_strength(const StringName &p_action) const;
+ bool is_action(const StringName &p_action, bool p_exact_match = false) const;
+ bool is_action_pressed(const StringName &p_action, bool p_allow_echo = false, bool p_exact_match = false) const;
+ bool is_action_released(const StringName &p_action, bool p_exact_match = false) const;
+ float get_action_strength(const StringName &p_action, bool p_exact_match = false) const;
+ float get_action_raw_strength(const StringName &p_action, bool p_exact_match = false) const;
// To be removed someday, since they do not make sense for all events
virtual bool is_pressed() const;
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index 53ed925c1f..c03e64eaf4 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -50,7 +50,7 @@ void InputMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event);
ClassDB::bind_method(D_METHOD("action_erase_events", "action"), &InputMap::action_erase_events);
ClassDB::bind_method(D_METHOD("action_get_events", "action"), &InputMap::_action_get_events);
- ClassDB::bind_method(D_METHOD("event_is_action", "event", "action"), &InputMap::event_is_action);
+ ClassDB::bind_method(D_METHOD("event_is_action", "event", "action", "exact_match"), &InputMap::event_is_action, DEFVAL(false));
ClassDB::bind_method(D_METHOD("load_from_project_settings"), &InputMap::load_from_project_settings);
}
@@ -95,7 +95,7 @@ List<StringName> InputMap::get_actions() const {
return actions;
}
-List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
+List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
ERR_FAIL_COND_V(!p_event.is_valid(), nullptr);
for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) {
@@ -106,7 +106,9 @@ List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Re
int device = e->get_device();
if (device == ALL_DEVICES || device == p_event->get_device()) {
- if (e->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) {
+ if (p_exact_match && e->shortcut_match(p_event)) {
+ return E;
+ } else if (!p_exact_match && e->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) {
return E;
}
}
@@ -134,7 +136,7 @@ void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone)
void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_MSG(p_event.is_null(), "It's not a reference to a valid InputEvent object.");
ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
- if (_find_event(input_map[p_action], p_event)) {
+ if (_find_event(input_map[p_action], p_event, true)) {
return; // Already addded.
}
@@ -143,13 +145,13 @@ void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent
bool InputMap::action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_V_MSG(!input_map.has(p_action), false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
- return (_find_event(input_map[p_action], p_event) != nullptr);
+ return (_find_event(input_map[p_action], p_event, true) != nullptr);
}
void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
- List<Ref<InputEvent>>::Element *E = _find_event(input_map[p_action], p_event);
+ List<Ref<InputEvent>>::Element *E = _find_event(input_map[p_action], p_event, true);
if (E) {
input_map[p_action].inputs.erase(E);
if (Input::get_singleton()->is_action_pressed(p_action)) {
@@ -185,11 +187,11 @@ const List<Ref<InputEvent>> *InputMap::action_get_events(const StringName &p_act
return &E->get().inputs;
}
-bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const {
- return event_get_action_status(p_event, p_action);
+bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match) const {
+ return event_get_action_status(p_event, p_action, p_exact_match);
}
-bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
+bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
Map<StringName, Action>::Element *E = input_map.find(p_action);
ERR_FAIL_COND_V_MSG(!E, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
@@ -207,7 +209,7 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str
bool pressed;
float strength;
float raw_strength;
- List<Ref<InputEvent>>::Element *event = _find_event(E->get(), p_event, &pressed, &strength, &raw_strength);
+ List<Ref<InputEvent>>::Element *event = _find_event(E->get(), p_event, p_exact_match, &pressed, &strength, &raw_strength);
if (event != nullptr) {
if (p_pressed != nullptr) {
*p_pressed = pressed;
diff --git a/core/input/input_map.h b/core/input/input_map.h
index 1646e7fadb..28c692c7ba 100644
--- a/core/input/input_map.h
+++ b/core/input/input_map.h
@@ -54,7 +54,7 @@ private:
mutable Map<StringName, Action> input_map;
- List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
+ List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
Array _action_get_events(const StringName &p_action);
Array _get_actions();
@@ -78,8 +78,8 @@ public:
void action_erase_events(const StringName &p_action);
const List<Ref<InputEvent>> *action_get_events(const StringName &p_action);
- bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const;
- bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
+ bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false) const;
+ bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool p_exact_match = false, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
const Map<StringName, Action> &get_action_map() const;
void load_from_project_settings();
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 6b4ff3f9a8..377581bb45 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -110,6 +110,7 @@ struct Vector3 {
_FORCE_INLINE_ Vector3 project(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t angle_to(const Vector3 &p_to) const;
+ _FORCE_INLINE_ real_t signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const;
_FORCE_INLINE_ Vector3 direction_to(const Vector3 &p_to) const;
_FORCE_INLINE_ Vector3 slide(const Vector3 &p_normal) const;
@@ -230,6 +231,13 @@ real_t Vector3::angle_to(const Vector3 &p_to) const {
return Math::atan2(cross(p_to).length(), dot(p_to));
}
+real_t Vector3::signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const {
+ Vector3 cross_to = cross(p_to);
+ real_t unsigned_angle = Math::atan2(cross_to.length(), dot(p_to));
+ real_t sign = cross_to.dot(p_axis);
+ return (sign < 0) ? -unsigned_angle : unsigned_angle;
+}
+
Vector3 Vector3::direction_to(const Vector3 &p_to) const {
Vector3 ret(p_to.x - x, p_to.y - y, p_to.z - z);
ret.normalize();
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 8f2cba138b..48f9816074 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1059,6 +1059,7 @@ static void _register_variant_builtin_methods() {
bind_method(Vector3, min_axis, sarray(), varray());
bind_method(Vector3, max_axis, sarray(), varray());
bind_method(Vector3, angle_to, sarray("to"), varray());
+ bind_method(Vector3, signed_angle_to, sarray("to", "axis"), varray());
bind_method(Vector3, direction_to, sarray("b"), varray());
bind_method(Vector3, distance_to, sarray("b"), varray());
bind_method(Vector3, distance_squared_to, sarray("b"), varray());