diff options
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; } |