summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/config/engine.cpp6
-rw-r--r--core/config/engine.h1
-rw-r--r--core/extension/gdextension.cpp4
-rw-r--r--core/variant/type_info.h1
-rw-r--r--doc/classes/CollisionPolygon2D.xml2
-rw-r--r--doc/classes/Node.xml2
-rw-r--r--editor/SCsub1
-rw-r--r--editor/debugger/editor_performance_profiler.cpp2
-rw-r--r--editor/debugger/editor_profiler.cpp6
-rw-r--r--editor/debugger/editor_visual_profiler.cpp2
-rw-r--r--editor/editor_builders.py10
-rw-r--r--editor/editor_properties.cpp16
-rw-r--r--editor/editor_properties.h3
-rw-r--r--editor/editor_translation.cpp24
-rw-r--r--editor/plugins/font_config_plugin.cpp20
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp36
-rw-r--r--editor/plugins/node_3d_editor_plugin.h8
-rw-r--r--editor/plugins/packed_scene_translation_parser_plugin.cpp4
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp35
-rw-r--r--editor/plugins/script_text_editor.cpp15
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp2
-rw-r--r--main/main.cpp8
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs2
-rw-r--r--modules/multiplayer/editor/multiplayer_editor_plugin.cpp2
-rw-r--r--modules/multiplayer/editor/replication_editor.cpp1
-rw-r--r--platform/linuxbsd/wayland/wayland_thread.cpp2
-rw-r--r--platform/macos/native_menu_macos.h2
-rw-r--r--platform/windows/native_menu_windows.h2
-rw-r--r--scene/2d/physics/collision_polygon_2d.cpp19
-rw-r--r--scene/gui/color_picker.cpp28
-rw-r--r--scene/gui/color_picker.h7
-rw-r--r--scene/gui/text_edit.cpp4
-rw-r--r--servers/SCsub2
-rw-r--r--servers/display/SCsub5
-rw-r--r--servers/display/native_menu.cpp (renamed from servers/native_menu.cpp)0
-rw-r--r--servers/display/native_menu.h (renamed from servers/native_menu.h)0
-rw-r--r--servers/display_server.h2
-rw-r--r--servers/register_server_types.cpp2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp2
39 files changed, 189 insertions, 101 deletions
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index d714ec42c2..9f4bff3779 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -266,6 +266,12 @@ void Engine::print_header(const String &p_string) const {
}
}
+void Engine::print_header_rich(const String &p_string) const {
+ if (_print_header) {
+ print_line_rich(p_string);
+ }
+}
+
void Engine::add_singleton(const Singleton &p_singleton) {
ERR_FAIL_COND_MSG(singleton_ptrs.has(p_singleton.name), vformat("Can't register singleton '%s' because it already exists.", p_singleton.name));
singletons.push_back(p_singleton);
diff --git a/core/config/engine.h b/core/config/engine.h
index be7cd62f66..d1495b36c2 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -126,6 +126,7 @@ public:
void set_print_error_messages(bool p_enabled);
bool is_printing_error_messages() const;
void print_header(const String &p_string) const;
+ void print_header_rich(const String &p_string) const;
void set_frame_delay(uint32_t p_msec);
uint32_t get_frame_delay() const;
diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp
index 5d43dceece..0ed4c3380c 100644
--- a/core/extension/gdextension.cpp
+++ b/core/extension/gdextension.cpp
@@ -735,7 +735,7 @@ Error GDExtension::open_library(const String &p_path, const String &p_entry_symb
bool library_copied = false;
if (Engine::get_singleton()->is_editor_hint()) {
if (!FileAccess::exists(abs_path)) {
- ERR_PRINT("GDExtension library not found: " + library_path);
+ ERR_PRINT("GDExtension library not found: " + abs_path);
return ERR_FILE_NOT_FOUND;
}
@@ -750,7 +750,7 @@ Error GDExtension::open_library(const String &p_path, const String &p_entry_symb
Error copy_err = DirAccess::copy_absolute(abs_path, copy_path);
if (copy_err) {
- ERR_PRINT("Error copying GDExtension library: " + library_path);
+ ERR_PRINT("Error copying GDExtension library: " + abs_path);
return ERR_CANT_CREATE;
}
FileAccess::set_hidden_attribute(copy_path, true);
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index 32c410463b..9c52db3345 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -296,6 +296,7 @@ public:
_FORCE_INLINE_ constexpr BitField(T p_value) { value = (int64_t)p_value; }
_FORCE_INLINE_ operator int64_t() const { return value; }
_FORCE_INLINE_ operator Variant() const { return value; }
+ _FORCE_INLINE_ BitField<T> operator^(const BitField<T> &p_b) const { return BitField<T>(value ^ p_b.value); }
};
#define TEMPL_MAKE_BITFIELD_TYPE_INFO(m_enum, m_impl) \
diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml
index 12f7024518..29535ffd64 100644
--- a/doc/classes/CollisionPolygon2D.xml
+++ b/doc/classes/CollisionPolygon2D.xml
@@ -4,7 +4,7 @@
A node that provides a polygon shape to a [CollisionObject2D] parent.
</brief_description>
<description>
- A node that provides a thickened polygon shape (a prism) to a [CollisionObject2D] parent and allows to edit it. The polygon can be concave or convex. This can give a detection shape to an [Area2D] or turn [PhysicsBody2D] into a solid object.
+ A node that provides a polygon shape to a [CollisionObject2D] parent and allows to edit it. The polygon can be concave or convex. This can give a detection shape to an [Area2D], turn [PhysicsBody2D] into a solid object, or give a hollow shape to a [StaticBody2D].
[b]Warning:[/b] A non-uniformly scaled [CollisionShape2D] will likely not behave as expected. Make sure to keep its scale the same on all axes and adjust its shape resource instead.
</description>
<tutorials>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 1ddcdce439..e6fdd229bf 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -100,7 +100,7 @@
<return type="void" />
<param index="0" name="event" type="InputEvent" />
<description>
- Called when an [InputEventKey] or [InputEventShortcut] hasn't been consumed by [method _input] or any GUI [Control] item. It is called before [method _unhandled_key_input] and [method _unhandled_input]. The input event propagates up through the node tree until a node consumes it.
+ Called when an [InputEventKey], [InputEventShortcut], or [InputEventJoypadButton] hasn't been consumed by [method _input] or any GUI [Control] item. It is called before [method _unhandled_key_input] and [method _unhandled_input]. The input event propagates up through the node tree until a node consumes it.
It is only called if shortcut processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process_shortcut_input].
To consume the input event and stop it propagating further to other nodes, [method Viewport.set_input_as_handled] can be called.
This method can be used to handle shortcuts. For generic GUI events, use [method _input] instead. Gameplay events should usually be handled with either [method _unhandled_input] or [method _unhandled_key_input].
diff --git a/editor/SCsub b/editor/SCsub
index 442d0a3b75..f4d30b68b1 100644
--- a/editor/SCsub
+++ b/editor/SCsub
@@ -104,6 +104,7 @@ if env.editor_build:
# Extractable translations
tlist = glob.glob(env.Dir("#editor/translations/extractable").abspath + "/*.po")
+ tlist.extend(glob.glob(env.Dir("#editor/translations/extractable").abspath + "/extractable.pot"))
env.Depends("#editor/extractable_translations.gen.h", tlist)
env.CommandNoCache(
"#editor/extractable_translations.gen.h",
diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp
index ffff362a94..da75715b6d 100644
--- a/editor/debugger/editor_performance_profiler.cpp
+++ b/editor/debugger/editor_performance_profiler.cpp
@@ -84,7 +84,7 @@ String EditorPerformanceProfiler::_create_label(float p_value, Performance::Moni
return String::humanize_size(p_value);
}
case Performance::MONITOR_TYPE_TIME: {
- return TS->format_number(rtos(p_value * 1000).pad_decimals(2)) + " " + RTR("ms");
+ return TS->format_number(rtos(p_value * 1000).pad_decimals(2)) + " " + TTR("ms");
}
default: {
return TS->format_number(rtos(p_value));
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index c1500631fe..ce08d40634 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -125,12 +125,12 @@ String EditorProfiler::_get_time_as_text(const Metric &m, float p_time, int p_ca
const int dmode = display_mode->get_selected();
if (dmode == DISPLAY_FRAME_TIME) {
- return TS->format_number(rtos(p_time * 1000).pad_decimals(2)) + " " + RTR("ms");
+ return TS->format_number(rtos(p_time * 1000).pad_decimals(2)) + " " + TTR("ms");
} else if (dmode == DISPLAY_AVERAGE_TIME) {
if (p_calls == 0) {
- return TS->format_number("0.00") + " " + RTR("ms");
+ return TS->format_number("0.00") + " " + TTR("ms");
} else {
- return TS->format_number(rtos((p_time / p_calls) * 1000).pad_decimals(2)) + " " + RTR("ms");
+ return TS->format_number(rtos((p_time / p_calls) * 1000).pad_decimals(2)) + " " + TTR("ms");
}
} else if (dmode == DISPLAY_FRAME_PERCENT) {
return _get_percent_txt(p_time, m.frame_time);
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index 72f1060589..8a5c464c2f 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -116,7 +116,7 @@ String EditorVisualProfiler::_get_time_as_text(float p_time) {
int dmode = display_mode->get_selected();
if (dmode == DISPLAY_FRAME_TIME) {
- return TS->format_number(String::num(p_time, 2)) + " " + RTR("ms");
+ return TS->format_number(String::num(p_time, 2)) + " " + TTR("ms");
} else if (dmode == DISPLAY_FRAME_PERCENT) {
return TS->format_number(String::num(p_time * 100 / graph_limit, 2)) + " " + TS->percent_sign();
}
diff --git a/editor/editor_builders.py b/editor/editor_builders.py
index 68595047fe..a25f4949c4 100644
--- a/editor/editor_builders.py
+++ b/editor/editor_builders.py
@@ -61,7 +61,9 @@ def make_translations_header(target, source, env, category):
xl_names = []
for i in range(len(sorted_paths)):
- if msgfmt_available:
+ name = os.path.splitext(os.path.basename(sorted_paths[i]))[0]
+ # msgfmt erases non-translated messages, so avoid using it if exporting the POT.
+ if msgfmt_available and name != category:
mo_path = os.path.join(tempfile.gettempdir(), uuid.uuid4().hex + ".mo")
cmd = "msgfmt " + sorted_paths[i] + " --no-hash -o " + mo_path
try:
@@ -79,7 +81,7 @@ def make_translations_header(target, source, env, category):
try:
os.remove(mo_path)
except OSError as e:
- # Do not fail the entire build if it cannot delete a temporary file
+ # Do not fail the entire build if it cannot delete a temporary file.
print(
"WARNING: Could not delete temporary .mo file: path=%r; [%s] %s"
% (mo_path, e.__class__.__name__, e)
@@ -88,11 +90,13 @@ def make_translations_header(target, source, env, category):
with open(sorted_paths[i], "rb") as f:
buf = f.read()
+ if name == category:
+ name = "source"
+
decomp_size = len(buf)
# Use maximum zlib compression level to further reduce file size
# (at the cost of initial build times).
buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
- name = os.path.splitext(os.path.basename(sorted_paths[i]))[0]
g.write("static const unsigned char _{}_translation_{}_compressed[] = {{\n".format(category, name))
for j in range(len(buf)):
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 0e3b408996..b7380c9fc2 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -2630,16 +2630,22 @@ void EditorPropertyColor::_set_read_only(bool p_read_only) {
}
void EditorPropertyColor::_color_changed(const Color &p_color) {
+ if (!live_changes_enabled) {
+ return;
+ }
+
// Cancel the color change if the current color is identical to the new one.
- if (get_edited_property_value() == p_color) {
+ if (((Color)get_edited_property_value()).is_equal_approx(p_color)) {
return;
}
- emit_changed(get_edited_property(), p_color, "", true);
+ // Preview color change, bypassing undo/redo.
+ get_edited_object()->set(get_edited_property(), p_color);
}
void EditorPropertyColor::_popup_closed() {
- if (picker->get_pick_color() != last_color) {
+ get_edited_object()->set(get_edited_property(), last_color);
+ if (!picker->get_pick_color().is_equal_approx(last_color)) {
emit_changed(get_edited_property(), picker->get_pick_color(), "", false);
}
}
@@ -2682,6 +2688,10 @@ void EditorPropertyColor::setup(bool p_show_alpha) {
picker->set_edit_alpha(p_show_alpha);
}
+void EditorPropertyColor::set_live_changes_enabled(bool p_enabled) {
+ live_changes_enabled = p_enabled;
+}
+
EditorPropertyColor::EditorPropertyColor() {
picker = memnew(ColorPickerButton);
add_child(picker);
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index fa759d5d19..ce164733fe 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -621,10 +621,10 @@ class EditorPropertyColor : public EditorProperty {
ColorPickerButton *picker = nullptr;
void _color_changed(const Color &p_color);
void _popup_closed();
- void _picker_created();
void _picker_opening();
Color last_color;
+ bool live_changes_enabled = true;
protected:
virtual void _set_read_only(bool p_read_only) override;
@@ -633,6 +633,7 @@ protected:
public:
virtual void update_property() override;
void setup(bool p_show_alpha);
+ void set_live_changes_enabled(bool p_enabled);
EditorPropertyColor();
};
diff --git a/editor/editor_translation.cpp b/editor/editor_translation.cpp
index 302a81669d..194d78326d 100644
--- a/editor/editor_translation.cpp
+++ b/editor/editor_translation.cpp
@@ -160,20 +160,22 @@ List<StringName> get_extractable_message_list() {
ExtractableTranslationList *etl = _extractable_translations;
List<StringName> msgids;
while (etl->data) {
- Vector<uint8_t> data;
- data.resize(etl->uncomp_size);
- int ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
- ERR_FAIL_COND_V_MSG(ret == -1, msgids, "Compressed file is corrupt.");
+ if (!strcmp(etl->lang, "source")) {
+ Vector<uint8_t> data;
+ data.resize(etl->uncomp_size);
+ int ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
+ ERR_FAIL_COND_V_MSG(ret == -1, msgids, "Compressed file is corrupt.");
- Ref<FileAccessMemory> fa;
- fa.instantiate();
- fa->open_custom(data.ptr(), data.size());
+ Ref<FileAccessMemory> fa;
+ fa.instantiate();
+ fa->open_custom(data.ptr(), data.size());
- Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
+ Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
- if (tr.is_valid()) {
- tr->get_message_list(&msgids);
- break;
+ if (tr.is_valid()) {
+ tr->get_message_list(&msgids);
+ break;
+ }
}
etl++;
diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp
index 70911ea364..be7ff6ba3e 100644
--- a/editor/plugins/font_config_plugin.cpp
+++ b/editor/plugins/font_config_plugin.cpp
@@ -716,7 +716,7 @@ void EditorPropertyOTFeatures::update_property() {
}
for (int i = 0; i < FGRP_MAX; i++) {
if (have_sub[i]) {
- menu->add_submenu_node_item(RTR(group_names[i]), menu_sub[i]);
+ menu->add_submenu_node_item(TTRGET(group_names[i]), menu_sub[i]);
}
}
@@ -848,15 +848,15 @@ EditorPropertyOTFeatures::EditorPropertyOTFeatures() {
menu_sub[i]->connect("id_pressed", callable_mp(this, &EditorPropertyOTFeatures::_add_feature));
}
- group_names[FGRP_STYLISTIC_SET] = "Stylistic Sets";
- group_names[FGRP_CHARACTER_VARIANT] = "Character Variants";
- group_names[FGRP_CAPITLS] = "Capitals";
- group_names[FGRP_LIGATURES] = "Ligatures";
- group_names[FGRP_ALTERNATES] = "Alternates";
- group_names[FGRP_EAL] = "East Asian Language";
- group_names[FGRP_EAW] = "East Asian Widths";
- group_names[FGRP_NUMAL] = "Numeral Alignment";
- group_names[FGRP_CUSTOM] = "Custom";
+ group_names[FGRP_STYLISTIC_SET] = TTRC("Stylistic Sets");
+ group_names[FGRP_CHARACTER_VARIANT] = TTRC("Character Variants");
+ group_names[FGRP_CAPITLS] = TTRC("Capitals");
+ group_names[FGRP_LIGATURES] = TTRC("Ligatures");
+ group_names[FGRP_ALTERNATES] = TTRC("Alternates");
+ group_names[FGRP_EAL] = TTRC("East Asian Language");
+ group_names[FGRP_EAW] = TTRC("East Asian Widths");
+ group_names[FGRP_NUMAL] = TTRC("Numeral Alignment");
+ group_names[FGRP_CUSTOM] = TTRC("Custom");
}
/*************************************************************************/
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 7a4a7ddaec..468d7fb051 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -691,11 +691,11 @@ Vector3 Node3DEditorViewport::_get_camera_position() const {
return _get_camera_transform().origin;
}
-Point2 Node3DEditorViewport::_point_to_screen(const Vector3 &p_point) {
+Point2 Node3DEditorViewport::point_to_screen(const Vector3 &p_point) {
return camera->unproject_position(p_point) * subviewport_container->get_stretch_shrink();
}
-Vector3 Node3DEditorViewport::_get_ray_pos(const Vector2 &p_pos) const {
+Vector3 Node3DEditorViewport::get_ray_pos(const Vector2 &p_pos) const {
return camera->project_ray_origin(p_pos / subviewport_container->get_stretch_shrink());
}
@@ -703,7 +703,7 @@ Vector3 Node3DEditorViewport::_get_camera_normal() const {
return -_get_camera_transform().basis.get_column(2);
}
-Vector3 Node3DEditorViewport::_get_ray(const Vector2 &p_pos) const {
+Vector3 Node3DEditorViewport::get_ray(const Vector2 &p_pos) const {
return camera->project_ray_normal(p_pos / subviewport_container->get_stretch_shrink());
}
@@ -769,8 +769,8 @@ void Node3DEditorViewport::_select_clicked(bool p_allow_locked) {
}
ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const {
- Vector3 ray = _get_ray(p_pos);
- Vector3 pos = _get_ray_pos(p_pos);
+ Vector3 ray = get_ray(p_pos);
+ Vector3 pos = get_ray_pos(p_pos);
Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink();
if (viewport->get_debug_draw() == Viewport::DEBUG_DRAW_SDFGI_PROBES) {
@@ -837,8 +837,8 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) const {
}
void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked_nodes) {
- Vector3 ray = _get_ray(p_pos);
- Vector3 pos = _get_ray_pos(p_pos);
+ Vector3 ray = get_ray(p_pos);
+ Vector3 pos = get_ray_pos(p_pos);
Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, pos + ray * camera->get_far(), get_tree()->get_root()->get_world_3d()->get_scenario());
HashSet<Node3D *> found_nodes;
@@ -1153,8 +1153,8 @@ void Node3DEditorViewport::_update_name() {
void Node3DEditorViewport::_compute_edit(const Point2 &p_point) {
_edit.original_local = spatial_editor->are_local_coords_enabled();
- _edit.click_ray = _get_ray(p_point);
- _edit.click_ray_pos = _get_ray_pos(p_point);
+ _edit.click_ray = get_ray(p_point);
+ _edit.click_ray_pos = get_ray_pos(p_point);
_edit.plane = TRANSFORM_VIEW;
spatial_editor->update_transform_gizmo();
_edit.center = spatial_editor->get_gizmo_transform().origin;
@@ -1233,8 +1233,8 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b
return false;
}
- Vector3 ray_pos = _get_ray_pos(p_screenpos);
- Vector3 ray = _get_ray(p_screenpos);
+ Vector3 ray_pos = get_ray_pos(p_screenpos);
+ Vector3 ray = get_ray(p_screenpos);
Transform3D gt = spatial_editor->get_gizmo_transform();
@@ -3115,7 +3115,7 @@ void Node3DEditorViewport::_draw() {
}
if (_edit.mode == TRANSFORM_ROTATE && _edit.show_rotation_line) {
- Point2 center = _point_to_screen(_edit.center);
+ Point2 center = point_to_screen(_edit.center);
Color handle_color;
switch (_edit.plane) {
@@ -4087,8 +4087,8 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const
const float MAX_DISTANCE = 50.0;
const float FALLBACK_DISTANCE = 5.0;
- Vector3 world_ray = _get_ray(p_pos);
- Vector3 world_pos = _get_ray_pos(p_pos);
+ Vector3 world_ray = get_ray(p_pos);
+ Vector3 world_pos = get_ray_pos(p_pos);
PhysicsDirectSpaceState3D *ss = get_tree()->get_root()->get_world_3d()->get_direct_space_state();
@@ -4250,8 +4250,8 @@ bool Node3DEditorViewport::_apply_preview_material(ObjectID p_target, const Poin
Ref<Mesh> mesh = mesh_instance->get_mesh();
int surface_count = mesh->get_surface_count();
- Vector3 world_ray = _get_ray(p_point);
- Vector3 world_pos = _get_ray_pos(p_point);
+ Vector3 world_ray = get_ray(p_point);
+ Vector3 world_pos = get_ray_pos(p_point);
int closest_surface = -1;
float closest_dist = 1e20;
@@ -4698,8 +4698,8 @@ void Node3DEditorViewport::apply_transform(Vector3 p_motion, double p_snap) {
// Update the current transform operation in response to an input.
void Node3DEditorViewport::update_transform(bool p_shift) {
- Vector3 ray_pos = _get_ray_pos(_edit.mouse_pos);
- Vector3 ray = _get_ray(_edit.mouse_pos);
+ Vector3 ray_pos = get_ray_pos(_edit.mouse_pos);
+ Vector3 ray = get_ray(_edit.mouse_pos);
double snap = EDITOR_GET("interface/inspector/default_float_step");
int snap_step_decimals = Math::range_step_decimals(snap);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 091432b35a..7ddbb74006 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -271,9 +271,7 @@ private:
void _select_clicked(bool p_allow_locked);
ObjectID _select_ray(const Point2 &p_pos) const;
void _find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked);
- Vector3 _get_ray_pos(const Vector2 &p_pos) const;
- Vector3 _get_ray(const Vector2 &p_pos) const;
- Point2 _point_to_screen(const Vector3 &p_point);
+
Transform3D _get_camera_transform() const;
int get_selected_count() const;
void cancel_transform();
@@ -481,6 +479,10 @@ public:
void reset();
bool is_freelook_active() const { return freelook_active; }
+ Vector3 get_ray_pos(const Vector2 &p_pos) const;
+ Vector3 get_ray(const Vector2 &p_pos) const;
+ Point2 point_to_screen(const Vector3 &p_point);
+
void focus_selection();
void assign_pending_data_pointers(
diff --git a/editor/plugins/packed_scene_translation_parser_plugin.cpp b/editor/plugins/packed_scene_translation_parser_plugin.cpp
index 86df57c469..e266a3241b 100644
--- a/editor/plugins/packed_scene_translation_parser_plugin.cpp
+++ b/editor/plugins/packed_scene_translation_parser_plugin.cpp
@@ -136,6 +136,10 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path,
if (property_name == "script" && property_value.get_type() == Variant::OBJECT && !property_value.is_null()) {
// Parse built-in script.
Ref<Script> s = Object::cast_to<Script>(property_value);
+ if (!s->is_built_in()) {
+ continue;
+ }
+
String extension = s->get_language()->get_extension();
if (EditorTranslationParser::get_singleton()->can_parse(extension)) {
Vector<String> temp;
diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp
index ffdc06ceee..e4522f5a03 100644
--- a/editor/plugins/path_3d_editor_plugin.cpp
+++ b/editor/plugins/path_3d_editor_plugin.cpp
@@ -473,6 +473,17 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p
if (mb.is_valid()) {
Point2 mbpos(mb->get_position().x, mb->get_position().y);
+ Node3DEditorViewport *viewport = nullptr;
+ for (uint32_t i = 0; i < Node3DEditor::VIEWPORTS_COUNT; i++) {
+ Node3DEditorViewport *vp = Node3DEditor::get_singleton()->get_editor_viewport(i);
+ if (vp->get_camera_3d() == p_camera) {
+ viewport = vp;
+ break;
+ }
+ }
+
+ ERR_FAIL_NULL_V(viewport, EditorPlugin::AFTER_GUI_INPUT_PASS);
+
if (!mb->is_pressed()) {
set_handle_clicked(false);
}
@@ -489,14 +500,14 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p
const Vector3 *r = v3a.ptr();
float closest_d = 1e20;
- if (p_camera->unproject_position(gt.xform(c->get_point_position(0))).distance_to(mbpos) < click_dist) {
+ if (viewport->point_to_screen(gt.xform(c->get_point_position(0))).distance_to(mbpos) < click_dist) {
return EditorPlugin::AFTER_GUI_INPUT_PASS; //nope, existing
}
for (int i = 0; i < c->get_point_count() - 1; i++) {
//find the offset and point index of the place to break up
int j = idx;
- if (p_camera->unproject_position(gt.xform(c->get_point_position(i + 1))).distance_to(mbpos) < click_dist) {
+ if (viewport->point_to_screen(gt.xform(c->get_point_position(i + 1))).distance_to(mbpos) < click_dist) {
return EditorPlugin::AFTER_GUI_INPUT_PASS; //nope, existing
}
@@ -508,16 +519,16 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p
to = gt.xform(to);
if (cdist > 0) {
Vector2 s[2];
- s[0] = p_camera->unproject_position(from);
- s[1] = p_camera->unproject_position(to);
+ s[0] = viewport->point_to_screen(from);
+ s[1] = viewport->point_to_screen(to);
Vector2 inters = Geometry2D::get_closest_point_to_segment(mbpos, s);
float d = inters.distance_to(mbpos);
if (d < 10 && d < closest_d) {
closest_d = d;
closest_seg = i;
- Vector3 ray_from = p_camera->project_ray_origin(mbpos);
- Vector3 ray_dir = p_camera->project_ray_normal(mbpos);
+ Vector3 ray_from = viewport->get_ray_pos(mbpos);
+ Vector3 ray_dir = viewport->get_ray(mbpos);
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(ray_from, ray_from + ray_dir * 4096, from, to, ra, rb);
@@ -557,8 +568,8 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p
origin = gt.xform(c->get_point_position(c->get_point_count() - 1));
}
Plane p(p_camera->get_transform().basis.get_column(2), origin);
- Vector3 ray_from = p_camera->project_ray_origin(mbpos);
- Vector3 ray_dir = p_camera->project_ray_normal(mbpos);
+ Vector3 ray_from = viewport->get_ray_pos(mbpos);
+ Vector3 ray_dir = viewport->get_ray(mbpos);
Vector3 inters;
if (p.intersects_ray(ray_from, ray_dir, &inters)) {
@@ -574,10 +585,10 @@ EditorPlugin::AfterGUIInput Path3DEditorPlugin::forward_3d_gui_input(Camera3D *p
} else if (mb->is_pressed() && ((mb->get_button_index() == MouseButton::LEFT && curve_del->is_pressed()) || (mb->get_button_index() == MouseButton::RIGHT && curve_edit->is_pressed()))) {
for (int i = 0; i < c->get_point_count(); i++) {
- real_t dist_to_p = p_camera->unproject_position(gt.xform(c->get_point_position(i))).distance_to(mbpos);
- real_t dist_to_p_out = p_camera->unproject_position(gt.xform(c->get_point_position(i) + c->get_point_out(i))).distance_to(mbpos);
- real_t dist_to_p_in = p_camera->unproject_position(gt.xform(c->get_point_position(i) + c->get_point_in(i))).distance_to(mbpos);
- real_t dist_to_p_up = p_camera->unproject_position(gt.xform(c->get_point_position(i) + c->get_point_baked_posture(i, true).get_column(1) * disk_size)).distance_to(mbpos);
+ real_t dist_to_p = viewport->point_to_screen(gt.xform(c->get_point_position(i))).distance_to(mbpos);
+ real_t dist_to_p_out = viewport->point_to_screen(gt.xform(c->get_point_position(i) + c->get_point_out(i))).distance_to(mbpos);
+ real_t dist_to_p_in = viewport->point_to_screen(gt.xform(c->get_point_position(i) + c->get_point_in(i))).distance_to(mbpos);
+ real_t dist_to_p_up = viewport->point_to_screen(gt.xform(c->get_point_position(i) + c->get_point_baked_posture(i, true).get_column(1) * disk_size)).distance_to(mbpos);
// Find the offset and point index of the place to break up.
// Also check for the control points.
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index c093f556ea..640c755ccf 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -1164,11 +1164,22 @@ void ScriptTextEditor::_update_connected_methods() {
// Add override icons to methods.
methods_found.clear();
for (int i = 0; i < functions.size(); i++) {
- StringName name = StringName(functions[i].get_slice(":", 0));
+ String raw_name = functions[i].get_slice(":", 0);
+ StringName name = StringName(raw_name);
if (methods_found.has(name)) {
continue;
}
+ // Account for inner classes
+ if (raw_name.contains(".")) {
+ // Strip inner class name from the method, and start from the right since
+ // our inner class might be inside another inner class
+ int pos = raw_name.rfind(".");
+ if (pos != -1) {
+ name = raw_name.substr(pos + 1);
+ }
+ }
+
String found_base_class;
StringName base_class = script->get_instance_base_type();
Ref<Script> inherited_script = script->get_base_script();
@@ -1217,7 +1228,7 @@ void ScriptTextEditor::_update_connected_methods() {
text_edit->set_line_gutter_icon(line, connection_gutter, get_parent_control()->get_editor_theme_icon(SNAME("MethodOverrideAndSlot")));
}
- methods_found.insert(name);
+ methods_found.insert(StringName(raw_name));
}
}
}
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 964558ee78..c83c47577d 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -6922,6 +6922,8 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par
} else if (Object::cast_to<EditorPropertyEnum>(prop)) {
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
Object::cast_to<EditorPropertyEnum>(prop)->set_option_button_clip(false);
+ } else if (Object::cast_to<EditorPropertyColor>(prop)) {
+ Object::cast_to<EditorPropertyColor>(prop)->set_live_changes_enabled(false);
}
editors.push_back(prop);
diff --git a/main/main.cpp b/main/main.cpp
index 41f82177bc..cf40f764cf 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -398,15 +398,15 @@ void Main::print_header(bool p_rich) {
if (VERSION_TIMESTAMP > 0) {
// Version timestamp available.
if (p_rich) {
- print_line_rich("\u001b[38;5;39m" + String(VERSION_NAME) + "\u001b[0m v" + get_full_version_string() + " (" + Time::get_singleton()->get_datetime_string_from_unix_time(VERSION_TIMESTAMP, true) + " UTC) - \u001b[4m" + String(VERSION_WEBSITE));
+ Engine::get_singleton()->print_header_rich("\u001b[38;5;39m" + String(VERSION_NAME) + "\u001b[0m v" + get_full_version_string() + " (" + Time::get_singleton()->get_datetime_string_from_unix_time(VERSION_TIMESTAMP, true) + " UTC) - \u001b[4m" + String(VERSION_WEBSITE));
} else {
- print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " (" + Time::get_singleton()->get_datetime_string_from_unix_time(VERSION_TIMESTAMP, true) + " UTC) - " + String(VERSION_WEBSITE));
+ Engine::get_singleton()->print_header(String(VERSION_NAME) + " v" + get_full_version_string() + " (" + Time::get_singleton()->get_datetime_string_from_unix_time(VERSION_TIMESTAMP, true) + " UTC) - " + String(VERSION_WEBSITE));
}
} else {
if (p_rich) {
- print_line_rich("\u001b[38;5;39m" + String(VERSION_NAME) + "\u001b[0m v" + get_full_version_string() + " - \u001b[4m" + String(VERSION_WEBSITE));
+ Engine::get_singleton()->print_header_rich("\u001b[38;5;39m" + String(VERSION_NAME) + "\u001b[0m v" + get_full_version_string() + " - \u001b[4m" + String(VERSION_WEBSITE));
} else {
- print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
+ Engine::get_singleton()->print_header(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
}
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
index 8d24582ba1..8679f32e1a 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
@@ -212,7 +212,7 @@ namespace Godot
private void Rotate(Quaternion quaternion)
{
- this *= new Basis(quaternion);
+ this = new Basis(quaternion) * this;
}
private void SetDiagonal(Vector3 diagonal)
diff --git a/modules/multiplayer/editor/multiplayer_editor_plugin.cpp b/modules/multiplayer/editor/multiplayer_editor_plugin.cpp
index 599926ec99..29ebc38edf 100644
--- a/modules/multiplayer/editor/multiplayer_editor_plugin.cpp
+++ b/modules/multiplayer/editor/multiplayer_editor_plugin.cpp
@@ -149,7 +149,7 @@ void MultiplayerEditorPlugin::_node_removed(Node *p_node) {
}
void MultiplayerEditorPlugin::_pinned() {
- if (!repl_editor->get_pin()->is_pressed()) {
+ if (!repl_editor->get_pin()->is_pressed() && repl_editor->get_current() == nullptr) {
if (repl_editor->is_visible_in_tree()) {
EditorNode::get_bottom_panel()->hide_bottom_panel();
}
diff --git a/modules/multiplayer/editor/replication_editor.cpp b/modules/multiplayer/editor/replication_editor.cpp
index f6df212d35..58803124cf 100644
--- a/modules/multiplayer/editor/replication_editor.cpp
+++ b/modules/multiplayer/editor/replication_editor.cpp
@@ -270,6 +270,7 @@ ReplicationEditor::ReplicationEditor() {
pin = memnew(Button);
pin->set_theme_type_variation("FlatButton");
pin->set_toggle_mode(true);
+ pin->set_tooltip_text(TTR("Pin replication editor"));
hb->add_child(pin);
tree = memnew(Tree);
diff --git a/platform/linuxbsd/wayland/wayland_thread.cpp b/platform/linuxbsd/wayland/wayland_thread.cpp
index 4057587db7..7f9008e952 100644
--- a/platform/linuxbsd/wayland/wayland_thread.cpp
+++ b/platform/linuxbsd/wayland/wayland_thread.cpp
@@ -1563,7 +1563,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point
}
if (old_pd.pressed_button_mask != pd.pressed_button_mask) {
- BitField<MouseButtonMask> pressed_mask_delta = BitField<MouseButtonMask>((uint32_t)old_pd.pressed_button_mask ^ (uint32_t)pd.pressed_button_mask);
+ BitField<MouseButtonMask> pressed_mask_delta = old_pd.pressed_button_mask ^ pd.pressed_button_mask;
const MouseButton buttons_to_test[] = {
MouseButton::LEFT,
diff --git a/platform/macos/native_menu_macos.h b/platform/macos/native_menu_macos.h
index c00a510fd5..1d9feb64a7 100644
--- a/platform/macos/native_menu_macos.h
+++ b/platform/macos/native_menu_macos.h
@@ -33,7 +33,7 @@
#include "core/templates/hash_map.h"
#include "core/templates/rid_owner.h"
-#include "servers/native_menu.h"
+#include "servers/display/native_menu.h"
#import <AppKit/AppKit.h>
#import <ApplicationServices/ApplicationServices.h>
diff --git a/platform/windows/native_menu_windows.h b/platform/windows/native_menu_windows.h
index 6eab56d8b6..74fd231903 100644
--- a/platform/windows/native_menu_windows.h
+++ b/platform/windows/native_menu_windows.h
@@ -33,7 +33,7 @@
#include "core/templates/hash_map.h"
#include "core/templates/rid_owner.h"
-#include "servers/native_menu.h"
+#include "servers/display/native_menu.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
diff --git a/scene/2d/physics/collision_polygon_2d.cpp b/scene/2d/physics/collision_polygon_2d.cpp
index 96ef346d23..72ee4d52c5 100644
--- a/scene/2d/physics/collision_polygon_2d.cpp
+++ b/scene/2d/physics/collision_polygon_2d.cpp
@@ -132,17 +132,16 @@ void CollisionPolygon2D::_notification(int p_what) {
}
if (polygon.size() > 2) {
-#define DEBUG_DECOMPOSE
-#if defined(TOOLS_ENABLED) && defined(DEBUG_DECOMPOSE)
- Vector<Vector<Vector2>> decomp = _decompose_in_convex();
-
- Color c(0.4, 0.9, 0.1);
- for (int i = 0; i < decomp.size(); i++) {
- c.set_hsv(Math::fmod(c.get_h() + 0.738, 1), c.get_s(), c.get_v(), 0.5);
- draw_colored_polygon(decomp[i], c);
+#ifdef TOOLS_ENABLED
+ if (build_mode == BUILD_SOLIDS) {
+ Vector<Vector<Vector2>> decomp = _decompose_in_convex();
+
+ Color c(0.4, 0.9, 0.1);
+ for (int i = 0; i < decomp.size(); i++) {
+ c.set_hsv(Math::fmod(c.get_h() + 0.738, 1), c.get_s(), c.get_v(), 0.5);
+ draw_colored_polygon(decomp[i], c);
+ }
}
-#else
- draw_colored_polygon(polygon, get_tree()->get_debug_collisions_color());
#endif
const Color stroke_color = Color(0.9, 0.2, 0.0);
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index ee2122f269..3b62f6c23d 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -714,6 +714,10 @@ Color ColorPicker::get_pick_color() const {
return color;
}
+Color ColorPicker::get_old_color() const {
+ return old_color;
+}
+
void ColorPicker::set_picker_shape(PickerShapeType p_shape) {
ERR_FAIL_INDEX(p_shape, SHAPE_MAX);
if (p_shape == current_shape) {
@@ -1514,7 +1518,7 @@ void ColorPicker::_pick_finished() {
return;
}
- if (Input::get_singleton()->is_key_pressed(Key::ESCAPE)) {
+ if (Input::get_singleton()->is_action_just_pressed(SNAME("ui_cancel"))) {
set_pick_color(old_color);
} else {
emit_signal(SNAME("color_changed"), color);
@@ -1627,7 +1631,12 @@ void ColorPicker::_html_focus_exit() {
if (c_text->is_menu_visible()) {
return;
}
- _html_submitted(c_text->get_text());
+
+ if (is_visible_in_tree()) {
+ _html_submitted(c_text->get_text());
+ } else {
+ _update_text_value();
+ }
}
void ColorPicker::set_can_add_swatches(bool p_enabled) {
@@ -2026,6 +2035,15 @@ ColorPicker::~ColorPicker() {
/////////////////
+void ColorPickerPopupPanel::_input_from_window(const Ref<InputEvent> &p_event) {
+ if (p_event->is_action_pressed(SNAME("ui_accept"), false, true)) {
+ _close_pressed();
+ }
+ PopupPanel::_input_from_window(p_event);
+}
+
+/////////////////
+
void ColorPickerButton::_about_to_popup() {
set_pressed(true);
if (picker) {
@@ -2040,6 +2058,10 @@ void ColorPickerButton::_color_changed(const Color &p_color) {
}
void ColorPickerButton::_modal_closed() {
+ if (Input::get_singleton()->is_action_just_pressed(SNAME("ui_cancel"))) {
+ set_pick_color(picker->get_old_color());
+ emit_signal(SNAME("color_changed"), color);
+ }
emit_signal(SNAME("popup_closed"));
set_pressed(false);
}
@@ -2137,7 +2159,7 @@ PopupPanel *ColorPickerButton::get_popup() {
void ColorPickerButton::_update_picker() {
if (!picker) {
- popup = memnew(PopupPanel);
+ popup = memnew(ColorPickerPopupPanel);
popup->set_wrap_controls(true);
picker = memnew(ColorPicker);
picker->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h
index 282926d1ff..ad028584b1 100644
--- a/scene/gui/color_picker.h
+++ b/scene/gui/color_picker.h
@@ -317,12 +317,11 @@ public:
void set_edit_alpha(bool p_show);
bool is_editing_alpha() const;
- int get_preset_size();
-
void _set_pick_color(const Color &p_color, bool p_update_sliders);
void set_pick_color(const Color &p_color);
Color get_pick_color() const;
void set_old_color(const Color &p_color);
+ Color get_old_color() const;
void set_display_old_color(bool p_enabled);
bool is_displaying_old_color() const;
@@ -375,6 +374,10 @@ public:
~ColorPicker();
};
+class ColorPickerPopupPanel : public PopupPanel {
+ virtual void _input_from_window(const Ref<InputEvent> &p_event) override;
+};
+
class ColorPickerButton : public Button {
GDCLASS(ColorPickerButton, Button);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 29e4956588..a7cd18e1a8 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1113,7 +1113,7 @@ void TextEdit::_notification(int p_what) {
Vector<Vector2> sel = TS->shaped_text_get_selection(rid, sel_from, sel_to);
// Show selection at the end of line.
- if (line < get_selection_to_line(c)) {
+ if (line_wrap_index == line_wrap_amount && line < get_selection_to_line(c)) {
if (rtl) {
sel.push_back(Vector2(-char_w, 0));
} else {
@@ -1123,7 +1123,7 @@ void TextEdit::_notification(int p_what) {
}
for (int j = 0; j < sel.size(); j++) {
- Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, Math::ceil(sel[j].y - sel[j].x), row_height);
+ Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, Math::ceil(sel[j].y) - sel[j].x, row_height);
if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) {
continue;
}
diff --git a/servers/SCsub b/servers/SCsub
index 2e4430f030..736bed68ec 100644
--- a/servers/SCsub
+++ b/servers/SCsub
@@ -7,7 +7,6 @@ env.servers_sources = []
env.add_source_files(env.servers_sources, "audio_server.cpp")
env.add_source_files(env.servers_sources, "camera_server.cpp")
env.add_source_files(env.servers_sources, "display_server.cpp")
-env.add_source_files(env.servers_sources, "native_menu.cpp")
env.add_source_files(env.servers_sources, "navigation_server_2d.cpp")
env.add_source_files(env.servers_sources, "navigation_server_3d.cpp")
env.add_source_files(env.servers_sources, "physics_server_2d.cpp")
@@ -19,6 +18,7 @@ env.add_source_files(env.servers_sources, "text_server.cpp")
SConscript("audio/SCsub")
SConscript("camera/SCsub")
SConscript("debugger/SCsub")
+SConscript("display/SCsub")
SConscript("extensions/SCsub")
SConscript("movie_writer/SCsub")
SConscript("navigation/SCsub")
diff --git a/servers/display/SCsub b/servers/display/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/display/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/native_menu.cpp b/servers/display/native_menu.cpp
index ca46560c7c..ca46560c7c 100644
--- a/servers/native_menu.cpp
+++ b/servers/display/native_menu.cpp
diff --git a/servers/native_menu.h b/servers/display/native_menu.h
index 2bc061a216..2bc061a216 100644
--- a/servers/native_menu.h
+++ b/servers/display/native_menu.h
diff --git a/servers/display_server.h b/servers/display_server.h
index 85b791ca69..39a80ae7c1 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -36,7 +36,7 @@
#include "core/os/os.h"
#include "core/variant/callable.h"
-#include "native_menu.h"
+#include "display/native_menu.h"
class Texture2D;
class Image;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 223d8f44e3..c03c0b7a40 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -57,11 +57,11 @@
#include "camera/camera_feed.h"
#include "camera_server.h"
#include "debugger/servers_debugger.h"
+#include "display/native_menu.h"
#include "display_server.h"
#include "movie_writer/movie_writer.h"
#include "movie_writer/movie_writer_mjpeg.h"
#include "movie_writer/movie_writer_pngwav.h"
-#include "native_menu.h"
#include "rendering/renderer_compositor.h"
#include "rendering/renderer_rd/framebuffer_cache_rd.h"
#include "rendering/renderer_rd/storage_rd/render_data_rd.h"
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 33bb5459f2..d78f3ba05b 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -546,6 +546,8 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis
VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW);
VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW | COLOR_PASS_FLAG_MOTION_VECTORS);
VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MOTION_VECTORS);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR | COLOR_PASS_FLAG_MULTIVIEW | COLOR_PASS_FLAG_MOTION_VECTORS);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MULTIVIEW | COLOR_PASS_FLAG_MOTION_VECTORS);
default: {
ERR_FAIL_MSG("Invalid color pass flag combination " + itos(p_params->color_pass_flags));
}