diff options
31 files changed, 175 insertions, 127 deletions
diff --git a/core/error/error_macros.cpp b/core/error/error_macros.cpp index 61bb949ed4..c236f30945 100644 --- a/core/error/error_macros.cpp +++ b/core/error/error_macros.cpp @@ -37,9 +37,16 @@ static ErrorHandlerList *error_handler_list = nullptr; void add_error_handler(ErrorHandlerList *p_handler) { + // If p_handler is already in error_handler_list + // we'd better remove it first then we can add it. + // This prevent cyclic redundancy. + remove_error_handler(p_handler); + _global_lock(); + p_handler->next = error_handler_list; error_handler_list = p_handler; + _global_unlock(); } diff --git a/doc/classes/CPUParticles3D.xml b/doc/classes/CPUParticles3D.xml index 83728a807b..da9c63c0f7 100644 --- a/doc/classes/CPUParticles3D.xml +++ b/doc/classes/CPUParticles3D.xml @@ -96,13 +96,13 @@ Minimum angle. </member> <member name="angular_velocity_curve" type="Curve" setter="set_param_curve" getter="get_param_curve"> - Each particle's angular velocity will vary along this [Curve]. + Each particle's angular velocity (rotation speed) will vary along this [Curve] over its lifetime. </member> <member name="angular_velocity_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0"> - Maximum angular velocity. + Maximum initial angular velocity (rotation speed) applied to each particle in [i]degrees[/i] per second. </member> <member name="angular_velocity_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0"> - Minimum angular velocity. + Minimum initial angular velocity (rotation speed) applied to each particle in [i]degrees[/i] per second. </member> <member name="anim_offset_curve" type="Curve" setter="set_param_curve" getter="get_param_curve"> Each particle's animation offset will vary along this [Curve]. diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml index ed778af26a..d2261ed4cc 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticlesMaterial.xml @@ -83,13 +83,13 @@ Minimum angle. </member> <member name="angular_velocity_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture"> - Each particle's angular velocity will vary along this [CurveTexture]. + Each particle's angular velocity (rotation speed) will vary along this [CurveTexture] over its lifetime. </member> <member name="angular_velocity_max" type="float" setter="set_param_max" getter="get_param_max" default="0.0"> - Maximum angular velocity. + Maximum initial angular velocity (rotation speed) applied to each particle in [i]degrees[/i] per second. </member> <member name="angular_velocity_min" type="float" setter="set_param_min" getter="get_param_min" default="0.0"> - Minimum angular velocity. + Minimum initial angular velocity (rotation speed) applied to each particle in [i]degrees[/i] per second. </member> <member name="anim_offset_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture"> Each particle's animation offset will vary along this [CurveTexture]. diff --git a/doc/classes/PhysicsDirectBodyState2D.xml b/doc/classes/PhysicsDirectBodyState2D.xml index fbadfd2702..9921974c6e 100644 --- a/doc/classes/PhysicsDirectBodyState2D.xml +++ b/doc/classes/PhysicsDirectBodyState2D.xml @@ -208,7 +208,7 @@ </methods> <members> <member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity"> - The body's rotational velocity. + The body's rotational velocity in [i]radians[/i] per second. </member> <member name="center_of_mass" type="Vector2" setter="" getter="get_center_of_mass"> The body's center of mass position relative to the body's center in the global coordinate system. @@ -223,7 +223,7 @@ The inverse of the mass of the body. </member> <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity"> - The body's linear velocity. + The body's linear velocity in pixels per second. </member> <member name="sleeping" type="bool" setter="set_sleep_state" getter="is_sleeping"> If [code]true[/code], this body is currently sleeping (not active). diff --git a/doc/classes/PhysicsDirectBodyState3D.xml b/doc/classes/PhysicsDirectBodyState3D.xml index 58c4294d66..77c99c55b1 100644 --- a/doc/classes/PhysicsDirectBodyState3D.xml +++ b/doc/classes/PhysicsDirectBodyState3D.xml @@ -215,7 +215,7 @@ </methods> <members> <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity"> - The body's rotational velocity. + The body's rotational velocity in [i]radians[/i] per second. </member> <member name="center_of_mass" type="Vector3" setter="" getter="get_center_of_mass"> The body's center of mass position relative to the body's center in the global coordinate system. @@ -230,7 +230,7 @@ The inverse of the mass of the body. </member> <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity"> - The body's linear velocity. + The body's linear velocity in units per second. </member> <member name="principal_inertia_axes" type="Basis" setter="" getter="get_principal_inertia_axes"> </member> diff --git a/doc/classes/RigidDynamicBody2D.xml b/doc/classes/RigidDynamicBody2D.xml index 0026c49651..b3644711a0 100644 --- a/doc/classes/RigidDynamicBody2D.xml +++ b/doc/classes/RigidDynamicBody2D.xml @@ -121,7 +121,7 @@ Defines how [member angular_damp] is applied. See [enum DampMode] for possible values. </member> <member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity" default="0.0"> - The body's rotational velocity. + The body's rotational velocity in [i]radians[/i] per second. </member> <member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true"> If [code]true[/code], the body can enter sleep mode when there is no movement. See [member sleeping]. @@ -179,7 +179,7 @@ Defines how [member linear_damp] is applied. See [enum DampMode] for possible values. </member> <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector2(0, 0)"> - The body's linear velocity. + The body's linear velocity in pixels per second. Can be used sporadically, but [b]don't set this every frame[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state. </member> <member name="lock_rotation" type="bool" setter="set_lock_rotation_enabled" getter="is_lock_rotation_enabled" default="false"> If [code]true[/code], the body cannot rotate. Gravity and forces only apply linear movement. diff --git a/doc/classes/RigidDynamicBody3D.xml b/doc/classes/RigidDynamicBody3D.xml index 3dffdcbf83..16fced737f 100644 --- a/doc/classes/RigidDynamicBody3D.xml +++ b/doc/classes/RigidDynamicBody3D.xml @@ -127,7 +127,7 @@ Defines how [member angular_damp] is applied. See [enum DampMode] for possible values. </member> <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity" default="Vector3(0, 0, 0)"> - RigidDynamicBody3D's rotational velocity. + The RigidDynamicBody3D's rotational velocity in [i]radians[/i] per second. </member> <member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true"> If [code]true[/code], the body can enter sleep mode when there is no movement. See [member sleeping]. @@ -185,7 +185,7 @@ Defines how [member linear_damp] is applied. See [enum DampMode] for possible values. </member> <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector3(0, 0, 0)"> - The body's linear velocity. Can be used sporadically, but [b]don't set this every frame[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state. + The body's linear velocity in units per second. Can be used sporadically, but [b]don't set this every frame[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state. </member> <member name="lock_rotation" type="bool" setter="set_lock_rotation_enabled" getter="is_lock_rotation_enabled" default="false"> If [code]true[/code], the body cannot rotate. Gravity and forces only apply linear movement. diff --git a/doc/classes/ScrollContainer.xml b/doc/classes/ScrollContainer.xml index 94d9bfdc31..676c62c93c 100644 --- a/doc/classes/ScrollContainer.xml +++ b/doc/classes/ScrollContainer.xml @@ -16,6 +16,12 @@ <argument index="0" name="control" type="Control" /> <description> Ensures the given [code]control[/code] is visible (must be a direct or indirect child of the ScrollContainer). Used by [member follow_focus]. + [b]Note:[/b] This will not work on a node that was just added during the same frame. If you want to scroll to a newly added child, you must wait until the next frame using [signal SceneTree.process_frame]: + [codeblock] + add_child(child_node) + await get_tree().process_frame + ensure_control_visible(child_node) + [/codeblock] </description> </method> <method name="get_h_scrollbar"> diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 14185ce2a4..a53938e3f1 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -413,17 +413,21 @@ bool EditorProperty::is_read_only() const { return read_only; } -Variant EditorPropertyRevert::get_property_revert_value(Object *p_object, const StringName &p_property) { +Variant EditorPropertyRevert::get_property_revert_value(Object *p_object, const StringName &p_property, bool *r_is_valid) { if (p_object->has_method("property_can_revert") && p_object->call("property_can_revert", p_property)) { + if (r_is_valid) { + *r_is_valid = true; + } return p_object->call("property_get_revert", p_property); } - return PropertyUtils::get_property_default_value(p_object, p_property); + return PropertyUtils::get_property_default_value(p_object, p_property, r_is_valid); } bool EditorPropertyRevert::can_property_revert(Object *p_object, const StringName &p_property) { - Variant revert_value = EditorPropertyRevert::get_property_revert_value(p_object, p_property); - if (revert_value.get_type() == Variant::NIL) { + bool is_valid_revert = false; + Variant revert_value = EditorPropertyRevert::get_property_revert_value(p_object, p_property, &is_valid_revert); + if (!is_valid_revert) { return false; } Variant current_value = p_object->get(p_property); @@ -637,7 +641,9 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) { } if (revert_rect.has_point(mpos)) { - Variant revert_value = EditorPropertyRevert::get_property_revert_value(object, property); + bool is_valid_revert = false; + Variant revert_value = EditorPropertyRevert::get_property_revert_value(object, property, &is_valid_revert); + ERR_FAIL_COND(!is_valid_revert); emit_changed(property, revert_value); update_property(); } @@ -783,8 +789,9 @@ static bool _is_value_potential_override(Node *p_node, const String &p_property) if (states_stack.size()) { return true; } else { + bool is_valid_default = false; bool is_class_default = false; - PropertyUtils::get_property_default_value(p_node, p_property, &states_stack, false, nullptr, &is_class_default); + PropertyUtils::get_property_default_value(p_node, p_property, &is_valid_default, &states_stack, false, nullptr, &is_class_default); return !is_class_default; } } diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index f2dfe32f82..d247978649 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -46,7 +46,7 @@ public: static bool get_instantiated_node_original_property(Node *p_node, const StringName &p_prop, Variant &value, bool p_check_class_default = true); static bool is_node_property_different(Node *p_node, const Variant &p_current, const Variant &p_orig); static bool is_property_value_different(const Variant &p_a, const Variant &p_b); - static Variant get_property_revert_value(Object *p_object, const StringName &p_property); + static Variant get_property_revert_value(Object *p_object, const StringName &p_property, bool *r_is_valid); static bool can_property_revert(Object *p_object, const StringName &p_property); }; diff --git a/editor/editor_toaster.cpp b/editor/editor_toaster.cpp index 0d9a546b8e..05b895519d 100644 --- a/editor/editor_toaster.cpp +++ b/editor/editor_toaster.cpp @@ -173,11 +173,7 @@ void EditorToaster::_error_handler(void *p_self, const char *p_func, const char } Severity severity = (p_type == ERR_HANDLER_WARNING) ? SEVERITY_WARNING : SEVERITY_ERROR; - if (Thread::get_caller_id() != Thread::get_main_id()) { - EditorToaster::get_singleton()->call_deferred(SNAME("popup_str"), err_str, severity, tooltip_str); - } else { - EditorToaster::get_singleton()->popup_str(err_str, severity, tooltip_str); - } + EditorToaster::get_singleton()->popup_str(err_str, severity, tooltip_str); } } @@ -387,6 +383,12 @@ Control *EditorToaster::popup(Control *p_control, Severity p_severity, double p_ } void EditorToaster::popup_str(String p_message, Severity p_severity, String p_tooltip) { + // Since "_popup_str" adds nodes to the tree, and since the "add_child" method is not + // thread-safe, it's better to defer the call to the next cycle to be thread-safe. + call_deferred(SNAME("_popup_str"), p_message, p_severity, p_tooltip); +} + +void EditorToaster::_popup_str(String p_message, Severity p_severity, String p_tooltip) { // Check if we already have a popup with the given message. Control *control = nullptr; for (KeyValue<Control *, Toast> element : toasts) { @@ -440,6 +442,11 @@ EditorToaster *EditorToaster::get_singleton() { return singleton; } +void EditorToaster::_bind_methods() { + // Binding method to make it defer-able. + ClassDB::bind_method(D_METHOD("_popup_str", "message", "severity", "tooltip"), &EditorToaster::_popup_str); +} + EditorToaster::EditorToaster() { set_notify_transform(true); set_process_internal(true); diff --git a/editor/editor_toaster.h b/editor/editor_toaster.h index aac80d8fb1..502498986a 100644 --- a/editor/editor_toaster.h +++ b/editor/editor_toaster.h @@ -94,9 +94,11 @@ private: void _set_notifications_enabled(bool p_enabled); void _repop_old(); + void _popup_str(String p_message, Severity p_severity, String p_tooltip); protected: static EditorToaster *singleton; + static void _bind_methods(); void _notification(int p_what); diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index c99b34e0c2..ad22aafb2b 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -216,6 +216,7 @@ void PluginConfigDialog::config(const String &p_config_path) { active_edit->hide(); Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 2))->hide(); subfolder_edit->hide(); + subfolder_validation->hide(); Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 2))->hide(); set_title(TTR("Edit a Plugin")); } else { @@ -224,6 +225,7 @@ void PluginConfigDialog::config(const String &p_config_path) { active_edit->show(); Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 2))->show(); subfolder_edit->show(); + subfolder_validation->show(); Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 2))->show(); set_title(TTR("Create a Plugin")); } diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 0925b34ac1..951af92467 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -231,6 +231,7 @@ void EditorAssetLibraryItemDescription::configure(const String &p_title, int p_a description->pop(); description->add_text("\n" + TTR("Description:") + "\n\n"); description->append_text(p_description); + description->set_selection_enabled(true); set_title(p_title); } diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index 7a85c5167b..2ce13b717a 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -398,7 +398,7 @@ void MeshInstance3DEditor::_create_outline_mesh() { } if (mesh->get_surface_count() == 0) { - err_dialog->set_text(TTR("Mesh has not surface to create outlines from.")); + err_dialog->set_text(TTR("Mesh has no surface to create outlines from.")); err_dialog->popup_centered(); return; } else if (mesh->get_surface_count() == 1 && mesh->surface_get_primitive_type(0) != Mesh::PRIMITIVE_TRIANGLES) { diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 1934850160..f7d8d471ce 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -432,7 +432,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } break; case TOOL_CUT: case TOOL_COPY: { - if (!edited_scene || !_validate_no_foreign()) { + if (!edited_scene || (p_tool == TOOL_CUT && !_validate_no_foreign())) { break; } @@ -3157,8 +3157,9 @@ void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap) states_stack_ready = true; } - Variant orig = PropertyUtils::get_property_default_value(p_node, E.name, &states_stack); - if (!PropertyUtils::is_property_value_different(v, orig)) { + bool is_valid_default = false; + Variant orig = PropertyUtils::get_property_default_value(p_node, E.name, &is_valid_default, &states_stack); + if (is_valid_default && !PropertyUtils::is_property_value_different(v, orig)) { continue; } diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 1ecde53dd0..7b64c0564e 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -484,7 +484,7 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type result = parser->head->get_datatype(); } else { Ref<GDScriptParserRef> ref = get_parser_for(ScriptServer::get_global_class_path(first)); - if (ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED) != OK) { + if (!ref.is_valid() || ref->raise_status(GDScriptParserRef::INTERFACE_SOLVED) != OK) { push_error(vformat(R"(Could not parse global class "%s" from "%s".)", first, ScriptServer::get_global_class_path(first)), p_type); return GDScriptParser::DataType(); } @@ -3691,9 +3691,27 @@ bool GDScriptAnalyzer::validate_call_arg(const List<GDScriptParser::DataType> &p bool GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_local, const String &p_context) { const StringName &name = p_local->name; GDScriptParser::DataType base = parser->current_class->get_datatype(); - GDScriptParser::ClassNode *base_class = base.class_type; + { + List<MethodInfo> gdscript_funcs; + GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); + + for (MethodInfo &info : gdscript_funcs) { + if (info.name == name) { + parser->push_warning(p_local, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in function"); + return true; + } + } + if (Variant::has_utility_function(name)) { + parser->push_warning(p_local, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in function"); + return true; + } else if (ClassDB::class_exists(name)) { + parser->push_warning(p_local, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "global class"); + return true; + } + } + while (base_class != nullptr) { if (base_class->has_member(name)) { parser->push_warning(p_local, GDScriptWarning::SHADOWED_VARIABLE, p_context, p_local->name, base_class->get_member(name).get_type_name(), itos(base_class->get_member(name).get_line())); @@ -3938,7 +3956,9 @@ Ref<GDScriptParserRef> GDScriptAnalyzer::get_parser_for(const String &p_path) { } else { Error err = OK; ref = GDScriptCache::get_parser(p_path, GDScriptParserRef::EMPTY, err, parser->script_path); - depended_parsers[p_path] = ref; + if (ref.is_valid()) { + depended_parsers[p_path] = ref; + } } return ref; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 98a93a1a53..48f58e51fe 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -827,24 +827,9 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper return nullptr; } - GDScriptParser::IdentifierNode *identifier = parse_identifier(); - -#ifdef DEBUG_ENABLED - List<MethodInfo> gdscript_funcs; - GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); - for (MethodInfo &info : gdscript_funcs) { - if (info.name == identifier->name) { - push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "local variable", identifier->name, "built-in function"); - } - } - if (Variant::has_utility_function(identifier->name)) { - push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "local variable", identifier->name, "built-in function"); - } -#endif - VariableNode *variable = alloc_node<VariableNode>(); - variable->identifier = identifier; - variable->export_info.name = identifier->name; + variable->identifier = parse_identifier(); + variable->export_info.name = variable->identifier->name; if (match(GDScriptTokenizer::Token::COLON)) { if (check(GDScriptTokenizer::Token::NEWLINE)) { @@ -1097,24 +1082,8 @@ GDScriptParser::ParameterNode *GDScriptParser::parse_parameter() { return nullptr; } - GDScriptParser::IdentifierNode *identifier = parse_identifier(); -#ifdef DEBUG_ENABLED - List<MethodInfo> gdscript_funcs; - GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs); - for (MethodInfo &info : gdscript_funcs) { - if (info.name == identifier->name) { - push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "parameter", identifier->name, "built-in function"); - } - } - if (Variant::has_utility_function(identifier->name)) { - push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "parameter", identifier->name, "built-in function"); - } else if (ClassDB::class_exists(identifier->name)) { - push_warning(identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, "parameter", identifier->name, "global class"); - } -#endif - ParameterNode *parameter = alloc_node<ParameterNode>(); - parameter->identifier = identifier; + parameter->identifier = parse_identifier(); if (match(GDScriptTokenizer::Token::COLON)) { if (check((GDScriptTokenizer::Token::EQUAL))) { diff --git a/modules/gdscript/tests/scripts/parser/warnings/shadowed_global_identifier.out b/modules/gdscript/tests/scripts/parser/warnings/shadowed_global_identifier.out index f2b29e5bad..c613140eb8 100644 --- a/modules/gdscript/tests/scripts/parser/warnings/shadowed_global_identifier.out +++ b/modules/gdscript/tests/scripts/parser/warnings/shadowed_global_identifier.out @@ -1,9 +1,9 @@ GDTEST_OK >> WARNING >> Line: 2 ->> SHADOWED_GLOBAL_IDENTIFIER ->> The local variable 'abs' has the same name as a built-in function. ->> WARNING ->> Line: 2 >> UNUSED_VARIABLE >> The local variable 'abs' is declared but never used in the block. If this is intended, prefix it with an underscore: '_abs' +>> WARNING +>> Line: 2 +>> SHADOWED_GLOBAL_IDENTIFIER +>> The variable 'abs' has the same name as a built-in function. diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp index 9deea79ea6..991d258054 100644 --- a/modules/visual_script/editor/visual_script_editor.cpp +++ b/modules/visual_script/editor/visual_script_editor.cpp @@ -3704,7 +3704,7 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i Variant::construct(pinfo.type, existing, &existingp, 1, ce); } - default_value_edit->set_position(Object::cast_to<Control>(p_button)->get_screen_position() + Vector2(0, Object::cast_to<Control>(p_button)->get_size().y)); + default_value_edit->set_position(Object::cast_to<Control>(p_button)->get_screen_position() + Vector2(0, Object::cast_to<Control>(p_button)->get_size().y) * graph->get_zoom()); default_value_edit->reset_size(); if (pinfo.type == Variant::NODE_PATH) { diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index d2cf9a62ee..d7d78ff5dc 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -484,6 +484,9 @@ Error OS_Windows::create_process(const String &p_path, const List<String> &p_arg #ifndef DEBUG_ENABLED dwCreationFlags |= CREATE_NO_WINDOW; #endif + if (p_path == get_executable_path() && GetConsoleWindow() != nullptr) { + dwCreationFlags |= CREATE_NEW_CONSOLE; + } int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, dwCreationFlags, nullptr, nullptr, si_w, &pi.pi); ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command); diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 6a8788ee6e..54e34b585e 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -42,9 +42,9 @@ Dictionary Node2D::_edit_get_state() const { } void Node2D::_edit_set_state(const Dictionary &p_state) { - pos = p_state["position"]; - angle = p_state["rotation"]; - _scale = p_state["scale"]; + position = p_state["position"]; + rotation = p_state["rotation"]; + scale = p_state["scale"]; skew = p_state["skew"]; _update_transform(); @@ -55,7 +55,7 @@ void Node2D::_edit_set_position(const Point2 &p_position) { } Point2 Node2D::_edit_get_position() const { - return pos; + return position; } void Node2D::_edit_set_scale(const Size2 &p_scale) { @@ -63,16 +63,16 @@ void Node2D::_edit_set_scale(const Size2 &p_scale) { } Size2 Node2D::_edit_get_scale() const { - return _scale; + return scale; } void Node2D::_edit_set_rotation(real_t p_rotation) { - angle = p_rotation; + rotation = p_rotation; _update_transform(); } real_t Node2D::_edit_get_rotation() const { - return angle; + return rotation; } bool Node2D::_edit_use_rotation() const { @@ -85,48 +85,44 @@ void Node2D::_edit_set_rect(const Rect2 &p_edit_rect) { Rect2 r = _edit_get_rect(); Vector2 zero_offset; - if (r.size.x != 0) { - zero_offset.x = -r.position.x / r.size.x; - } - if (r.size.y != 0) { - zero_offset.y = -r.position.y / r.size.y; - } - Size2 new_scale(1, 1); if (r.size.x != 0) { + zero_offset.x = -r.position.x / r.size.x; new_scale.x = p_edit_rect.size.x / r.size.x; } + if (r.size.y != 0) { + zero_offset.y = -r.position.y / r.size.y; new_scale.y = p_edit_rect.size.y / r.size.y; } Point2 new_pos = p_edit_rect.position + p_edit_rect.size * zero_offset; Transform2D postxf; - postxf.set_rotation_scale_and_skew(angle, _scale, skew); + postxf.set_rotation_scale_and_skew(rotation, scale, skew); new_pos = postxf.xform(new_pos); - pos += new_pos; - _scale *= new_scale; + position += new_pos; + scale *= new_scale; _update_transform(); } #endif void Node2D::_update_xform_values() { - pos = _mat.elements[2]; - angle = _mat.get_rotation(); - _scale = _mat.get_scale(); - skew = _mat.get_skew(); + position = transform.elements[2]; + rotation = transform.get_rotation(); + scale = transform.get_scale(); + skew = transform.get_skew(); _xform_dirty = false; } void Node2D::_update_transform() { - _mat.set_rotation_scale_and_skew(angle, _scale, skew); - _mat.elements[2] = pos; + transform.set_rotation_scale_and_skew(rotation, scale, skew); + transform.elements[2] = position; - RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), _mat); + RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), transform); if (!is_inside_tree()) { return; @@ -139,7 +135,7 @@ void Node2D::set_position(const Point2 &p_pos) { if (_xform_dirty) { ((Node2D *)this)->_update_xform_values(); } - pos = p_pos; + position = p_pos; _update_transform(); } @@ -147,7 +143,7 @@ void Node2D::set_rotation(real_t p_radians) { if (_xform_dirty) { ((Node2D *)this)->_update_xform_values(); } - angle = p_radians; + rotation = p_radians; _update_transform(); } @@ -163,13 +159,13 @@ void Node2D::set_scale(const Size2 &p_scale) { if (_xform_dirty) { ((Node2D *)this)->_update_xform_values(); } - _scale = p_scale; + scale = p_scale; // Avoid having 0 scale values, can lead to errors in physics and rendering. - if (Math::is_zero_approx(_scale.x)) { - _scale.x = CMP_EPSILON; + if (Math::is_zero_approx(scale.x)) { + scale.x = CMP_EPSILON; } - if (Math::is_zero_approx(_scale.y)) { - _scale.y = CMP_EPSILON; + if (Math::is_zero_approx(scale.y)) { + scale.y = CMP_EPSILON; } _update_transform(); } @@ -178,7 +174,7 @@ Point2 Node2D::get_position() const { if (_xform_dirty) { ((Node2D *)this)->_update_xform_values(); } - return pos; + return position; } real_t Node2D::get_rotation() const { @@ -186,7 +182,7 @@ real_t Node2D::get_rotation() const { ((Node2D *)this)->_update_xform_values(); } - return angle; + return rotation; } real_t Node2D::get_skew() const { @@ -202,11 +198,11 @@ Size2 Node2D::get_scale() const { ((Node2D *)this)->_update_xform_values(); } - return _scale; + return scale; } Transform2D Node2D::get_transform() const { - return _mat; + return transform; } void Node2D::rotate(real_t p_radians) { @@ -287,10 +283,10 @@ void Node2D::set_global_scale(const Size2 &p_scale) { } void Node2D::set_transform(const Transform2D &p_transform) { - _mat = p_transform; + transform = p_transform; _xform_dirty = true; - RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), _mat); + RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), transform); if (!is_inside_tree()) { return; diff --git a/scene/2d/node_2d.h b/scene/2d/node_2d.h index 3e66541e32..41897127b1 100644 --- a/scene/2d/node_2d.h +++ b/scene/2d/node_2d.h @@ -36,15 +36,15 @@ class Node2D : public CanvasItem { GDCLASS(Node2D, CanvasItem); - Point2 pos; - real_t angle = 0.0; - Size2 _scale = Vector2(1, 1); + Point2 position; + real_t rotation = 0.0; + Size2 scale = Vector2(1, 1); real_t skew = 0.0; int z_index = 0; bool z_relative = true; bool y_sort_enabled = false; - Transform2D _mat; + Transform2D transform; bool _xform_dirty = false; diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 910cf3a37d..58cd42010f 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -884,15 +884,16 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa Light3D *light = lights_found[i].light; Transform3D xf = lights_found[i].xform; + Color linear_color = light->get_color().to_linear(); if (Object::cast_to<DirectionalLight3D>(light)) { DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light); - lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE)); + lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE)); } else if (Object::cast_to<OmniLight3D>(light)) { OmniLight3D *l = Object::cast_to<OmniLight3D>(light); - lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); + lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); } else if (Object::cast_to<SpotLight3D>(light)) { SpotLight3D *l = Object::cast_to<SpotLight3D>(light); - lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); + lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); } } for (int i = 0; i < probes_found.size(); i++) { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index c9060033f2..63e3740a97 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -4275,7 +4275,10 @@ double TextEdit::get_scroll_pos_for_line(int p_line, int p_wrap_index) const { return p_line; } - double new_line_scroll_pos = get_visible_line_count_in_range(0, CLAMP(p_line, 0, text.size() - 1)); + double new_line_scroll_pos = 0.0; + if (p_line > 0) { + new_line_scroll_pos = get_visible_line_count_in_range(0, MIN(p_line - 1, text.size() - 1)); + } new_line_scroll_pos += p_wrap_index; return new_line_scroll_pos; } @@ -4339,7 +4342,7 @@ int TextEdit::get_visible_line_count_in_range(int p_from_line, int p_to_line) co /* Returns the total number of (lines + wrapped - hidden). */ if (!_is_hiding_enabled() && get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) { - return p_to_line - p_from_line; + return (p_to_line - p_from_line) + 1; } int total_rows = 0; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index af4032a77d..34845d5875 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -462,6 +462,10 @@ void Viewport::_notification(int p_what) { RenderingServer::get_singleton()->viewport_set_parent_viewport(viewport, RID()); } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + if (!get_tree()) { + return; + } + if (get_tree()->is_debugging_collisions_hint() && contact_2d_debug.is_valid()) { RenderingServer::get_singleton()->canvas_item_clear(contact_2d_debug); RenderingServer::get_singleton()->canvas_item_set_draw_index(contact_2d_debug, 0xFFFFF); //very high index @@ -1183,7 +1187,7 @@ void Viewport::_gui_show_tooltip() { Control *tooltip_owner = nullptr; String tooltip_text = _gui_get_tooltip( gui.tooltip_control, - gui.tooltip_control->get_screen_transform().xform_inv(gui.last_mouse_pos), + gui.tooltip_control->get_global_transform().xform_inv(gui.last_mouse_pos), &tooltip_owner); tooltip_text = tooltip_text.strip_edges(); if (tooltip_text.is_empty()) { @@ -1712,7 +1716,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.tooltip_popup) { if (gui.tooltip_control) { - String tooltip = _gui_get_tooltip(over, gui.tooltip_control->get_screen_transform().xform_inv(mpos)); + String tooltip = _gui_get_tooltip(over, gui.tooltip_control->get_global_transform().xform_inv(mpos)); if (tooltip.length() == 0) { _gui_cancel_tooltip(); diff --git a/scene/property_utils.cpp b/scene/property_utils.cpp index e3c65bbc6e..6ffc1f148a 100644 --- a/scene/property_utils.cpp +++ b/scene/property_utils.cpp @@ -50,7 +50,7 @@ bool PropertyUtils::is_property_value_different(const Variant &p_a, const Varian } } -Variant PropertyUtils::get_property_default_value(const Object *p_object, const StringName &p_property, const Vector<SceneState::PackState> *p_states_stack_cache, bool p_update_exports, const Node *p_owner, bool *r_is_class_default) { +Variant PropertyUtils::get_property_default_value(const Object *p_object, const StringName &p_property, bool *r_is_valid, const Vector<SceneState::PackState> *p_states_stack_cache, bool p_update_exports, const Node *p_owner, bool *r_is_class_default) { // This function obeys the way property values are set when an object is instantiated, // which is the following (the latter wins): // 1. Default value from builtin class @@ -60,6 +60,9 @@ Variant PropertyUtils::get_property_default_value(const Object *p_object, const if (r_is_class_default) { *r_is_class_default = false; } + if (r_is_valid) { + *r_is_valid = false; + } Ref<Script> topmost_script; @@ -71,6 +74,9 @@ Variant PropertyUtils::get_property_default_value(const Object *p_object, const bool found = false; Variant value_in_ancestor = ia.state->get_property_value(ia.node, p_property, found); if (found) { + if (r_is_valid) { + *r_is_valid = true; + } return value_in_ancestor; } // Save script for later @@ -97,6 +103,9 @@ Variant PropertyUtils::get_property_default_value(const Object *p_object, const } Variant default_value; if (topmost_script->get_property_default_value(p_property, default_value)) { + if (r_is_valid) { + *r_is_valid = true; + } return default_value; } } @@ -105,7 +114,7 @@ Variant PropertyUtils::get_property_default_value(const Object *p_object, const if (r_is_class_default) { *r_is_class_default = true; } - return ClassDB::class_get_default_property_value(p_object->get_class_name(), p_property); + return ClassDB::class_get_default_property_value(p_object->get_class_name(), p_property, r_is_valid); } // Like SceneState::PackState, but using a raw pointer to avoid the cost of diff --git a/scene/property_utils.h b/scene/property_utils.h index fde9163548..aa06649cdc 100644 --- a/scene/property_utils.h +++ b/scene/property_utils.h @@ -38,7 +38,7 @@ class PropertyUtils { public: static bool is_property_value_different(const Variant &p_a, const Variant &p_b); // Gets the most pure default value, the one that would be set when the node has just been instantiated - static Variant get_property_default_value(const Object *p_object, const StringName &p_property, const Vector<SceneState::PackState> *p_states_stack_cache = nullptr, bool p_update_exports = false, const Node *p_owner = nullptr, bool *r_is_class_default = nullptr); + static Variant get_property_default_value(const Object *p_object, const StringName &p_property, bool *r_is_valid = nullptr, const Vector<SceneState::PackState> *p_states_stack_cache = nullptr, bool p_update_exports = false, const Node *p_owner = nullptr, bool *r_is_class_default = nullptr); // Gets the instance/inheritance states of this node, in order of precedence, // that is, from the topmost (the most able to override values) to the lowermost diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 9023b758b6..283a3a4883 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -882,6 +882,14 @@ void register_scene_types() { ClassDB::add_compatibility_class("GIProbeData", "VoxelGIData"); ClassDB::add_compatibility_class("BakedLightmap", "LightmapGI"); ClassDB::add_compatibility_class("BakedLightmapData", "LightmapGIData"); + // Portal and room occlusion was replaced by raster occlusion (OccluderInstance3D node). + ClassDB::add_compatibility_class("Portal", "Node3D"); + ClassDB::add_compatibility_class("Room", "Node3D"); + ClassDB::add_compatibility_class("RoomManager", "Node3D"); + ClassDB::add_compatibility_class("RoomGroup", "Node3D"); + ClassDB::add_compatibility_class("Occluder", "Node3D"); + // The OccluderShapeSphere resource (used in the old Occluder node) is not present anymore. + ClassDB::add_compatibility_class("OccluderShapeSphere", "Resource"); // Renamed in 4.0. // Keep alphabetical ordering to easily locate classes and avoid duplicates. diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index e6b499d4f1..b2a339b850 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -501,8 +501,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map Variant value = forced_value.get_type() == Variant::NIL ? p_node->get(name) : forced_value; if (!pinned_props.has(name) && forced_value.get_type() == Variant::NIL) { - Variant default_value = PropertyUtils::get_property_default_value(p_node, name, &states_stack, true); - if (!PropertyUtils::is_property_value_different(value, default_value)) { + bool is_valid_default = false; + Variant default_value = PropertyUtils::get_property_default_value(p_node, name, &is_valid_default, &states_stack, true); + if (is_valid_default && !PropertyUtils::is_property_value_different(value, default_value)) { continue; } } diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 0c0ee67962..b077501a38 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -5314,7 +5314,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (tk.type == TK_CURSOR) { //do nothing - } else if (tk.type == TK_IDENTIFIER) { } else if (tk.type == TK_PERIOD) { DataType dt = expr->get_datatype(); String st = expr->get_datatype_name(); @@ -6931,7 +6930,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun block->parent_block = p_block; cf->blocks.push_back(block); err = _parse_block(block, p_function_info, true, p_can_break, p_can_continue); - + if (err) { + return err; + } } else { _set_tkpos(pos); //rollback } |