summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig10
-rw-r--r--core/object/object.cpp2
-rw-r--r--core/variant/callable.cpp27
-rw-r--r--core/variant/callable.h3
-rw-r--r--core/variant/callable_bind.cpp52
-rw-r--r--core/variant/callable_bind.h2
-rw-r--r--core/variant/variant.cpp17
-rw-r--r--core/variant/variant_call.cpp1
-rw-r--r--doc/classes/Callable.xml6
-rw-r--r--doc/classes/Control.xml66
-rw-r--r--doc/classes/PhysicsDirectBodyState2D.xml7
-rw-r--r--doc/classes/PhysicsDirectBodyState2DExtension.xml6
-rw-r--r--editor/action_map_editor.cpp2
-rw-r--r--editor/create_dialog.cpp2
-rw-r--r--editor/editor_audio_buses.cpp2
-rw-r--r--editor/editor_autoload_settings.cpp2
-rw-r--r--editor/editor_inspector.cpp2
-rw-r--r--editor/editor_properties.cpp4
-rw-r--r--editor/editor_properties_array_dict.cpp2
-rw-r--r--editor/editor_resource_picker.cpp2
-rw-r--r--editor/editor_settings_dialog.cpp2
-rw-r--r--editor/export/project_export.cpp2
-rw-r--r--editor/filesystem_dock.cpp4
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp2
-rw-r--r--editor/plugins/script_editor_plugin.cpp2
-rw-r--r--editor/plugins/script_text_editor.cpp2
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--editor/plugins/text_editor.cpp2
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp2
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp2
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp2
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp4
-rw-r--r--editor/scene_tree_editor.cpp2
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.gd6
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd1
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/class_from_parent.gd20
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd4
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lookup_class.gd56
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/lookup_signal.gd58
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.gd4
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/double_dictionary_comma.gd2
-rw-r--r--modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd6
-rw-r--r--modules/gdscript/tests/scripts/parser/features/advanced_expression_matching.gd62
-rw-r--r--modules/gdscript/tests/scripts/parser/features/basic_expression_matching.gd48
-rw-r--r--modules/gdscript/tests/scripts/parser/features/lambda_callable.gd6
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_dictionary.gd76
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd40
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd10
-rw-r--r--modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.gd2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd2
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd24
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.gd9
-rw-r--r--modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.out3
-rw-r--r--modules/multiplayer/editor/replication_editor.cpp2
-rw-r--r--scene/gui/color_picker.cpp2
-rw-r--r--scene/gui/control.cpp66
-rw-r--r--scene/gui/control.h7
-rw-r--r--scene/gui/tab_container.cpp2
-rw-r--r--scene/gui/tree.cpp6
-rw-r--r--servers/extensions/physics_server_2d_extension.cpp1
-rw-r--r--servers/extensions/physics_server_2d_extension.h1
-rw-r--r--servers/physics_2d/godot_body_2d.h6
-rw-r--r--servers/physics_2d/godot_body_direct_state_2d.cpp5
-rw-r--r--servers/physics_2d/godot_body_direct_state_2d.h2
-rw-r--r--servers/physics_2d/godot_body_pair_2d.cpp37
-rw-r--r--servers/physics_2d/godot_body_pair_2d.h1
-rw-r--r--servers/physics_server_2d.cpp1
-rw-r--r--servers/physics_server_2d.h1
-rw-r--r--servers/rendering/renderer_rd/effects/luminance.cpp255
-rw-r--r--servers/rendering/renderer_rd/effects/luminance.h120
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp138
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h51
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp85
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h5
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/luminance_reduce.glsl (renamed from servers/rendering/renderer_rd/shaders/luminance_reduce.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl (renamed from servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster_inc.glsl (renamed from servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl)0
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp22
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h9
89 files changed, 892 insertions, 654 deletions
diff --git a/.editorconfig b/.editorconfig
index 92ee947a82..4bb7553b16 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -21,3 +21,13 @@ indent_size = 4
[*.{yml,yaml}]
indent_style = space
indent_size = 2
+
+# GDScript unit test files
+[*.gd]
+indent_style = tab
+indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.out]
+insert_final_newline = true
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 1f0a7e516d..2cb56dfe6c 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1055,7 +1055,7 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int
if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD && !ClassDB::class_exists(target->get_class_name())) {
//most likely object is not initialized yet, do not throw error.
} else {
- ERR_PRINT("Error calling from signal '" + String(p_name) + "' to callable: " + Variant::get_callable_error_text(c.callable, args, argc + c.callable.get_bound_arguments_count(), ce) + ".");
+ ERR_PRINT("Error calling from signal '" + String(p_name) + "' to callable: " + Variant::get_callable_error_text(c.callable, args, argc, ce) + ".");
err = ERR_METHOD_NOT_FOUND;
}
}
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index fd85fe78f6..2f2acc55a6 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -117,6 +117,7 @@ Callable Callable::bindv(const Array &p_arguments) {
}
Callable Callable::unbind(int p_argcount) const {
+ ERR_FAIL_COND_V_MSG(p_argcount <= 0, Callable(*this), "Amount of unbind() arguments must be 1 or greater.");
return Callable(memnew(CallableCustomUnbind(*this, p_argcount)));
}
@@ -159,6 +160,27 @@ int Callable::get_bound_arguments_count() const {
}
}
+void Callable::get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const {
+ if (!is_null() && is_custom()) {
+ custom->get_bound_arguments(r_arguments, r_argcount);
+ } else {
+ r_arguments.clear();
+ r_argcount = 0;
+ }
+}
+
+Array Callable::get_bound_arguments() const {
+ Vector<Variant> arr;
+ int ac;
+ get_bound_arguments_ref(arr, ac);
+ Array ret;
+ ret.resize(arr.size());
+ for (int i = 0; i < arr.size(); i++) {
+ ret[i] = arr[i];
+ }
+ return ret;
+}
+
CallableCustom *Callable::get_custom() const {
ERR_FAIL_COND_V_MSG(!is_custom(), nullptr,
vformat("Can't get custom on non-CallableCustom \"%s\".", operator String()));
@@ -370,6 +392,11 @@ int CallableCustom::get_bound_arguments_count() const {
return 0;
}
+void CallableCustom::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
+ r_arguments = Vector<Variant>();
+ r_argcount = 0;
+}
+
CallableCustom::CallableCustom() {
ref_count.init();
}
diff --git a/core/variant/callable.h b/core/variant/callable.h
index 10d291ac24..0abbb64c0b 100644
--- a/core/variant/callable.h
+++ b/core/variant/callable.h
@@ -108,6 +108,8 @@ public:
StringName get_method() const;
CallableCustom *get_custom() const;
int get_bound_arguments_count() const;
+ void get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const; // Internal engine use, the exposed one is below.
+ Array get_bound_arguments() const;
uint32_t hash() const;
@@ -149,6 +151,7 @@ public:
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
virtual const Callable *get_base_comparator() const;
virtual int get_bound_arguments_count() const;
+ virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const;
CallableCustom();
virtual ~CallableCustom() {}
diff --git a/core/variant/callable_bind.cpp b/core/variant/callable_bind.cpp
index 83035dc70d..5be91c6e11 100644
--- a/core/variant/callable_bind.cpp
+++ b/core/variant/callable_bind.cpp
@@ -91,6 +91,43 @@ int CallableCustomBind::get_bound_arguments_count() const {
return callable.get_bound_arguments_count() + binds.size();
}
+void CallableCustomBind::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
+ Vector<Variant> sub_args;
+ int sub_count;
+ callable.get_bound_arguments_ref(sub_args, sub_count);
+
+ if (sub_count == 0) {
+ r_arguments = binds;
+ r_argcount = binds.size();
+ return;
+ }
+
+ int new_count = sub_count + binds.size();
+ r_argcount = new_count;
+
+ if (new_count <= 0) {
+ // Removed more arguments than it adds.
+ r_arguments = Vector<Variant>();
+ return;
+ }
+
+ r_arguments.resize(new_count);
+
+ if (sub_count > 0) {
+ for (int i = 0; i < sub_count; i++) {
+ r_arguments.write[i] = sub_args[i];
+ }
+ for (int i = 0; i < binds.size(); i++) {
+ r_arguments.write[i + sub_count] = binds[i];
+ }
+ r_argcount = new_count;
+ } else {
+ for (int i = 0; i < binds.size() + sub_count; i++) {
+ r_arguments.write[i] = binds[i - sub_count];
+ }
+ }
+}
+
void CallableCustomBind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
const Variant **args = (const Variant **)alloca(sizeof(const Variant **) * (binds.size() + p_argcount));
for (int i = 0; i < p_argcount; i++) {
@@ -172,6 +209,21 @@ int CallableCustomUnbind::get_bound_arguments_count() const {
return callable.get_bound_arguments_count() - argcount;
}
+void CallableCustomUnbind::get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const {
+ Vector<Variant> sub_args;
+ int sub_count;
+ callable.get_bound_arguments_ref(sub_args, sub_count);
+
+ r_argcount = sub_args.size() - argcount;
+
+ if (argcount >= sub_args.size()) {
+ r_arguments = Vector<Variant>();
+ } else {
+ sub_args.resize(sub_args.size() - argcount);
+ r_arguments = sub_args;
+ }
+}
+
void CallableCustomUnbind::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
if (argcount > p_argcount) {
r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h
index a79a521b5b..278ed335d0 100644
--- a/core/variant/callable_bind.h
+++ b/core/variant/callable_bind.h
@@ -52,6 +52,7 @@ public:
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override;
virtual int get_bound_arguments_count() const override;
+ virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
Callable get_callable() { return callable; }
Vector<Variant> get_binds() { return binds; }
@@ -77,6 +78,7 @@ public:
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override;
virtual int get_bound_arguments_count() const override;
+ virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const override;
Callable get_callable() { return callable; }
int get_unbinds() { return argcount; }
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index bff6656a88..ca42738b05 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -3654,7 +3654,22 @@ String Variant::get_call_error_text(Object *p_base, const StringName &p_method,
}
String Variant::get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) {
- return get_call_error_text(p_callable.get_object(), p_callable.get_method(), p_argptrs, p_argcount, ce);
+ Vector<Variant> binds;
+ int args_bound;
+ p_callable.get_bound_arguments_ref(binds, args_bound);
+ if (args_bound <= 0) {
+ return get_call_error_text(p_callable.get_object(), p_callable.get_method(), p_argptrs, MAX(0, p_argcount + args_bound), ce);
+ } else {
+ Vector<const Variant *> argptrs;
+ argptrs.resize(p_argcount + binds.size());
+ for (int i = 0; i < p_argcount; i++) {
+ argptrs.write[i] = p_argptrs[i];
+ }
+ for (int i = 0; i < binds.size(); i++) {
+ argptrs.write[i + p_argcount] = &binds[i];
+ }
+ return get_call_error_text(p_callable.get_object(), p_callable.get_method(), (const Variant **)argptrs.ptr(), argptrs.size(), ce);
+ }
}
void Variant::register_types() {
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 6c06b63dab..05fb62ff12 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -2017,6 +2017,7 @@ static void _register_variant_builtin_methods() {
bind_method(Callable, get_object_id, sarray(), varray());
bind_method(Callable, get_method, sarray(), varray());
bind_method(Callable, get_bound_arguments_count, sarray(), varray());
+ bind_method(Callable, get_bound_arguments, sarray(), varray());
bind_method(Callable, hash, sarray(), varray());
bind_method(Callable, bindv, sarray("arguments"), varray());
bind_method(Callable, unbind, sarray("argcount"), varray());
diff --git a/doc/classes/Callable.xml b/doc/classes/Callable.xml
index a6fffae8b5..d1fdaef29c 100644
--- a/doc/classes/Callable.xml
+++ b/doc/classes/Callable.xml
@@ -107,6 +107,12 @@
Calls the method represented by this [Callable]. Unlike [method call], this method expects all arguments to be contained inside the [param arguments] [Array].
</description>
</method>
+ <method name="get_bound_arguments" qualifiers="const">
+ <return type="Array" />
+ <description>
+ Return the bound arguments (as long as [method get_bound_arguments_count] is greater than zero), or empty (if [method get_bound_arguments_count] is less than or equal to zero).
+ </description>
+ </method>
<method name="get_bound_arguments_count" qualifiers="const">
<return type="int" />
<description>
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index b9f3275dfe..08964cf21d 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -780,67 +780,13 @@
</method>
<method name="set_drag_forwarding">
<return type="void" />
- <param index="0" name="target" type="Object" />
+ <param index="0" name="drag_func" type="Callable" />
+ <param index="1" name="can_drop_func" type="Callable" />
+ <param index="2" name="drop_func" type="Callable" />
<description>
- Forwards the handling of this control's drag and drop to [param target] object.
- Forwarding can be implemented in the target object similar to the methods [method _get_drag_data], [method _can_drop_data], and [method _drop_data] but with two differences:
- 1. The function name must be suffixed with [b]_fw[/b]
- 2. The function must take an extra argument that is the control doing the forwarding
- [codeblocks]
- [gdscript]
- # ThisControl.gd
- extends Control
- export(Control) var target_control
-
- func _ready():
- set_drag_forwarding(target_control)
-
- # TargetControl.gd
- extends Control
-
- func _can_drop_data_fw(position, data, from_control):
- return true
-
- func _drop_data_fw(position, data, from_control):
- my_handle_data(data) # Your handler method.
-
- func _get_drag_data_fw(position, from_control):
- set_drag_preview(my_preview)
- return my_data()
- [/gdscript]
- [csharp]
- // ThisControl.cs
- public class ThisControl : Control
- {
- [Export]
- public Control TargetControl { get; set; }
- public override void _Ready()
- {
- SetDragForwarding(TargetControl);
- }
- }
-
- // TargetControl.cs
- public class TargetControl : Control
- {
- public void CanDropDataFw(Vector2 position, object data, Control fromControl)
- {
- return true;
- }
-
- public void DropDataFw(Vector2 position, object data, Control fromControl)
- {
- MyHandleData(data); // Your handler method.
- }
-
- public void GetDragDataFw(Vector2 position, Control fromControl)
- {
- SetDragPreview(MyPreview);
- return MyData();
- }
- }
- [/csharp]
- [/codeblocks]
+ Forwards the handling of this control's [method _get_drag_data], [method _can_drop_data] and [method _drop_data] virtual functions to delegate callables.
+ For each argument, if not empty, the delegate callable is used, otherwise the local (virtual) function is used.
+ The function format for each callable should be exactly the same as the virtual functions described above.
</description>
</method>
<method name="set_drag_preview">
diff --git a/doc/classes/PhysicsDirectBodyState2D.xml b/doc/classes/PhysicsDirectBodyState2D.xml
index eca6a1cbc7..a46de4c189 100644
--- a/doc/classes/PhysicsDirectBodyState2D.xml
+++ b/doc/classes/PhysicsDirectBodyState2D.xml
@@ -151,6 +151,13 @@
[b]Note:[/b] By default, this returns 0 unless bodies are configured to monitor contacts. See [member RigidBody2D.contact_monitor].
</description>
</method>
+ <method name="get_contact_impulse" qualifiers="const">
+ <return type="Vector2" />
+ <param index="0" name="contact_idx" type="int" />
+ <description>
+ Returns the impulse created by the contact.
+ </description>
+ </method>
<method name="get_contact_local_normal" qualifiers="const">
<return type="Vector2" />
<param index="0" name="contact_idx" type="int" />
diff --git a/doc/classes/PhysicsDirectBodyState2DExtension.xml b/doc/classes/PhysicsDirectBodyState2DExtension.xml
index 8fd34c1243..496cbf9136 100644
--- a/doc/classes/PhysicsDirectBodyState2DExtension.xml
+++ b/doc/classes/PhysicsDirectBodyState2DExtension.xml
@@ -130,6 +130,12 @@
<description>
</description>
</method>
+ <method name="_get_contact_impulse" qualifiers="virtual const">
+ <return type="Vector2" />
+ <param index="0" name="contact_idx" type="int" />
+ <description>
+ </description>
+ </method>
<method name="_get_contact_local_normal" qualifiers="virtual const">
<return type="Vector2" />
<param index="0" name="contact_idx" type="int" />
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 8e55f3a1c3..712b11d7d7 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -578,7 +578,7 @@ ActionMapEditor::ActionMapEditor() {
action_tree->connect("button_clicked", callable_mp(this, &ActionMapEditor::_tree_button_pressed));
main_vbox->add_child(action_tree);
- action_tree->set_drag_forwarding(this);
+ action_tree->set_drag_forwarding_compat(this);
// Adding event dialog
event_config_dialog = memnew(InputEventConfigurationDialog);
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 76d70b09e6..6e701cb6bd 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -754,7 +754,7 @@ CreateDialog::CreateDialog() {
favorites->connect("cell_selected", callable_mp(this, &CreateDialog::_favorite_selected));
favorites->connect("item_activated", callable_mp(this, &CreateDialog::_favorite_activated));
favorites->add_theme_constant_override("draw_guides", 1);
- favorites->set_drag_forwarding(this);
+ favorites->set_drag_forwarding_compat(this);
fav_vb->add_margin_child(TTR("Favorites:"), favorites, true);
VBoxContainer *rec_vb = memnew(VBoxContainer);
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 5296749c18..7ef99d56ab 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -903,7 +903,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
effects->connect("item_edited", callable_mp(this, &EditorAudioBus::_effect_edited));
effects->connect("cell_selected", callable_mp(this, &EditorAudioBus::_effect_selected));
effects->set_edit_checkbox_cell_only_when_checkbox_is_pressed(true);
- effects->set_drag_forwarding(this);
+ effects->set_drag_forwarding_compat(this);
effects->connect("item_mouse_selected", callable_mp(this, &EditorAudioBus::_effect_rmb));
effects->set_allow_rmb_select(true);
effects->set_focus_mode(FOCUS_CLICK);
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index db251c857c..4001b849ff 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -935,7 +935,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
tree->set_select_mode(Tree::SELECT_MULTI);
tree->set_allow_reselect(true);
- tree->set_drag_forwarding(this);
+ tree->set_drag_forwarding_compat(this);
tree->set_columns(4);
tree->set_column_titles_visible(true);
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 54d43bbf44..12aa44891d 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -2065,7 +2065,7 @@ void EditorInspectorArray::_setup() {
ae.panel = memnew(PanelContainer);
ae.panel->set_focus_mode(FOCUS_ALL);
ae.panel->set_mouse_filter(MOUSE_FILTER_PASS);
- ae.panel->set_drag_forwarding(this);
+ ae.panel->set_drag_forwarding_compat(this);
ae.panel->set_meta("index", begin_array_index + i);
ae.panel->set_tooltip_text(vformat(TTR("Element %d: %s%d*"), i, array_element_prefix, i));
ae.panel->connect("focus_entered", callable_mp((CanvasItem *)ae.panel, &PanelContainer::queue_redraw));
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 7aa050227d..8ef394a59f 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -569,7 +569,7 @@ EditorPropertyPath::EditorPropertyPath() {
HBoxContainer *path_hb = memnew(HBoxContainer);
add_child(path_hb);
path = memnew(LineEdit);
- path->set_drag_forwarding(this);
+ path->set_drag_forwarding_compat(this);
path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
path_hb->add_child(path);
path->connect("text_submitted", callable_mp(this, &EditorPropertyPath::_path_selected));
@@ -3686,7 +3686,7 @@ EditorPropertyNodePath::EditorPropertyNodePath() {
assign->set_h_size_flags(SIZE_EXPAND_FILL);
assign->set_clip_text(true);
assign->connect("pressed", callable_mp(this, &EditorPropertyNodePath::_node_assign));
- assign->set_drag_forwarding(this);
+ assign->set_drag_forwarding_compat(this);
hbc->add_child(assign);
clear = memnew(Button);
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 10f46283e6..ed667aa7c8 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -715,7 +715,7 @@ EditorPropertyArray::EditorPropertyArray() {
edit->set_clip_text(true);
edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_edit_pressed));
edit->set_toggle_mode(true);
- edit->set_drag_forwarding(this);
+ edit->set_drag_forwarding_compat(this);
edit->connect("draw", callable_mp(this, &EditorPropertyArray::_button_draw));
add_child(edit);
add_focusable(edit);
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 94152dfd49..6b733e11f7 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -950,7 +950,7 @@ EditorResourcePicker::EditorResourcePicker(bool p_hide_assign_button_controls) {
assign_button->set_flat(true);
assign_button->set_h_size_flags(SIZE_EXPAND_FILL);
assign_button->set_clip_text(true);
- assign_button->set_drag_forwarding(this);
+ assign_button->set_drag_forwarding_compat(this);
add_child(assign_button);
assign_button->connect("pressed", callable_mp(this, &EditorResourcePicker::_resource_selected));
assign_button->connect("draw", callable_mp(this, &EditorResourcePicker::_button_draw));
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index 5985af21cd..2881302775 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -793,7 +793,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
shortcuts->connect("item_activated", callable_mp(this, &EditorSettingsDialog::_shortcut_cell_double_clicked));
tab_shortcuts->add_child(shortcuts);
- shortcuts->set_drag_forwarding(this);
+ shortcuts->set_drag_forwarding_compat(this);
// Adding event dialog
shortcut_editor = memnew(InputEventConfigurationDialog);
diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp
index 3e06633cc8..df5d2dcd29 100644
--- a/editor/export/project_export.cpp
+++ b/editor/export/project_export.cpp
@@ -1023,7 +1023,7 @@ ProjectExportDialog::ProjectExportDialog() {
mc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
presets = memnew(ItemList);
// TODO: Must reimplement drag forwarding.
- //presets->set_drag_forwarding(this);
+ //presets->set_drag_forwarding_compat(this);
mc->add_child(presets);
presets->connect("item_selected", callable_mp(this, &ProjectExportDialog::_edit_preset));
duplicate_preset = memnew(Button);
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index e66be6ce49..8306723f5c 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -3116,7 +3116,7 @@ FileSystemDock::FileSystemDock() {
tree = memnew(Tree);
tree->set_hide_root(true);
- tree->set_drag_forwarding(this);
+ tree->set_drag_forwarding_compat(this);
tree->set_allow_rmb_select(true);
tree->set_select_mode(Tree::SELECT_MULTI);
tree->set_custom_minimum_size(Size2(0, 15 * EDSCALE));
@@ -3153,7 +3153,7 @@ FileSystemDock::FileSystemDock() {
files = memnew(ItemList);
files->set_v_size_flags(SIZE_EXPAND_FILL);
files->set_select_mode(ItemList::SELECT_MULTI);
- files->set_drag_forwarding(this);
+ files->set_drag_forwarding_compat(this);
files->connect("item_clicked", callable_mp(this, &FileSystemDock::_file_list_item_clicked));
files->connect("gui_input", callable_mp(this, &FileSystemDock::_file_list_gui_input));
files->connect("multi_selected", callable_mp(this, &FileSystemDock::_file_multi_selected));
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 942b6b51cf..4fe1a6c034 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -4921,7 +4921,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p
c->add_child(viewport);
surface = memnew(Control);
- surface->set_drag_forwarding(this);
+ surface->set_drag_forwarding_compat(this);
add_child(surface);
surface->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
surface->set_clip_contents(true);
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index 27cad1cb7e..2a5529e229 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -379,7 +379,7 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() {
tree->set_column_expand(1, true);
tree->set_v_size_flags(SIZE_EXPAND_FILL);
- tree->set_drag_forwarding(this);
+ tree->set_drag_forwarding_compat(this);
vbc->add_child(tree);
dialog = memnew(AcceptDialog);
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index a23874ea05..caa42b677c 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -3669,7 +3669,7 @@ ScriptEditor::ScriptEditor() {
_sort_list_on_update = true;
script_list->connect("item_clicked", callable_mp(this, &ScriptEditor::_script_list_clicked), CONNECT_DEFERRED);
script_list->set_allow_rmb_select(true);
- script_list->set_drag_forwarding(this);
+ script_list->set_drag_forwarding_compat(this);
context_menu = memnew(PopupMenu);
add_child(context_menu);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 9406701ade..4d525cc5a9 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -2167,7 +2167,7 @@ ScriptTextEditor::ScriptTextEditor() {
connection_info_dialog = memnew(ConnectionInfoDialog);
- code_editor->get_text_editor()->set_drag_forwarding(this);
+ code_editor->get_text_editor()->set_drag_forwarding_compat(this);
}
ScriptTextEditor::~ScriptTextEditor() {
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index da6a1ea0af..a822584619 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -451,7 +451,7 @@ ShaderEditorPlugin::ShaderEditorPlugin() {
vb->add_child(shader_list);
shader_list->connect("item_selected", callable_mp(this, &ShaderEditorPlugin::_shader_selected));
shader_list->connect("item_clicked", callable_mp(this, &ShaderEditorPlugin::_shader_list_clicked));
- shader_list->set_drag_forwarding(this);
+ shader_list->set_drag_forwarding_compat(this);
main_split->add_child(vb);
vb->set_custom_minimum_size(Size2(200, 300) * EDSCALE);
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index 0c8fc08795..956150ec69 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -813,7 +813,7 @@ void Skeleton3DEditor::create_editors() {
joint_tree->set_v_size_flags(SIZE_EXPAND_FILL);
joint_tree->set_h_size_flags(SIZE_EXPAND_FILL);
joint_tree->set_allow_rmb_select(true);
- joint_tree->set_drag_forwarding(this);
+ joint_tree->set_drag_forwarding_compat(this);
s_con->add_child(joint_tree);
pose_editor = memnew(BoneTransformEditor(skeleton));
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 66892372cf..7603a5e55d 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -1408,7 +1408,7 @@ SpriteFramesEditor::SpriteFramesEditor() {
frame_list->set_max_columns(0);
frame_list->set_icon_mode(ItemList::ICON_MODE_TOP);
frame_list->set_max_text_lines(2);
- frame_list->set_drag_forwarding(this);
+ frame_list->set_drag_forwarding_compat(this);
frame_list->connect("gui_input", callable_mp(this, &SpriteFramesEditor::_frame_list_gui_input));
frame_list->connect("item_selected", callable_mp(this, &SpriteFramesEditor::_frame_list_item_selected));
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index f3f0542b9b..ad5881c76f 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -650,7 +650,7 @@ TextEditor::TextEditor() {
goto_line_dialog = memnew(GotoLineDialog);
add_child(goto_line_dialog);
- code_editor->get_text_editor()->set_drag_forwarding(this);
+ code_editor->get_text_editor()->set_drag_forwarding_compat(this);
}
TextEditor::~TextEditor() {
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index e7dc5d825b..dd4daa45b7 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -2236,7 +2236,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
scene_tiles_list = memnew(ItemList);
scene_tiles_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
scene_tiles_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- scene_tiles_list->set_drag_forwarding(this);
+ scene_tiles_list->set_drag_forwarding_compat(this);
scene_tiles_list->set_select_mode(ItemList::SELECT_MULTI);
scene_tiles_list->connect("multi_selected", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_multi_selected));
scene_tiles_list->connect("empty_clicked", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_lmb_empty_clicked));
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index d269a7c0ec..b44cb18dc7 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -728,7 +728,7 @@ TileSetEditor::TileSetEditor() {
sources_list->add_user_signal(MethodInfo("sort_request"));
sources_list->connect("sort_request", callable_mp(this, &TileSetEditor::_update_sources_list).bind(-1));
sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
- sources_list->set_drag_forwarding(this);
+ sources_list->set_drag_forwarding_compat(this);
split_container_left_side->add_child(sources_list);
HBoxContainer *sources_bottom_actions = memnew(HBoxContainer);
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
index 5af338caa0..0ff8788626 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
@@ -509,7 +509,7 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() {
scene_tiles_list = memnew(ItemList);
scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL);
scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL);
- scene_tiles_list->set_drag_forwarding(this);
+ scene_tiles_list->set_drag_forwarding_compat(this);
scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_tile_inspector).unbind(1));
scene_tiles_list->connect("item_selected", callable_mp(this, &TileSetScenesCollectionSourceEditor::_update_action_buttons).unbind(1));
scene_tiles_list->connect("item_activated", callable_mp(this, &TileSetScenesCollectionSourceEditor::_scenes_list_item_activated));
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 4cf397ffd0..46ec3bcdd1 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -4915,7 +4915,7 @@ VisualShaderEditor::VisualShaderEditor() {
graph->set_h_size_flags(SIZE_EXPAND_FILL);
graph->set_show_zoom_label(true);
add_child(graph);
- graph->set_drag_forwarding(this);
+ graph->set_drag_forwarding_compat(this);
float graph_minimap_opacity = EDITOR_GET("editors/visual_editors/minimap_opacity");
graph->set_minimap_opacity(graph_minimap_opacity);
float graph_lines_curvature = EDITOR_GET("editors/visual_editors/lines_curvature");
@@ -5146,7 +5146,7 @@ VisualShaderEditor::VisualShaderEditor() {
members = memnew(Tree);
members_vb->add_child(members);
- members->set_drag_forwarding(this);
+ members->set_drag_forwarding_compat(this);
members->set_h_size_flags(SIZE_EXPAND_FILL);
members->set_v_size_flags(SIZE_EXPAND_FILL);
members->set_hide_root(true);
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index dad584ea92..2f50172f54 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -1415,7 +1415,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
add_child(tree);
- tree->set_drag_forwarding(this);
+ tree->set_drag_forwarding_compat(this);
if (p_can_rename) {
tree->set_allow_rmb_select(true);
tree->connect("item_mouse_selected", callable_mp(this, &SceneTreeEditor::_rmb_select));
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index e54e5e4c48..7bde4e7c4b 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -2110,14 +2110,14 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
bool compatible = true;
GDScriptParser::DataType op_type = assigned_value_type;
- if (p_assignment->operation != GDScriptParser::AssignmentNode::OP_NONE) {
+ if (p_assignment->operation != GDScriptParser::AssignmentNode::OP_NONE && !op_type.is_variant()) {
op_type = get_operation_type(p_assignment->variant_op, assignee_type, assigned_value_type, compatible, p_assignment->assigned_value);
}
p_assignment->set_datatype(op_type);
// If Assignee is a variant, then you can assign anything
// When the assigned value has a known type, further checks are possible.
- if (assignee_type.is_hard_type() && !assignee_type.is_variant() && op_type.is_hard_type()) {
+ if (assignee_type.is_hard_type() && !assignee_type.is_variant() && op_type.is_hard_type() && !op_type.is_variant()) {
if (compatible) {
compatible = is_type_compatible(assignee_type, op_type, true, p_assignment->assigned_value);
if (!compatible) {
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.gd b/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.gd
index 98f1f3ec2d..81d5d59ae8 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.gd
+++ b/modules/gdscript/tests/scripts/analyzer/errors/enum_preload_unnamed_assign_to_named.gd
@@ -1,4 +1,5 @@
enum MyEnum { VALUE_A, VALUE_B, VALUE_C = 42 }
+
func test():
const P = preload("../features/enum_value_from_parent.gd")
var local_var: MyEnum
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd
index 65c0d9dabc..200c352223 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd
+++ b/modules/gdscript/tests/scripts/analyzer/errors/outer_class_lookup.gd
@@ -1,12 +1,12 @@
class A:
- class B:
- func test():
- print(A.B.D)
+ class B:
+ func test():
+ print(A.B.D)
class C:
- class D:
- pass
+ class D:
+ pass
func test():
- var inst = A.B.new()
- inst.test()
+ var inst = A.B.new()
+ inst.test()
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.gd b/modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.gd
index 63587942f7..393b66c9f0 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.gd
+++ b/modules/gdscript/tests/scripts/analyzer/errors/return_null_in_void_func.gd
@@ -1,2 +1,2 @@
func test() -> void:
- return null
+ return null
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.gd b/modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.gd
index 0ee4e7ea36..6be2730bab 100644
--- a/modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.gd
+++ b/modules/gdscript/tests/scripts/analyzer/errors/return_variant_in_void_func.gd
@@ -1,4 +1,4 @@
func test() -> void:
- var a
- a = 1
- return a
+ var a
+ a = 1
+ return a
diff --git a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd
index 7881a0feb6..a94487d989 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/base_outer_resolution.gd
@@ -11,4 +11,3 @@ func test() -> void:
Extend.InnerClass.InnerInnerClass.test_a_b_c(A.new(), B.new(), C.new())
Extend.InnerClass.InnerInnerClass.test_enum(C.TestEnum.HELLO_WORLD)
Extend.InnerClass.InnerInnerClass.test_a_prime(A.APrime.new())
-
diff --git a/modules/gdscript/tests/scripts/analyzer/features/class_from_parent.gd b/modules/gdscript/tests/scripts/analyzer/features/class_from_parent.gd
index 30e7deb05a..7c846c59bd 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/class_from_parent.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/class_from_parent.gd
@@ -1,19 +1,19 @@
class A:
- var x = 3
+ var x = 3
class B:
- var x = 4
+ var x = 4
class C:
- var x = 5
+ var x = 5
class Test:
- var a = A.new()
- var b: B = B.new()
- var c := C.new()
+ var a = A.new()
+ var b: B = B.new()
+ var c := C.new()
func test():
- var test_instance := Test.new()
- prints(test_instance.a.x)
- prints(test_instance.b.x)
- prints(test_instance.c.x)
+ var test_instance := Test.new()
+ prints(test_instance.a.x)
+ prints(test_instance.b.x)
+ prints(test_instance.c.x)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd
index 757744b6f1..0c740935b9 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant.gd
@@ -2,5 +2,5 @@ const External = preload("external_enum_as_constant_external.notest.gd")
const MyEnum = External.MyEnum
func test():
- print(MyEnum.WAITING == 0)
- print(MyEnum.GODOT == 1)
+ print(MyEnum.WAITING == 0)
+ print(MyEnum.GODOT == 1)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd
index 7c090844d0..24c1e41aab 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/external_enum_as_constant_external.notest.gd
@@ -1,4 +1,4 @@
enum MyEnum {
- WAITING,
- GODOT
+ WAITING,
+ GODOT
}
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lookup_class.gd b/modules/gdscript/tests/scripts/analyzer/features/lookup_class.gd
index 4a2ab7bcba..541da78332 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/lookup_class.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/lookup_class.gd
@@ -1,50 +1,50 @@
# Inner-outer class lookup
class A:
- const Q: = "right one"
+ const Q: = "right one"
class X:
- const Q: = "wrong one"
+ const Q: = "wrong one"
class Y extends X:
- class B extends A:
- static func check() -> void:
- print(Q)
+ class B extends A:
+ static func check() -> void:
+ print(Q)
# External class lookup
const External: = preload("lookup_class_external.notest.gd")
class Internal extends External.A:
- static func check() -> void:
- print(TARGET)
+ static func check() -> void:
+ print(TARGET)
- class E extends External.E:
- static func check() -> void:
- print(TARGET)
- print(WAITING)
+ class E extends External.E:
+ static func check() -> void:
+ print(TARGET)
+ print(WAITING)
# Variable lookup
class C:
- var Q := 'right one'
+ var Q := 'right one'
class D:
- const Q := 'wrong one'
+ const Q := 'wrong one'
class E extends D:
- class F extends C:
- func check() -> void:
- print(Q)
+ class F extends C:
+ func check() -> void:
+ print(Q)
# Test
func test() -> void:
- # Inner-outer class lookup
- Y.B.check()
- print("---")
-
- # External class lookup
- Internal.check()
- Internal.E.check()
- print("---")
-
- # Variable lookup
- var f: = E.F.new()
- f.check()
+ # Inner-outer class lookup
+ Y.B.check()
+ print("---")
+
+ # External class lookup
+ Internal.check()
+ Internal.E.check()
+ print("---")
+
+ # Variable lookup
+ var f: = E.F.new()
+ f.check()
diff --git a/modules/gdscript/tests/scripts/analyzer/features/lookup_signal.gd b/modules/gdscript/tests/scripts/analyzer/features/lookup_signal.gd
index b19d5ee4f9..26cf6c7322 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/lookup_signal.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/lookup_signal.gd
@@ -1,41 +1,41 @@
signal hello
func get_signal() -> Signal:
- return hello
+ return hello
class A:
- signal hello
+ signal hello
- func get_signal() -> Signal:
- return hello
+ func get_signal() -> Signal:
+ return hello
- class B:
- signal hello
+ class B:
+ signal hello
- func get_signal() -> Signal:
- return hello
+ func get_signal() -> Signal:
+ return hello
class C extends A.B:
- func get_signal() -> Signal:
- return hello
+ func get_signal() -> Signal:
+ return hello
func test():
- var a: = A.new()
- var b: = A.B.new()
- var c: = C.new()
-
- var hello_a_result: = hello == a.get_signal()
- var hello_b_result: = hello == b.get_signal()
- var hello_c_result: = hello == c.get_signal()
- var a_b_result: = a.get_signal() == b.get_signal()
- var a_c_result: = a.get_signal() == c.get_signal()
- var b_c_result: = b.get_signal() == c.get_signal()
- var c_c_result: = c.get_signal() == c.get_signal()
-
- print("hello == A.hello? %s" % hello_a_result)
- print("hello == A.B.hello? %s" % hello_b_result)
- print("hello == C.hello? %s" % hello_c_result)
- print("A.hello == A.B.hello? %s" % a_b_result)
- print("A.hello == C.hello? %s" % a_c_result)
- print("A.B.hello == C.hello? %s" % b_c_result)
- print("C.hello == C.hello? %s" % c_c_result)
+ var a: = A.new()
+ var b: = A.B.new()
+ var c: = C.new()
+
+ var hello_a_result: = hello == a.get_signal()
+ var hello_b_result: = hello == b.get_signal()
+ var hello_c_result: = hello == c.get_signal()
+ var a_b_result: = a.get_signal() == b.get_signal()
+ var a_c_result: = a.get_signal() == c.get_signal()
+ var b_c_result: = b.get_signal() == c.get_signal()
+ var c_c_result: = c.get_signal() == c.get_signal()
+
+ print("hello == A.hello? %s" % hello_a_result)
+ print("hello == A.B.hello? %s" % hello_b_result)
+ print("hello == C.hello? %s" % hello_c_result)
+ print("A.hello == A.B.hello? %s" % a_b_result)
+ print("A.hello == C.hello? %s" % a_c_result)
+ print("A.B.hello == C.hello? %s" % b_c_result)
+ print("C.hello == C.hello? %s" % c_c_result)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.gd b/modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.gd
index c9caef7d7c..95f04421d1 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/return_variant_typed.gd
@@ -1,5 +1,5 @@
func variant() -> Variant:
- return 'variant'
+ return 'variant'
func test():
- print(variant())
+ print(variant())
diff --git a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd
index ada6030132..179e454073 100644
--- a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd
+++ b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd
@@ -3,4 +3,4 @@
class_name HelloWorld
func test():
- pass
+ pass
diff --git a/modules/gdscript/tests/scripts/parser/errors/double_dictionary_comma.gd b/modules/gdscript/tests/scripts/parser/errors/double_dictionary_comma.gd
index 92dfb2366d..816783f239 100644
--- a/modules/gdscript/tests/scripts/parser/errors/double_dictionary_comma.gd
+++ b/modules/gdscript/tests/scripts/parser/errors/double_dictionary_comma.gd
@@ -1,2 +1,2 @@
func test():
- var dictionary = { hello = "world",, }
+ var dictionary = { hello = "world",, }
diff --git a/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd
index 4608c778aa..7a745bd995 100644
--- a/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd
+++ b/modules/gdscript/tests/scripts/parser/errors/match_multiple_variable_binds_in_branch.gd
@@ -1,4 +1,4 @@
func test():
- match 1:
- [[[var a]]], 2:
- pass
+ match 1:
+ [[[var a]]], 2:
+ pass
diff --git a/modules/gdscript/tests/scripts/parser/features/advanced_expression_matching.gd b/modules/gdscript/tests/scripts/parser/features/advanced_expression_matching.gd
index 43b513045b..a7197bf68f 100644
--- a/modules/gdscript/tests/scripts/parser/features/advanced_expression_matching.gd
+++ b/modules/gdscript/tests/scripts/parser/features/advanced_expression_matching.gd
@@ -1,34 +1,34 @@
func foo(x):
- match x:
- 1 + 1:
- print("1+1")
- [1,2,[1,{1:2,2:var z,..}]]:
- print("[1,2,[1,{1:2,2:var z,..}]]")
- print(z)
- 1 if true else 2:
- print("1 if true else 2")
- 1 < 2:
- print("1 < 2")
- 1 or 2 and 1:
- print("1 or 2 and 1")
- 6 | 1:
- print("1 | 1")
- 1 >> 1:
- print("1 >> 1")
- 1, 2 or 3, 4:
- print("1, 2 or 3, 4")
- _:
- print("wildcard")
+ match x:
+ 1 + 1:
+ print("1+1")
+ [1,2,[1,{1:2,2:var z,..}]]:
+ print("[1,2,[1,{1:2,2:var z,..}]]")
+ print(z)
+ 1 if true else 2:
+ print("1 if true else 2")
+ 1 < 2:
+ print("1 < 2")
+ 1 or 2 and 1:
+ print("1 or 2 and 1")
+ 6 | 1:
+ print("1 | 1")
+ 1 >> 1:
+ print("1 >> 1")
+ 1, 2 or 3, 4:
+ print("1, 2 or 3, 4")
+ _:
+ print("wildcard")
func test():
- foo(6 | 1)
- foo(1 >> 1)
- foo(2)
- foo(1)
- foo(1+1)
- foo(1 < 2)
- foo([2, 1])
- foo(4)
- foo([1, 2, [1, {1 : 2, 2:3}]])
- foo([1, 2, [1, {1 : 2, 2:[1,3,5, "123"], 4:2}]])
- foo([1, 2, [1, {1 : 2}]])
+ foo(6 | 1)
+ foo(1 >> 1)
+ foo(2)
+ foo(1)
+ foo(1+1)
+ foo(1 < 2)
+ foo([2, 1])
+ foo(4)
+ foo([1, 2, [1, {1 : 2, 2:3}]])
+ foo([1, 2, [1, {1 : 2, 2:[1,3,5, "123"], 4:2}]])
+ foo([1, 2, [1, {1 : 2}]])
diff --git a/modules/gdscript/tests/scripts/parser/features/basic_expression_matching.gd b/modules/gdscript/tests/scripts/parser/features/basic_expression_matching.gd
index 2b46f1e88a..c959c6c6af 100644
--- a/modules/gdscript/tests/scripts/parser/features/basic_expression_matching.gd
+++ b/modules/gdscript/tests/scripts/parser/features/basic_expression_matching.gd
@@ -1,27 +1,27 @@
func foo(x):
- match x:
- 1:
- print("1")
- 2:
- print("2")
- [1, 2]:
- print("[1, 2]")
- 3 or 4:
- print("3 or 4")
- 4:
- print("4")
- {1 : 2, 2 : 3}:
- print("{1 : 2, 2 : 3}")
- _:
- print("wildcard")
+ match x:
+ 1:
+ print("1")
+ 2:
+ print("2")
+ [1, 2]:
+ print("[1, 2]")
+ 3 or 4:
+ print("3 or 4")
+ 4:
+ print("4")
+ {1 : 2, 2 : 3}:
+ print("{1 : 2, 2 : 3}")
+ _:
+ print("wildcard")
func test():
- foo(0)
- foo(1)
- foo(2)
- foo([1, 2])
- foo(3)
- foo(4)
- foo([4,4])
- foo({1 : 2, 2 : 3})
- foo({1 : 2, 4 : 3})
+ foo(0)
+ foo(1)
+ foo(2)
+ foo([1, 2])
+ foo(3)
+ foo(4)
+ foo([4,4])
+ foo({1 : 2, 2 : 3})
+ foo({1 : 2, 4 : 3})
diff --git a/modules/gdscript/tests/scripts/parser/features/lambda_callable.gd b/modules/gdscript/tests/scripts/parser/features/lambda_callable.gd
index c3b2506156..17d00bce3c 100644
--- a/modules/gdscript/tests/scripts/parser/features/lambda_callable.gd
+++ b/modules/gdscript/tests/scripts/parser/features/lambda_callable.gd
@@ -1,4 +1,4 @@
func test():
- var my_lambda = func(x):
- print(x)
- my_lambda.call("hello")
+ var my_lambda = func(x):
+ print(x)
+ my_lambda.call("hello")
diff --git a/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd b/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd
index 377dd25e9e..75857fb8ff 100644
--- a/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd
+++ b/modules/gdscript/tests/scripts/parser/features/match_dictionary.gd
@@ -1,43 +1,43 @@
func foo(x):
- match x:
- {"key1": "value1", "key2": "value2"}:
- print('{"key1": "value1", "key2": "value2"}')
- {"key1": "value1", "key2"}:
- print('{"key1": "value1", "key2"}')
- {"key1", "key2": "value2"}:
- print('{"key1", "key2": "value2"}')
- {"key1", "key2"}:
- print('{"key1", "key2"}')
- {"key1": "value1"}:
- print('{"key1": "value1"}')
- {"key1"}:
- print('{"key1"}')
- _:
- print("wildcard")
+ match x:
+ {"key1": "value1", "key2": "value2"}:
+ print('{"key1": "value1", "key2": "value2"}')
+ {"key1": "value1", "key2"}:
+ print('{"key1": "value1", "key2"}')
+ {"key1", "key2": "value2"}:
+ print('{"key1", "key2": "value2"}')
+ {"key1", "key2"}:
+ print('{"key1", "key2"}')
+ {"key1": "value1"}:
+ print('{"key1": "value1"}')
+ {"key1"}:
+ print('{"key1"}')
+ _:
+ print("wildcard")
func bar(x):
- match x:
- {0}:
- print("0")
- {1}:
- print("1")
- {2}:
- print("2")
- _:
- print("wildcard")
+ match x:
+ {0}:
+ print("0")
+ {1}:
+ print("1")
+ {2}:
+ print("2")
+ _:
+ print("wildcard")
func test():
- foo({"key1": "value1", "key2": "value2"})
- foo({"key1": "value1", "key2": ""})
- foo({"key1": "", "key2": "value2"})
- foo({"key1": "", "key2": ""})
- foo({"key1": "value1"})
- foo({"key1": ""})
- foo({"key1": "value1", "key2": "value2", "key3": "value3"})
- foo({"key1": "value1", "key3": ""})
- foo({"key2": "value2"})
- foo({"key3": ""})
- bar({0: "0"})
- bar({1: "1"})
- bar({2: "2"})
- bar({3: "3"})
+ foo({"key1": "value1", "key2": "value2"})
+ foo({"key1": "value1", "key2": ""})
+ foo({"key1": "", "key2": "value2"})
+ foo({"key1": "", "key2": ""})
+ foo({"key1": "value1"})
+ foo({"key1": ""})
+ foo({"key1": "value1", "key2": "value2", "key3": "value3"})
+ foo({"key1": "value1", "key3": ""})
+ foo({"key2": "value2"})
+ foo({"key3": ""})
+ bar({0: "0"})
+ bar({1: "1"})
+ bar({2: "2"})
+ bar({3: "3"})
diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd
index dbe223f5f5..a278ea1154 100644
--- a/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd
+++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_patterns_with_array.gd
@@ -1,26 +1,26 @@
func foo(x):
- match x:
- 1, [2]:
- print('1, [2]')
- _:
- print('wildcard')
+ match x:
+ 1, [2]:
+ print('1, [2]')
+ _:
+ print('wildcard')
func bar(x):
- match x:
- [1], [2], [3]:
- print('[1], [2], [3]')
- [4]:
- print('[4]')
- _:
- print('wildcard')
+ match x:
+ [1], [2], [3]:
+ print('[1], [2], [3]')
+ [4]:
+ print('[4]')
+ _:
+ print('wildcard')
func test():
- foo(1)
- foo([2])
- foo(2)
- bar([1])
- bar([2])
- bar([3])
- bar([4])
- bar([5])
+ foo(1)
+ foo([2])
+ foo(2)
+ bar([1])
+ bar([2])
+ bar([3])
+ bar([4])
+ bar([5])
diff --git a/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd
index a0ae7fb17c..0a71f33c25 100644
--- a/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd
+++ b/modules/gdscript/tests/scripts/parser/features/match_multiple_variable_binds_in_pattern.gd
@@ -1,6 +1,6 @@
func test():
- match [1, 2, 3]:
- [var a, var b, var c]:
- print(a == 1)
- print(b == 2)
- print(c == 3)
+ match [1, 2, 3]:
+ [var a, var b, var c]:
+ print(a == 1)
+ print(b == 2)
+ print(c == 3)
diff --git a/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.gd b/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.gd
index 935fb773dc..7b350e81ad 100644
--- a/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.gd
+++ b/modules/gdscript/tests/scripts/runtime/errors/constant_dictionary_erase.gd
@@ -1,4 +1,4 @@
const dictionary := {}
func test():
- dictionary.erase(0)
+ dictionary.erase(0)
diff --git a/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd
index 9b64084fa6..bd38259cec 100644
--- a/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/array_string_stringname_equivalent.gd
@@ -9,7 +9,7 @@ func test():
array_sname.push_back(&"godot")
print("String in Array: ", "godot" in array_sname)
- # Not equal because the values are different types.
+ # Not equal because the values are different types.
print("Arrays not equal: ", array_str != array_sname)
var string_array: Array[String] = []
diff --git a/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd b/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd
index 1f15026f17..94bac1974f 100644
--- a/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/dictionary_string_stringname_equivalent.gd
@@ -13,5 +13,5 @@ func test():
print("String gets StringName: ", stringname_dict.get("abc"))
stringname_dict[&"abc"] = 42
- # They compare equal because StringName keys are converted to String.
+ # They compare equal because StringName keys are converted to String.
print("String Dictionary == StringName Dictionary: ", string_dict == stringname_dict)
diff --git a/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd b/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd
index f33ba7dffd..252e100bda 100644
--- a/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd
+++ b/modules/gdscript/tests/scripts/runtime/features/parameter_shadowing.gd
@@ -3,23 +3,23 @@
var a: int = 1
func shadow_regular_assignment(a: Variant, b: Variant) -> void:
- print(a)
- print(self.a)
- a = b
- print(a)
- print(self.a)
+ print(a)
+ print(self.a)
+ a = b
+ print(a)
+ print(self.a)
var v := Vector2(0.0, 0.0)
func shadow_subscript_assignment(v: Vector2, x: float) -> void:
- print(v)
- print(self.v)
- v.x += x
- print(v)
- print(self.v)
+ print(v)
+ print(self.v)
+ v.x += x
+ print(v)
+ print(self.v)
func test():
- shadow_regular_assignment('a', 'b')
- shadow_subscript_assignment(Vector2(1.0, 1.0), 5.0)
+ shadow_regular_assignment('a', 'b')
+ shadow_subscript_assignment(Vector2(1.0, 1.0), 5.0)
diff --git a/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.gd b/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.gd
new file mode 100644
index 0000000000..af3f3cb941
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.gd
@@ -0,0 +1,9 @@
+# https://github.com/godotengine/godot/issues/71172
+
+func test():
+ @warning_ignore(narrowing_conversion)
+ var foo: int = 0.0
+ print(typeof(foo) == TYPE_INT)
+ var dict : Dictionary = {"a":0.0}
+ foo = dict.get("a")
+ print(typeof(foo) == TYPE_INT)
diff --git a/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.out b/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.out
new file mode 100644
index 0000000000..9d111a8322
--- /dev/null
+++ b/modules/gdscript/tests/scripts/runtime/features/use_conversion_assign_with_variant_value.out
@@ -0,0 +1,3 @@
+GDTEST_OK
+true
+true
diff --git a/modules/multiplayer/editor/replication_editor.cpp b/modules/multiplayer/editor/replication_editor.cpp
index dbf1eecf0e..4ab41cfcb0 100644
--- a/modules/multiplayer/editor/replication_editor.cpp
+++ b/modules/multiplayer/editor/replication_editor.cpp
@@ -250,7 +250,7 @@ ReplicationEditor::ReplicationEditor() {
tree->add_child(drop_label);
drop_label->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
- tree->set_drag_forwarding(this);
+ tree->set_drag_forwarding_compat(this);
}
void ReplicationEditor::_bind_methods() {
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 944363bcb0..b5846cb692 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -642,7 +642,7 @@ inline int ColorPicker::_get_preset_size() {
void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
ColorPresetButton *btn_preset_new = memnew(ColorPresetButton(p_color, p_size));
btn_preset_new->set_tooltip_text(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1)));
- btn_preset_new->set_drag_forwarding(this);
+ btn_preset_new->set_drag_forwarding_compat(this);
btn_preset_new->set_button_group(preset_group);
preset_container->add_child(btn_preset_new);
btn_preset_new->set_pressed(true);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 8460728448..6e85ae5c0e 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -1813,33 +1813,53 @@ bool Control::is_focus_owner_in_shortcut_context() const {
// Drag and drop handling.
-void Control::set_drag_forwarding(Object *p_target) {
- if (p_target) {
- data.drag_owner = p_target->get_instance_id();
+void Control::set_drag_forwarding_compat(Object *p_base) {
+ if (p_base != nullptr) {
+ data.forward_drag = Callable(p_base, "_get_drag_data_fw").bind(this);
+ data.forward_can_drop = Callable(p_base, "_can_drop_data_fw").bind(this);
+ data.forward_drop = Callable(p_base, "_drop_data_fw").bind(this);
+
} else {
- data.drag_owner = ObjectID();
+ data.forward_drag = Callable();
+ data.forward_can_drop = Callable();
+ data.forward_drop = Callable();
}
}
+void Control::set_drag_forwarding(const Callable &p_drag, const Callable &p_can_drop, const Callable &p_drop) {
+ data.forward_drag = p_drag;
+ data.forward_can_drop = p_can_drop;
+ data.forward_drop = p_drop;
+}
+
Variant Control::get_drag_data(const Point2 &p_point) {
- if (data.drag_owner.is_valid()) {
- Object *obj = ObjectDB::get_instance(data.drag_owner);
- if (obj) {
- return obj->call("_get_drag_data_fw", p_point, this);
+ Variant ret;
+ if (data.forward_drag.is_valid()) {
+ Variant p = p_point;
+ const Variant *vp[1] = { &p };
+ Callable::CallError ce;
+ data.forward_drag.callp((const Variant **)vp, 1, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_FAIL_V_MSG(Variant(), "Error calling forwarded method from 'get_drag_data': " + Variant::get_callable_error_text(data.forward_drag, (const Variant **)vp, 1, ce) + ".");
}
+ return ret;
}
- Variant dd;
- GDVIRTUAL_CALL(_get_drag_data, p_point, dd);
- return dd;
+ GDVIRTUAL_CALL(_get_drag_data, p_point, ret);
+ return ret;
}
bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
- if (data.drag_owner.is_valid()) {
- Object *obj = ObjectDB::get_instance(data.drag_owner);
- if (obj) {
- return obj->call("_can_drop_data_fw", p_point, p_data, this);
+ if (data.forward_can_drop.is_valid()) {
+ Variant ret;
+ Variant p = p_point;
+ const Variant *vp[2] = { &p, &p_data };
+ Callable::CallError ce;
+ data.forward_can_drop.callp((const Variant **)vp, 2, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_FAIL_V_MSG(Variant(), "Error calling forwarded method from 'can_drop_data': " + Variant::get_callable_error_text(data.forward_can_drop, (const Variant **)vp, 2, ce) + ".");
}
+ return ret;
}
bool ret = false;
@@ -1848,12 +1868,16 @@ bool Control::can_drop_data(const Point2 &p_point, const Variant &p_data) const
}
void Control::drop_data(const Point2 &p_point, const Variant &p_data) {
- if (data.drag_owner.is_valid()) {
- Object *obj = ObjectDB::get_instance(data.drag_owner);
- if (obj) {
- obj->call("_drop_data_fw", p_point, p_data, this);
- return;
+ if (data.forward_drop.is_valid()) {
+ Variant ret;
+ Variant p = p_point;
+ const Variant *vp[2] = { &p, &p_data };
+ Callable::CallError ce;
+ data.forward_drop.callp((const Variant **)vp, 2, ret, ce);
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_FAIL_MSG("Error calling forwarded method from 'drop_data': " + Variant::get_callable_error_text(data.forward_drop, (const Variant **)vp, 2, ce) + ".");
}
+ return;
}
GDVIRTUAL_CALL(_drop_data, p_point, p_data);
@@ -3189,7 +3213,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("grab_click_focus"), &Control::grab_click_focus);
- ClassDB::bind_method(D_METHOD("set_drag_forwarding", "target"), &Control::set_drag_forwarding);
+ ClassDB::bind_method(D_METHOD("set_drag_forwarding", "drag_func", "can_drop_func", "drop_func"), &Control::set_drag_forwarding);
ClassDB::bind_method(D_METHOD("set_drag_preview", "control"), &Control::set_drag_preview);
ClassDB::bind_method(D_METHOD("is_drag_successful"), &Control::is_drag_successful);
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 9705dd62db..52efe42bd5 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -168,7 +168,9 @@ private:
Control *parent_control = nullptr;
Window *parent_window = nullptr;
CanvasItem *parent_canvas_item = nullptr;
- ObjectID drag_owner;
+ Callable forward_drag;
+ Callable forward_can_drop;
+ Callable forward_drop;
// Positioning and sizing.
@@ -499,7 +501,8 @@ public:
// Drag and drop handling.
- virtual void set_drag_forwarding(Object *p_target);
+ virtual void set_drag_forwarding(const Callable &p_drag, const Callable &p_can_drop, const Callable &p_drop);
+ virtual void set_drag_forwarding_compat(Object *p_base);
virtual Variant get_drag_data(const Point2 &p_point);
virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const;
virtual void drop_data(const Point2 &p_point, const Variant &p_data);
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index cd1ebba5d1..3457cfa94f 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -975,7 +975,7 @@ void TabContainer::_bind_methods() {
TabContainer::TabContainer() {
tab_bar = memnew(TabBar);
- tab_bar->set_drag_forwarding(this);
+ tab_bar->set_drag_forwarding_compat(this);
add_child(tab_bar, false, INTERNAL_MODE_FRONT);
tab_bar->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE);
tab_bar->connect("tab_changed", callable_mp(this, &TabContainer::_on_tab_changed));
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index e76abe57ba..3458b87b8d 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -4850,7 +4850,11 @@ void Tree::_do_incr_search(const String &p_add) {
return;
}
- item->select(col);
+ if (select_mode == SELECT_MULTI) {
+ item->set_as_cursor(col);
+ } else {
+ item->select(col);
+ }
ensure_cursor_is_visible();
}
diff --git a/servers/extensions/physics_server_2d_extension.cpp b/servers/extensions/physics_server_2d_extension.cpp
index a0c082ee44..a174ceadac 100644
--- a/servers/extensions/physics_server_2d_extension.cpp
+++ b/servers/extensions/physics_server_2d_extension.cpp
@@ -101,6 +101,7 @@ void PhysicsDirectBodyState2DExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_contact_collider_object, "contact_idx");
GDVIRTUAL_BIND(_get_contact_collider_shape, "contact_idx");
GDVIRTUAL_BIND(_get_contact_collider_velocity_at_position, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_impulse, "contact_idx");
GDVIRTUAL_BIND(_get_step);
GDVIRTUAL_BIND(_integrate_forces);
diff --git a/servers/extensions/physics_server_2d_extension.h b/servers/extensions/physics_server_2d_extension.h
index c4970f6398..0008653f66 100644
--- a/servers/extensions/physics_server_2d_extension.h
+++ b/servers/extensions/physics_server_2d_extension.h
@@ -100,6 +100,7 @@ public:
EXBIND1RC(Object *, get_contact_collider_object, int)
EXBIND1RC(int, get_contact_collider_shape, int)
EXBIND1RC(Vector2, get_contact_collider_velocity_at_position, int)
+ EXBIND1RC(Vector2, get_contact_impulse, int)
EXBIND0RC(real_t, get_step)
EXBIND0(integrate_forces)
diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h
index 34da64dac9..71dc826604 100644
--- a/servers/physics_2d/godot_body_2d.h
+++ b/servers/physics_2d/godot_body_2d.h
@@ -132,6 +132,7 @@ class GodotBody2D : public GodotCollisionObject2D {
ObjectID collider_instance_id;
RID collider;
Vector2 collider_velocity_at_pos;
+ Vector2 impulse;
};
Vector<Contact> contacts; //no contacts by default
@@ -190,7 +191,7 @@ public:
_FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }
_FORCE_INLINE_ bool can_report_contacts() const { return !contacts.is_empty(); }
- _FORCE_INLINE_ void add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_normal, real_t p_depth, int p_local_shape, const Vector2 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector2 &p_collider_velocity_at_pos);
+ _FORCE_INLINE_ void add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_normal, real_t p_depth, int p_local_shape, const Vector2 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector2 &p_collider_velocity_at_pos, const Vector2 &p_impulse);
_FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); }
_FORCE_INLINE_ void remove_exception(const RID &p_exception) { exceptions.erase(p_exception); }
@@ -340,7 +341,7 @@ public:
//add contact inline
-void GodotBody2D::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_normal, real_t p_depth, int p_local_shape, const Vector2 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector2 &p_collider_velocity_at_pos) {
+void GodotBody2D::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_normal, real_t p_depth, int p_local_shape, const Vector2 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector2 &p_collider_velocity_at_pos, const Vector2 &p_impulse) {
int c_max = contacts.size();
if (c_max == 0) {
@@ -380,6 +381,7 @@ void GodotBody2D::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local
c[idx].collider_instance_id = p_collider_instance_id;
c[idx].collider = p_collider;
c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos;
+ c[idx].impulse = p_impulse;
}
#endif // GODOT_BODY_2D_H
diff --git a/servers/physics_2d/godot_body_direct_state_2d.cpp b/servers/physics_2d/godot_body_direct_state_2d.cpp
index 35092b631a..2fa933ce17 100644
--- a/servers/physics_2d/godot_body_direct_state_2d.cpp
+++ b/servers/physics_2d/godot_body_direct_state_2d.cpp
@@ -210,6 +210,11 @@ Vector2 GodotPhysicsDirectBodyState2D::get_contact_collider_velocity_at_position
return body->contacts[p_contact_idx].collider_velocity_at_pos;
}
+Vector2 GodotPhysicsDirectBodyState2D::get_contact_impulse(int p_contact_idx) const {
+ ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
+ return body->contacts[p_contact_idx].impulse;
+}
+
PhysicsDirectSpaceState2D *GodotPhysicsDirectBodyState2D::get_space_state() {
return body->get_space()->get_direct_state();
}
diff --git a/servers/physics_2d/godot_body_direct_state_2d.h b/servers/physics_2d/godot_body_direct_state_2d.h
index c01ee62920..545d52ad23 100644
--- a/servers/physics_2d/godot_body_direct_state_2d.h
+++ b/servers/physics_2d/godot_body_direct_state_2d.h
@@ -92,8 +92,8 @@ public:
virtual Vector2 get_contact_collider_position(int p_contact_idx) const override;
virtual ObjectID get_contact_collider_id(int p_contact_idx) const override;
virtual int get_contact_collider_shape(int p_contact_idx) const override;
-
virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const override;
+ virtual Vector2 get_contact_impulse(int p_contact_idx) const override;
virtual PhysicsDirectSpaceState2D *get_space_state() override;
diff --git a/servers/physics_2d/godot_body_pair_2d.cpp b/servers/physics_2d/godot_body_pair_2d.cpp
index 474367def0..40dbb4fcf4 100644
--- a/servers/physics_2d/godot_body_pair_2d.cpp
+++ b/servers/physics_2d/godot_body_pair_2d.cpp
@@ -434,21 +434,6 @@ bool GodotBodyPair2D::pre_solve(real_t p_step) {
c.rA = global_A - A->get_center_of_mass();
c.rB = global_B - B->get_center_of_mass() - offset_B;
- if (A->can_report_contacts()) {
- Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x);
- A->add_contact(global_A + offset_A, -c.normal, depth, shape_A, global_B + offset_A, shape_B, B->get_instance_id(), B->get_self(), crB + B->get_linear_velocity());
- }
-
- if (B->can_report_contacts()) {
- Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x);
- B->add_contact(global_B + offset_A, c.normal, depth, shape_B, global_A + offset_A, shape_A, A->get_instance_id(), A->get_self(), crA + A->get_linear_velocity());
- }
-
- if (report_contacts_only) {
- collided = false;
- continue;
- }
-
// Precompute normal mass, tangent mass, and bias.
real_t rnA = c.rA.dot(c.normal);
real_t rnB = c.rB.dot(c.normal);
@@ -466,11 +451,28 @@ bool GodotBodyPair2D::pre_solve(real_t p_step) {
c.bias = -bias * inv_dt * MIN(0.0f, -depth + max_penetration);
c.depth = depth;
+ Vector2 P = c.acc_normal_impulse * c.normal + c.acc_tangent_impulse * tangent;
+
+ c.acc_impulse -= P;
+
+ if (A->can_report_contacts()) {
+ Vector2 crB(-B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x);
+ A->add_contact(global_A + offset_A, -c.normal, depth, shape_A, global_B + offset_A, shape_B, B->get_instance_id(), B->get_self(), crB + B->get_linear_velocity(), c.acc_impulse);
+ }
+
+ if (B->can_report_contacts()) {
+ Vector2 crA(-A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x);
+ B->add_contact(global_B + offset_A, c.normal, depth, shape_B, global_A + offset_A, shape_A, A->get_instance_id(), A->get_self(), crA + A->get_linear_velocity(), c.acc_impulse);
+ }
+
+ if (report_contacts_only) {
+ collided = false;
+ continue;
+ }
+
#ifdef ACCUMULATE_IMPULSES
{
// Apply normal + friction impulse
- Vector2 P = c.acc_normal_impulse * c.normal + c.acc_tangent_impulse * tangent;
-
if (collide_A) {
A->apply_impulse(-P, c.rA + A->get_center_of_mass());
}
@@ -581,6 +583,7 @@ void GodotBodyPair2D::solve(real_t p_step) {
if (collide_B) {
B->apply_impulse(j, c.rB + B->get_center_of_mass());
}
+ c.acc_impulse -= j;
}
}
diff --git a/servers/physics_2d/godot_body_pair_2d.h b/servers/physics_2d/godot_body_pair_2d.h
index 7e7a9839c1..4e9bfa6022 100644
--- a/servers/physics_2d/godot_body_pair_2d.h
+++ b/servers/physics_2d/godot_body_pair_2d.h
@@ -59,6 +59,7 @@ class GodotBodyPair2D : public GodotConstraint2D {
Vector2 position;
Vector2 normal;
Vector2 local_A, local_B;
+ Vector2 acc_impulse; // accumulated impulse
real_t acc_normal_impulse = 0.0; // accumulated normal impulse (Pn)
real_t acc_tangent_impulse = 0.0; // accumulated tangent impulse (Pt)
real_t acc_bias_impulse = 0.0; // accumulated normal impulse for position bias (Pnb)
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index 4973b9970a..214de27b35 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -126,6 +126,7 @@ void PhysicsDirectBodyState2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_contact_collider_object", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_object);
ClassDB::bind_method(D_METHOD("get_contact_collider_shape", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_shape);
ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_position", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_velocity_at_position);
+ ClassDB::bind_method(D_METHOD("get_contact_impulse", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_impulse);
ClassDB::bind_method(D_METHOD("get_step"), &PhysicsDirectBodyState2D::get_step);
ClassDB::bind_method(D_METHOD("integrate_forces"), &PhysicsDirectBodyState2D::integrate_forces);
ClassDB::bind_method(D_METHOD("get_space_state"), &PhysicsDirectBodyState2D::get_space_state);
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index aac4d9d69e..836ab5bd76 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -99,6 +99,7 @@ public:
virtual Object *get_contact_collider_object(int p_contact_idx) const;
virtual int get_contact_collider_shape(int p_contact_idx) const = 0;
virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const = 0;
+ virtual Vector2 get_contact_impulse(int p_contact_idx) const = 0;
virtual real_t get_step() const = 0;
virtual void integrate_forces();
diff --git a/servers/rendering/renderer_rd/effects/luminance.cpp b/servers/rendering/renderer_rd/effects/luminance.cpp
new file mode 100644
index 0000000000..7462282932
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/luminance.cpp
@@ -0,0 +1,255 @@
+/**************************************************************************/
+/* luminance.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "luminance.h"
+#include "../framebuffer_cache_rd.h"
+#include "../uniform_set_cache_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+
+using namespace RendererRD;
+
+Luminance::Luminance(bool p_prefer_raster_effects) {
+ prefer_raster_effects = p_prefer_raster_effects;
+
+ if (prefer_raster_effects) {
+ Vector<String> luminance_reduce_modes;
+ luminance_reduce_modes.push_back("\n#define FIRST_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FIRST
+ luminance_reduce_modes.push_back("\n"); // LUMINANCE_REDUCE_FRAGMENT
+ luminance_reduce_modes.push_back("\n#define FINAL_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FINAL
+
+ luminance_reduce_raster.shader.initialize(luminance_reduce_modes);
+ luminance_reduce_raster.shader_version = luminance_reduce_raster.shader.version_create();
+
+ for (int i = 0; i < LUMINANCE_REDUCE_FRAGMENT_MAX; i++) {
+ luminance_reduce_raster.pipelines[i].setup(luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+ } else {
+ // Initialize luminance_reduce
+ Vector<String> luminance_reduce_modes;
+ luminance_reduce_modes.push_back("\n#define READ_TEXTURE\n");
+ luminance_reduce_modes.push_back("\n");
+ luminance_reduce_modes.push_back("\n#define WRITE_LUMINANCE\n");
+
+ luminance_reduce.shader.initialize(luminance_reduce_modes);
+ luminance_reduce.shader_version = luminance_reduce.shader.version_create();
+
+ for (int i = 0; i < LUMINANCE_REDUCE_MAX; i++) {
+ luminance_reduce.pipelines[i] = RD::get_singleton()->compute_pipeline_create(luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, i));
+ }
+
+ for (int i = 0; i < LUMINANCE_REDUCE_FRAGMENT_MAX; i++) {
+ luminance_reduce_raster.pipelines[i].clear();
+ }
+ }
+}
+
+Luminance::~Luminance() {
+ if (prefer_raster_effects) {
+ luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
+ } else {
+ luminance_reduce.shader.version_free(luminance_reduce.shader_version);
+ }
+}
+
+void Luminance::LuminanceBuffers::set_prefer_raster_effects(bool p_prefer_raster_effects) {
+ prefer_raster_effects = p_prefer_raster_effects;
+}
+
+void Luminance::LuminanceBuffers::configure(RenderSceneBuffersRD *p_render_buffers) {
+ Size2i internal_size = p_render_buffers->get_internal_size();
+ int w = internal_size.x;
+ int h = internal_size.y;
+
+ while (true) {
+ w = MAX(w / 8, 1);
+ h = MAX(h / 8, 1);
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R32_SFLOAT;
+ tf.width = w;
+ tf.height = h;
+
+ bool final = w == 1 && h == 1;
+
+ if (prefer_raster_effects) {
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ } else {
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+ if (final) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT;
+ }
+ }
+
+ RID texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ reduce.push_back(texture);
+
+ if (final) {
+ current = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ break;
+ }
+ }
+}
+
+void Luminance::LuminanceBuffers::free_data() {
+ for (int i = 0; i < reduce.size(); i++) {
+ RD::get_singleton()->free(reduce[i]);
+ }
+ reduce.clear();
+
+ if (current.is_valid()) {
+ RD::get_singleton()->free(current);
+ current = RID();
+ }
+}
+
+Ref<Luminance::LuminanceBuffers> Luminance::get_luminance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ if (p_render_buffers->has_custom_data(RB_LUMINANCE_BUFFERS)) {
+ return p_render_buffers->get_custom_data(RB_LUMINANCE_BUFFERS);
+ }
+
+ Ref<LuminanceBuffers> buffers;
+ buffers.instantiate();
+ buffers->set_prefer_raster_effects(prefer_raster_effects);
+ buffers->configure(p_render_buffers.ptr());
+
+ p_render_buffers->set_custom_data(RB_LUMINANCE_BUFFERS, buffers);
+
+ return buffers;
+}
+
+RID Luminance::get_current_luminance_buffer(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ if (p_render_buffers->has_custom_data(RB_LUMINANCE_BUFFERS)) {
+ Ref<LuminanceBuffers> buffers = p_render_buffers->get_custom_data(RB_LUMINANCE_BUFFERS);
+ return buffers->current;
+ }
+
+ return RID();
+}
+
+void Luminance::luminance_reduction(RID p_source_texture, const Size2i p_source_size, Ref<LuminanceBuffers> p_luminance_buffers, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ if (prefer_raster_effects) {
+ LuminanceReduceRasterPushConstant push_constant;
+ memset(&push_constant, 0, sizeof(LuminanceReduceRasterPushConstant));
+
+ push_constant.max_luminance = p_max_luminance;
+ push_constant.min_luminance = p_min_luminance;
+ push_constant.exposure_adjust = p_adjust;
+
+ for (int i = 0; i < p_luminance_buffers->reduce.size(); i++) {
+ push_constant.source_size[0] = i == 0 ? p_source_size.x : push_constant.dest_size[0];
+ push_constant.source_size[1] = i == 0 ? p_source_size.y : push_constant.dest_size[1];
+ push_constant.dest_size[0] = MAX(push_constant.source_size[0] / 8, 1);
+ push_constant.dest_size[1] = MAX(push_constant.source_size[1] / 8, 1);
+
+ bool final = !p_set && (push_constant.dest_size[0] == 1) && (push_constant.dest_size[1] == 1);
+ LuminanceReduceRasterMode mode = final ? LUMINANCE_REDUCE_FRAGMENT_FINAL : (i == 0 ? LUMINANCE_REDUCE_FRAGMENT_FIRST : LUMINANCE_REDUCE_FRAGMENT);
+ RID shader = luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, mode);
+
+ RID framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_luminance_buffers->reduce[i]);
+
+ RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, i == 0 ? p_source_texture : p_luminance_buffers->reduce[i - 1] }));
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, luminance_reduce_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0);
+ if (final) {
+ RD::Uniform u_current_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_luminance_buffers->current }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_current_texture), 1);
+ }
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(LuminanceReduceRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ }
+ } else {
+ LuminanceReducePushConstant push_constant;
+ memset(&push_constant, 0, sizeof(LuminanceReducePushConstant));
+
+ push_constant.source_size[0] = p_source_size.x;
+ push_constant.source_size[1] = p_source_size.y;
+ push_constant.max_luminance = p_max_luminance;
+ push_constant.min_luminance = p_min_luminance;
+ push_constant.exposure_adjust = p_adjust;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ for (int i = 0; i < p_luminance_buffers->reduce.size(); i++) {
+ RID shader;
+
+ if (i == 0) {
+ shader = luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, LUMINANCE_REDUCE_READ);
+ RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_texture }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_READ]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0);
+ } else {
+ RD::get_singleton()->compute_list_add_barrier(compute_list); //needs barrier, wait until previous is done
+
+ if (i == p_luminance_buffers->reduce.size() - 1 && !p_set) {
+ shader = luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, LUMINANCE_REDUCE_WRITE);
+ RD::Uniform u_current_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_luminance_buffers->current }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_WRITE]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_current_texture), 2);
+ } else {
+ shader = luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, LUMINANCE_REDUCE);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE]);
+ }
+
+ RD::Uniform u_source_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_luminance_buffers->reduce[i - 1]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0);
+ }
+
+ RD::Uniform u_reduce_texture(RD::UNIFORM_TYPE_IMAGE, 0, p_luminance_buffers->reduce[i]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_reduce_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(LuminanceReducePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.source_size[0], push_constant.source_size[1], 1);
+
+ push_constant.source_size[0] = MAX(push_constant.source_size[0] / 8, 1);
+ push_constant.source_size[1] = MAX(push_constant.source_size[1] / 8, 1);
+ }
+
+ RD::get_singleton()->compute_list_end();
+ }
+
+ SWAP(p_luminance_buffers->current, p_luminance_buffers->reduce.write[p_luminance_buffers->reduce.size() - 1]);
+}
diff --git a/servers/rendering/renderer_rd/effects/luminance.h b/servers/rendering/renderer_rd/effects/luminance.h
new file mode 100644
index 0000000000..0f343fceab
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/luminance.h
@@ -0,0 +1,120 @@
+/**************************************************************************/
+/* luminance.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef LUMINANCE_RD_H
+#define LUMINANCE_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/luminance_reduce.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+#define RB_LUMINANCE_BUFFERS SNAME("luminance_buffers")
+
+namespace RendererRD {
+
+class Luminance {
+private:
+ bool prefer_raster_effects;
+
+ enum LuminanceReduceMode {
+ LUMINANCE_REDUCE_READ,
+ LUMINANCE_REDUCE,
+ LUMINANCE_REDUCE_WRITE,
+ LUMINANCE_REDUCE_MAX
+ };
+
+ struct LuminanceReducePushConstant {
+ int32_t source_size[2];
+ float max_luminance;
+ float min_luminance;
+ float exposure_adjust;
+ float pad[3];
+ };
+
+ struct LuminanceReduce {
+ LuminanceReduceShaderRD shader;
+ RID shader_version;
+ RID pipelines[LUMINANCE_REDUCE_MAX];
+ } luminance_reduce;
+
+ enum LuminanceReduceRasterMode {
+ LUMINANCE_REDUCE_FRAGMENT_FIRST,
+ LUMINANCE_REDUCE_FRAGMENT,
+ LUMINANCE_REDUCE_FRAGMENT_FINAL,
+ LUMINANCE_REDUCE_FRAGMENT_MAX
+ };
+
+ struct LuminanceReduceRasterPushConstant {
+ int32_t source_size[2];
+ int32_t dest_size[2];
+ float exposure_adjust;
+ float min_luminance;
+ float max_luminance;
+ uint32_t pad1;
+ };
+
+ struct LuminanceReduceFragment {
+ LuminanceReduceRasterShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX];
+ } luminance_reduce_raster;
+
+public:
+ class LuminanceBuffers : public RenderBufferCustomDataRD {
+ GDCLASS(LuminanceBuffers, RenderBufferCustomDataRD);
+
+ private:
+ bool prefer_raster_effects;
+
+ public:
+ Vector<RID> reduce;
+ RID current;
+
+ virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
+ virtual void free_data() override;
+
+ void set_prefer_raster_effects(bool p_prefer_raster_effects);
+ };
+
+ Ref<LuminanceBuffers> get_luminance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers);
+ RID get_current_luminance_buffer(Ref<RenderSceneBuffersRD> p_render_buffers);
+ void luminance_reduction(RID p_source_texture, const Size2i p_source_size, Ref<LuminanceBuffers> p_luminance_buffers, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
+
+ Luminance(bool p_prefer_raster_effects);
+ ~Luminance();
+};
+
+} // namespace RendererRD
+
+#endif // LUMINANCE_RD_H
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index 6d15d5c77b..b7a1396f9c 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -55,36 +55,13 @@ RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
u.append_id(p_image);
uniforms.push_back(u);
//any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 1);
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0), 1);
image_to_uniform_set_cache[p_image] = uniform_set;
return uniform_set;
}
-RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
- if (texture_to_uniform_set_cache.has(p_texture)) {
- RID uniform_set = texture_to_uniform_set_cache[p_texture];
- if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- return uniform_set;
- }
- }
-
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
- u.append_id(p_texture);
- uniforms.push_back(u);
- // anything with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, 0), 0);
-
- texture_to_uniform_set_cache[p_texture] = uniform_set;
-
- return uniform_set;
-}
-
RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) {
if (texture_to_compute_uniform_set_cache.has(p_texture)) {
RID uniform_set = texture_to_compute_uniform_set_cache[p_texture];
@@ -101,86 +78,13 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m
u.append_id(p_texture);
uniforms.push_back(u);
//any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 0);
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0), 0);
texture_to_compute_uniform_set_cache[p_texture] = uniform_set;
return uniform_set;
}
-void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
- ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
-
- luminance_reduce.push_constant.source_size[0] = p_source_size.x;
- luminance_reduce.push_constant.source_size[1] = p_source_size.y;
- luminance_reduce.push_constant.max_luminance = p_max_luminance;
- luminance_reduce.push_constant.min_luminance = p_min_luminance;
- luminance_reduce.push_constant.exposure_adjust = p_adjust;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- for (int i = 0; i < p_reduce.size(); i++) {
- if (i == 0) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_READ]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_texture), 0);
- } else {
- RD::get_singleton()->compute_list_add_barrier(compute_list); //needs barrier, wait until previous is done
-
- if (i == p_reduce.size() - 1 && !p_set) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_WRITE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_prev_luminance), 2);
- } else {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE]);
- }
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_reduce[i - 1]), 0);
- }
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_reduce[i]), 1);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &luminance_reduce.push_constant, sizeof(LuminanceReducePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, luminance_reduce.push_constant.source_size[0], luminance_reduce.push_constant.source_size[1], 1);
-
- luminance_reduce.push_constant.source_size[0] = MAX(luminance_reduce.push_constant.source_size[0] / 8, 1);
- luminance_reduce.push_constant.source_size[1] = MAX(luminance_reduce.push_constant.source_size[1] / 8, 1);
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster version of luminance reduction with the clustered renderer.");
- ERR_FAIL_COND_MSG(p_reduce.size() != p_fb.size(), "Incorrect frame buffer account for luminance reduction.");
-
- luminance_reduce_raster.push_constant.max_luminance = p_max_luminance;
- luminance_reduce_raster.push_constant.min_luminance = p_min_luminance;
- luminance_reduce_raster.push_constant.exposure_adjust = p_adjust;
-
- for (int i = 0; i < p_reduce.size(); i++) {
- luminance_reduce_raster.push_constant.source_size[0] = i == 0 ? p_source_size.x : luminance_reduce_raster.push_constant.dest_size[0];
- luminance_reduce_raster.push_constant.source_size[1] = i == 0 ? p_source_size.y : luminance_reduce_raster.push_constant.dest_size[1];
- luminance_reduce_raster.push_constant.dest_size[0] = MAX(luminance_reduce_raster.push_constant.source_size[0] / 8, 1);
- luminance_reduce_raster.push_constant.dest_size[1] = MAX(luminance_reduce_raster.push_constant.source_size[1] / 8, 1);
-
- bool final = !p_set && (luminance_reduce_raster.push_constant.dest_size[0] == 1) && (luminance_reduce_raster.push_constant.dest_size[1] == 1);
- LuminanceReduceRasterMode mode = final ? LUMINANCE_REDUCE_FRAGMENT_FINAL : (i == 0 ? LUMINANCE_REDUCE_FRAGMENT_FIRST : LUMINANCE_REDUCE_FRAGMENT);
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, luminance_reduce_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_fb[i])));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(i == 0 ? p_source_texture : p_reduce[i - 1]), 0);
- if (final) {
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_prev_luminance), 1);
- }
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &luminance_reduce_raster.push_constant, sizeof(LuminanceReduceRasterPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
- }
-}
-
void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) {
roughness_limiter.push_constant.screen_size[0] = p_size.x;
roughness_limiter.push_constant.screen_size[1] = p_size.y;
@@ -270,39 +174,6 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
prefer_raster_effects = p_prefer_raster_effects;
- if (prefer_raster_effects) {
- Vector<String> luminance_reduce_modes;
- luminance_reduce_modes.push_back("\n#define FIRST_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FIRST
- luminance_reduce_modes.push_back("\n"); // LUMINANCE_REDUCE_FRAGMENT
- luminance_reduce_modes.push_back("\n#define FINAL_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FINAL
-
- luminance_reduce_raster.shader.initialize(luminance_reduce_modes);
- memset(&luminance_reduce_raster.push_constant, 0, sizeof(LuminanceReduceRasterPushConstant));
- luminance_reduce_raster.shader_version = luminance_reduce_raster.shader.version_create();
-
- for (int i = 0; i < LUMINANCE_REDUCE_FRAGMENT_MAX; i++) {
- luminance_reduce_raster.pipelines[i].setup(luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
- }
- } else {
- // Initialize luminance_reduce
- Vector<String> luminance_reduce_modes;
- luminance_reduce_modes.push_back("\n#define READ_TEXTURE\n");
- luminance_reduce_modes.push_back("\n");
- luminance_reduce_modes.push_back("\n#define WRITE_LUMINANCE\n");
-
- luminance_reduce.shader.initialize(luminance_reduce_modes);
-
- luminance_reduce.shader_version = luminance_reduce.shader.version_create();
-
- for (int i = 0; i < LUMINANCE_REDUCE_MAX; i++) {
- luminance_reduce.pipelines[i] = RD::get_singleton()->compute_pipeline_create(luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, i));
- }
-
- for (int i = 0; i < LUMINANCE_REDUCE_FRAGMENT_MAX; i++) {
- luminance_reduce_raster.pipelines[i].clear();
- }
- }
-
if (!prefer_raster_effects) {
// Initialize roughness limiter
Vector<String> shader_modes;
@@ -368,11 +239,6 @@ EffectsRD::~EffectsRD() {
RD::get_singleton()->free(default_mipmap_sampler);
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
- if (prefer_raster_effects) {
- luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
- } else {
- luminance_reduce.shader.version_free(luminance_reduce.shader_version);
- }
if (!prefer_raster_effects) {
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
}
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index bbe240b241..45198e5fc5 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -33,8 +33,6 @@
#include "core/math/projection.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
-#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
@@ -45,51 +43,6 @@ class EffectsRD {
private:
bool prefer_raster_effects;
- enum LuminanceReduceMode {
- LUMINANCE_REDUCE_READ,
- LUMINANCE_REDUCE,
- LUMINANCE_REDUCE_WRITE,
- LUMINANCE_REDUCE_MAX
- };
-
- struct LuminanceReducePushConstant {
- int32_t source_size[2];
- float max_luminance;
- float min_luminance;
- float exposure_adjust;
- float pad[3];
- };
-
- struct LuminanceReduce {
- LuminanceReducePushConstant push_constant;
- LuminanceReduceShaderRD shader;
- RID shader_version;
- RID pipelines[LUMINANCE_REDUCE_MAX];
- } luminance_reduce;
-
- enum LuminanceReduceRasterMode {
- LUMINANCE_REDUCE_FRAGMENT_FIRST,
- LUMINANCE_REDUCE_FRAGMENT,
- LUMINANCE_REDUCE_FRAGMENT_FINAL,
- LUMINANCE_REDUCE_FRAGMENT_MAX
- };
-
- struct LuminanceReduceRasterPushConstant {
- int32_t source_size[2];
- int32_t dest_size[2];
- float exposure_adjust;
- float min_luminance;
- float max_luminance;
- uint32_t pad1;
- };
-
- struct LuminanceReduceFragment {
- LuminanceReduceRasterPushConstant push_constant;
- LuminanceReduceRasterShaderRD shader;
- RID shader_version;
- PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX];
- } luminance_reduce_raster;
-
struct RoughnessLimiterPushConstant {
int32_t screen_size[2];
float curve;
@@ -164,15 +117,11 @@ private:
RBMap<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache;
RID _get_uniform_set_from_image(RID p_texture);
- RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
public:
bool get_prefer_raster_effects();
- void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
- void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
-
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
void sort_buffer(RID p_uniform_set, int p_size);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index d426c4fc2e..1d45db8eaf 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -249,57 +249,6 @@ Ref<RenderSceneBuffers> RendererSceneRenderRD::render_buffers_create() {
return rb;
}
-void RendererSceneRenderRD::_allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb) {
- ERR_FAIL_COND(!rb->luminance.current.is_null());
-
- Size2i internal_size = rb->get_internal_size();
- int w = internal_size.x;
- int h = internal_size.y;
-
- while (true) {
- w = MAX(w / 8, 1);
- h = MAX(h / 8, 1);
-
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = w;
- tf.height = h;
-
- bool final = w == 1 && h == 1;
-
- if (_render_buffers_can_be_storage()) {
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
- if (final) {
- tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT;
- }
- } else {
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
- }
-
- RID texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- rb->luminance.reduce.push_back(texture);
- if (!_render_buffers_can_be_storage()) {
- Vector<RID> fb;
- fb.push_back(texture);
-
- rb->luminance.fb.push_back(RD::get_singleton()->framebuffer_create(fb));
- }
-
- if (final) {
- rb->luminance.current = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- if (!_render_buffers_can_be_storage()) {
- Vector<RID> fb;
- fb.push_back(rb->luminance.current);
-
- rb->luminance.current_fb = RD::get_singleton()->framebuffer_create(fb);
- }
- break;
- }
- }
-}
-
void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) {
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
ERR_FAIL_COND(rb.is_null());
@@ -443,9 +392,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RENDER_TIMESTAMP("Auto exposure");
RD::get_singleton()->draw_command_begin_label("Auto exposure");
- if (rb->luminance.current.is_null()) {
- _allocate_luminance_textures(rb);
- }
+
+ Ref<RendererRD::Luminance::LuminanceBuffers> luminance_buffers = luminance->get_luminance_buffers(rb);
+
uint64_t auto_exposure_version = RSG::camera_attributes->camera_attributes_get_auto_exposure_version(p_render_data->camera_attributes);
bool set_immediate = auto_exposure_version != rb->get_auto_exposure_version();
rb->set_auto_exposure_version(auto_exposure_version);
@@ -453,16 +402,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
double step = RSG::camera_attributes->camera_attributes_get_auto_exposure_adjust_speed(p_render_data->camera_attributes) * time_step;
float auto_exposure_min_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_min_sensitivity(p_render_data->camera_attributes);
float auto_exposure_max_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_max_sensitivity(p_render_data->camera_attributes);
- if (can_use_storage) {
- RendererCompositorRD::singleton->get_effects()->luminance_reduction(internal_texture, internal_size, rb->luminance.reduce, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate);
- } else {
- RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(internal_texture, internal_size, rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate);
- }
+ luminance->luminance_reduction(internal_texture, internal_size, luminance_buffers, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate);
+
// Swap final reduce with prev luminance.
- SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
- if (!can_use_storage) {
- SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]);
- }
auto_exposure_scale = RSG::camera_attributes->camera_attributes_get_auto_exposure_scale(p_render_data->camera_attributes);
@@ -496,8 +438,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
if (i == 0) {
RID luminance_texture;
- if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) {
- luminance_texture = rb->luminance.current;
+ if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) {
+ luminance_texture = luminance->get_current_luminance_buffer(rb); // this will return and empty RID if we don't have an auto exposure buffer
}
RID source = rb->get_internal_texture(l);
RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
@@ -530,9 +472,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RendererRD::ToneMapper::TonemapSettings tonemap;
- if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) {
+ tonemap.exposure_texture = luminance->get_current_luminance_buffer(rb);
+ if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && tonemap.exposure_texture.is_valid()) {
tonemap.use_auto_exposure = true;
- tonemap.exposure_texture = rb->luminance.current;
tonemap.auto_exposure_scale = auto_exposure_scale;
} else {
tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
@@ -746,10 +688,11 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD>
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) {
- if (p_render_buffers->luminance.current.is_valid()) {
+ RID luminance_texture = luminance->get_current_luminance_buffer(p_render_buffers);
+ if (luminance_texture.is_valid()) {
Size2i rtsize = texture_storage->render_target_get_size(render_target);
- copy_effects->copy_to_fb_rect(p_render_buffers->luminance.current, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize / 8), false, true);
+ copy_effects->copy_to_fb_rect(luminance_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize / 8), false, true);
}
}
@@ -1334,6 +1277,7 @@ void RendererSceneRenderRD::init() {
bool can_use_vrs = is_vrs_supported();
bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage));
copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage));
+ luminance = memnew(RendererRD::Luminance(!can_use_storage));
tone_mapper = memnew(RendererRD::ToneMapper);
if (can_use_vrs) {
vrs = memnew(RendererRD::VRS);
@@ -1354,6 +1298,9 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
if (copy_effects) {
memdelete(copy_effects);
}
+ if (luminance) {
+ memdelete(luminance);
+ }
if (tone_mapper) {
memdelete(tone_mapper);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 54f068c314..6fa2f7a570 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -38,6 +38,7 @@
#include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
#include "servers/rendering/renderer_rd/effects/fsr.h"
+#include "servers/rendering/renderer_rd/effects/luminance.h"
#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
#include "servers/rendering/renderer_rd/effects/vrs.h"
#include "servers/rendering/renderer_rd/environment/fog.h"
@@ -105,6 +106,7 @@ protected:
RendererRD::ForwardIDStorage *forward_id_storage = nullptr;
RendererRD::BokehDOF *bokeh_dof = nullptr;
RendererRD::CopyEffects *copy_effects = nullptr;
+ RendererRD::Luminance *luminance = nullptr;
RendererRD::ToneMapper *tone_mapper = nullptr;
RendererRD::FSR *fsr = nullptr;
RendererRD::VRS *vrs = nullptr;
@@ -180,9 +182,6 @@ private:
/* RENDER BUFFERS */
- // TODO move into effects/luminance.h/cpp
- void _allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb);
-
/* GI */
bool screen_space_roughness_limiter = false;
float screen_space_roughness_limiter_amount = 0.25;
diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce.glsl b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce.glsl
index 0ee4cf6e31..0ee4cf6e31 100644
--- a/servers/rendering/renderer_rd/shaders/luminance_reduce.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce.glsl
diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl
index 29ebd74a90..29ebd74a90 100644
--- a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.glsl
diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster_inc.glsl
index b8860f6518..b8860f6518 100644
--- a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster_inc.glsl
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
index a953bac433..d67a848a40 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
@@ -94,28 +94,6 @@ void RenderSceneBuffersRD::cleanup() {
free_named_texture(E.value);
}
named_textures.clear();
-
- // old stuff, to be re-evaluated...
-
- for (int i = 0; i < luminance.fb.size(); i++) {
- RD::get_singleton()->free(luminance.fb[i]);
- }
- luminance.fb.clear();
-
- for (int i = 0; i < luminance.reduce.size(); i++) {
- RD::get_singleton()->free(luminance.reduce[i]);
- }
- luminance.reduce.clear();
-
- if (luminance.current_fb.is_valid()) {
- RD::get_singleton()->free(luminance.current_fb);
- luminance.current_fb = RID();
- }
-
- if (luminance.current.is_valid()) {
- RD::get_singleton()->free(luminance.current);
- luminance.current = RID();
- }
}
void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
index 1bd542500c..ff946f410f 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
@@ -213,15 +213,6 @@ public:
// 2 full size, 2 half size
WeightBuffers weight_buffers[4]; // Only used in raster
-
- struct Luminance {
- Vector<RID> reduce;
- RID current;
-
- // used only on mobile renderer
- Vector<RID> fb;
- RID current_fb;
- } luminance;
};
#endif // RENDER_SCENE_BUFFERS_RD_H