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.xml13
-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_node.cpp1
-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--editor/renames_map_3_to_4.cpp4
-rw-r--r--modules/gdscript/gdscript.cpp2
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp103
-rw-r--r--modules/gdscript/gdscript_byte_codegen.h29
-rw-r--r--modules/gdscript/gdscript_function.h2
-rw-r--r--modules/gdscript/gdscript_vm.cpp32
-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/macos/export/export_plugin.cpp2
-rw-r--r--platform/web/display_server_web.cpp1
-rw-r--r--platform/windows/display_server_windows.cpp2
-rw-r--r--scene/2d/skeleton_2d.cpp13
-rw-r--r--scene/2d/skeleton_2d.h3
-rw-r--r--scene/gui/item_list.cpp14
-rw-r--r--scene/gui/popup_menu.cpp6
-rw-r--r--scene/gui/text_edit.cpp4
36 files changed, 208 insertions, 99 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..c421fe1543 100644
--- a/doc/classes/Bone2D.xml
+++ b/doc/classes/Bone2D.xml
@@ -31,12 +31,6 @@
[b]Note:[/b] This is different from the [code]Bone2D[/code]'s rotation. The bone angle is the rotation of the bone shown by the [code]Bone2D[/code] gizmo, and because [code]Bone2D[/code] bones are based on positions, this can vary from the actual rotation of the [code]Bone2D[/code] node.
</description>
</method>
- <method name="get_default_length" qualifiers="const">
- <return type="float" />
- <description>
- Deprecated. Please use [code]get_length[/code] instead.
- </description>
- </method>
<method name="get_index_in_skeleton" qualifiers="const">
<return type="int" />
<description>
@@ -70,13 +64,6 @@
[b]Note:[/b] This is different from the [code]Bone2D[/code]'s rotation. The bone angle is the rotation of the bone shown by the [code]Bone2D[/code] gizmo, and because [code]Bone2D[/code] bones are based on positions, this can vary from the actual rotation of the [code]Bone2D[/code] node.
</description>
</method>
- <method name="set_default_length">
- <return type="void" />
- <param index="0" name="default_length" type="float" />
- <description>
- Deprecated. Please use [code]set_length[/code] instead.
- </description>
- </method>
<method name="set_length">
<return type="void" />
<param index="0" name="length" type="float" />
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_node.cpp b/editor/editor_node.cpp
index a0e876315c..b854da8e4f 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -8116,6 +8116,7 @@ void EditorPluginList::forward_3d_force_draw_over_viewport(Control *p_overlay) {
}
void EditorPluginList::add_plugin(EditorPlugin *p_plugin) {
+ ERR_FAIL_COND(plugins_list.has(p_plugin));
plugins_list.push_back(p_plugin);
}
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/editor/renames_map_3_to_4.cpp b/editor/renames_map_3_to_4.cpp
index 4df6092558..277df4e66c 100644
--- a/editor/renames_map_3_to_4.cpp
+++ b/editor/renames_map_3_to_4.cpp
@@ -291,6 +291,7 @@ const char *RenamesMap3To4::gdscript_function_renames[][2] = {
{ "get_cull_mask_bit", "get_cull_mask_value" }, // Camera3D
{ "get_cursor_position", "get_caret_column" }, // LineEdit
{ "get_d", "get_distance" }, // LineShape2D
+ { "get_default_length", "get_length" }, // Bone2D
{ "get_depth_bias_enable", "get_depth_bias_enabled" }, // RDPipelineRasterizationState
{ "get_device", "get_output_device" }, // AudioServer
{ "get_device_list", "get_output_device_list" }, // AudioServer
@@ -490,6 +491,7 @@ const char *RenamesMap3To4::gdscript_function_renames[][2] = {
{ "set_cull_mask_bit", "set_cull_mask_value" }, // Camera3D
{ "set_cursor_position", "set_caret_column" }, // LineEdit
{ "set_d", "set_distance" }, // WorldMarginShape2D
+ { "set_default_length", "set_length" }, // Bone2D
{ "set_depth_bias_enable", "set_depth_bias_enabled" }, // RDPipelineRasterizationState
{ "set_device", "set_output_device" }, // AudioServer
{ "set_doubleclick", "set_double_click" }, // InputEventMouseButton
@@ -749,6 +751,7 @@ const char *RenamesMap3To4::csharp_function_renames[][2] = {
{ "GetCullMaskBit", "GetCullMaskValue" }, // Camera3D
{ "GetCursorPosition", "GetCaretColumn" }, // LineEdit
{ "GetD", "GetDistance" }, // LineShape2D
+ { "GetDefaultLength", "GetLength" }, // Bone2D
{ "GetDepthBiasEnable", "GetDepthBiasEnabled" }, // RDPipelineRasterizationState
{ "GetDevice", "GetOutputDevice" }, // AudioServer
{ "GetDeviceList", "GetOutputDeviceList" }, // AudioServer
@@ -938,6 +941,7 @@ const char *RenamesMap3To4::csharp_function_renames[][2] = {
{ "SetCullMaskBit", "SetCullMaskValue" }, // Camera3D
{ "SetCursorPosition", "SetCaretColumn" }, // LineEdit
{ "SetD", "SetDistance" }, // WorldMarginShape2D
+ { "SetDefaultLength", "SetLength" }, // Bone2D
{ "SetDepthBiasEnable", "SetDepthBiasEnabled" }, // RDPipelineRasterizationState
{ "SetDevice", "SetOutputDevice" }, // AudioServer
{ "SetDoubleclick", "SetDoubleClick" }, // InputEventMouseButton
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index fe79f37454..00f8d2817a 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -2563,7 +2563,7 @@ GDScriptLanguage::GDScriptLanguage() {
script_frame_time = 0;
_debug_call_stack_pos = 0;
- int dmcs = GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/settings/gdscript/max_call_stack", PROPERTY_HINT_RANGE, "1024,4096,1,or_greater"), 1024);
+ int dmcs = GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/settings/gdscript/max_call_stack", PROPERTY_HINT_RANGE, "512," + itos(GDScriptFunction::MAX_CALL_DEPTH - 1) + ",1"), 1024);
if (EngineDebugger::is_active()) {
//debugging enabled!
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/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index f45c1f9577..2624fb8dd9 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -544,6 +544,8 @@ private:
#endif
public:
+ static constexpr int MAX_CALL_DEPTH = 2048; // Limit to try to avoid crash because of a stack overflow.
+
struct CallState {
GDScript *script = nullptr;
GDScriptInstance *instance = nullptr;
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 44c95a1c32..9f7d27d841 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -459,6 +459,33 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
r_err.error = Callable::CallError::CALL_OK;
+ static thread_local int call_depth = 0;
+ if (unlikely(++call_depth > MAX_CALL_DEPTH)) {
+ call_depth--;
+#ifdef DEBUG_ENABLED
+ String err_file;
+ if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && !p_instance->script->path.is_empty()) {
+ err_file = p_instance->script->path;
+ } else if (_script) {
+ err_file = _script->path;
+ }
+ if (err_file.is_empty()) {
+ err_file = "<built-in>";
+ }
+ String err_func = name;
+ if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && !p_instance->script->name.is_empty()) {
+ err_func = p_instance->script->name + "." + err_func;
+ }
+ int err_line = _initial_line;
+ const char *err_text = "Stack overflow. Check for infinite recursion in your script.";
+ if (!GDScriptLanguage::get_singleton()->debug_break(err_text, false)) {
+ // Debugger break did not happen.
+ _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text, false, ERR_HANDLER_SCRIPT);
+ }
+#endif
+ return _get_default_variant_for_data_type(return_type);
+ }
+
Variant retvalue;
Variant *stack = nullptr;
Variant **instruction_args = nullptr;
@@ -493,10 +520,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
r_err.argument = _argument_count;
+ call_depth--;
return _get_default_variant_for_data_type(return_type);
} else if (p_argcount < _argument_count - _default_arg_count) {
r_err.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_err.argument = _argument_count - _default_arg_count;
+ call_depth--;
return _get_default_variant_for_data_type(return_type);
} else {
defarg = _argument_count - p_argcount;
@@ -524,6 +553,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_err.argument = i;
r_err.expected = argument_types[i].builtin_type;
+ call_depth--;
return _get_default_variant_for_data_type(return_type);
}
if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
@@ -3597,5 +3627,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
stack[i].~Variant();
}
+ call_depth--;
+
return retvalue;
}
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/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp
index bb96308a75..5a097adf39 100644
--- a/platform/macos/export/export_plugin.cpp
+++ b/platform/macos/export/export_plugin.cpp
@@ -137,7 +137,7 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "application/copyright_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), true));
#ifdef MACOS_ENABLED
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/codesign", PROPERTY_HINT_ENUM, "Disabled,Built-in (ad-hoc only),rcodesign,Xcode codesign"), 3, true));
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/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp
index 96711bbe72..4fdc7b3584 100644
--- a/scene/2d/skeleton_2d.cpp
+++ b/scene/2d/skeleton_2d.cpp
@@ -378,9 +378,6 @@ void Bone2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_skeleton_rest"), &Bone2D::get_skeleton_rest);
ClassDB::bind_method(D_METHOD("get_index_in_skeleton"), &Bone2D::get_index_in_skeleton);
- ClassDB::bind_method(D_METHOD("set_default_length", "default_length"), &Bone2D::set_default_length);
- ClassDB::bind_method(D_METHOD("get_default_length"), &Bone2D::get_default_length);
-
ClassDB::bind_method(D_METHOD("set_autocalculate_length_and_angle", "auto_calculate"), &Bone2D::set_autocalculate_length_and_angle);
ClassDB::bind_method(D_METHOD("get_autocalculate_length_and_angle"), &Bone2D::get_autocalculate_length_and_angle);
ClassDB::bind_method(D_METHOD("set_length", "length"), &Bone2D::set_length);
@@ -416,16 +413,6 @@ void Bone2D::apply_rest() {
set_transform(rest);
}
-void Bone2D::set_default_length(real_t p_length) {
- WARN_DEPRECATED_MSG("set_default_length is deprecated. Please use set_length instead!");
- set_length(p_length);
-}
-
-real_t Bone2D::get_default_length() const {
- WARN_DEPRECATED_MSG("get_default_length is deprecated. Please use get_length instead!");
- return get_length();
-}
-
int Bone2D::get_index_in_skeleton() const {
ERR_FAIL_COND_V(!skeleton, -1);
skeleton->_update_bone_setup();
diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h
index 149ab64306..6a36a31552 100644
--- a/scene/2d/skeleton_2d.h
+++ b/scene/2d/skeleton_2d.h
@@ -80,9 +80,6 @@ public:
PackedStringArray get_configuration_warnings() const override;
- void set_default_length(real_t p_length);
- real_t get_default_length() const;
-
void set_autocalculate_length_and_angle(bool p_autocalculate);
bool get_autocalculate_length_and_angle() const;
void set_length(real_t p_length);
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;
}