Allow actions to provide an analog value
This commit is contained in:
parent
93ae37f118
commit
ebfa731012
|
@ -41,9 +41,10 @@ void InputMap::_bind_methods() {
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action);
|
ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action);
|
||||||
ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions);
|
ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions);
|
||||||
ClassDB::bind_method(D_METHOD("add_action", "action"), &InputMap::add_action);
|
ClassDB::bind_method(D_METHOD("add_action", "action", "deadzone"), &InputMap::add_action, DEFVAL(0.5f));
|
||||||
ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action);
|
ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("action_set_deadzone", "deadzone"), &InputMap::action_set_deadzone);
|
||||||
ClassDB::bind_method(D_METHOD("action_add_event", "action", "event"), &InputMap::action_add_event);
|
ClassDB::bind_method(D_METHOD("action_add_event", "action", "event"), &InputMap::action_add_event);
|
||||||
ClassDB::bind_method(D_METHOD("action_has_event", "action", "event"), &InputMap::action_has_event);
|
ClassDB::bind_method(D_METHOD("action_has_event", "action", "event"), &InputMap::action_has_event);
|
||||||
ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event);
|
ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event);
|
||||||
|
@ -52,12 +53,13 @@ void InputMap::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals);
|
ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputMap::add_action(const StringName &p_action) {
|
void InputMap::add_action(const StringName &p_action, float p_deadzone) {
|
||||||
|
|
||||||
ERR_FAIL_COND(input_map.has(p_action));
|
ERR_FAIL_COND(input_map.has(p_action));
|
||||||
input_map[p_action] = Action();
|
input_map[p_action] = Action();
|
||||||
static int last_id = 1;
|
static int last_id = 1;
|
||||||
input_map[p_action].id = last_id;
|
input_map[p_action].id = last_id;
|
||||||
|
input_map[p_action].deadzone = p_deadzone;
|
||||||
last_id++;
|
last_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +98,9 @@ List<StringName> InputMap::get_actions() const {
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Ref<InputEvent> >::Element *InputMap::_find_event(List<Ref<InputEvent> > &p_list, const Ref<InputEvent> &p_event, bool p_action_test) const {
|
List<Ref<InputEvent> >::Element *InputMap::_find_event(Action p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength) const {
|
||||||
|
|
||||||
for (List<Ref<InputEvent> >::Element *E = p_list.front(); E; E = E->next()) {
|
for (List<Ref<InputEvent> >::Element *E = p_action.inputs.front(); E; E = E->next()) {
|
||||||
|
|
||||||
const Ref<InputEvent> e = E->get();
|
const Ref<InputEvent> e = E->get();
|
||||||
|
|
||||||
|
@ -106,9 +108,11 @@ List<Ref<InputEvent> >::Element *InputMap::_find_event(List<Ref<InputEvent> > &p
|
||||||
// continue;
|
// continue;
|
||||||
|
|
||||||
int device = e->get_device();
|
int device = e->get_device();
|
||||||
if (device == ALL_DEVICES || device == p_event->get_device())
|
if (device == ALL_DEVICES || device == p_event->get_device()) {
|
||||||
if (e->action_match(p_event))
|
if (e->action_match(p_event, p_pressed, p_strength, p_action.deadzone)) {
|
||||||
return E;
|
return E;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -119,11 +123,18 @@ bool InputMap::has_action(const StringName &p_action) const {
|
||||||
return input_map.has(p_action);
|
return input_map.has(p_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone) {
|
||||||
|
|
||||||
|
ERR_FAIL_COND(!input_map.has(p_action));
|
||||||
|
|
||||||
|
input_map[p_action].deadzone = p_deadzone;
|
||||||
|
}
|
||||||
|
|
||||||
void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
|
void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
|
||||||
|
|
||||||
ERR_FAIL_COND(p_event.is_null());
|
ERR_FAIL_COND(p_event.is_null());
|
||||||
ERR_FAIL_COND(!input_map.has(p_action));
|
ERR_FAIL_COND(!input_map.has(p_action));
|
||||||
if (_find_event(input_map[p_action].inputs, p_event))
|
if (_find_event(input_map[p_action], p_event))
|
||||||
return; //already gots
|
return; //already gots
|
||||||
|
|
||||||
input_map[p_action].inputs.push_back(p_event);
|
input_map[p_action].inputs.push_back(p_event);
|
||||||
|
@ -132,14 +143,14 @@ 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) {
|
bool InputMap::action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!input_map.has(p_action), false);
|
ERR_FAIL_COND_V(!input_map.has(p_action), false);
|
||||||
return (_find_event(input_map[p_action].inputs, p_event) != NULL);
|
return (_find_event(input_map[p_action], p_event) != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
|
void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) {
|
||||||
|
|
||||||
ERR_FAIL_COND(!input_map.has(p_action));
|
ERR_FAIL_COND(!input_map.has(p_action));
|
||||||
|
|
||||||
List<Ref<InputEvent> >::Element *E = _find_event(input_map[p_action].inputs, p_event);
|
List<Ref<InputEvent> >::Element *E = _find_event(input_map[p_action], p_event);
|
||||||
if (E)
|
if (E)
|
||||||
input_map[p_action].inputs.erase(E);
|
input_map[p_action].inputs.erase(E);
|
||||||
}
|
}
|
||||||
|
@ -168,19 +179,33 @@ const List<Ref<InputEvent> > *InputMap::get_action_list(const StringName &p_acti
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const {
|
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_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength) const {
|
||||||
Map<StringName, Action>::Element *E = input_map.find(p_action);
|
Map<StringName, Action>::Element *E = input_map.find(p_action);
|
||||||
if (!E) {
|
if (!E) {
|
||||||
ERR_EXPLAIN("Request for nonexistent InputMap action: " + String(p_action));
|
ERR_EXPLAIN("Request for nonexistent InputMap action: " + String(p_action));
|
||||||
ERR_FAIL_COND_V(!E, false);
|
ERR_FAIL_COND_V(!E, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<InputEventAction> iea = p_event;
|
Ref<InputEventAction> input_event_action = p_event;
|
||||||
if (iea.is_valid()) {
|
if (input_event_action.is_valid()) {
|
||||||
return iea->get_action() == p_action;
|
return input_event_action->get_action() == p_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _find_event(E->get().inputs, p_event, true) != NULL;
|
bool pressed;
|
||||||
|
float strength;
|
||||||
|
List<Ref<InputEvent> >::Element *event = _find_event(E->get(), p_event, &pressed, &strength);
|
||||||
|
if (event != NULL) {
|
||||||
|
if (p_pressed != NULL)
|
||||||
|
*p_pressed = pressed;
|
||||||
|
if (p_strength != NULL)
|
||||||
|
*p_strength = strength;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Map<StringName, InputMap::Action> &InputMap::get_action_map() const {
|
const Map<StringName, InputMap::Action> &InputMap::get_action_map() const {
|
||||||
|
@ -202,16 +227,16 @@ void InputMap::load_from_globals() {
|
||||||
|
|
||||||
String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length());
|
String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length());
|
||||||
|
|
||||||
add_action(name);
|
Dictionary action = ProjectSettings::get_singleton()->get(pi.name);
|
||||||
|
float deadzone = action.has("deadzone") ? (float)action["deadzone"] : 0.5f;
|
||||||
|
Array events = action["events"];
|
||||||
|
|
||||||
Array va = ProjectSettings::get_singleton()->get(pi.name);
|
add_action(name, deadzone);
|
||||||
|
for (int i = 0; i < events.size(); i++) {
|
||||||
for (int i = 0; i < va.size(); i++) {
|
Ref<InputEvent> event = events[i];
|
||||||
|
if (event.is_null())
|
||||||
Ref<InputEvent> ie = va[i];
|
|
||||||
if (ie.is_null())
|
|
||||||
continue;
|
continue;
|
||||||
action_add_event(name, ie);
|
action_add_event(name, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
|
|
||||||
struct Action {
|
struct Action {
|
||||||
int id;
|
int id;
|
||||||
|
float deadzone;
|
||||||
List<Ref<InputEvent> > inputs;
|
List<Ref<InputEvent> > inputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ private:
|
||||||
|
|
||||||
mutable Map<StringName, Action> input_map;
|
mutable Map<StringName, Action> input_map;
|
||||||
|
|
||||||
List<Ref<InputEvent> >::Element *_find_event(List<Ref<InputEvent> > &p_list, const Ref<InputEvent> &p_event, bool p_action_test = false) const;
|
List<Ref<InputEvent> >::Element *_find_event(Action p_action, const Ref<InputEvent> &p_event, bool *p_pressed = NULL, float *p_strength = NULL) const;
|
||||||
|
|
||||||
Array _get_action_list(const StringName &p_action);
|
Array _get_action_list(const StringName &p_action);
|
||||||
Array _get_actions();
|
Array _get_actions();
|
||||||
|
@ -67,15 +68,17 @@ public:
|
||||||
|
|
||||||
bool has_action(const StringName &p_action) const;
|
bool has_action(const StringName &p_action) const;
|
||||||
List<StringName> get_actions() const;
|
List<StringName> get_actions() const;
|
||||||
void add_action(const StringName &p_action);
|
void add_action(const StringName &p_action, float p_deadzone = 0.5);
|
||||||
void erase_action(const StringName &p_action);
|
void erase_action(const StringName &p_action);
|
||||||
|
|
||||||
|
void action_set_deadzone(const StringName &p_action, float p_deadzone);
|
||||||
void action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event);
|
void action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event);
|
||||||
bool action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event);
|
bool action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event);
|
||||||
void action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event);
|
void action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event);
|
||||||
|
|
||||||
const List<Ref<InputEvent> > *get_action_list(const StringName &p_action);
|
const List<Ref<InputEvent> > *get_action_list(const StringName &p_action);
|
||||||
bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const;
|
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 = NULL, float *p_strength = NULL) const;
|
||||||
|
|
||||||
const Map<StringName, Action> &get_action_map() const;
|
const Map<StringName, Action> &get_action_map() const;
|
||||||
void load_from_globals();
|
void load_from_globals();
|
||||||
|
|
|
@ -57,6 +57,7 @@ void Input::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &Input::is_action_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_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("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("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false));
|
ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false));
|
||||||
ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &Input::remove_joy_mapping);
|
ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &Input::remove_joy_mapping);
|
||||||
ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &Input::joy_connection_changed);
|
ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &Input::joy_connection_changed);
|
||||||
|
@ -118,7 +119,7 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
|
|
||||||
String pf = p_function;
|
String pf = p_function;
|
||||||
if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || pf == "is_action_just_pressed" || pf == "is_action_just_released")) {
|
if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || pf == "is_action_just_pressed" || pf == "is_action_just_released" || pf == "get_action_strength")) {
|
||||||
|
|
||||||
List<PropertyInfo> pinfo;
|
List<PropertyInfo> pinfo;
|
||||||
ProjectSettings::get_singleton()->get_property_list(&pinfo);
|
ProjectSettings::get_singleton()->get_property_list(&pinfo);
|
||||||
|
|
|
@ -85,6 +85,7 @@ public:
|
||||||
virtual bool is_action_pressed(const StringName &p_action) const = 0;
|
virtual bool is_action_pressed(const StringName &p_action) const = 0;
|
||||||
virtual bool is_action_just_pressed(const StringName &p_action) const = 0;
|
virtual bool is_action_just_pressed(const StringName &p_action) const = 0;
|
||||||
virtual bool is_action_just_released(const StringName &p_action) const = 0;
|
virtual bool is_action_just_released(const StringName &p_action) const = 0;
|
||||||
|
virtual float get_action_strength(const StringName &p_action) const = 0;
|
||||||
|
|
||||||
virtual float get_joy_axis(int p_device, int p_axis) const = 0;
|
virtual float get_joy_axis(int p_device, int p_axis) const = 0;
|
||||||
virtual String get_joy_name(int p_idx) = 0;
|
virtual String get_joy_name(int p_idx) = 0;
|
||||||
|
|
|
@ -41,11 +41,6 @@ int InputEvent::get_device() const {
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEvent::is_pressed() const {
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputEvent::is_action(const StringName &p_action) const {
|
bool InputEvent::is_action(const StringName &p_action) const {
|
||||||
|
|
||||||
return InputMap::get_singleton()->event_is_action(Ref<InputEvent>((InputEvent *)this), p_action);
|
return InputMap::get_singleton()->event_is_action(Ref<InputEvent>((InputEvent *)this), p_action);
|
||||||
|
@ -53,11 +48,29 @@ bool InputEvent::is_action(const StringName &p_action) const {
|
||||||
|
|
||||||
bool InputEvent::is_action_pressed(const StringName &p_action) const {
|
bool InputEvent::is_action_pressed(const StringName &p_action) const {
|
||||||
|
|
||||||
return (is_pressed() && !is_echo() && is_action(p_action));
|
bool pressed;
|
||||||
|
bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed);
|
||||||
|
return valid && pressed && !is_echo();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEvent::is_action_released(const StringName &p_action) const {
|
bool InputEvent::is_action_released(const StringName &p_action) const {
|
||||||
|
|
||||||
return (!is_pressed() && is_action(p_action));
|
bool pressed;
|
||||||
|
bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed);
|
||||||
|
return valid && !pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
float InputEvent::get_action_strength(const StringName &p_action) const {
|
||||||
|
|
||||||
|
bool pressed;
|
||||||
|
float strength;
|
||||||
|
bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed, &strength);
|
||||||
|
return valid ? strength : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputEvent::is_pressed() const {
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEvent::is_echo() const {
|
bool InputEvent::is_echo() const {
|
||||||
|
@ -75,7 +88,7 @@ String InputEvent::as_text() const {
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEvent::action_match(const Ref<InputEvent> &p_event) const {
|
bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -95,15 +108,16 @@ void InputEvent::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_device", "device"), &InputEvent::set_device);
|
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("get_device"), &InputEvent::get_device);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("is_pressed"), &InputEvent::is_pressed);
|
|
||||||
ClassDB::bind_method(D_METHOD("is_action", "action"), &InputEvent::is_action);
|
ClassDB::bind_method(D_METHOD("is_action", "action"), &InputEvent::is_action);
|
||||||
ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &InputEvent::is_action_pressed);
|
ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &InputEvent::is_action_pressed);
|
||||||
ClassDB::bind_method(D_METHOD("is_action_released", "action"), &InputEvent::is_action_released);
|
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_pressed"), &InputEvent::is_pressed);
|
||||||
ClassDB::bind_method(D_METHOD("is_echo"), &InputEvent::is_echo);
|
ClassDB::bind_method(D_METHOD("is_echo"), &InputEvent::is_echo);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("as_text"), &InputEvent::as_text);
|
ClassDB::bind_method(D_METHOD("as_text"), &InputEvent::as_text);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("action_match", "event"), &InputEvent::action_match);
|
|
||||||
ClassDB::bind_method(D_METHOD("shortcut_match", "event"), &InputEvent::shortcut_match);
|
ClassDB::bind_method(D_METHOD("shortcut_match", "event"), &InputEvent::shortcut_match);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("is_action_type"), &InputEvent::is_action_type);
|
ClassDB::bind_method(D_METHOD("is_action_type"), &InputEvent::is_action_type);
|
||||||
|
@ -281,7 +295,7 @@ String InputEventKey::as_text() const {
|
||||||
return kc;
|
return kc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEventKey::action_match(const Ref<InputEvent> &p_event) const {
|
bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
|
||||||
|
|
||||||
Ref<InputEventKey> key = p_event;
|
Ref<InputEventKey> key = p_event;
|
||||||
if (key.is_null())
|
if (key.is_null())
|
||||||
|
@ -290,7 +304,14 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event) const {
|
||||||
uint32_t code = get_scancode_with_modifiers();
|
uint32_t code = get_scancode_with_modifiers();
|
||||||
uint32_t event_code = key->get_scancode_with_modifiers();
|
uint32_t event_code = key->get_scancode_with_modifiers();
|
||||||
|
|
||||||
return get_scancode() == key->get_scancode() && (!key->is_pressed() || (code & event_code) == code);
|
bool match = get_scancode() == key->get_scancode() && (!key->is_pressed() || (code & event_code) == code);
|
||||||
|
if (match) {
|
||||||
|
if (p_pressed != NULL)
|
||||||
|
*p_pressed = key->is_pressed();
|
||||||
|
if (p_strength != NULL)
|
||||||
|
*p_strength = (*p_pressed) ? 1.0f : 0.0f;
|
||||||
|
}
|
||||||
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEventKey::shortcut_match(const Ref<InputEvent> &p_event) const {
|
bool InputEventKey::shortcut_match(const Ref<InputEvent> &p_event) const {
|
||||||
|
@ -446,13 +467,21 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co
|
||||||
return mb;
|
return mb;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event) const {
|
bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
|
||||||
|
|
||||||
Ref<InputEventMouseButton> mb = p_event;
|
Ref<InputEventMouseButton> mb = p_event;
|
||||||
if (mb.is_null())
|
if (mb.is_null())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return mb->button_index == button_index;
|
bool match = mb->button_index == button_index;
|
||||||
|
if (match) {
|
||||||
|
if (p_pressed != NULL)
|
||||||
|
*p_pressed = mb->is_pressed();
|
||||||
|
if (p_strength != NULL)
|
||||||
|
*p_strength = (*p_pressed) ? 1.0f : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventMouseButton::as_text() const {
|
String InputEventMouseButton::as_text() const {
|
||||||
|
@ -610,6 +639,7 @@ void InputEventJoypadMotion::set_axis_value(float p_value) {
|
||||||
|
|
||||||
axis_value = p_value;
|
axis_value = p_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
float InputEventJoypadMotion::get_axis_value() const {
|
float InputEventJoypadMotion::get_axis_value() const {
|
||||||
|
|
||||||
return axis_value;
|
return axis_value;
|
||||||
|
@ -617,16 +647,23 @@ float InputEventJoypadMotion::get_axis_value() const {
|
||||||
|
|
||||||
bool InputEventJoypadMotion::is_pressed() const {
|
bool InputEventJoypadMotion::is_pressed() const {
|
||||||
|
|
||||||
return Math::abs(axis_value) > 0.5f;
|
return Math::abs(axis_value) >= 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event) const {
|
bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
|
||||||
|
|
||||||
Ref<InputEventJoypadMotion> jm = p_event;
|
Ref<InputEventJoypadMotion> jm = p_event;
|
||||||
if (jm.is_null())
|
if (jm.is_null())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return (axis == jm->axis && ((axis_value < 0) == (jm->axis_value < 0) || jm->axis_value == 0));
|
bool match = (axis == jm->axis && ((axis_value < 0) == (jm->axis_value < 0) || jm->axis_value == 0));
|
||||||
|
if (match) {
|
||||||
|
if (p_pressed != NULL)
|
||||||
|
*p_pressed = Math::abs(jm->get_axis_value() >= p_deadzone);
|
||||||
|
if (p_strength != NULL)
|
||||||
|
*p_strength = (*p_pressed) ? Math::inverse_lerp(p_deadzone, 1.0f, Math::abs(jm->get_axis_value())) : 0.0f;
|
||||||
|
}
|
||||||
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventJoypadMotion::as_text() const {
|
String InputEventJoypadMotion::as_text() const {
|
||||||
|
@ -681,13 +718,21 @@ float InputEventJoypadButton::get_pressure() const {
|
||||||
return pressure;
|
return pressure;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event) const {
|
bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
|
||||||
|
|
||||||
Ref<InputEventJoypadButton> jb = p_event;
|
Ref<InputEventJoypadButton> jb = p_event;
|
||||||
if (jb.is_null())
|
if (jb.is_null())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return button_index == jb->button_index;
|
bool match = button_index == jb->button_index;
|
||||||
|
if (match) {
|
||||||
|
if (p_pressed != NULL)
|
||||||
|
*p_pressed = jb->is_pressed();
|
||||||
|
if (p_strength != NULL)
|
||||||
|
*p_strength = (*p_pressed) ? 1.0f : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
String InputEventJoypadButton::as_text() const {
|
String InputEventJoypadButton::as_text() const {
|
||||||
|
|
|
@ -154,16 +154,21 @@ public:
|
||||||
void set_device(int p_device);
|
void set_device(int p_device);
|
||||||
int get_device() const;
|
int get_device() const;
|
||||||
|
|
||||||
|
bool is_action(const StringName &p_action) const;
|
||||||
|
bool is_action_pressed(const StringName &p_action) const;
|
||||||
|
bool is_action_released(const StringName &p_action) const;
|
||||||
|
float get_action_strength(const StringName &p_action) const;
|
||||||
|
|
||||||
|
// To be removed someday, since they do not make sense for all events
|
||||||
virtual bool is_pressed() const;
|
virtual bool is_pressed() const;
|
||||||
virtual bool is_action(const StringName &p_action) const;
|
|
||||||
virtual bool is_action_pressed(const StringName &p_action) const;
|
|
||||||
virtual bool is_action_released(const StringName &p_action) const;
|
|
||||||
virtual bool is_echo() const;
|
virtual bool is_echo() const;
|
||||||
|
// ...-.
|
||||||
|
|
||||||
virtual String as_text() const;
|
virtual String as_text() const;
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
|
||||||
|
|
||||||
virtual bool action_match(const Ref<InputEvent> &p_event) const;
|
virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const;
|
||||||
virtual bool shortcut_match(const Ref<InputEvent> &p_event) const;
|
virtual bool shortcut_match(const Ref<InputEvent> &p_event) const;
|
||||||
virtual bool is_action_type() const;
|
virtual bool is_action_type() const;
|
||||||
|
|
||||||
|
@ -244,7 +249,7 @@ public:
|
||||||
|
|
||||||
uint32_t get_scancode_with_modifiers() const;
|
uint32_t get_scancode_with_modifiers() const;
|
||||||
|
|
||||||
virtual bool action_match(const Ref<InputEvent> &p_event) const;
|
virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const;
|
||||||
virtual bool shortcut_match(const Ref<InputEvent> &p_event) const;
|
virtual bool shortcut_match(const Ref<InputEvent> &p_event) const;
|
||||||
|
|
||||||
virtual bool is_action_type() const { return true; }
|
virtual bool is_action_type() const { return true; }
|
||||||
|
@ -305,7 +310,7 @@ public:
|
||||||
bool is_doubleclick() const;
|
bool is_doubleclick() const;
|
||||||
|
|
||||||
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
|
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
|
||||||
virtual bool action_match(const Ref<InputEvent> &p_event) const;
|
virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const;
|
||||||
|
|
||||||
virtual bool is_action_type() const { return true; }
|
virtual bool is_action_type() const { return true; }
|
||||||
virtual String as_text() const;
|
virtual String as_text() const;
|
||||||
|
@ -352,7 +357,8 @@ public:
|
||||||
float get_axis_value() const;
|
float get_axis_value() const;
|
||||||
|
|
||||||
virtual bool is_pressed() const;
|
virtual bool is_pressed() const;
|
||||||
virtual bool action_match(const Ref<InputEvent> &p_event) const;
|
|
||||||
|
virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const;
|
||||||
|
|
||||||
virtual bool is_action_type() const { return true; }
|
virtual bool is_action_type() const { return true; }
|
||||||
virtual String as_text() const;
|
virtual String as_text() const;
|
||||||
|
@ -379,7 +385,7 @@ public:
|
||||||
void set_pressure(float p_pressure);
|
void set_pressure(float p_pressure);
|
||||||
float get_pressure() const;
|
float get_pressure() const;
|
||||||
|
|
||||||
virtual bool action_match(const Ref<InputEvent> &p_event) const;
|
virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const;
|
||||||
|
|
||||||
virtual bool is_action_type() const { return true; }
|
virtual bool is_action_type() const { return true; }
|
||||||
virtual String as_text() const;
|
virtual String as_text() const;
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
#include "variant_parser.h"
|
#include "variant_parser.h"
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#define FORMAT_VERSION 3
|
#define FORMAT_VERSION 4
|
||||||
|
|
||||||
ProjectSettings *ProjectSettings::singleton = NULL;
|
ProjectSettings *ProjectSettings::singleton = NULL;
|
||||||
|
|
||||||
|
@ -262,6 +262,23 @@ bool ProjectSettings::_load_resource_pack(const String &p_pack) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProjectSettings::_convert_to_last_version() {
|
||||||
|
if (!has_setting("config_version") || (int)get_setting("config_version") <= 3) {
|
||||||
|
|
||||||
|
// Converts the actions from array to dictionary (array of events to dictionary with deadzone + events)
|
||||||
|
for (Map<StringName, ProjectSettings::VariantContainer>::Element *E = props.front(); E; E = E->next()) {
|
||||||
|
Variant value = E->get().variant;
|
||||||
|
if (String(E->key()).begins_with("input/") && value.get_type() == Variant::ARRAY) {
|
||||||
|
Array array = value;
|
||||||
|
Dictionary action;
|
||||||
|
action["deadzone"] = Variant(0.5f);
|
||||||
|
action["events"] = array;
|
||||||
|
E->get().variant = action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bool p_upwards) {
|
Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bool p_upwards) {
|
||||||
|
|
||||||
//If looking for files in network, just use network!
|
//If looking for files in network, just use network!
|
||||||
|
@ -390,6 +407,8 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo
|
||||||
if (resource_path.length() && resource_path[resource_path.length() - 1] == '/')
|
if (resource_path.length() && resource_path[resource_path.length() - 1] == '/')
|
||||||
resource_path = resource_path.substr(0, resource_path.length() - 1); // chop end
|
resource_path = resource_path.substr(0, resource_path.length() - 1); // chop end
|
||||||
|
|
||||||
|
_convert_to_last_version();
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,8 @@ protected:
|
||||||
|
|
||||||
Error _save_custom_bnd(const String &p_file);
|
Error _save_custom_bnd(const String &p_file);
|
||||||
|
|
||||||
|
void _convert_to_last_version();
|
||||||
|
|
||||||
bool _load_resource_pack(const String &p_pack);
|
bool _load_resource_pack(const String &p_pack);
|
||||||
|
|
||||||
void _add_property_info_bind(const Dictionary &p_info);
|
void _add_property_info_bind(const Dictionary &p_info);
|
||||||
|
|
|
@ -178,15 +178,15 @@ void ProjectSettingsEditor::_action_edited() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int order = ProjectSettings::get_singleton()->get_order(add_at);
|
int order = ProjectSettings::get_singleton()->get_order(add_at);
|
||||||
Array va = ProjectSettings::get_singleton()->get(add_at);
|
Dictionary action = ProjectSettings::get_singleton()->get(add_at);
|
||||||
|
|
||||||
setting = true;
|
setting = true;
|
||||||
undo_redo->create_action(TTR("Rename Input Action Event"));
|
undo_redo->create_action(TTR("Rename Input Action Event"));
|
||||||
undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", add_at);
|
undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", add_at);
|
||||||
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", action_prop, va);
|
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", action_prop, action);
|
||||||
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", action_prop, order);
|
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", action_prop, order);
|
||||||
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", action_prop);
|
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", action_prop);
|
||||||
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", add_at, va);
|
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", add_at, action);
|
||||||
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", add_at, order);
|
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", add_at, order);
|
||||||
undo_redo->add_do_method(this, "_update_actions");
|
undo_redo->add_do_method(this, "_update_actions");
|
||||||
undo_redo->add_undo_method(this, "_update_actions");
|
undo_redo->add_undo_method(this, "_update_actions");
|
||||||
|
@ -203,8 +203,9 @@ void ProjectSettingsEditor::_device_input_add() {
|
||||||
Ref<InputEvent> ie;
|
Ref<InputEvent> ie;
|
||||||
String name = add_at;
|
String name = add_at;
|
||||||
int idx = edit_idx;
|
int idx = edit_idx;
|
||||||
Array old_val = ProjectSettings::get_singleton()->get(name);
|
Dictionary old_val = ProjectSettings::get_singleton()->get(name);
|
||||||
Array arr = old_val.duplicate();
|
Dictionary action = old_val.duplicate();
|
||||||
|
Array events = action["events"];
|
||||||
|
|
||||||
switch (add_type) {
|
switch (add_type) {
|
||||||
|
|
||||||
|
@ -215,9 +216,9 @@ void ProjectSettingsEditor::_device_input_add() {
|
||||||
mb->set_button_index(device_index->get_selected() + 1);
|
mb->set_button_index(device_index->get_selected() + 1);
|
||||||
mb->set_device(_get_current_device());
|
mb->set_device(_get_current_device());
|
||||||
|
|
||||||
for (int i = 0; i < arr.size(); i++) {
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
|
||||||
Ref<InputEventMouseButton> aie = arr[i];
|
Ref<InputEventMouseButton> aie = events[i];
|
||||||
if (aie.is_null())
|
if (aie.is_null())
|
||||||
continue;
|
continue;
|
||||||
if (aie->get_device() == mb->get_device() && aie->get_button_index() == mb->get_button_index()) {
|
if (aie->get_device() == mb->get_device() && aie->get_button_index() == mb->get_button_index()) {
|
||||||
|
@ -233,20 +234,26 @@ void ProjectSettingsEditor::_device_input_add() {
|
||||||
Ref<InputEventJoypadMotion> jm;
|
Ref<InputEventJoypadMotion> jm;
|
||||||
jm.instance();
|
jm.instance();
|
||||||
jm->set_axis(device_index->get_selected() >> 1);
|
jm->set_axis(device_index->get_selected() >> 1);
|
||||||
jm->set_axis_value(device_index->get_selected() & 1 ? 1 : -1);
|
|
||||||
jm->set_device(_get_current_device());
|
jm->set_device(_get_current_device());
|
||||||
|
|
||||||
for (int i = 0; i < arr.size(); i++) {
|
bool should_update_event = true;
|
||||||
|
Variant deadzone = device_special_value->get_value();
|
||||||
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
|
||||||
Ref<InputEventJoypadMotion> aie = arr[i];
|
Ref<InputEventJoypadMotion> aie = events[i];
|
||||||
if (aie.is_null())
|
if (aie.is_null())
|
||||||
continue;
|
continue;
|
||||||
if (aie->get_device() == jm->get_device() && aie->get_axis() == jm->get_axis() && aie->get_axis_value() == jm->get_axis_value()) {
|
if (aie->get_device() == jm->get_device() && aie->get_axis() == jm->get_axis()) {
|
||||||
return;
|
should_update_event = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!should_update_event && deadzone == action["deadzone"])
|
||||||
|
return;
|
||||||
|
|
||||||
ie = jm;
|
ie = jm;
|
||||||
|
action["deadzone"] = deadzone;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case INPUT_JOY_BUTTON: {
|
case INPUT_JOY_BUTTON: {
|
||||||
|
@ -257,9 +264,9 @@ void ProjectSettingsEditor::_device_input_add() {
|
||||||
jb->set_button_index(device_index->get_selected());
|
jb->set_button_index(device_index->get_selected());
|
||||||
jb->set_device(_get_current_device());
|
jb->set_device(_get_current_device());
|
||||||
|
|
||||||
for (int i = 0; i < arr.size(); i++) {
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
|
||||||
Ref<InputEventJoypadButton> aie = arr[i];
|
Ref<InputEventJoypadButton> aie = events[i];
|
||||||
if (aie.is_null())
|
if (aie.is_null())
|
||||||
continue;
|
continue;
|
||||||
if (aie->get_device() == jb->get_device() && aie->get_button_index() == jb->get_button_index()) {
|
if (aie->get_device() == jb->get_device() && aie->get_button_index() == jb->get_button_index()) {
|
||||||
|
@ -272,14 +279,15 @@ void ProjectSettingsEditor::_device_input_add() {
|
||||||
default: {}
|
default: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx < 0 || idx >= arr.size()) {
|
if (idx < 0 || idx >= events.size()) {
|
||||||
arr.push_back(ie);
|
events.push_back(ie);
|
||||||
} else {
|
} else {
|
||||||
arr[idx] = ie;
|
events[idx] = ie;
|
||||||
}
|
}
|
||||||
|
action["events"] = events;
|
||||||
|
|
||||||
undo_redo->create_action(TTR("Add Input Action Event"));
|
undo_redo->create_action(TTR("Add Input Action Event"));
|
||||||
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, arr);
|
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action);
|
||||||
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
|
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
|
||||||
undo_redo->add_do_method(this, "_update_actions");
|
undo_redo->add_do_method(this, "_update_actions");
|
||||||
undo_redo->add_undo_method(this, "_update_actions");
|
undo_redo->add_undo_method(this, "_update_actions");
|
||||||
|
@ -320,12 +328,13 @@ void ProjectSettingsEditor::_press_a_key_confirm() {
|
||||||
String name = add_at;
|
String name = add_at;
|
||||||
int idx = edit_idx;
|
int idx = edit_idx;
|
||||||
|
|
||||||
Array old_val = ProjectSettings::get_singleton()->get(name);
|
Dictionary old_val = ProjectSettings::get_singleton()->get(name);
|
||||||
Array arr = old_val.duplicate();
|
Dictionary action = old_val.duplicate();
|
||||||
|
Array events = action["events"];
|
||||||
|
|
||||||
for (int i = 0; i < arr.size(); i++) {
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
|
||||||
Ref<InputEventKey> aie = arr[i];
|
Ref<InputEventKey> aie = events[i];
|
||||||
if (aie.is_null())
|
if (aie.is_null())
|
||||||
continue;
|
continue;
|
||||||
if (aie->get_scancode_with_modifiers() == ie->get_scancode_with_modifiers()) {
|
if (aie->get_scancode_with_modifiers() == ie->get_scancode_with_modifiers()) {
|
||||||
|
@ -333,14 +342,15 @@ void ProjectSettingsEditor::_press_a_key_confirm() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idx < 0 || idx >= arr.size()) {
|
if (idx < 0 || idx >= events.size()) {
|
||||||
arr.push_back(ie);
|
events.push_back(ie);
|
||||||
} else {
|
} else {
|
||||||
arr[idx] = ie;
|
events[idx] = ie;
|
||||||
}
|
}
|
||||||
|
action["events"] = events;
|
||||||
|
|
||||||
undo_redo->create_action(TTR("Add Input Action Event"));
|
undo_redo->create_action(TTR("Add Input Action Event"));
|
||||||
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, arr);
|
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action);
|
||||||
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
|
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
|
||||||
undo_redo->add_do_method(this, "_update_actions");
|
undo_redo->add_do_method(this, "_update_actions");
|
||||||
undo_redo->add_undo_method(this, "_update_actions");
|
undo_redo->add_undo_method(this, "_update_actions");
|
||||||
|
@ -418,6 +428,9 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even
|
||||||
last_wait_for_key = Ref<InputEvent>();
|
last_wait_for_key = Ref<InputEvent>();
|
||||||
press_a_key->popup_centered(Size2(250, 80) * EDSCALE);
|
press_a_key->popup_centered(Size2(250, 80) * EDSCALE);
|
||||||
press_a_key->grab_focus();
|
press_a_key->grab_focus();
|
||||||
|
|
||||||
|
device_special_value_label->hide();
|
||||||
|
device_special_value->hide();
|
||||||
} break;
|
} break;
|
||||||
case INPUT_MOUSE_BUTTON: {
|
case INPUT_MOUSE_BUTTON: {
|
||||||
|
|
||||||
|
@ -443,6 +456,9 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even
|
||||||
_set_current_device(0);
|
_set_current_device(0);
|
||||||
device_input->get_ok()->set_text(TTR("Add"));
|
device_input->get_ok()->set_text(TTR("Add"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device_special_value_label->hide();
|
||||||
|
device_special_value->hide();
|
||||||
} break;
|
} break;
|
||||||
case INPUT_JOY_MOTION: {
|
case INPUT_JOY_MOTION: {
|
||||||
|
|
||||||
|
@ -464,6 +480,15 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even
|
||||||
_set_current_device(0);
|
_set_current_device(0);
|
||||||
device_input->get_ok()->set_text(TTR("Add"));
|
device_input->get_ok()->set_text(TTR("Add"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device_special_value_label->set_text(TTR("Deadzone (global to the action):"));
|
||||||
|
device_special_value_label->show();
|
||||||
|
device_special_value->set_min(0.0f);
|
||||||
|
device_special_value->set_max(1.0f);
|
||||||
|
device_special_value->set_step(0.01f);
|
||||||
|
Dictionary action = ProjectSettings::get_singleton()->get(add_at);
|
||||||
|
device_special_value->set_value(action.has("deadzone") ? action["deadzone"] : Variant(0.5f));
|
||||||
|
device_special_value->show();
|
||||||
} break;
|
} break;
|
||||||
case INPUT_JOY_BUTTON: {
|
case INPUT_JOY_BUTTON: {
|
||||||
|
|
||||||
|
@ -486,6 +511,8 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even
|
||||||
device_input->get_ok()->set_text(TTR("Add"));
|
device_input->get_ok()->set_text(TTR("Add"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device_special_value_label->hide();
|
||||||
|
device_special_value->hide();
|
||||||
} break;
|
} break;
|
||||||
default: {}
|
default: {}
|
||||||
}
|
}
|
||||||
|
@ -522,18 +549,17 @@ void ProjectSettingsEditor::_action_activated() {
|
||||||
|
|
||||||
String name = "input/" + ti->get_parent()->get_text(0);
|
String name = "input/" + ti->get_parent()->get_text(0);
|
||||||
int idx = ti->get_metadata(0);
|
int idx = ti->get_metadata(0);
|
||||||
Array va = ProjectSettings::get_singleton()->get(name);
|
Dictionary action = ProjectSettings::get_singleton()->get(name);
|
||||||
|
Array events = action["events"];
|
||||||
|
|
||||||
ERR_FAIL_INDEX(idx, va.size());
|
ERR_FAIL_INDEX(idx, events.size());
|
||||||
|
Ref<InputEvent> event = events[idx];
|
||||||
Ref<InputEvent> ie = va[idx];
|
if (event.is_null())
|
||||||
|
|
||||||
if (ie.is_null())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
add_at = name;
|
add_at = name;
|
||||||
edit_idx = idx;
|
edit_idx = idx;
|
||||||
_edit_item(ie);
|
_edit_item(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, int p_id) {
|
void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, int p_id) {
|
||||||
|
@ -543,6 +569,7 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column,
|
||||||
ERR_FAIL_COND(!ti);
|
ERR_FAIL_COND(!ti);
|
||||||
|
|
||||||
if (p_id == 1) {
|
if (p_id == 1) {
|
||||||
|
// Add action event
|
||||||
Point2 ofs = input_editor->get_global_position();
|
Point2 ofs = input_editor->get_global_position();
|
||||||
Rect2 ir = input_editor->get_item_rect(ti);
|
Rect2 ir = input_editor->get_item_rect(ti);
|
||||||
ir.position.y -= input_editor->get_scroll().y;
|
ir.position.y -= input_editor->get_scroll().y;
|
||||||
|
@ -554,14 +581,12 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column,
|
||||||
edit_idx = -1;
|
edit_idx = -1;
|
||||||
|
|
||||||
} else if (p_id == 2) {
|
} else if (p_id == 2) {
|
||||||
//remove
|
// Remove
|
||||||
|
|
||||||
if (ti->get_parent() == input_editor->get_root()) {
|
if (ti->get_parent() == input_editor->get_root()) {
|
||||||
|
// Remove action
|
||||||
//remove main thing
|
|
||||||
|
|
||||||
String name = "input/" + ti->get_text(0);
|
String name = "input/" + ti->get_text(0);
|
||||||
Variant old_val = ProjectSettings::get_singleton()->get(name);
|
Dictionary old_val = ProjectSettings::get_singleton()->get(name);
|
||||||
int order = ProjectSettings::get_singleton()->get_order(name);
|
int order = ProjectSettings::get_singleton()->get_order(name);
|
||||||
|
|
||||||
undo_redo->create_action(TTR("Erase Input Action"));
|
undo_redo->create_action(TTR("Erase Input Action"));
|
||||||
|
@ -575,24 +600,19 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column,
|
||||||
undo_redo->commit_action();
|
undo_redo->commit_action();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//remove action
|
// Remove action event
|
||||||
String name = "input/" + ti->get_parent()->get_text(0);
|
String name = "input/" + ti->get_parent()->get_text(0);
|
||||||
Variant old_val = ProjectSettings::get_singleton()->get(name);
|
Dictionary old_val = ProjectSettings::get_singleton()->get(name);
|
||||||
|
Dictionary action = old_val.duplicate();
|
||||||
int idx = ti->get_metadata(0);
|
int idx = ti->get_metadata(0);
|
||||||
|
|
||||||
Array va = old_val;
|
Array events = action["events"];
|
||||||
|
ERR_FAIL_INDEX(idx, events.size());
|
||||||
ERR_FAIL_INDEX(idx, va.size());
|
events.remove(idx);
|
||||||
|
action["events"] = events;
|
||||||
for (int i = idx; i < va.size() - 1; i++) {
|
|
||||||
|
|
||||||
va[i] = va[i + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
va.resize(va.size() - 1);
|
|
||||||
|
|
||||||
undo_redo->create_action(TTR("Erase Input Action Event"));
|
undo_redo->create_action(TTR("Erase Input Action Event"));
|
||||||
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, va);
|
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action);
|
||||||
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
|
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val);
|
||||||
undo_redo->add_do_method(this, "_update_actions");
|
undo_redo->add_do_method(this, "_update_actions");
|
||||||
undo_redo->add_undo_method(this, "_update_actions");
|
undo_redo->add_undo_method(this, "_update_actions");
|
||||||
|
@ -601,30 +621,31 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column,
|
||||||
undo_redo->commit_action();
|
undo_redo->commit_action();
|
||||||
}
|
}
|
||||||
} else if (p_id == 3) {
|
} else if (p_id == 3) {
|
||||||
//edit
|
// Edit
|
||||||
|
|
||||||
if (ti->get_parent() == input_editor->get_root()) {
|
if (ti->get_parent() == input_editor->get_root()) {
|
||||||
|
// Edit action name
|
||||||
ti->set_as_cursor(0);
|
ti->set_as_cursor(0);
|
||||||
input_editor->edit_selected();
|
input_editor->edit_selected();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//edit action
|
// Edit action event
|
||||||
String name = "input/" + ti->get_parent()->get_text(0);
|
String name = "input/" + ti->get_parent()->get_text(0);
|
||||||
int idx = ti->get_metadata(0);
|
int idx = ti->get_metadata(0);
|
||||||
Array va = ProjectSettings::get_singleton()->get(name);
|
Dictionary action = ProjectSettings::get_singleton()->get(name);
|
||||||
|
|
||||||
ERR_FAIL_INDEX(idx, va.size());
|
Array events = action["events"];
|
||||||
|
ERR_FAIL_INDEX(idx, events.size());
|
||||||
|
|
||||||
Ref<InputEvent> ie = va[idx];
|
Ref<InputEvent> event = events[idx];
|
||||||
|
|
||||||
if (ie.is_null())
|
if (event.is_null())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ti->set_as_cursor(0);
|
ti->set_as_cursor(0);
|
||||||
add_at = name;
|
add_at = name;
|
||||||
edit_idx = idx;
|
edit_idx = idx;
|
||||||
_edit_item(ie);
|
_edit_item(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,17 +681,18 @@ void ProjectSettingsEditor::_update_actions() {
|
||||||
}
|
}
|
||||||
item->set_custom_bg_color(0, get_color("prop_subsection", "Editor"));
|
item->set_custom_bg_color(0, get_color("prop_subsection", "Editor"));
|
||||||
|
|
||||||
Array actions = ProjectSettings::get_singleton()->get(pi.name);
|
Dictionary action = ProjectSettings::get_singleton()->get(pi.name);
|
||||||
|
Array events = action["events"];
|
||||||
|
|
||||||
for (int i = 0; i < actions.size(); i++) {
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
|
||||||
Ref<InputEvent> ie = actions[i];
|
Ref<InputEvent> event = events[i];
|
||||||
if (ie.is_null())
|
if (event.is_null())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TreeItem *action = input_editor->create_item(item);
|
TreeItem *action = input_editor->create_item(item);
|
||||||
|
|
||||||
Ref<InputEventKey> k = ie;
|
Ref<InputEventKey> k = event;
|
||||||
if (k.is_valid()) {
|
if (k.is_valid()) {
|
||||||
|
|
||||||
String str = keycode_get_string(k->get_scancode()).capitalize();
|
String str = keycode_get_string(k->get_scancode()).capitalize();
|
||||||
|
@ -687,7 +709,7 @@ void ProjectSettingsEditor::_update_actions() {
|
||||||
action->set_icon(0, get_icon("Keyboard", "EditorIcons"));
|
action->set_icon(0, get_icon("Keyboard", "EditorIcons"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<InputEventJoypadButton> jb = ie;
|
Ref<InputEventJoypadButton> jb = event;
|
||||||
|
|
||||||
if (jb.is_valid()) {
|
if (jb.is_valid()) {
|
||||||
|
|
||||||
|
@ -701,7 +723,7 @@ void ProjectSettingsEditor::_update_actions() {
|
||||||
action->set_icon(0, get_icon("JoyButton", "EditorIcons"));
|
action->set_icon(0, get_icon("JoyButton", "EditorIcons"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<InputEventMouseButton> mb = ie;
|
Ref<InputEventMouseButton> mb = event;
|
||||||
|
|
||||||
if (mb.is_valid()) {
|
if (mb.is_valid()) {
|
||||||
String str = _get_device_string(mb->get_device()) + ", ";
|
String str = _get_device_string(mb->get_device()) + ", ";
|
||||||
|
@ -718,7 +740,7 @@ void ProjectSettingsEditor::_update_actions() {
|
||||||
action->set_icon(0, get_icon("Mouse", "EditorIcons"));
|
action->set_icon(0, get_icon("Mouse", "EditorIcons"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<InputEventJoypadMotion> jm = ie;
|
Ref<InputEventJoypadMotion> jm = event;
|
||||||
|
|
||||||
if (jm.is_valid()) {
|
if (jm.is_valid()) {
|
||||||
|
|
||||||
|
@ -732,7 +754,7 @@ void ProjectSettingsEditor::_update_actions() {
|
||||||
action->add_button(0, get_icon("Edit", "EditorIcons"), 3, false, TTR("Edit"));
|
action->add_button(0, get_icon("Edit", "EditorIcons"), 3, false, TTR("Edit"));
|
||||||
action->add_button(0, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove"));
|
action->add_button(0, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove"));
|
||||||
action->set_metadata(0, i);
|
action->set_metadata(0, i);
|
||||||
action->set_meta("__input", ie);
|
action->set_meta("__input", event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,10 +914,12 @@ void ProjectSettingsEditor::_action_adds(String) {
|
||||||
|
|
||||||
void ProjectSettingsEditor::_action_add() {
|
void ProjectSettingsEditor::_action_add() {
|
||||||
|
|
||||||
Array va;
|
Dictionary action;
|
||||||
|
action["events"] = Array();
|
||||||
|
action["deadzone"] = 0.5f;
|
||||||
String name = "input/" + action_name->get_text();
|
String name = "input/" + action_name->get_text();
|
||||||
undo_redo->create_action(TTR("Add Input Action"));
|
undo_redo->create_action(TTR("Add Input Action"));
|
||||||
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, va);
|
undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action);
|
||||||
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name);
|
undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name);
|
||||||
undo_redo->add_do_method(this, "_update_actions");
|
undo_redo->add_do_method(this, "_update_actions");
|
||||||
undo_redo->add_undo_method(this, "_update_actions");
|
undo_redo->add_undo_method(this, "_update_actions");
|
||||||
|
@ -1814,6 +1838,14 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
|
||||||
device_index = memnew(OptionButton);
|
device_index = memnew(OptionButton);
|
||||||
vbc_right->add_child(device_index);
|
vbc_right->add_child(device_index);
|
||||||
|
|
||||||
|
l = memnew(Label);
|
||||||
|
l->set_text(TTR("Special value:"));
|
||||||
|
vbc_right->add_child(l);
|
||||||
|
device_special_value_label = l;
|
||||||
|
|
||||||
|
device_special_value = memnew(SpinBox);
|
||||||
|
vbc_right->add_child(device_special_value);
|
||||||
|
|
||||||
setting = false;
|
setting = false;
|
||||||
|
|
||||||
//translations
|
//translations
|
||||||
|
|
|
@ -83,6 +83,8 @@ class ProjectSettingsEditor : public AcceptDialog {
|
||||||
OptionButton *device_id;
|
OptionButton *device_id;
|
||||||
OptionButton *device_index;
|
OptionButton *device_index;
|
||||||
Label *device_index_label;
|
Label *device_index_label;
|
||||||
|
SpinBox *device_special_value;
|
||||||
|
Label *device_special_value_label;
|
||||||
MenuButton *popup_copy_to_feature;
|
MenuButton *popup_copy_to_feature;
|
||||||
|
|
||||||
LineEdit *action_name;
|
LineEdit *action_name;
|
||||||
|
|
|
@ -127,6 +127,14 @@ bool InputDefault::is_action_just_released(const StringName &p_action) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float InputDefault::get_action_strength(const StringName &p_action) const {
|
||||||
|
const Map<StringName, Action>::Element *E = action_state.find(p_action);
|
||||||
|
if (!E)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
return E->get().strength;
|
||||||
|
}
|
||||||
|
|
||||||
float InputDefault::get_joy_axis(int p_device, int p_axis) const {
|
float InputDefault::get_joy_axis(int p_device, int p_axis) const {
|
||||||
|
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
@ -330,16 +338,18 @@ void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p_event->is_echo()) {
|
for (const Map<StringName, InputMap::Action>::Element *E = InputMap::get_singleton()->get_action_map().front(); E; E = E->next()) {
|
||||||
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())) {
|
||||||
|
|
||||||
if (InputMap::get_singleton()->event_is_action(p_event, E->key()) && is_action_pressed(E->key()) != p_event->is_pressed()) {
|
// Save the action's state
|
||||||
|
if (!p_event->is_echo() && is_action_pressed(E->key()) != p_event->is_action_pressed(E->key())) {
|
||||||
Action action;
|
Action action;
|
||||||
action.physics_frame = Engine::get_singleton()->get_physics_frames();
|
action.physics_frame = Engine::get_singleton()->get_physics_frames();
|
||||||
action.idle_frame = Engine::get_singleton()->get_idle_frames();
|
action.idle_frame = Engine::get_singleton()->get_idle_frames();
|
||||||
action.pressed = p_event->is_pressed();
|
action.pressed = p_event->is_action_pressed(E->key());
|
||||||
action_state[E->key()] = action;
|
action_state[E->key()] = action;
|
||||||
}
|
}
|
||||||
|
action_state[E->key()].strength = p_event->get_action_strength(E->key());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ class InputDefault : public Input {
|
||||||
uint64_t physics_frame;
|
uint64_t physics_frame;
|
||||||
uint64_t idle_frame;
|
uint64_t idle_frame;
|
||||||
bool pressed;
|
bool pressed;
|
||||||
|
float strength;
|
||||||
};
|
};
|
||||||
|
|
||||||
Map<StringName, Action> action_state;
|
Map<StringName, Action> action_state;
|
||||||
|
@ -182,6 +183,7 @@ public:
|
||||||
virtual bool is_action_pressed(const StringName &p_action) const;
|
virtual bool is_action_pressed(const StringName &p_action) const;
|
||||||
virtual bool is_action_just_pressed(const StringName &p_action) const;
|
virtual bool is_action_just_pressed(const StringName &p_action) const;
|
||||||
virtual bool is_action_just_released(const StringName &p_action) const;
|
virtual bool is_action_just_released(const StringName &p_action) const;
|
||||||
|
virtual float get_action_strength(const StringName &p_action) const;
|
||||||
|
|
||||||
virtual float get_joy_axis(int p_device, int p_axis) const;
|
virtual float get_joy_axis(int p_device, int p_axis) const;
|
||||||
String get_joy_name(int p_idx);
|
String get_joy_name(int p_idx);
|
||||||
|
|
Loading…
Reference in New Issue