diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 93934f23205..ffe30a6ecb6 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -1387,7 +1387,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/occlusion_culling/bvh_build_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), 2);
GLOBAL_DEF(PropertyInfo(Variant::INT, "memory/limits/multithreaded_server/rid_pool_prealloc", PROPERTY_HINT_RANGE, "0,500,1"), 60); // No negative and limit to 500 due to crashes.
GLOBAL_DEF_RST("internationalization/rendering/force_right_to_left_layout_direction", false);
- GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "internationalization/rendering/root_node_layout_direction", PROPERTY_HINT_ENUM, "Based on Locale,Left-to-Right,Right-to-Left"), 0);
+ GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "internationalization/rendering/root_node_layout_direction", PROPERTY_HINT_ENUM, "Based on Application Locale,Left-to-Right,Right-to-Left,Based on System Locale"), 0);
GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/timers/incremental_search_max_interval_msec", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"), 2000);
diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml
index 6edd8af7cc9..45f383dc20e 100644
--- a/doc/classes/EditorSettings.xml
+++ b/doc/classes/EditorSettings.xml
@@ -599,6 +599,9 @@
If [code]true[/code], embed modal windows such as docks inside the main editor window. When single-window mode is enabled, tooltips will also be embedded inside the main editor window, which means they can't be displayed outside of the editor window.
+
+ Editor UI default layout direction.
+
When the editor window is unfocused, the amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU/GPU usage, which can improve battery life on laptops (in addition to improving the running project's performance if the editor has to redraw continuously). However, higher values will result in a less responsive editor. The default value is set to limit the editor to 20 FPS when the editor window is unfocused. See also [member interface/editor/low_processor_mode_sleep_usec].
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 119e684f1e8..66abb895a71 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -6909,6 +6909,10 @@ EditorNode::EditorNode() {
AcceptDialog::set_swap_cancel_ok(swap_cancel_ok == 2);
}
+ int ed_root_dir = EDITOR_GET("interface/editor/ui_layout_direction");
+ Control::set_root_layout_direction(ed_root_dir);
+ Window::set_root_layout_direction(ed_root_dir);
+
ResourceLoader::set_abort_on_missing_resources(false);
ResourceLoader::set_error_notify_func(&EditorNode::add_io_error);
ResourceLoader::set_dependency_error_notify_func(&EditorNode::_dependency_error_report);
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 1eaeee97a57..dab0ff12bd5 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -400,6 +400,8 @@ void EditorSettings::_load_defaults(Ref p_extra_config) {
const String display_scale_hint_string = vformat("Auto (%d%%),75%%,100%%,125%%,150%%,175%%,200%%,Custom", Math::round(get_auto_display_scale() * 100));
EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/display_scale", 0, display_scale_hint_string, PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
+ EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/ui_layout_direction", 0, "Based on Application Locale,Left-to-Right,Right-to-Left,Based on System Locale", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
+
String ed_screen_hints = "Screen With Mouse Pointer:-4,Screen With Keyboard Focus:-3,Primary Screen:-2"; // Note: Main Window Screen:-1 is not used for the main window.
for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) {
ed_screen_hints += ",Screen " + itos(i + 1) + ":" + itos(i);
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 40c482eb90b..f337428a229 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -2847,6 +2847,10 @@ ProjectManager::ProjectManager() {
AcceptDialog::set_swap_cancel_ok(swap_cancel_ok == 2);
}
+ int pm_root_dir = EDITOR_GET("interface/editor/ui_layout_direction");
+ Control::set_root_layout_direction(pm_root_dir);
+ Window::set_root_layout_direction(pm_root_dir);
+
EditorColorMap::create();
EditorTheme::initialize();
Ref theme = create_custom_theme();
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index ed54bd000cb..84ca6bac5ba 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -197,6 +197,12 @@ void Control::reparent(Node *p_parent, bool p_keep_global_transform) {
// Editor integration.
+int Control::root_layout_direction = 0;
+
+void Control::set_root_layout_direction(int p_root_dir) {
+ root_layout_direction = p_root_dir;
+}
+
void Control::get_argument_options(const StringName &p_function, int p_idx, List *r_options) const {
ERR_READ_THREAD_GUARD;
Node::get_argument_options(p_function, p_idx, r_options);
@@ -3024,10 +3030,35 @@ bool Control::is_layout_rtl() const {
if (data.is_rtl_dirty) {
const_cast(this)->data.is_rtl_dirty = false;
if (data.layout_dir == LAYOUT_DIRECTION_INHERITED) {
+#ifdef TOOLS_ENABLED
+ if (is_part_of_edited_scene() && GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
+ const_cast(this)->data.is_rtl = true;
+ return data.is_rtl;
+ }
+ if (is_inside_tree()) {
+ Node *edited_scene_root = get_tree()->get_edited_scene_root();
+ if (edited_scene_root == this) {
+ int proj_root_layout_direction = GLOBAL_GET(SNAME("internationalization/rendering/root_node_layout_direction"));
+ if (proj_root_layout_direction == 1) {
+ const_cast(this)->data.is_rtl = false;
+ } else if (proj_root_layout_direction == 2) {
+ const_cast(this)->data.is_rtl = true;
+ } else if (proj_root_layout_direction == 3) {
+ String locale = OS::get_singleton()->get_locale();
+ const_cast(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
+ } else {
+ String locale = TranslationServer::get_singleton()->get_tool_locale();
+ const_cast(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
+ }
+ return data.is_rtl;
+ }
+ }
+#else
if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
const_cast(this)->data.is_rtl = true;
return data.is_rtl;
}
+#endif
Node *parent_node = get_parent();
while (parent_node) {
Control *parent_control = Object::cast_to(parent_node);
@@ -3044,11 +3075,13 @@ bool Control::is_layout_rtl() const {
parent_node = parent_node->get_parent();
}
- int root_dir = GLOBAL_GET(SNAME("internationalization/rendering/root_node_layout_direction"));
- if (root_dir == 1) {
+ if (root_layout_direction == 1) {
const_cast(this)->data.is_rtl = false;
- } else if (root_dir == 2) {
+ } else if (root_layout_direction == 2) {
const_cast(this)->data.is_rtl = true;
+ } else if (root_layout_direction == 3) {
+ String locale = OS::get_singleton()->get_locale();
+ const_cast(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
} else {
String locale = TranslationServer::get_singleton()->get_tool_locale();
const_cast(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
diff --git a/scene/gui/control.h b/scene/gui/control.h
index db1bd3a346a..aec61dc2fe9 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -317,6 +317,8 @@ private:
// Extra properties.
+ static int root_layout_direction;
+
String get_tooltip_text() const;
protected:
@@ -403,6 +405,8 @@ public:
// Editor integration.
+ static void set_root_layout_direction(int p_root_dir);
+
virtual void get_argument_options(const StringName &p_function, int p_idx, List *r_options) const override;
PackedStringArray get_configuration_warnings() const override;
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 2c28dc31d60..a3474ebc488 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -40,6 +40,14 @@
#include "scene/theme/theme_db.h"
#include "scene/theme/theme_owner.h"
+// Editor integration.
+
+int Window::root_layout_direction = 0;
+
+void Window::set_root_layout_direction(int p_root_dir) {
+ root_layout_direction = p_root_dir;
+}
+
// Dynamic properties.
bool Window::_set(const StringName &p_name, const Variant &p_value) {
@@ -2517,9 +2525,32 @@ Window::LayoutDirection Window::get_layout_direction() const {
bool Window::is_layout_rtl() const {
ERR_READ_THREAD_GUARD_V(false);
if (layout_dir == LAYOUT_DIRECTION_INHERITED) {
+#ifdef TOOLS_ENABLED
+ if (is_part_of_edited_scene() && GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
+ return true;
+ }
+ if (is_inside_tree()) {
+ Node *edited_scene_root = get_tree()->get_edited_scene_root();
+ if (edited_scene_root == this) {
+ int proj_root_layout_direction = GLOBAL_GET(SNAME("internationalization/rendering/root_node_layout_direction"));
+ if (proj_root_layout_direction == 1) {
+ return false;
+ } else if (proj_root_layout_direction == 2) {
+ return true;
+ } else if (proj_root_layout_direction == 3) {
+ String locale = OS::get_singleton()->get_locale();
+ return TS->is_locale_right_to_left(locale);
+ } else {
+ String locale = TranslationServer::get_singleton()->get_tool_locale();
+ return TS->is_locale_right_to_left(locale);
+ }
+ }
+ }
+#else
if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
return true;
}
+#endif
Node *parent_node = get_parent();
while (parent_node) {
Control *parent_control = Object::cast_to(parent_node);
@@ -2534,11 +2565,13 @@ bool Window::is_layout_rtl() const {
parent_node = parent_node->get_parent();
}
- int root_dir = GLOBAL_GET(SNAME("internationalization/rendering/root_node_layout_direction"));
- if (root_dir == 1) {
+ if (root_layout_direction == 1) {
return false;
- } else if (root_dir == 2) {
+ } else if (root_layout_direction == 2) {
return true;
+ } else if (root_layout_direction == 3) {
+ String locale = OS::get_singleton()->get_locale();
+ return TS->is_locale_right_to_left(locale);
} else {
String locale = TranslationServer::get_singleton()->get_tool_locale();
return TS->is_locale_right_to_left(locale);
diff --git a/scene/main/window.h b/scene/main/window.h
index 8a54b6c7d3e..1292f94f916 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -234,6 +234,8 @@ private:
Ref debugger_stop_shortcut;
+ static int root_layout_direction;
+
protected:
virtual Rect2i _popup_adjust_rect() const { return Rect2i(); }
virtual void _post_popup() {}
@@ -260,6 +262,8 @@ public:
NOTIFICATION_THEME_CHANGED = 32
};
+ static void set_root_layout_direction(int p_root_dir);
+
void set_title(const String &p_title);
String get_title() const;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 3727c788fde..e3a4a966de1 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -454,6 +454,10 @@ void register_scene_types() {
AcceptDialog::set_swap_cancel_ok(swap_cancel_ok);
#endif
+ int root_dir = GLOBAL_GET("internationalization/rendering/root_node_layout_direction");
+ Control::set_root_layout_direction(root_dir);
+ Window::set_root_layout_direction(root_dir);
+
/* REGISTER ANIMATION */
GDREGISTER_CLASS(Tween);
GDREGISTER_ABSTRACT_CLASS(Tweener);