diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index b5765ac9487..c56b0a15ce9 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -228,7 +228,14 @@
- Return the forced neighbour for moving the input focus to. When pressing TAB or directional/joypad directions focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+ Return the forced neighbour for moving the input focus to. When pressing directional/joypad directions, focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+
+
+
+
+
+
+ Return the 'focus_next' for moving input focus to. When pressing TAB, focus is moved to the next control in the tree. However, the control to move to can be forced with this function.
@@ -238,6 +245,13 @@
Return which control is owning the keyboard focus, or null if no one.
+
+
+
+
+ Return the 'focus_previous' for moving input focus to. When pressing Shift+TAB focus is moved to the previous control in the tree. However, the control to move to can be forced with this function.
+
+
@@ -676,7 +690,25 @@
- Force a neighbour for moving the input focus to. When pressing TAB or directional/joypad directions focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+ Force a neighbour for moving the input focus to. When pressing directional/joypad directions, focus is moved to the next control in that direction. However, the neighbour to move to can be forced with this function.
+
+
+
+
+
+
+
+
+ Force the 'focus_next' for moving input focus to. When pressing TAB, focus is moved to the next control in the tree. However, the control to move to can be forced with this function.
+
+
+
+
+
+
+
+
+ Force the 'focus_previous' for moving input focus to. When pressing Shift+TAB, focus is moved to the previous control in the tree. However, the control to move to can be forced with this function.
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index e73ada9f313..3976a2ad48e 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -1847,6 +1847,25 @@ Control *Control::find_next_valid_focus() const {
while (true) {
+ // If the focus property is manually overwritten, attempt to use it.
+
+ if (!data.focus_next.is_empty()) {
+ Node *n = get_node(data.focus_next);
+ if (n) {
+ from = Object::cast_to(n);
+
+ if (!from) {
+
+ ERR_EXPLAIN("Next focus node is not a control: " + n->get_name());
+ ERR_FAIL_V(NULL);
+ }
+ } else {
+ return NULL;
+ }
+ if (from->is_visible() && from->get_focus_mode() != FOCUS_NONE)
+ return from;
+ }
+
// find next child
Control *next_child = NULL;
@@ -1926,6 +1945,25 @@ Control *Control::find_prev_valid_focus() const {
while (true) {
+ // If the focus property is manually overwritten, attempt to use it.
+
+ if (!data.focus_prev.is_empty()) {
+ Node *n = get_node(data.focus_prev);
+ if (n) {
+ from = Object::cast_to(n);
+
+ if (!from) {
+
+ ERR_EXPLAIN("Prev focus node is not a control: " + n->get_name());
+ ERR_FAIL_V(NULL);
+ }
+ } else {
+ return NULL;
+ }
+ if (from->is_visible() && from->get_focus_mode() != FOCUS_NONE)
+ return from;
+ }
+
// find prev child
Control *prev_child = NULL;
@@ -2157,6 +2195,26 @@ NodePath Control::get_focus_neighbour(Margin p_margin) const {
return data.focus_neighbour[p_margin];
}
+void Control::set_focus_next(const NodePath &p_next) {
+
+ data.focus_next = p_next;
+}
+
+NodePath Control::get_focus_next() const {
+
+ return data.focus_next;
+}
+
+void Control::set_focus_previous(const NodePath &p_prev) {
+
+ data.focus_prev = p_prev;
+}
+
+NodePath Control::get_focus_previous() const {
+
+ return data.focus_prev;
+}
+
#define MAX_NEIGHBOUR_SEARCH_COUNT 512
Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) {
@@ -2172,7 +2230,7 @@ Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) {
if (!c) {
- ERR_EXPLAIN("Next focus node is not a control: " + n->get_name());
+ ERR_EXPLAIN("Neighbour focus node is not a control: " + n->get_name());
ERR_FAIL_V(NULL);
}
} else {
@@ -2677,6 +2735,12 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_focus_neighbour", "margin", "neighbour"), &Control::set_focus_neighbour);
ClassDB::bind_method(D_METHOD("get_focus_neighbour", "margin"), &Control::get_focus_neighbour);
+ ClassDB::bind_method(D_METHOD("set_focus_next", "next"), &Control::set_focus_next);
+ ClassDB::bind_method(D_METHOD("get_focus_next"), &Control::get_focus_next);
+
+ ClassDB::bind_method(D_METHOD("set_focus_previous", "previous"), &Control::set_focus_previous);
+ ClassDB::bind_method(D_METHOD("get_focus_previous"), &Control::get_focus_previous);
+
ClassDB::bind_method(D_METHOD("force_drag", "data", "preview"), &Control::force_drag);
ClassDB::bind_method(D_METHOD("set_mouse_filter", "filter"), &Control::set_mouse_filter);
@@ -2737,6 +2801,8 @@ void Control::_bind_methods() {
ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_top"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_TOP);
ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_right"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_RIGHT);
ADD_PROPERTYINZ(PropertyInfo(Variant::NODE_PATH, "focus_neighbour_bottom"), "set_focus_neighbour", "get_focus_neighbour", MARGIN_BOTTOM);
+ ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_next"), "set_focus_next", "get_focus_next");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "focus_previous"), "set_focus_previous", "get_focus_previous");
ADD_GROUP("Mouse", "mouse_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mouse_filter", PROPERTY_HINT_ENUM, "Stop,Pass,Ignore"), "set_mouse_filter", "get_mouse_filter");
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 4d0e3934ad5..94c484ca50b 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -191,6 +191,8 @@ private:
ObjectID modal_prev_focus_owner;
NodePath focus_neighbour[4];
+ NodePath focus_next;
+ NodePath focus_prev;
HashMap, StringNameHasher> icon_override;
HashMap, StringNameHasher> shader_override;
@@ -374,6 +376,11 @@ public:
void set_focus_neighbour(Margin p_margin, const NodePath &p_neighbour);
NodePath get_focus_neighbour(Margin p_margin) const;
+ void set_focus_next(const NodePath &p_next);
+ NodePath get_focus_next() const;
+ void set_focus_previous(const NodePath &p_prev);
+ NodePath get_focus_previous() const;
+
Control *get_focus_owner() const;
void set_mouse_filter(MouseFilter p_filter);