summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/AStar2D.xml2
-rw-r--r--doc/classes/Animation.xml2
-rw-r--r--doc/classes/Bone2D.xml4
-rw-r--r--doc/classes/BoneAttachment3D.xml4
-rw-r--r--doc/classes/BoxMesh.xml2
-rw-r--r--doc/classes/EditorInspectorPlugin.xml2
-rw-r--r--doc/classes/EditorNode3DGizmoPlugin.xml4
-rw-r--r--doc/classes/EditorPlugin.xml4
-rw-r--r--doc/classes/GeometryInstance3D.xml4
-rw-r--r--doc/classes/NavigationLink2D.xml2
-rw-r--r--doc/classes/NavigationLink3D.xml2
-rw-r--r--doc/classes/NavigationPathQueryResult2D.xml2
-rw-r--r--doc/classes/NavigationPathQueryResult3D.xml2
-rw-r--r--editor/editor_inspector.h2
-rw-r--r--editor/editor_plugin.cpp6
-rw-r--r--editor/editor_plugin.h4
-rw-r--r--editor/editor_settings.cpp4
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp6
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp103
-rw-r--r--modules/gdscript/gdscript_byte_codegen.h29
-rw-r--r--platform/android/display_server_android.cpp2
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp18
-rw-r--r--platform/macos/display_server_macos.mm2
-rw-r--r--platform/web/display_server_web.cpp1
-rw-r--r--platform/windows/display_server_windows.cpp2
-rw-r--r--scene/gui/item_list.cpp14
-rw-r--r--scene/gui/popup_menu.cpp6
-rw-r--r--scene/gui/text_edit.cpp4
28 files changed, 169 insertions, 70 deletions
diff --git a/doc/classes/AStar2D.xml b/doc/classes/AStar2D.xml
index 2414b068e6..d80d784366 100644
--- a/doc/classes/AStar2D.xml
+++ b/doc/classes/AStar2D.xml
@@ -175,7 +175,7 @@
<method name="get_point_capacity" qualifiers="const">
<return type="int" />
<description>
- Returns the capacity of the structure backing the points, useful in conjunction with [code]reserve_space[/code].
+ Returns the capacity of the structure backing the points, useful in conjunction with [method reserve_space].
</description>
</method>
<method name="get_point_connections">
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index 74ee13a3d2..9b834f2635 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -108,7 +108,7 @@
<return type="bool" />
<param index="0" name="track_idx" type="int" />
<description>
- Returns [code]true[/code] if the track at [code]idx[/code] will be blended with other animations.
+ Returns [code]true[/code] if the track at [param track_idx] will be blended with other animations.
</description>
</method>
<method name="audio_track_set_key_end_offset">
diff --git a/doc/classes/Bone2D.xml b/doc/classes/Bone2D.xml
index d452edd1aa..81999cebab 100644
--- a/doc/classes/Bone2D.xml
+++ b/doc/classes/Bone2D.xml
@@ -34,7 +34,7 @@
<method name="get_default_length" qualifiers="const">
<return type="float" />
<description>
- Deprecated. Please use [code]get_length[/code] instead.
+ Deprecated. Please use [method get_length] instead.
</description>
</method>
<method name="get_index_in_skeleton" qualifiers="const">
@@ -74,7 +74,7 @@
<return type="void" />
<param index="0" name="default_length" type="float" />
<description>
- Deprecated. Please use [code]set_length[/code] instead.
+ Deprecated. Please use [method set_length] instead.
</description>
</method>
<method name="set_length">
diff --git a/doc/classes/BoneAttachment3D.xml b/doc/classes/BoneAttachment3D.xml
index dd01de3607..850aa4c2f2 100644
--- a/doc/classes/BoneAttachment3D.xml
+++ b/doc/classes/BoneAttachment3D.xml
@@ -33,14 +33,14 @@
<return type="void" />
<param index="0" name="external_skeleton" type="NodePath" />
<description>
- Sets the [NodePath] to the external skeleton that the BoneAttachment3D node should use. The external [Skeleton3D] node is only used when [code]use_external_skeleton[/code] is set to [code]true[/code].
+ Sets the [NodePath] to the external skeleton that the BoneAttachment3D node should use. See [method set_use_external_skeleton] to enable the external [Skeleton3D] node.
</description>
</method>
<method name="set_use_external_skeleton">
<return type="void" />
<param index="0" name="use_external_skeleton" type="bool" />
<description>
- Sets whether the BoneAttachment3D node will use an extenral [Skeleton3D] node rather than attenpting to use its parent node as the [Skeleton3D]. When set to [code]true[/code], the BoneAttachment3D node will use the external [Skeleton3D] node set in [code]set_external_skeleton[/code].
+ Sets whether the BoneAttachment3D node will use an extenral [Skeleton3D] node rather than attenpting to use its parent node as the [Skeleton3D]. When set to [code]true[/code], the BoneAttachment3D node will use the external [Skeleton3D] node set in [method set_external_skeleton].
</description>
</method>
</methods>
diff --git a/doc/classes/BoxMesh.xml b/doc/classes/BoxMesh.xml
index 84e6d6f87d..f8cae0fc72 100644
--- a/doc/classes/BoxMesh.xml
+++ b/doc/classes/BoxMesh.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
Generate an axis-aligned box [PrimitiveMesh].
- The box's UV layout is arranged in a 3×2 layout that allows texturing each face individually. To apply the same texture on all faces, change the material's UV property to [code]Vector3(3, 2, 1)[/code].
+ The box's UV layout is arranged in a 3×2 layout that allows texturing each face individually. To apply the same texture on all faces, change the material's UV property to [code]Vector3(3, 2, 1)[/code]. This is equivalent to adding [code]UV *= vec2(3.0, 2.0)[/code] in a vertex shader.
[b]Note:[/b] When using a large textured [BoxMesh] (e.g. as a floor), you may stumble upon UV jittering issues depending on the camera angle. To solve this, increase [member subdivide_depth], [member subdivide_height] and [member subdivide_width] until you no longer notice UV jittering.
</description>
<tutorials>
diff --git a/doc/classes/EditorInspectorPlugin.xml b/doc/classes/EditorInspectorPlugin.xml
index 7ffd7f9426..bbd383edc0 100644
--- a/doc/classes/EditorInspectorPlugin.xml
+++ b/doc/classes/EditorInspectorPlugin.xml
@@ -18,7 +18,7 @@
<methods>
<method name="_can_handle" qualifiers="virtual const">
<return type="bool" />
- <param index="0" name="object" type="Variant" />
+ <param index="0" name="object" type="Object" />
<description>
Returns [code]true[/code] if this object can be handled by this plugin.
</description>
diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml
index 3ab13ec5c0..7c012f8ef6 100644
--- a/doc/classes/EditorNode3DGizmoPlugin.xml
+++ b/doc/classes/EditorNode3DGizmoPlugin.xml
@@ -138,7 +138,7 @@
<param index="1" name="subgizmo_id" type="int" />
<param index="2" name="transform" type="Transform3D" />
<description>
- Override this method to update the node properties during subgizmo editing (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). The [param transform] is given in the Node3D's local coordinate system. Called for this plugin's active gizmos.
+ Override this method to update the node properties during subgizmo editing (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). The [param transform] is given in the Node3D's local coordinate system. Called for this plugin's active gizmos.
</description>
</method>
<method name="_subgizmos_intersect_frustum" qualifiers="virtual const">
@@ -147,7 +147,7 @@
<param index="1" name="camera" type="Camera3D" />
<param index="2" name="frustum_planes" type="Plane[]" />
<description>
- Override this method to allow selecting subgizmos using mouse drag box selection. Given a [param camera] and [param frustum_planes], this method should return which subgizmos are contained within the frustums. The [param frustum_planes] argument consists of an [code]Array[/code] with all the [code]Plane[/code]s that make up the selection frustum. The returned value should contain a list of unique subgizmo identifiers, these identifiers can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos]. Called for this plugin's active gizmos.
+ Override this method to allow selecting subgizmos using mouse drag box selection. Given a [param camera] and [param frustum_planes], this method should return which subgizmos are contained within the frustums. The [param frustum_planes] argument consists of an [code]Array[/code] with all the [code]Plane[/code]s that make up the selection frustum. The returned value should contain a list of unique subgizmo identifiers, these identifiers can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos]. Called for this plugin's active gizmos.
</description>
</method>
<method name="_subgizmos_intersect_ray" qualifiers="virtual const">
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index f4b912de9e..95c0f8efe1 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -38,7 +38,7 @@
</method>
<method name="_edit" qualifiers="virtual">
<return type="void" />
- <param index="0" name="object" type="Variant" />
+ <param index="0" name="object" type="Object" />
<description>
This function is used for plugins that edit specific object types (nodes or resources). It requests the editor to edit the given object.
[param object] can be [code]null[/code] if the plugin was editing an object, but there is no longer any selected object handled by this plugin. It can be used to cleanup editing state.
@@ -295,7 +295,7 @@
</method>
<method name="_handles" qualifiers="virtual const">
<return type="bool" />
- <param index="0" name="object" type="Variant" />
+ <param index="0" name="object" type="Object" />
<description>
Implement this function if your plugin edits a specific type of object (Resource or Node). If you return [code]true[/code], then you will get the functions [method _edit] and [method _make_visible] called when the editor requests them. If you have declared the methods [method _forward_canvas_gui_input] and [method _forward_3d_gui_input] these will be called too.
</description>
diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml
index 127c5daf95..2bb55a1f40 100644
--- a/doc/classes/GeometryInstance3D.xml
+++ b/doc/classes/GeometryInstance3D.xml
@@ -46,10 +46,10 @@
[b]Note:[/b] Lights' bake mode will also affect the global illumination rendering. See [member Light3D.light_bake_mode].
</member>
<member name="ignore_occlusion_culling" type="bool" setter="set_ignore_occlusion_culling" getter="is_ignoring_occlusion_culling" default="false">
- If [code]true[/code], disables occlusion culling for this instance. Useful for gizmos that must be rendered even when occlusion culling is in use.
+ If [code]true[/code], disables occlusion culling for this instance. Useful for gizmos that must be rendered even when occlusion culling is in use.
</member>
<member name="lod_bias" type="float" setter="set_lod_bias" getter="get_lod_bias" default="1.0">
- Changes how quickly the mesh transitions to a lower level of detail. A value of 0 will force the mesh to its lowest level of detail, a value of 1 will use the default settings, and larger values will keep the mesh in a higher level of detail at farther distances.
+ Changes how quickly the mesh transitions to a lower level of detail. A value of 0 will force the mesh to its lowest level of detail, a value of 1 will use the default settings, and larger values will keep the mesh in a higher level of detail at farther distances.
Useful for testing level of detail transitions in the editor.
</member>
<member name="material_overlay" type="Material" setter="set_material_overlay" getter="get_material_overlay">
diff --git a/doc/classes/NavigationLink2D.xml b/doc/classes/NavigationLink2D.xml
index 3f5b1fb184..b3768c357c 100644
--- a/doc/classes/NavigationLink2D.xml
+++ b/doc/classes/NavigationLink2D.xml
@@ -4,7 +4,7 @@
Creates a link between two positions that [NavigationServer2D] can route agents through.
</brief_description>
<description>
- Creates a link between two positions that [NavigationServer2D] can route agents through. Links can be used to express navigation methods that aren't just traveling along the surface of the navigation mesh, like zip-lines, teleporters, or jumping across gaps.
+ Creates a link between two positions that [NavigationServer2D] can route agents through. Links can be used to express navigation methods that aren't just traveling along the surface of the navigation mesh, like zip-lines, teleporters, or jumping across gaps.
</description>
<tutorials>
<link title="Using NavigationLinks">$DOCS_URL/tutorials/navigation/navigation_using_navigationlinks.html</link>
diff --git a/doc/classes/NavigationLink3D.xml b/doc/classes/NavigationLink3D.xml
index 4081426dcd..63abecf631 100644
--- a/doc/classes/NavigationLink3D.xml
+++ b/doc/classes/NavigationLink3D.xml
@@ -4,7 +4,7 @@
Creates a link between two positions that [NavigationServer3D] can route agents through.
</brief_description>
<description>
- Creates a link between two positions that [NavigationServer3D] can route agents through. Links can be used to express navigation methods that aren't just traveling along the surface of the navigation mesh, like zip-lines, teleporters, or jumping across gaps.
+ Creates a link between two positions that [NavigationServer3D] can route agents through. Links can be used to express navigation methods that aren't just traveling along the surface of the navigation mesh, like zip-lines, teleporters, or jumping across gaps.
</description>
<tutorials>
<link title="Using NavigationLinks">$DOCS_URL/tutorials/navigation/navigation_using_navigationlinks.html</link>
diff --git a/doc/classes/NavigationPathQueryResult2D.xml b/doc/classes/NavigationPathQueryResult2D.xml
index 7bc588619d..2bf7961b35 100644
--- a/doc/classes/NavigationPathQueryResult2D.xml
+++ b/doc/classes/NavigationPathQueryResult2D.xml
@@ -13,7 +13,7 @@
<method name="reset">
<return type="void" />
<description>
- Reset the result object to its initial state. This is useful to reuse the object across multiple queries.
+ Reset the result object to its initial state. This is useful to reuse the object across multiple queries.
</description>
</method>
</methods>
diff --git a/doc/classes/NavigationPathQueryResult3D.xml b/doc/classes/NavigationPathQueryResult3D.xml
index 118a597b6c..a49eb14b67 100644
--- a/doc/classes/NavigationPathQueryResult3D.xml
+++ b/doc/classes/NavigationPathQueryResult3D.xml
@@ -13,7 +13,7 @@
<method name="reset">
<return type="void" />
<description>
- Reset the result object to its initial state. This is useful to reuse the object across multiple queries.
+ Reset the result object to its initial state. This is useful to reuse the object across multiple queries.
</description>
</method>
</methods>
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index 4ffba18181..01231108d8 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -225,7 +225,7 @@ public:
protected:
static void _bind_methods();
- GDVIRTUAL1RC(bool, _can_handle, Variant)
+ GDVIRTUAL1RC(bool, _can_handle, Object *)
GDVIRTUAL1(_parse_begin, Object *)
GDVIRTUAL2(_parse_category, Object *, String)
GDVIRTUAL2(_parse_group, Object *, String)
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 14cdbc364e..7b01ae69bf 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -662,11 +662,7 @@ void EditorPlugin::make_visible(bool p_visible) {
}
void EditorPlugin::edit(Object *p_object) {
- if (Object::cast_to<Resource>(p_object)) {
- GDVIRTUAL_CALL(_edit, Ref<Resource>(Object::cast_to<Resource>(p_object)));
- } else {
- GDVIRTUAL_CALL(_edit, p_object);
- }
+ GDVIRTUAL_CALL(_edit, p_object);
}
bool EditorPlugin::handles(Object *p_object) const {
diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h
index a5a17acdf1..74f46b2d0b 100644
--- a/editor/editor_plugin.h
+++ b/editor/editor_plugin.h
@@ -164,8 +164,8 @@ protected:
GDVIRTUAL0RC(Ref<Texture2D>, _get_plugin_icon)
GDVIRTUAL0RC(bool, _has_main_screen)
GDVIRTUAL1(_make_visible, bool)
- GDVIRTUAL1(_edit, Variant)
- GDVIRTUAL1RC(bool, _handles, Variant)
+ GDVIRTUAL1(_edit, Object *)
+ GDVIRTUAL1RC(bool, _handles, Object *)
GDVIRTUAL0RC(Dictionary, _get_state)
GDVIRTUAL1(_set_state, Dictionary)
GDVIRTUAL0(_clear)
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 23e32dcbd8..c90f8e9bf0 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -1490,11 +1490,11 @@ void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, c
}
// Override the existing shortcut only if it wasn't customized by the user (i.e. still "original").
+ sc->set_meta("original", events.duplicate(true));
+
if (Shortcut::is_event_array_equal(sc->get_events(), sc->get_meta("original"))) {
sc->set_events(events);
}
-
- sc->set_meta("original", events.duplicate(true));
}
Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, Key p_keycode) {
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index c41bf4b8cc..20b3cf3618 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -807,13 +807,17 @@ void SpriteFramesEditor::_animation_name_edited() {
return;
}
+ if (new_name.is_empty()) {
+ new_name = "new_animation";
+ }
+
new_name = new_name.replace("/", "_").replace(",", " ");
String name = new_name;
int counter = 0;
while (frames->has_animation(name)) {
counter++;
- name = new_name + " " + itos(counter);
+ name = new_name + "_" + itos(counter);
}
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index ec7a2b0f1c..45008b0e87 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -143,6 +143,11 @@ void GDScriptByteCodeGenerator::pop_temporary() {
ERR_FAIL_COND(used_temporaries.is_empty());
int slot_idx = used_temporaries.back()->get();
const StackSlot &slot = temporaries[slot_idx];
+ if (slot.type == Variant::OBJECT) {
+ // Avoid keeping in the stack long-lived references to objects,
+ // which may prevent RefCounted objects from being freed.
+ write_assign_false(Address(Address::TEMPORARY, slot_idx));
+ }
temporaries_pool[slot.type].push_back(slot_idx);
used_temporaries.pop_back();
}
@@ -954,7 +959,7 @@ void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Addres
append(index);
}
-GDScriptCodeGenerator::Address GDScriptByteCodeGenerator::get_call_target(const GDScriptCodeGenerator::Address &p_target, Variant::Type p_type) {
+GDScriptByteCodeGenerator::CallTarget GDScriptByteCodeGenerator::get_call_target(const GDScriptCodeGenerator::Address &p_target, Variant::Type p_type) {
if (p_target.mode == Address::NIL) {
GDScriptDataType type;
if (p_type != Variant::NIL) {
@@ -963,10 +968,9 @@ GDScriptCodeGenerator::Address GDScriptByteCodeGenerator::get_call_target(const
type.builtin_type = p_type;
}
uint32_t addr = add_temporary(type);
- pop_temporary();
- return Address(Address::TEMPORARY, addr, type);
+ return CallTarget(Address(Address::TEMPORARY, addr, type), true, this);
} else {
- return p_target;
+ return CallTarget(p_target, false, this);
}
}
@@ -976,9 +980,11 @@ void GDScriptByteCodeGenerator::write_call(const Address &p_target, const Addres
append(p_arguments[i]);
}
append(p_base);
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(p_function_name);
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) {
@@ -986,9 +992,11 @@ void GDScriptByteCodeGenerator::write_super_call(const Address &p_target, const
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(p_function_name);
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
@@ -997,9 +1005,11 @@ void GDScriptByteCodeGenerator::write_call_async(const Address &p_target, const
append(p_arguments[i]);
}
append(p_base);
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(p_function_name);
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_call_gdscript_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) {
@@ -1008,9 +1018,11 @@ void GDScriptByteCodeGenerator::write_call_gdscript_utility(const Address &p_tar
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(gds_function);
+ ct.cleanup();
#ifdef DEBUG_ENABLED
add_debug_name(gds_utilities_names, get_gds_utility_pos(gds_function), p_function);
#endif
@@ -1034,18 +1046,19 @@ void GDScriptByteCodeGenerator::write_call_utility(const Address &p_target, cons
if (is_validated) {
Variant::Type result_type = Variant::has_utility_function_return_value(p_function) ? Variant::get_utility_function_return_type(p_function) : Variant::NIL;
- Address target = get_call_target(p_target, result_type);
- Variant::Type temp_type = temporaries[target.address].type;
+ CallTarget ct = get_call_target(p_target, result_type);
+ Variant::Type temp_type = temporaries[ct.target.address].type;
if (result_type != temp_type) {
- write_type_adjust(target, result_type);
+ write_type_adjust(ct.target, result_type);
}
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_UTILITY_VALIDATED, 1 + p_arguments.size());
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(target);
+ append(ct.target);
append(p_arguments.size());
append(Variant::get_validated_utility_function(p_function));
+ ct.cleanup();
#ifdef DEBUG_ENABLED
add_debug_name(utilities_names, get_utility_pos(Variant::get_validated_utility_function(p_function)), p_function);
#endif
@@ -1054,9 +1067,11 @@ void GDScriptByteCodeGenerator::write_call_utility(const Address &p_target, cons
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(p_function);
+ ct.cleanup();
}
}
@@ -1085,10 +1100,12 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target,
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_type);
append(p_method);
append(p_arguments.size());
+ ct.cleanup();
} else {
write_call(p_target, p_base, p_method, p_arguments);
}
@@ -1096,10 +1113,10 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target,
}
Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method);
- Address target = get_call_target(p_target, result_type);
- Variant::Type temp_type = temporaries[target.address].type;
+ CallTarget ct = get_call_target(p_target, result_type);
+ Variant::Type temp_type = temporaries[ct.target.address].type;
if (result_type != temp_type) {
- write_type_adjust(target, result_type);
+ write_type_adjust(ct.target, result_type);
}
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_BUILTIN_TYPE_VALIDATED, 2 + p_arguments.size());
@@ -1108,9 +1125,11 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target,
append(p_arguments[i]);
}
append(p_base);
- append(target);
+ append(ct.target);
append(p_arguments.size());
append(Variant::get_validated_builtin_method(p_type, p_method));
+ ct.cleanup();
+
#ifdef DEBUG_ENABLED
add_debug_name(builtin_methods_names, get_builtin_method_pos(Variant::get_validated_builtin_method(p_type, p_method)), p_method);
#endif
@@ -1135,9 +1154,11 @@ void GDScriptByteCodeGenerator::write_call_native_static(const Address &p_target
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(method);
append(p_arguments.size());
+ ct.cleanup();
return;
}
}
@@ -1147,10 +1168,12 @@ void GDScriptByteCodeGenerator::write_call_method_bind(const Address &p_target,
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
+ CallTarget ct = get_call_target(p_target);
append(p_base);
- append(get_call_target(p_target));
+ append(ct.target);
append(p_arguments.size());
append(p_method);
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) {
@@ -1212,9 +1235,11 @@ void GDScriptByteCodeGenerator::write_call_ptrcall(const Address &p_target, cons
append(p_arguments[i]);
}
append(p_base);
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(p_method);
+ ct.cleanup();
if (is_ptrcall) {
alloc_ptrcall(p_arguments.size());
}
@@ -1228,9 +1253,11 @@ void GDScriptByteCodeGenerator::write_call_self(const Address &p_target, const S
append(p_arguments[i]);
}
append(GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(p_function_name);
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_call_self_async(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) {
@@ -1239,9 +1266,11 @@ void GDScriptByteCodeGenerator::write_call_self_async(const Address &p_target, c
append(p_arguments[i]);
}
append(GDScriptFunction::ADDR_SELF);
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(p_function_name);
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
@@ -1250,9 +1279,11 @@ void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_targ
append(p_arguments[i]);
}
append(p_base);
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(p_function_name);
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_lambda(const Address &p_target, GDScriptFunction *p_function, const Vector<Address> &p_captures, bool p_use_self) {
@@ -1261,9 +1292,11 @@ void GDScriptByteCodeGenerator::write_lambda(const Address &p_target, GDScriptFu
append(p_captures[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_captures.size());
append(p_function);
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) {
@@ -1300,9 +1333,11 @@ void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(Variant::get_validated_constructor(p_type, valid_constructor));
+ ct.cleanup();
#ifdef DEBUG_ENABLED
add_debug_name(constructors_names, get_constructor_pos(Variant::get_validated_constructor(p_type, valid_constructor)), Variant::get_type_name(p_type));
#endif
@@ -1314,9 +1349,11 @@ void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
append(p_type);
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_construct_array(const Address &p_target, const Vector<Address> &p_arguments) {
@@ -1324,8 +1361,10 @@ void GDScriptByteCodeGenerator::write_construct_array(const Address &p_target, c
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size());
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_construct_typed_array(const Address &p_target, const GDScriptDataType &p_element_type, const Vector<Address> &p_arguments) {
@@ -1333,11 +1372,13 @@ void GDScriptByteCodeGenerator::write_construct_typed_array(const Address &p_tar
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(get_constant_pos(p_element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
append(p_arguments.size());
append(p_element_type.builtin_type);
append(p_element_type.native_type);
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) {
@@ -1345,8 +1386,10 @@ void GDScriptByteCodeGenerator::write_construct_dictionary(const Address &p_targ
for (int i = 0; i < p_arguments.size(); i++) {
append(p_arguments[i]);
}
- append(get_call_target(p_target));
+ CallTarget ct = get_call_target(p_target);
+ append(ct.target);
append(p_arguments.size() / 2); // This is number of key-value pairs, so only half of actual arguments.
+ ct.cleanup();
}
void GDScriptByteCodeGenerator::write_await(const Address &p_target, const Address &p_operand) {
diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h
index 8aa02b86c4..1d1b22e196 100644
--- a/modules/gdscript/gdscript_byte_codegen.h
+++ b/modules/gdscript/gdscript_byte_codegen.h
@@ -48,6 +48,33 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
const static int RESERVED_STACK = 3; // For self, class, and nil.
+ struct CallTarget {
+ Address target;
+ bool is_new_temporary = false;
+ GDScriptByteCodeGenerator *codegen = nullptr;
+#ifdef DEV_ENABLED
+ bool cleaned = false;
+#endif
+
+ void cleanup() {
+ DEV_ASSERT(!cleaned);
+ if (is_new_temporary) {
+ codegen->pop_temporary();
+ }
+#ifdef DEV_ENABLED
+ cleaned = true;
+#endif
+ }
+
+ CallTarget(Address p_target, bool p_is_new_temporary, GDScriptByteCodeGenerator *p_codegen) :
+ target(p_target),
+ is_new_temporary(p_is_new_temporary),
+ codegen(p_codegen) {}
+ ~CallTarget() { DEV_ASSERT(cleaned); }
+ CallTarget(const CallTarget &) = delete;
+ CallTarget &operator=(CallTarget &) = delete;
+ };
+
bool ended = false;
GDScriptFunction *function = nullptr;
bool debug_stack = false;
@@ -326,7 +353,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
}
}
- Address get_call_target(const Address &p_target, Variant::Type p_type = Variant::NIL);
+ CallTarget get_call_target(const Address &p_target, Variant::Type p_type = Variant::NIL);
int address_of(const Address &p_address) {
switch (p_address.mode) {
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 3fcb926f86..af4ba1255b 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -656,6 +656,7 @@ void DisplayServerAndroid::_cursor_set_shape_helper(CursorShape p_shape, bool fo
}
void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape) {
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
_cursor_set_shape_helper(p_shape);
}
@@ -664,6 +665,7 @@ DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const {
}
void DisplayServerAndroid::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
String cursor_path = p_cursor.is_valid() ? p_cursor->get_path() : "";
if (!cursor_path.is_empty()) {
cursor_path = ProjectSettings::get_singleton()->globalize_path(cursor_path);
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 896b7b95eb..dff2f536a8 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -2057,6 +2057,22 @@ void DisplayServerX11::_validate_mode_on_map(WindowID p_window) {
} else if (wd.minimized && !_window_minimize_check(p_window)) {
_set_wm_minimized(p_window, true);
}
+
+ if (wd.on_top) {
+ Atom wm_state = XInternAtom(x11_display, "_NET_WM_STATE", False);
+ Atom wm_above = XInternAtom(x11_display, "_NET_WM_STATE_ABOVE", False);
+
+ XClientMessageEvent xev;
+ memset(&xev, 0, sizeof(xev));
+ xev.type = ClientMessage;
+ xev.window = wd.x11_window;
+ xev.message_type = wm_state;
+ xev.format = 32;
+ xev.data.l[0] = _NET_WM_STATE_ADD;
+ xev.data.l[1] = wm_above;
+ xev.data.l[3] = 1;
+ XSendEvent(x11_display, DefaultRootWindow(x11_display), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&xev);
+ }
}
bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const {
@@ -2599,6 +2615,8 @@ DisplayServerX11::CursorShape DisplayServerX11::cursor_get_shape() const {
void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
_THREAD_SAFE_METHOD_
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
+
if (p_cursor.is_valid()) {
HashMap<CursorShape, Vector<Variant>>::Iterator cursor_c = cursors_cache.find(p_shape);
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 65546392c1..14778b5f03 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -3284,6 +3284,8 @@ DisplayServerMacOS::CursorShape DisplayServerMacOS::cursor_get_shape() const {
void DisplayServerMacOS::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
_THREAD_SAFE_METHOD_
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
+
if (p_cursor.is_valid()) {
HashMap<CursorShape, Vector<Variant>>::Iterator cursor_c = cursors_cache.find(p_shape);
diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp
index e89a79834b..565d439a92 100644
--- a/platform/web/display_server_web.cpp
+++ b/platform/web/display_server_web.cpp
@@ -395,6 +395,7 @@ DisplayServer::CursorShape DisplayServerWeb::cursor_get_shape() const {
}
void DisplayServerWeb::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
if (p_cursor.is_valid()) {
Ref<Texture2D> texture = p_cursor;
Ref<AtlasTexture> atlas_texture = p_cursor;
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 1cfc9c9f47..d2889a3442 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -1719,6 +1719,8 @@ DisplayServer::CursorShape DisplayServerWindows::cursor_get_shape() const {
void DisplayServerWindows::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
_THREAD_SAFE_METHOD_
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
+
if (p_cursor.is_valid()) {
RBMap<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape);
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 25a27d5e1a..d367a8d281 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -801,8 +801,9 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) {
search_string = ""; //any mousepress cancels
for (int i = 4; i > 0; i--) {
- if (current - current_columns * i >= 0 && CAN_SELECT(current - current_columns * i)) {
- set_current(current - current_columns * i);
+ int index = current - current_columns * i;
+ if (index >= 0 && index < items.size() && CAN_SELECT(index)) {
+ set_current(index);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
emit_signal(SNAME("item_selected"), current);
@@ -815,8 +816,9 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) {
search_string = ""; //any mousepress cancels
for (int i = 4; i > 0; i--) {
- if (current + current_columns * i < items.size() && CAN_SELECT(current + current_columns * i)) {
- set_current(current + current_columns * i);
+ int index = current + current_columns * i;
+ if (index >= 0 && index < items.size() && CAN_SELECT(index)) {
+ set_current(index);
ensure_current_is_visible();
if (select_mode == SELECT_SINGLE) {
emit_signal(SNAME("item_selected"), current);
@@ -832,7 +834,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) {
if (current % current_columns != 0) {
int current_row = current / current_columns;
int next = current - 1;
- while (!CAN_SELECT(next)) {
+ while (next >= 0 && !CAN_SELECT(next)) {
next = next - 1;
}
if (next < 0 || !IS_SAME_ROW(next, current_row)) {
@@ -852,7 +854,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) {
if (current % current_columns != (current_columns - 1) && current + 1 < items.size()) {
int current_row = current / current_columns;
int next = current + 1;
- while (!CAN_SELECT(next)) {
+ while (next < items.size() && !CAN_SELECT(next)) {
next = next + 1;
}
if (items.size() <= next || !IS_SAME_ROW(next, current_row)) {
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 1a6adca121..cf73729c0a 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -1715,12 +1715,12 @@ void PopupMenu::activate_item(int p_item) {
need_hide = false;
}
+ emit_signal(SNAME("id_pressed"), id);
+ emit_signal(SNAME("index_pressed"), p_item);
+
if (need_hide) {
hide();
}
-
- emit_signal(SNAME("id_pressed"), id);
- emit_signal(SNAME("index_pressed"), p_item);
}
void PopupMenu::remove_item(int p_idx) {
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index d785280701..2b3b577697 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -4362,7 +4362,9 @@ int TextEdit::get_minimap_line_at_pos(const Point2i &p_pos) const {
if (first_vis_line > 0 && minimap_line >= 0) {
minimap_line -= get_next_visible_line_index_offset_from(first_vis_line, 0, -num_lines_before).x;
minimap_line -= (minimap_line > 0 && smooth_scroll_enabled ? 1 : 0);
- } else {
+ }
+
+ if (minimap_line < 0) {
minimap_line = 0;
}