From 2a8c59c171e609d739dcc59d15e3e205dbf47cde Mon Sep 17 00:00:00 2001 From: Nathan Franke Date: Thu, 29 Oct 2020 05:01:28 -0500 Subject: [PATCH] Use Array for node configuration warnings Previously, the warnings were passed as a string and delimitation of which were hard coded at each implementation. --- doc/classes/Node.xml | 14 +-- editor/scene_tree_editor.cpp | 6 +- scene/2d/animated_sprite_2d.cpp | 13 ++- scene/2d/animated_sprite_2d.h | 2 +- scene/2d/canvas_modulate.cpp | 23 ++--- scene/2d/canvas_modulate.h | 2 +- scene/2d/collision_object_2d.cpp | 11 +-- scene/2d/collision_object_2d.h | 2 +- scene/2d/collision_polygon_2d.cpp | 30 ++----- scene/2d/collision_polygon_2d.h | 2 +- scene/2d/collision_shape_2d.cpp | 16 ++-- scene/2d/collision_shape_2d.h | 2 +- scene/2d/cpu_particles_2d.cpp | 9 +- scene/2d/cpu_particles_2d.h | 2 +- scene/2d/gpu_particles_2d.cpp | 20 ++--- scene/2d/gpu_particles_2d.h | 2 +- scene/2d/joints_2d.cpp | 53 ++++------- scene/2d/joints_2d.h | 2 +- scene/2d/light_2d.cpp | 13 ++- scene/2d/light_2d.h | 2 +- scene/2d/light_occluder_2d.cpp | 16 ++-- scene/2d/light_occluder_2d.h | 2 +- scene/2d/navigation_agent_2d.cpp | 11 +-- scene/2d/navigation_agent_2d.h | 2 +- scene/2d/navigation_obstacle_2d.cpp | 11 +-- scene/2d/navigation_obstacle_2d.h | 2 +- scene/2d/navigation_region_2d.cpp | 19 ++-- scene/2d/navigation_region_2d.h | 2 +- scene/2d/parallax_layer.cpp | 11 +-- scene/2d/parallax_layer.h | 2 +- scene/2d/path_2d.cpp | 17 ++-- scene/2d/path_2d.h | 2 +- scene/2d/physics_body_2d.cpp | 13 ++- scene/2d/physics_body_2d.h | 2 +- scene/2d/remote_transform_2d.cpp | 13 ++- scene/2d/remote_transform_2d.h | 2 +- scene/2d/skeleton_2d.cpp | 20 ++--- scene/2d/skeleton_2d.h | 2 +- scene/2d/tile_map.cpp | 15 ++-- scene/2d/tile_map.h | 2 +- scene/2d/visibility_notifier_2d.cpp | 11 +-- scene/2d/visibility_notifier_2d.h | 2 +- scene/3d/collision_object_3d.cpp | 11 +-- scene/3d/collision_object_3d.h | 2 +- scene/3d/collision_polygon_3d.cpp | 18 ++-- scene/3d/collision_polygon_3d.h | 2 +- scene/3d/collision_shape_3d.cpp | 23 ++--- scene/3d/collision_shape_3d.h | 2 +- scene/3d/cpu_particles_3d.cpp | 14 +-- scene/3d/cpu_particles_3d.h | 2 +- scene/3d/gi_probe.cpp | 14 ++- scene/3d/gi_probe.h | 2 +- scene/3d/gpu_particles_3d.cpp | 29 +++--- scene/3d/gpu_particles_3d.h | 2 +- scene/3d/light_3d.cpp | 33 +++---- scene/3d/light_3d.h | 4 +- scene/3d/navigation_agent_3d.cpp | 11 +-- scene/3d/navigation_agent_3d.h | 2 +- scene/3d/navigation_obstacle_3d.cpp | 13 ++- scene/3d/navigation_obstacle_3d.h | 2 +- scene/3d/navigation_region_3d.cpp | 21 ++--- scene/3d/navigation_region_3d.h | 2 +- scene/3d/path_3d.cpp | 32 +++---- scene/3d/path_3d.h | 2 +- scene/3d/physics_body_3d.cpp | 15 ++-- scene/3d/physics_body_3d.h | 2 +- scene/3d/physics_joint_3d.cpp | 53 ++++------- scene/3d/physics_joint_3d.h | 2 +- scene/3d/remote_transform_3d.cpp | 13 ++- scene/3d/remote_transform_3d.h | 2 +- scene/3d/soft_body_3d.cpp | 22 ++--- scene/3d/soft_body_3d.h | 2 +- scene/3d/sprite_3d.cpp | 13 ++- scene/3d/sprite_3d.h | 2 +- scene/3d/vehicle_body_3d.cpp | 11 +-- scene/3d/vehicle_body_3d.h | 2 +- scene/3d/world_environment.cpp | 31 +++---- scene/3d/world_environment.h | 2 +- scene/3d/xr_nodes.cpp | 118 ++++++++++--------------- scene/3d/xr_nodes.h | 8 +- scene/animation/animation_tree.cpp | 30 ++----- scene/animation/animation_tree.h | 2 +- scene/gui/container.cpp | 12 ++- scene/gui/container.h | 2 +- scene/gui/control.cpp | 15 ++-- scene/gui/control.h | 2 +- scene/gui/range.cpp | 16 ++-- scene/gui/range.h | 2 +- scene/gui/scroll_container.cpp | 12 ++- scene/gui/scroll_container.h | 2 +- scene/main/node.cpp | 26 ++++-- scene/main/node.h | 5 +- scene/main/shader_globals_override.cpp | 13 ++- scene/main/shader_globals_override.h | 2 +- scene/main/viewport.cpp | 11 +-- scene/main/viewport.h | 2 +- 96 files changed, 426 insertions(+), 674 deletions(-) diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 7750d45226a..b5335e47cdb 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -37,13 +37,13 @@ Corresponds to the [constant NOTIFICATION_EXIT_TREE] notification in [method Object._notification] and signal [signal tree_exiting]. To get notified when the node has already left the active tree, connect to the [signal tree_exited]. - - + + - The string returned from this method is displayed as a warning in the Scene Dock if the script that overrides it is a [code]tool[/code] script. - Returning an empty string produces no warning. - Call [method update_configuration_warning] when the warning needs to be updated for this node. + The elements in the array returned from this method are displayed as warnings in the Scene Dock if the script that overrides it is a [code]tool[/code] script. + Returning an empty array produces no warnings. + Call [method update_configuration_warnings] when the warnings need to be updated for this node. @@ -856,12 +856,12 @@ Sets whether this is an instance load placeholder. See [InstancePlaceholder]. - + Updates the warning displayed for this node in the Scene Dock. - Use [method _get_configuration_warning] to setup the warning message to display. + Use [method _get_configuration_warnings] to setup the warning message to display. diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index b5e9aec8540..ec37fa53b35 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -120,7 +120,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i } undo_redo->commit_action(); } else if (p_id == BUTTON_WARNING) { - String config_err = n->get_configuration_warning(); + String config_err = n->get_configuration_warnings_as_string(); if (config_err == String()) { return; } @@ -252,9 +252,9 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll if (can_rename) { //should be can edit.. - String warning = p_node->get_configuration_warning(); + String warning = p_node->get_configuration_warnings_as_string(); if (!warning.is_empty()) { - item->add_button(0, get_theme_icon("NodeWarning", "EditorIcons"), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + p_node->get_configuration_warning()); + item->add_button(0, get_theme_icon("NodeWarning", "EditorIcons"), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + warning); } int num_connections = p_node->get_persistent_signal_connection_count(); diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index 4aa079b0137..9ee37670d15 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -272,7 +272,7 @@ void AnimatedSprite2D::set_sprite_frames(const Ref &p_frames) { notify_property_list_changed(); _reset_timeout(); update(); - update_configuration_warning(); + update_configuration_warnings(); } Ref AnimatedSprite2D::get_sprite_frames() const { @@ -440,17 +440,14 @@ StringName AnimatedSprite2D::get_animation() const { return animation; } -String AnimatedSprite2D::get_configuration_warning() const { - String warning = Node2D::get_configuration_warning(); +TypedArray AnimatedSprite2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (frames.is_null()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite to display frames."); + warnings.push_back(TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite to display frames.")); } - return warning; + return warnings; } void AnimatedSprite2D::_bind_methods() { diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h index 14ecb18866b..ef0027edf16 100644 --- a/scene/2d/animated_sprite_2d.h +++ b/scene/2d/animated_sprite_2d.h @@ -109,7 +109,7 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; AnimatedSprite2D(); }; diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp index 5d5aaae5056..52eabefbcb5 100644 --- a/scene/2d/canvas_modulate.cpp +++ b/scene/2d/canvas_modulate.cpp @@ -51,7 +51,7 @@ void CanvasModulate::_notification(int p_what) { remove_from_group("_canvas_modulate_" + itos(get_canvas().get_id())); } - update_configuration_warning(); + update_configuration_warnings(); } } @@ -73,24 +73,19 @@ Color CanvasModulate::get_color() const { return color; } -String CanvasModulate::get_configuration_warning() const { - if (!is_visible_in_tree() || !is_inside_tree()) { - return String(); - } +TypedArray CanvasModulate::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); - String warning = Node2D::get_configuration_warning(); + if (is_visible_in_tree() && is_inside_tree()) { + List nodes; + get_tree()->get_nodes_in_group("_canvas_modulate_" + itos(get_canvas().get_id()), &nodes); - List nodes; - get_tree()->get_nodes_in_group("_canvas_modulate_" + itos(get_canvas().get_id()), &nodes); - - if (nodes.size() > 1) { - if (!warning.is_empty()) { - warning += "\n\n"; + if (nodes.size() > 1) { + warnings.push_back(TTR("Only one visible CanvasModulate is allowed per scene (or set of instanced scenes). The first created one will work, while the rest will be ignored.")); } - warning += TTR("Only one visible CanvasModulate is allowed per scene (or set of instanced scenes). The first created one will work, while the rest will be ignored."); } - return warning; + return warnings; } CanvasModulate::CanvasModulate() { diff --git a/scene/2d/canvas_modulate.h b/scene/2d/canvas_modulate.h index 4d55a5d9cbd..3d85a92a110 100644 --- a/scene/2d/canvas_modulate.h +++ b/scene/2d/canvas_modulate.h @@ -46,7 +46,7 @@ public: void set_color(const Color &p_color); Color get_color() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; CanvasModulate(); ~CanvasModulate(); diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index c83ed36917d..30728a2755d 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -363,17 +363,14 @@ void CollisionObject2D::_update_pickable() { } } -String CollisionObject2D::get_configuration_warning() const { - String warning = Node2D::get_configuration_warning(); +TypedArray CollisionObject2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (shapes.is_empty()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape2D or CollisionPolygon2D as a child to define its shape."); + warnings.push_back(TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape2D or CollisionPolygon2D as a child to define its shape.")); } - return warning; + return warnings; } void CollisionObject2D::_bind_methods() { diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h index e82b61d4413..7a1fd23e729 100644 --- a/scene/2d/collision_object_2d.h +++ b/scene/2d/collision_object_2d.h @@ -107,7 +107,7 @@ public: void set_pickable(bool p_enabled); bool is_pickable() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; _FORCE_INLINE_ RID get_rid() const { return rid; } diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index 38198c496e8..a69ef73a546 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -204,7 +204,7 @@ void CollisionPolygon2D::set_polygon(const Vector &p_polygon) { _update_in_shape_owner(); } update(); - update_configuration_warning(); + update_configuration_warnings(); } Vector CollisionPolygon2D::get_polygon() const { @@ -219,7 +219,7 @@ void CollisionPolygon2D::set_build_mode(BuildMode p_mode) { _update_in_shape_owner(); } update(); - update_configuration_warning(); + update_configuration_warnings(); } CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const { @@ -240,40 +240,28 @@ bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, doubl } #endif -String CollisionPolygon2D::get_configuration_warning() const { - String warning = Node2D::get_configuration_warning(); +TypedArray CollisionPolygon2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to(get_parent())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."); + warnings.push_back(TTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape.")); } int polygon_count = polygon.size(); if (polygon_count == 0) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("An empty CollisionPolygon2D has no effect on collision."); + warnings.push_back(TTR("An empty CollisionPolygon2D has no effect on collision.")); } else { bool solids = build_mode == BUILD_SOLIDS; if (solids) { if (polygon_count < 3) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Invalid polygon. At least 3 points are needed in 'Solids' build mode."); + warnings.push_back(TTR("Invalid polygon. At least 3 points are needed in 'Solids' build mode.")); } } else if (polygon_count < 2) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Invalid polygon. At least 2 points are needed in 'Segments' build mode."); + warnings.push_back(TTR("Invalid polygon. At least 2 points are needed in 'Segments' build mode.")); } } - return warning; + return warnings; } void CollisionPolygon2D::set_disabled(bool p_disabled) { diff --git a/scene/2d/collision_polygon_2d.h b/scene/2d/collision_polygon_2d.h index 9df98026293..95dd8c9e212 100644 --- a/scene/2d/collision_polygon_2d.h +++ b/scene/2d/collision_polygon_2d.h @@ -78,7 +78,7 @@ public: void set_polygon(const Vector &p_polygon); Vector get_polygon() const; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; void set_disabled(bool p_disabled); bool is_disabled() const; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 93949f741bc..d9009ef85ca 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -162,7 +162,7 @@ void CollisionShape2D::set_shape(const Ref &p_shape) { shape->connect("changed", callable_mp(this, &CollisionShape2D::_shape_changed)); } - update_configuration_warning(); + update_configuration_warnings(); } Ref CollisionShape2D::get_shape() const { @@ -177,19 +177,23 @@ bool CollisionShape2D::_edit_is_selected_on_click(const Point2 &p_point, double return shape->_edit_is_selected_on_click(p_point, p_tolerance); } -String CollisionShape2D::get_configuration_warning() const { +TypedArray CollisionShape2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); + if (!Object::cast_to(get_parent())) { - return TTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."); + warnings.push_back(TTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape.")); } if (!shape.is_valid()) { - return TTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!"); + warnings.push_back(TTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!")); } + Ref convex = shape; Ref concave = shape; if (convex.is_valid() || concave.is_valid()) { - return TTR("Polygon-based shapes are not meant be used nor edited directly through the CollisionShape2D node. Please use the CollisionPolygon2D node instead."); + warnings.push_back(TTR("Polygon-based shapes are not meant be used nor edited directly through the CollisionShape2D node. Please use the CollisionPolygon2D node instead.")); } - return String(); + + return warnings; } void CollisionShape2D::set_disabled(bool p_disabled) { diff --git a/scene/2d/collision_shape_2d.h b/scene/2d/collision_shape_2d.h index 695d0c6657f..eaf72627c82 100644 --- a/scene/2d/collision_shape_2d.h +++ b/scene/2d/collision_shape_2d.h @@ -72,7 +72,7 @@ public: void set_one_way_collision_margin(real_t p_margin); real_t get_one_way_collision_margin() const; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; CollisionShape2D(); }; diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 6a69a4c6184..5f2efeb8ca3 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -244,18 +244,15 @@ bool CPUParticles2D::get_fractional_delta() const { return fractional_delta; } -String CPUParticles2D::get_configuration_warning() const { - String warnings = Node2D::get_configuration_warning(); +TypedArray CPUParticles2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); CanvasItemMaterial *mat = Object::cast_to(get_material().ptr()); if (get_material().is_null() || (mat && !mat->get_particles_animation())) { if (get_param(PARAM_ANIM_SPEED) != 0.0 || get_param(PARAM_ANIM_OFFSET) != 0.0 || get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid()) { - if (warnings != String()) { - warnings += "\n"; - } - warnings += "- " + TTR("CPUParticles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled."); + warnings.push_back(TTR("CPUParticles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled.")); } } diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index ab04ee4a57b..ba34a0f45d6 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -275,7 +275,7 @@ public: void set_gravity(const Vector2 &p_gravity); Vector2 get_gravity() const; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; void restart(); diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index af70c47f7c8..8a0631a6148 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -137,7 +137,7 @@ void GPUParticles2D::set_process_material(const Ref &p_material) { } RS::get_singleton()->particles_set_process_material(particles, material_rid); - update_configuration_warning(); + update_configuration_warnings(); } void GPUParticles2D::set_speed_scale(float p_scale) { @@ -216,18 +216,15 @@ bool GPUParticles2D::get_fractional_delta() const { return fractional_delta; } -String GPUParticles2D::get_configuration_warning() const { +TypedArray GPUParticles2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); + if (RenderingServer::get_singleton()->is_low_end()) { - return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles2D\" option for this purpose."); + warnings.push_back(TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles2D\" option for this purpose.")); } - String warnings = Node2D::get_configuration_warning(); - if (process_material.is_null()) { - if (warnings != String()) { - warnings += "\n"; - } - warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted."); + warnings.push_back(TTR("A material to process the particles is not assigned, so no behavior is imprinted.")); } else { CanvasItemMaterial *mat = Object::cast_to(get_material().ptr()); @@ -236,10 +233,7 @@ String GPUParticles2D::get_configuration_warning() const { if (process && (process->get_param(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) { - if (warnings != String()) { - warnings += "\n"; - } - warnings += "- " + TTR("Particles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled."); + warnings.push_back(TTR("Particles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled.")); } } } diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index 774cef9cc92..20f9f768ede 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -110,7 +110,7 @@ public: void set_texture(const Ref &p_texture); Ref get_texture() const; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; void restart(); Rect2 capture_rect() const; diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp index 7d9cdd52acb..8a4ccc2f960 100644 --- a/scene/2d/joints_2d.cpp +++ b/scene/2d/joints_2d.cpp @@ -66,6 +66,7 @@ void Joint2D::_update_joint(bool p_only_free) { if (p_only_free || !is_inside_tree()) { PhysicsServer2D::get_singleton()->joint_clear(joint); warning = String(); + update_configuration_warnings(); return; } @@ -76,42 +77,25 @@ void Joint2D::_update_joint(bool p_only_free) { PhysicsBody2D *body_b = Object::cast_to(node_b); if (node_a && !body_a && node_b && !body_b) { - PhysicsServer2D::get_singleton()->joint_clear(joint); warning = TTR("Node A and Node B must be PhysicsBody2Ds"); - update_configuration_warning(); - return; - } - - if (node_a && !body_a) { - PhysicsServer2D::get_singleton()->joint_clear(joint); + } else if (node_a && !body_a) { warning = TTR("Node A must be a PhysicsBody2D"); - update_configuration_warning(); - return; - } - - if (node_b && !body_b) { - PhysicsServer2D::get_singleton()->joint_clear(joint); + } else if (node_b && !body_b) { warning = TTR("Node B must be a PhysicsBody2D"); - update_configuration_warning(); - return; - } - - if (!body_a || !body_b) { - PhysicsServer2D::get_singleton()->joint_clear(joint); + } else if (!body_a || !body_b) { warning = TTR("Joint is not connected to two PhysicsBody2Ds"); - update_configuration_warning(); - return; - } - - if (body_a == body_b) { - PhysicsServer2D::get_singleton()->joint_clear(joint); + } else if (body_a == body_b) { warning = TTR("Node A and Node B must be different PhysicsBody2Ds"); - update_configuration_warning(); - return; + } else { + warning = String(); } - warning = String(); - update_configuration_warning(); + update_configuration_warnings(); + + if (!warning.is_empty()) { + PhysicsServer2D::get_singleton()->joint_clear(joint); + return; + } if (body_a) { body_a->force_update_transform(); @@ -211,17 +195,14 @@ bool Joint2D::get_exclude_nodes_from_collision() const { return exclude_from_collision; } -String Joint2D::get_configuration_warning() const { - String node_warning = Node2D::get_configuration_warning(); +TypedArray Joint2D::get_configuration_warnings() const { + TypedArray warnings = Node2D::get_configuration_warnings(); if (!warning.is_empty()) { - if (!node_warning.is_empty()) { - node_warning += "\n\n"; - } - node_warning += warning; + warnings.push_back(warning); } - return node_warning; + return warnings; } void Joint2D::_bind_methods() { diff --git a/scene/2d/joints_2d.h b/scene/2d/joints_2d.h index 08e02ee29d3..dc5a08f815e 100644 --- a/scene/2d/joints_2d.h +++ b/scene/2d/joints_2d.h @@ -62,7 +62,7 @@ protected: _FORCE_INLINE_ bool is_configured() const { return configured; } public: - virtual String get_configuration_warning() const override; + virtual TypedArray get_configuration_warnings() const override; void set_node_a(const NodePath &p_node_a); NodePath get_node_a() const; diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 99e35cad1dc..8fb765f16bf 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -373,7 +373,7 @@ void PointLight2D::set_texture(const Ref &p_texture) { RS::get_singleton()->canvas_light_set_texture(_get_light(), RID()); } - update_configuration_warning(); + update_configuration_warnings(); } Ref PointLight2D::get_texture() const { @@ -390,17 +390,14 @@ Vector2 PointLight2D::get_texture_offset() const { return texture_offset; } -String PointLight2D::get_configuration_warning() const { - String warning = Node2D::get_configuration_warning(); +TypedArray PointLight2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!texture.is_valid()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("A texture with the shape of the light must be supplied to the \"Texture\" property."); + warnings.push_back(TTR("A texture with the shape of the light must be supplied to the \"Texture\" property.")); } - return warning; + return warnings; } void PointLight2D::set_texture_scale(real_t p_scale) { diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index ae6cf6d0a05..d9ecd81f1c8 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -169,7 +169,7 @@ public: void set_texture_scale(real_t p_scale); real_t get_texture_scale() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; PointLight2D(); }; diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp index 9589702e2e0..fdc28f81c2e 100644 --- a/scene/2d/light_occluder_2d.cpp +++ b/scene/2d/light_occluder_2d.cpp @@ -242,24 +242,18 @@ int LightOccluder2D::get_occluder_light_mask() const { return mask; } -String LightOccluder2D::get_configuration_warning() const { - String warning = Node2D::get_configuration_warning(); +TypedArray LightOccluder2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!occluder_polygon.is_valid()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("An occluder polygon must be set (or drawn) for this occluder to take effect."); + warnings.push_back(TTR("An occluder polygon must be set (or drawn) for this occluder to take effect.")); } if (occluder_polygon.is_valid() && occluder_polygon->get_polygon().size() == 0) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("The occluder polygon for this occluder is empty. Please draw a polygon."); + warnings.push_back(TTR("The occluder polygon for this occluder is empty. Please draw a polygon.")); } - return warning; + return warnings; } void LightOccluder2D::set_as_sdf_collision(bool p_enable) { diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h index f567c6d965a..b4a48d10629 100644 --- a/scene/2d/light_occluder_2d.h +++ b/scene/2d/light_occluder_2d.h @@ -106,7 +106,7 @@ public: void set_as_sdf_collision(bool p_enable); bool is_set_as_sdf_collision() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; LightOccluder2D(); ~LightOccluder2D(); diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 064fcc91a40..a18687afed7 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -239,17 +239,14 @@ void NavigationAgent2D::_avoidance_done(Vector3 p_new_velocity) { emit_signal("velocity_computed", velocity); } -String NavigationAgent2D::get_configuration_warning() const { - String warning = Node::get_configuration_warning(); +TypedArray NavigationAgent2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to(get_parent())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("The NavigationAgent2D can be used only under a Node2D node"); + warnings.push_back(TTR("The NavigationAgent2D can be used only under a Node2D node")); } - return warning; + return warnings; } void NavigationAgent2D::update_navigation() { diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h index 153ede8cec9..138ba3bc642 100644 --- a/scene/2d/navigation_agent_2d.h +++ b/scene/2d/navigation_agent_2d.h @@ -136,7 +136,7 @@ public: void set_velocity(Vector2 p_velocity); void _avoidance_done(Vector3 p_new_velocity); - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; private: void update_navigation(); diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index 965e2b6dc1e..a06f7a9fd07 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -69,17 +69,14 @@ NavigationObstacle2D::~NavigationObstacle2D() { agent = RID(); // Pointless } -String NavigationObstacle2D::get_configuration_warning() const { - String warning = Node::get_configuration_warning(); +TypedArray NavigationObstacle2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to(get_parent())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("The NavigationObstacle2D only serves to provide collision avoidance to a Node2D object."); + warnings.push_back(TTR("The NavigationObstacle2D only serves to provide collision avoidance to a Node2D object.")); } - return warning; + return warnings; } void NavigationObstacle2D::update_agent_shape() { diff --git a/scene/2d/navigation_obstacle_2d.h b/scene/2d/navigation_obstacle_2d.h index 135ca4651eb..9cffc2c0c35 100644 --- a/scene/2d/navigation_obstacle_2d.h +++ b/scene/2d/navigation_obstacle_2d.h @@ -52,7 +52,7 @@ public: return agent; } - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; private: void update_agent_shape(); diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index 8be8c8db4ae..d2caf5bea85 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -491,7 +491,7 @@ void NavigationRegion2D::set_navigation_polygon(const Ref &p_ } _navpoly_changed(); - update_configuration_warning(); + update_configuration_warnings(); } Ref NavigationRegion2D::get_navigation_polygon() const { @@ -509,21 +509,16 @@ void NavigationRegion2D::_map_changed(RID p_map) { } } -String NavigationRegion2D::get_configuration_warning() const { - if (!is_visible_in_tree() || !is_inside_tree()) { - return String(); - } +TypedArray NavigationRegion2D::get_configuration_warnings() const { + TypedArray warnings = Node2D::get_configuration_warnings(); - String warning = Node2D::get_configuration_warning(); - - if (!navpoly.is_valid()) { - if (!warning.is_empty()) { - warning += "\n\n"; + if (is_visible_in_tree() && is_inside_tree()) { + if (!navpoly.is_valid()) { + warnings.push_back(TTR("A NavigationMesh resource must be set or created for this node to work. Please set a property or draw a polygon.")); } - warning += TTR("A NavigationPolygon resource must be set or created for this node to work. Please set a property or draw a polygon."); } - return warning; + return warnings; } void NavigationRegion2D::_bind_methods() { diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h index 58f04599be9..2db8d70791f 100644 --- a/scene/2d/navigation_region_2d.h +++ b/scene/2d/navigation_region_2d.h @@ -120,7 +120,7 @@ public: void set_navigation_polygon(const Ref &p_navpoly); Ref get_navigation_polygon() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; NavigationRegion2D(); ~NavigationRegion2D(); diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index 725e858a43b..228020d3832 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -135,17 +135,14 @@ void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, real_t p_s _update_mirroring(); } -String ParallaxLayer::get_configuration_warning() const { - String warning = Node2D::get_configuration_warning(); +TypedArray ParallaxLayer::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to(get_parent())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("ParallaxLayer node only works when set as child of a ParallaxBackground node."); + warnings.push_back(TTR("ParallaxLayer node only works when set as child of a ParallaxBackground node.")); } - return warning; + return warnings; } void ParallaxLayer::_bind_methods() { diff --git a/scene/2d/parallax_layer.h b/scene/2d/parallax_layer.h index e826e6da9ce..cc2d2e096e7 100644 --- a/scene/2d/parallax_layer.h +++ b/scene/2d/parallax_layer.h @@ -61,7 +61,7 @@ public: void set_base_offset_and_scale(const Point2 &p_offset, real_t p_scale, const Point2 &p_screen_offset); - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; ParallaxLayer(); }; diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index be160ee1ddb..9912612c4fe 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -249,21 +249,16 @@ void PathFollow2D::_validate_property(PropertyInfo &property) const { } } -String PathFollow2D::get_configuration_warning() const { - if (!is_visible_in_tree() || !is_inside_tree()) { - return String(); - } +TypedArray PathFollow2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); - String warning = Node2D::get_configuration_warning(); - - if (!Object::cast_to(get_parent())) { - if (!warning.is_empty()) { - warning += "\n\n"; + if (is_visible_in_tree() && is_inside_tree()) { + if (!Object::cast_to(get_parent())) { + warnings.push_back(TTR("PathFollow2D only works when set as a child of a Path2D node.")); } - warning += TTR("PathFollow2D only works when set as a child of a Path2D node."); } - return warning; + return warnings; } void PathFollow2D::_bind_methods() { diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h index 671ab493c39..3b12f025fcd 100644 --- a/scene/2d/path_2d.h +++ b/scene/2d/path_2d.h @@ -105,7 +105,7 @@ public: void set_cubic_interpolation(bool p_enable); bool get_cubic_interpolation() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; PathFollow2D() {} }; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index a615d966873..830834c9646 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -708,26 +708,23 @@ void RigidBody2D::_notification(int p_what) { if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warning(); + update_configuration_warnings(); } } #endif } -String RigidBody2D::get_configuration_warning() const { +TypedArray RigidBody2D::get_configuration_warnings() const { Transform2D t = get_transform(); - String warning = CollisionObject2D::get_configuration_warning(); + TypedArray warnings = CollisionObject2D::get_configuration_warnings(); if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.elements[0].length() - 1.0) > 0.05 || ABS(t.elements[1].length() - 1.0) > 0.05)) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Size changes to RigidBody2D (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."); + warnings.push_back(TTR("Size changes to RigidBody2D (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); } - return warning; + return warnings; } void RigidBody2D::_bind_methods() { diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 2dc853b23be..aeec662e5cf 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -246,7 +246,7 @@ public: TypedArray get_colliding_bodies() const; //function for script - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; RigidBody2D(); ~RigidBody2D(); diff --git a/scene/2d/remote_transform_2d.cpp b/scene/2d/remote_transform_2d.cpp index f10714e28af..a7613dc009f 100644 --- a/scene/2d/remote_transform_2d.cpp +++ b/scene/2d/remote_transform_2d.cpp @@ -138,7 +138,7 @@ void RemoteTransform2D::set_remote_node(const NodePath &p_remote_node) { _update_remote(); } - update_configuration_warning(); + update_configuration_warnings(); } NodePath RemoteTransform2D::get_remote_node() const { @@ -185,17 +185,14 @@ void RemoteTransform2D::force_update_cache() { _update_cache(); } -String RemoteTransform2D::get_configuration_warning() const { - String warning = Node2D::get_configuration_warning(); +TypedArray RemoteTransform2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!has_node(remote_node) || !Object::cast_to(get_node(remote_node))) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Path property must point to a valid Node2D node to work."); + warnings.push_back(TTR("Path property must point to a valid Node2D node to work.")); } - return warning; + return warnings; } void RemoteTransform2D::_bind_methods() { diff --git a/scene/2d/remote_transform_2d.h b/scene/2d/remote_transform_2d.h index 4a26d7b3393..36fddb58c72 100644 --- a/scene/2d/remote_transform_2d.h +++ b/scene/2d/remote_transform_2d.h @@ -70,7 +70,7 @@ public: void force_update_cache(); - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; RemoteTransform2D(); }; diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 2d19d254b15..22180797f0e 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -100,7 +100,7 @@ void Bone2D::set_rest(const Transform2D &p_rest) { skeleton->_make_bone_setup_dirty(); } - update_configuration_warning(); + update_configuration_warnings(); } Transform2D Bone2D::get_rest() const { @@ -133,27 +133,21 @@ int Bone2D::get_index_in_skeleton() const { return skeleton_index; } -String Bone2D::get_configuration_warning() const { - String warning = Node2D::get_configuration_warning(); +TypedArray Bone2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!skeleton) { - if (!warning.is_empty()) { - warning += "\n\n"; - } if (parent_bone) { - warning += TTR("This Bone2D chain should end at a Skeleton2D node."); + warnings.push_back(TTR("This Bone2D chain should end at a Skeleton2D node.")); } else { - warning += TTR("A Bone2D only works with a Skeleton2D or another Bone2D as parent node."); + warnings.push_back(TTR("A Bone2D only works with a Skeleton2D or another Bone2D as parent node.")); } } if (rest == Transform2D(0, 0, 0, 0, 0, 0)) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("This bone lacks a proper REST pose. Go to the Skeleton2D node and set one."); + warnings.push_back(TTR("This bone lacks a proper REST pose. Go to the Skeleton2D node and set one.")); } - return warning; + return warnings; } Bone2D::Bone2D() { diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h index 1f43ea742ba..fd62b87bde0 100644 --- a/scene/2d/skeleton_2d.h +++ b/scene/2d/skeleton_2d.h @@ -60,7 +60,7 @@ public: void apply_rest(); Transform2D get_skeleton_rest() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; void set_default_length(real_t p_length); real_t get_default_length() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 81a5b0b28c4..776d3bca5fb 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -59,7 +59,7 @@ void TileMap::_notification(int p_what) { RID space = get_world_2d()->get_space(); _update_quadrant_transform(); _update_quadrant_space(space); - update_configuration_warning(); + update_configuration_warnings(); } break; @@ -1301,7 +1301,7 @@ void TileMap::set_collision_use_parent(bool p_use_parent) { _recreate_quadrants(); notify_property_list_changed(); - update_configuration_warning(); + update_configuration_warnings(); } void TileMap::set_collision_friction(float p_friction) { @@ -1693,17 +1693,14 @@ void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) { } } -String TileMap::get_configuration_warning() const { - String warning = Node2D::get_configuration_warning(); +TypedArray TileMap::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (use_parent && !collision_parent) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - return TTR("TileMap with Use Parent on needs a parent CollisionObject2D to give shapes to. Please use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."); + warnings.push_back(TTR("TileMap with Use Parent on needs a parent CollisionObject2D to give shapes to. Please use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape.")); } - return warning; + return warnings; } void TileMap::_bind_methods() { diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 26c84a0bb9f..9d27053fee7 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -340,7 +340,7 @@ public: void set_clip_uv(bool p_enable); bool get_clip_uv() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; virtual void set_texture_filter(CanvasItem::TextureFilter p_texture_filter) override; diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index 916038a1f35..8feb47f1cc3 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -310,18 +310,15 @@ void VisibilityEnabler2D::_node_removed(Node *p_node) { nodes.erase(p_node); } -String VisibilityEnabler2D::get_configuration_warning() const { - String warning = VisibilityNotifier2D::get_configuration_warning(); +TypedArray VisibilityEnabler2D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); #ifdef TOOLS_ENABLED if (is_inside_tree() && get_parent() && (get_parent()->get_filename() == String() && get_parent() != get_tree()->get_edited_scene_root())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("VisibilityEnabler2D works best when used with the edited scene root directly as parent."); + warnings.push_back(TTR("VisibilityEnabler2D works best when used with the edited scene root directly as parent.")); } #endif - return warning; + return warnings; } void VisibilityEnabler2D::_bind_methods() { diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h index 3d1701a1e57..7f4a5bc193a 100644 --- a/scene/2d/visibility_notifier_2d.h +++ b/scene/2d/visibility_notifier_2d.h @@ -102,7 +102,7 @@ public: void set_enabler(Enabler p_enabler, bool p_enable); bool is_enabler_enabled(Enabler p_enabler) const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; VisibilityEnabler2D(); }; diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 39880db29ca..352a7939876 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -395,17 +395,14 @@ bool CollisionObject3D::get_capture_input_on_drag() const { return capture_input_on_drag; } -String CollisionObject3D::get_configuration_warning() const { - String warning = Node3D::get_configuration_warning(); +TypedArray CollisionObject3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (shapes.is_empty()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape3D or CollisionPolygon3D as a child to define its shape."); + warnings.push_back(TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape3D or CollisionPolygon3D as a child to define its shape.")); } - return warning; + return warnings; } CollisionObject3D::CollisionObject3D() { diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index fe201769842..a2a0cbf9889 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -110,7 +110,7 @@ public: _FORCE_INLINE_ RID get_rid() const { return rid; } - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; CollisionObject3D(); ~CollisionObject3D(); diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp index e3e2eb46694..ac715b22b22 100644 --- a/scene/3d/collision_polygon_3d.cpp +++ b/scene/3d/collision_polygon_3d.cpp @@ -121,7 +121,7 @@ void CollisionPolygon3D::set_polygon(const Vector &p_polygon) { if (parent) { _build_polygon(); } - update_configuration_warning(); + update_configuration_warnings(); update_gizmo(); } @@ -167,24 +167,18 @@ void CollisionPolygon3D::set_margin(real_t p_margin) { } } -String CollisionPolygon3D::get_configuration_warning() const { - String warning = Node3D::get_configuration_warning(); +TypedArray CollisionPolygon3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to(get_parent())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape."); + warnings.push_back(TTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape.")); } if (polygon.is_empty()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("An empty CollisionPolygon3D has no effect on collision."); + warnings.push_back(TTR("An empty CollisionPolygon3D has no effect on collision.")); } - return warning; + return warnings; } bool CollisionPolygon3D::_is_editable_3d_polygon() const { diff --git a/scene/3d/collision_polygon_3d.h b/scene/3d/collision_polygon_3d.h index 750751b5099..73b8a8e0e31 100644 --- a/scene/3d/collision_polygon_3d.h +++ b/scene/3d/collision_polygon_3d.h @@ -74,7 +74,7 @@ public: real_t get_margin() const; void set_margin(real_t p_margin); - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; CollisionPolygon3D(); }; diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index 242d82ab4ce..bec87914c06 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -120,34 +120,25 @@ void CollisionShape3D::resource_changed(RES res) { update_gizmo(); } -String CollisionShape3D::get_configuration_warning() const { - String warning = Node3D::get_configuration_warning(); +TypedArray CollisionShape3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to(get_parent())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape."); + warnings.push_back(TTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape.")); } if (!shape.is_valid()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("A shape must be provided for CollisionShape3D to function. Please create a shape resource for it."); + warnings.push_back(TTR("A shape must be provided for CollisionShape3D to function. Please create a shape resource for it.")); } if (shape.is_valid() && Object::cast_to(get_parent()) && Object::cast_to(*shape) && Object::cast_to(get_parent())->get_mode() != RigidBody3D::MODE_STATIC) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static."); + warnings.push_back(TTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static.")); } - return warning; + return warnings; } void CollisionShape3D::_bind_methods() { @@ -188,7 +179,7 @@ void CollisionShape3D::set_shape(const Ref &p_shape) { if (is_inside_tree()) { _shape_changed(); } - update_configuration_warning(); + update_configuration_warnings(); } Ref CollisionShape3D::get_shape() const { diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h index 5512417f75f..56a4ae30397 100644 --- a/scene/3d/collision_shape_3d.h +++ b/scene/3d/collision_shape_3d.h @@ -64,7 +64,7 @@ public: void set_disabled(bool p_disabled); bool is_disabled() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; CollisionShape3D(); ~CollisionShape3D(); diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index d22d7ff3ab1..780773bb575 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -189,8 +189,8 @@ bool CPUParticles3D::get_fractional_delta() const { return fractional_delta; } -String CPUParticles3D::get_configuration_warning() const { - String warnings = GeometryInstance3D::get_configuration_warning(); +TypedArray CPUParticles3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); bool mesh_found = false; bool anim_material_found = false; @@ -209,18 +209,12 @@ String CPUParticles3D::get_configuration_warning() const { anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); if (!mesh_found) { - if (warnings != String()) { - warnings += "\n"; - } - warnings += "- " + TTR("Nothing is visible because no mesh has been assigned."); + warnings.push_back(TTR("Nothing is visible because no mesh has been assigned.")); } if (!anim_material_found && (get_param(PARAM_ANIM_SPEED) != 0.0 || get_param(PARAM_ANIM_OFFSET) != 0.0 || get_param_curve(PARAM_ANIM_SPEED).is_valid() || get_param_curve(PARAM_ANIM_OFFSET).is_valid())) { - if (warnings != String()) { - warnings += "\n"; - } - warnings += "- " + TTR("CPUParticles3D animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\"."); + warnings.push_back(TTR("CPUParticles3D animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\".")); } return warnings; diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h index 10ac32622d9..c073c93c47b 100644 --- a/scene/3d/cpu_particles_3d.h +++ b/scene/3d/cpu_particles_3d.h @@ -280,7 +280,7 @@ public: void set_gravity(const Vector3 &p_gravity); Vector3 get_gravity() const; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; void restart(); diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index 43f820e5d4c..0da53d01019 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -503,19 +503,15 @@ Vector GIProbe::get_faces(uint32_t p_usage_flags) const { return Vector(); } -String GIProbe::get_configuration_warning() const { - String warning = VisualInstance3D::get_configuration_warning(); +TypedArray GIProbe::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (RenderingServer::get_singleton()->is_low_end()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead."); + warnings.push_back(TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead.")); } else if (probe_data.is_null()) { - warning += TTR("No GIProbe data set, so this node is disabled. Bake static objects to enable GI."); + warnings.push_back(TTR("No GIProbe data set, so this node is disabled. Bake static objects to enable GI.")); } - - return warning; + return warnings; } void GIProbe::_bind_methods() { diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h index 534b425557c..dac7dd3e171 100644 --- a/scene/3d/gi_probe.h +++ b/scene/3d/gi_probe.h @@ -165,7 +165,7 @@ public: virtual AABB get_aabb() const override; virtual Vector get_faces(uint32_t p_usage_flags) const override; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; GIProbe(); ~GIProbe(); diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index e2cfc2ed87b..a075dcf990b 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -115,7 +115,7 @@ void GPUParticles3D::set_process_material(const Ref &p_material) { } RS::get_singleton()->particles_set_process_material(particles, material_rid); - update_configuration_warning(); + update_configuration_warnings(); } void GPUParticles3D::set_speed_scale(float p_scale) { @@ -208,7 +208,7 @@ void GPUParticles3D::set_draw_pass_mesh(int p_pass, const Ref &p_mesh) { RS::get_singleton()->particles_set_draw_pass_mesh(particles, p_pass, mesh_rid); - update_configuration_warning(); + update_configuration_warnings(); } Ref GPUParticles3D::get_draw_pass_mesh(int p_pass) const { @@ -235,12 +235,12 @@ bool GPUParticles3D::get_fractional_delta() const { return fractional_delta; } -String GPUParticles3D::get_configuration_warning() const { - if (RenderingServer::get_singleton()->is_low_end()) { - return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles3D node instead. You can use the \"Convert to CPUParticles3D\" option for this purpose."); - } +TypedArray GPUParticles3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); - String warnings = GeometryInstance3D::get_configuration_warning(); + if (RenderingServer::get_singleton()->is_low_end()) { + warnings.push_back(TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles3D node instead. You can use the \"Convert to CPUParticles3D\" option for this purpose.")); + } bool meshes_found = false; bool anim_material_found = false; @@ -264,26 +264,17 @@ String GPUParticles3D::get_configuration_warning() const { anim_material_found = anim_material_found || (spat && spat->get_billboard_mode() == StandardMaterial3D::BILLBOARD_PARTICLES); if (!meshes_found) { - if (warnings != String()) { - warnings += "\n"; - } - warnings += "- " + TTR("Nothing is visible because meshes have not been assigned to draw passes."); + warnings.push_back(TTR("Nothing is visible because meshes have not been assigned to draw passes.")); } if (process_material.is_null()) { - if (warnings != String()) { - warnings += "\n"; - } - warnings += "- " + TTR("A material to process the particles is not assigned, so no behavior is imprinted."); + warnings.push_back(TTR("A material to process the particles is not assigned, so no behavior is imprinted.")); } else { const ParticlesMaterial *process = Object::cast_to(process_material.ptr()); if (!anim_material_found && process && (process->get_param(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) { - if (warnings != String()) { - warnings += "\n"; - } - warnings += "- " + TTR("Particles animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\"."); + warnings.push_back(TTR("Particles animation requires the usage of a StandardMaterial3D whose Billboard Mode is set to \"Particle Billboard\".")); } } diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h index 0c1a1a510c0..b9e2b5ccef9 100644 --- a/scene/3d/gpu_particles_3d.h +++ b/scene/3d/gpu_particles_3d.h @@ -125,7 +125,7 @@ public: void set_draw_pass_mesh(int p_pass, const Ref &p_mesh); Ref get_draw_pass_mesh(int p_pass) const; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; void set_sub_emitter(const NodePath &p_path); NodePath get_sub_emitter() const; diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index f109640aefa..d45749d36b1 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -48,7 +48,7 @@ void Light3D::set_param(Param p_param, float p_value) { update_gizmo(); if (p_param == PARAM_SPOT_ANGLE) { - update_configuration_warning(); + update_configuration_warnings(); } } } @@ -63,7 +63,7 @@ void Light3D::set_shadow(bool p_enable) { RS::get_singleton()->light_set_shadow(light, p_enable); if (type == RenderingServer::LIGHT_SPOT || type == RenderingServer::LIGHT_OMNI) { - update_configuration_warning(); + update_configuration_warnings(); } notify_property_list_changed(); @@ -153,7 +153,7 @@ void Light3D::set_projector(const Ref &p_texture) { projector = p_texture; RID tex_id = projector.is_valid() ? projector->get_rid() : RID(); RS::get_singleton()->light_set_projector(light, tex_id); - update_configuration_warning(); + update_configuration_warnings(); } Ref Light3D::get_projector() const { @@ -457,17 +457,14 @@ OmniLight3D::ShadowMode OmniLight3D::get_shadow_mode() const { return shadow_mode; } -String OmniLight3D::get_configuration_warning() const { - String warning = Light3D::get_configuration_warning(); +TypedArray OmniLight3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!has_shadow() && get_projector().is_valid()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Projector texture only works with shadows active."); + warnings.push_back(TTR("Projector texture only works with shadows active.")); } - return warning; + return warnings; } void OmniLight3D::_bind_methods() { @@ -491,24 +488,18 @@ OmniLight3D::OmniLight3D() : set_param(PARAM_SHADOW_NORMAL_BIAS, 2.0); } -String SpotLight3D::get_configuration_warning() const { - String warning = Light3D::get_configuration_warning(); +TypedArray SpotLight3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (has_shadow() && get_param(PARAM_SPOT_ANGLE) >= 90.0) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("A SpotLight3D with an angle wider than 90 degrees cannot cast shadows."); + warnings.push_back(TTR("A SpotLight3D with an angle wider than 90 degrees cannot cast shadows.")); } if (!has_shadow() && get_projector().is_valid()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Projector texture only works with shadows active."); + warnings.push_back(TTR("Projector texture only works with shadows active.")); } - return warning; + return warnings; } void SpotLight3D::_bind_methods() { diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index 311db54bcea..e145b08b743 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -202,7 +202,7 @@ public: void set_shadow_mode(ShadowMode p_mode); ShadowMode get_shadow_mode() const; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; OmniLight3D(); }; @@ -216,7 +216,7 @@ protected: static void _bind_methods(); public: - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; SpotLight3D() : Light3D(RenderingServer::LIGHT_SPOT) {} diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 21ca3d70dd8..7346f243ba7 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -245,17 +245,14 @@ void NavigationAgent3D::_avoidance_done(Vector3 p_new_velocity) { emit_signal("velocity_computed", p_new_velocity); } -String NavigationAgent3D::get_configuration_warning() const { - String warning = Node::get_configuration_warning(); +TypedArray NavigationAgent3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to(get_parent())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("The NavigationAgent3D can be used only under a spatial node."); + warnings.push_back(TTR("The NavigationAgent3D can be used only under a spatial node.")); } - return warning; + return warnings; } void NavigationAgent3D::update_navigation() { diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index 22db889618a..814c0714e81 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -143,7 +143,7 @@ public: void set_velocity(Vector3 p_velocity); void _avoidance_done(Vector3 p_new_velocity); - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; private: void update_navigation(); diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index df03bca4fda..20ffc3b00e8 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -76,17 +76,14 @@ NavigationObstacle3D::~NavigationObstacle3D() { agent = RID(); // Pointless } -String NavigationObstacle3D::get_configuration_warning() const { - String warning = Node::get_configuration_warning(); +TypedArray NavigationObstacle3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); - if (!parent_node3d) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("The NavigationObstacle3D only serves to provide collision avoidance to a spatial object."); + if (!Object::cast_to(get_parent())) { + warnings.push_back(TTR("The NavigationObstacle3D only serves to provide collision avoidance to a spatial object.")); } - return warning; + return warnings; } void NavigationObstacle3D::update_agent_shape() { diff --git a/scene/3d/navigation_obstacle_3d.h b/scene/3d/navigation_obstacle_3d.h index b1bb53724a7..2f78f624a45 100644 --- a/scene/3d/navigation_obstacle_3d.h +++ b/scene/3d/navigation_obstacle_3d.h @@ -52,7 +52,7 @@ public: return agent; } - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; private: void update_agent_shape(); diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 3ca704e4b82..0afad624043 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -135,7 +135,7 @@ void NavigationRegion3D::set_navigation_mesh(const Ref &p_navmes emit_signal("navigation_mesh_changed"); update_gizmo(); - update_configuration_warning(); + update_configuration_warnings(); } Ref NavigationRegion3D::get_navigation_mesh() const { @@ -177,21 +177,16 @@ void NavigationRegion3D::_bake_finished(Ref p_nav_mesh) { emit_signal("bake_finished"); } -String NavigationRegion3D::get_configuration_warning() const { - if (!is_visible_in_tree() || !is_inside_tree()) { - return String(); - } +TypedArray NavigationRegion3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); - String warning = Node3D::get_configuration_warning(); - - if (!navmesh.is_valid()) { - if (!warning.is_empty()) { - warning += "\n\n"; + if (is_visible_in_tree() && is_inside_tree()) { + if (!navmesh.is_valid()) { + warnings.push_back(TTR("A NavigationMesh resource must be set or created for this node to work.")); } - warning += TTR("A NavigationMesh resource must be set or created for this node to work."); } - return warning; + return warnings; } void NavigationRegion3D::_bind_methods() { @@ -217,7 +212,7 @@ void NavigationRegion3D::_bind_methods() { void NavigationRegion3D::_navigation_changed() { update_gizmo(); - update_configuration_warning(); + update_configuration_warnings(); } NavigationRegion3D::NavigationRegion3D() { diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h index 52fa2d61596..c2045215b1a 100644 --- a/scene/3d/navigation_region_3d.h +++ b/scene/3d/navigation_region_3d.h @@ -66,7 +66,7 @@ public: void bake_navigation_mesh(); void _bake_finished(Ref p_nav_mesh); - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; NavigationRegion3D(); ~NavigationRegion3D(); diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp index 7e2601902bd..4ec4ee62073 100644 --- a/scene/3d/path_3d.cpp +++ b/scene/3d/path_3d.cpp @@ -50,7 +50,7 @@ void Path3D::_curve_changed() { for (int i = 0; i < get_child_count(); i++) { PathFollow3D *child = Object::cast_to(get_child(i)); if (child) { - child->update_configuration_warning(); + child->update_configuration_warnings(); } } } @@ -241,29 +241,21 @@ void PathFollow3D::_validate_property(PropertyInfo &property) const { } } -String PathFollow3D::get_configuration_warning() const { - if (!is_visible_in_tree() || !is_inside_tree()) { - return String(); - } +TypedArray PathFollow3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); - String warning = Node3D::get_configuration_warning(); - - if (!Object::cast_to(get_parent())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("PathFollow3D only works when set as a child of a Path3D node."); - } else { - Path3D *path = Object::cast_to(get_parent()); - if (path->get_curve().is_valid() && !path->get_curve()->is_up_vector_enabled() && rotation_mode == ROTATION_ORIENTED) { - if (!warning.is_empty()) { - warning += "\n\n"; + if (is_visible_in_tree() && is_inside_tree()) { + if (!Object::cast_to(get_parent())) { + warnings.push_back(TTR("PathFollow3D only works when set as a child of a Path3D node.")); + } else { + Path3D *path = Object::cast_to(get_parent()); + if (path->get_curve().is_valid() && !path->get_curve()->is_up_vector_enabled() && rotation_mode == ROTATION_ORIENTED) { + warnings.push_back(TTR("PathFollow3D's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its parent Path3D's Curve resource.")); } - warning += TTR("PathFollow3D's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its parent Path3D's Curve resource."); } } - return warning; + return warnings; } void PathFollow3D::_bind_methods() { @@ -368,7 +360,7 @@ float PathFollow3D::get_unit_offset() const { void PathFollow3D::set_rotation_mode(RotationMode p_rotation_mode) { rotation_mode = p_rotation_mode; - update_configuration_warning(); + update_configuration_warnings(); _update_transform(); } diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h index 17ee47593e6..8545370a4a7 100644 --- a/scene/3d/path_3d.h +++ b/scene/3d/path_3d.h @@ -104,7 +104,7 @@ public: void set_cubic_interpolation(bool p_enable); bool get_cubic_interpolation() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; PathFollow3D() {} }; diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index e225c1f22d2..2afbebdacc6 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -444,7 +444,7 @@ void RigidBody3D::_notification(int p_what) { if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warning(); + update_configuration_warnings(); } } @@ -469,7 +469,7 @@ void RigidBody3D::set_mode(Mode p_mode) { PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC); } break; } - update_configuration_warning(); + update_configuration_warnings(); } RigidBody3D::Mode RigidBody3D::get_mode() const { @@ -709,19 +709,16 @@ Array RigidBody3D::get_colliding_bodies() const { return ret; } -String RigidBody3D::get_configuration_warning() const { +TypedArray RigidBody3D::get_configuration_warnings() const { Transform t = get_transform(); - String warning = CollisionObject3D::get_configuration_warning(); + TypedArray warnings = Node::get_configuration_warnings(); if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Size changes to RigidBody3D (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."); + warnings.push_back(TTR("Size changes to RigidBody3D (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); } - return warning; + return warnings; } void RigidBody3D::_bind_methods() { diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 1450fce6a6d..9515b044ab8 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -238,7 +238,7 @@ public: void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()); void apply_torque_impulse(const Vector3 &p_impulse); - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; RigidBody3D(); ~RigidBody3D(); diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp index de9c75621b9..3d58d1c10eb 100644 --- a/scene/3d/physics_joint_3d.cpp +++ b/scene/3d/physics_joint_3d.cpp @@ -65,6 +65,7 @@ void Joint3D::_update_joint(bool p_only_free) { if (p_only_free || !is_inside_tree()) { PhysicsServer3D::get_singleton()->joint_clear(joint); warning = String(); + update_configuration_warnings(); return; } @@ -75,42 +76,25 @@ void Joint3D::_update_joint(bool p_only_free) { PhysicsBody3D *body_b = Object::cast_to(node_b); if (node_a && !body_a && node_b && !body_b) { - PhysicsServer3D::get_singleton()->joint_clear(joint); warning = TTR("Node A and Node B must be PhysicsBody3Ds"); - update_configuration_warning(); - return; - } - - if (node_a && !body_a) { - PhysicsServer3D::get_singleton()->joint_clear(joint); + } else if (node_a && !body_a) { warning = TTR("Node A must be a PhysicsBody3D"); - update_configuration_warning(); - return; - } - - if (node_b && !body_b) { - PhysicsServer3D::get_singleton()->joint_clear(joint); + } else if (node_b && !body_b) { warning = TTR("Node B must be a PhysicsBody3D"); - update_configuration_warning(); - return; - } - - if (!body_a && !body_b) { - PhysicsServer3D::get_singleton()->joint_clear(joint); + } else if (!body_a && !body_b) { warning = TTR("Joint is not connected to any PhysicsBody3Ds"); - update_configuration_warning(); - return; - } - - if (body_a == body_b) { - PhysicsServer3D::get_singleton()->joint_clear(joint); + } else if (body_a == body_b) { warning = TTR("Node A and Node B must be different PhysicsBody3Ds"); - update_configuration_warning(); - return; + } else { + warning = String(); } - warning = String(); - update_configuration_warning(); + update_configuration_warnings(); + + if (!warning.is_empty()) { + PhysicsServer3D::get_singleton()->joint_clear(joint); + return; + } configured = true; @@ -206,17 +190,14 @@ bool Joint3D::get_exclude_nodes_from_collision() const { return exclude_from_collision; } -String Joint3D::get_configuration_warning() const { - String node_warning = Node3D::get_configuration_warning(); +TypedArray Joint3D::get_configuration_warnings() const { + TypedArray warnings = Node3D::get_configuration_warnings(); if (!warning.is_empty()) { - if (!node_warning.is_empty()) { - node_warning += "\n\n"; - } - node_warning += warning; + warnings.push_back(warning); } - return node_warning; + return warnings; } void Joint3D::_bind_methods() { diff --git a/scene/3d/physics_joint_3d.h b/scene/3d/physics_joint_3d.h index f624ba602b2..3e0ea38a5cb 100644 --- a/scene/3d/physics_joint_3d.h +++ b/scene/3d/physics_joint_3d.h @@ -63,7 +63,7 @@ protected: _FORCE_INLINE_ bool is_configured() const { return configured; } public: - virtual String get_configuration_warning() const override; + virtual TypedArray get_configuration_warnings() const override; void set_node_a(const NodePath &p_node_a); NodePath get_node_a() const; diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp index 83ac813c53b..29a407905bc 100644 --- a/scene/3d/remote_transform_3d.cpp +++ b/scene/3d/remote_transform_3d.cpp @@ -133,7 +133,7 @@ void RemoteTransform3D::set_remote_node(const NodePath &p_remote_node) { _update_remote(); } - update_configuration_warning(); + update_configuration_warnings(); } NodePath RemoteTransform3D::get_remote_node() const { @@ -179,17 +179,14 @@ void RemoteTransform3D::force_update_cache() { _update_cache(); } -String RemoteTransform3D::get_configuration_warning() const { - String warning = Node3D::get_configuration_warning(); +TypedArray RemoteTransform3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!has_node(remote_node) || !Object::cast_to(get_node(remote_node))) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("The \"Remote Path\" property must point to a valid Node3D or Node3D-derived node to work."); + warnings.push_back(TTR("The \"Remote Path\" property must point to a valid Node3D or Node3D-derived node to work.")); } - return warning; + return warnings; } void RemoteTransform3D::_bind_methods() { diff --git a/scene/3d/remote_transform_3d.h b/scene/3d/remote_transform_3d.h index 21005d92d1a..321bd3b51e8 100644 --- a/scene/3d/remote_transform_3d.h +++ b/scene/3d/remote_transform_3d.h @@ -70,7 +70,7 @@ public: void force_update_cache(); - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; RemoteTransform3D(); }; diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 3fde4d6ef3c..08e25b589eb 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -249,7 +249,7 @@ void SoftBody3D::_softbody_changed() { prepare_physics_server(); _reset_points_offsets(); #ifdef TOOLS_ENABLED - update_configuration_warning(); + update_configuration_warnings(); #endif } @@ -301,7 +301,7 @@ void SoftBody3D::_notification(int p_what) { if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { if (Engine::get_singleton()->is_editor_hint()) { - update_configuration_warning(); + update_configuration_warnings(); } } @@ -366,27 +366,19 @@ void SoftBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable"); } -String SoftBody3D::get_configuration_warning() const { - String warning = MeshInstance3D::get_configuration_warning(); +TypedArray SoftBody3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (get_mesh().is_null()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - - warning += TTR("This body will be ignored until you set a mesh."); + warnings.push_back(TTR("This body will be ignored until you set a mesh.")); } Transform t = get_transform(); if ((ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - - warning += TTR("Size changes to SoftBody3D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."); + warnings.push_back(TTR("Size changes to SoftBody3D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); } - return warning; + return warnings; } void SoftBody3D::_update_physics_server() { diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h index f98df39209c..0d0d39d48f4 100644 --- a/scene/3d/soft_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -113,7 +113,7 @@ protected: void _notification(int p_what); static void _bind_methods(); - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; protected: void _update_physics_server(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 0be54e72436..33b8b488c6f 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -928,7 +928,7 @@ void AnimatedSprite3D::set_sprite_frames(const Ref &p_frames) { notify_property_list_changed(); _reset_timeout(); _queue_update(); - update_configuration_warning(); + update_configuration_warnings(); } Ref AnimatedSprite3D::get_sprite_frames() const { @@ -1058,17 +1058,14 @@ StringName AnimatedSprite3D::get_animation() const { return animation; } -String AnimatedSprite3D::get_configuration_warning() const { - String warning = SpriteBase3D::get_configuration_warning(); +TypedArray AnimatedSprite3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (frames.is_null()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames."); + warnings.push_back(TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames.")); } - return warning; + return warnings; } void AnimatedSprite3D::_bind_methods() { diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index d1bc8dc7373..5e47e66bcb6 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -236,7 +236,7 @@ public: virtual Rect2 get_item_rect() const override; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; AnimatedSprite3D(); }; diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index 5b0b3b89d3b..edd58347f0b 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -102,17 +102,14 @@ void VehicleWheel3D::_notification(int p_what) { } } -String VehicleWheel3D::get_configuration_warning() const { - String warning = Node3D::get_configuration_warning(); +TypedArray VehicleWheel3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!Object::cast_to(get_parent())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("VehicleWheel3D serves to provide a wheel system to a VehicleBody3D. Please use it as a child of a VehicleBody3D."); + warnings.push_back(TTR("VehicleWheel3D serves to provide a wheel system to a VehicleBody3D. Please use it as a child of a VehicleBody3D.")); } - return warning; + return warnings; } void VehicleWheel3D::_update(PhysicsDirectBodyState3D *s) { diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h index 860fa7e3b70..646071a3638 100644 --- a/scene/3d/vehicle_body_3d.h +++ b/scene/3d/vehicle_body_3d.h @@ -145,7 +145,7 @@ public: void set_steering(real_t p_steering); real_t get_steering() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; VehicleWheel3D(); }; diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index 214ffd6bd51..829ecc5ec2d 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -65,7 +65,7 @@ void WorldEnvironment::_update_current_environment() { } else { get_viewport()->find_world_3d()->set_environment(Ref()); } - get_tree()->call_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warning"); + get_tree()->call_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); } void WorldEnvironment::_update_current_camera_effects() { @@ -76,7 +76,7 @@ void WorldEnvironment::_update_current_camera_effects() { get_viewport()->find_world_3d()->set_camera_effects(Ref()); } - get_tree()->call_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warning"); + get_tree()->call_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), "update_configuration_warnings"); } void WorldEnvironment::set_environment(const Ref &p_environment) { @@ -96,7 +96,7 @@ void WorldEnvironment::set_environment(const Ref &p_environment) { if (is_inside_tree()) { _update_current_environment(); } else { - update_configuration_warning(); + update_configuration_warnings(); } } @@ -121,7 +121,7 @@ void WorldEnvironment::set_camera_effects(const Ref &p_camera_eff if (is_inside_tree()) { _update_current_camera_effects(); } else { - update_configuration_warning(); + update_configuration_warnings(); } } @@ -129,35 +129,26 @@ Ref WorldEnvironment::get_camera_effects() const { return camera_effects; } -String WorldEnvironment::get_configuration_warning() const { - String warning = Node::get_configuration_warning(); +TypedArray WorldEnvironment::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!environment.is_valid()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("WorldEnvironment requires its \"Environment\" property to contain an Environment to have a visible effect."); + warnings.push_back(TTR("WorldEnvironment requires its \"Environment\" property to contain an Environment to have a visible effect.")); } if (!is_inside_tree()) { - return warning; + return warnings; } if (environment.is_valid() && get_viewport()->find_world_3d()->get_environment() != environment) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Only the first Environment has an effect in a scene (or set of instantiated scenes)."); + warnings.push_back(("Only the first Environment has an effect in a scene (or set of instantiated scenes).")); } if (camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() != camera_effects) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Only the first CameraEffects has an effect in a scene (or set of instantiated scenes)."); + warnings.push_back(TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes).")); } - return warning; + return warnings; } void WorldEnvironment::_bind_methods() { diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h index e3f28d6d6b3..9e85982381d 100644 --- a/scene/3d/world_environment.h +++ b/scene/3d/world_environment.h @@ -55,7 +55,7 @@ public: void set_camera_effects(const Ref &p_camera_effects); Ref get_camera_effects() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; WorldEnvironment(); }; diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index 63be4352d5d..b5037f9be76 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -55,23 +55,18 @@ void XRCamera3D::_notification(int p_what) { }; }; -String XRCamera3D::get_configuration_warning() const { - if (!is_visible() || !is_inside_tree()) { - return String(); +TypedArray XRCamera3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); + + if (is_visible() && is_inside_tree()) { + // must be child node of XROrigin3D! + XROrigin3D *origin = Object::cast_to(get_parent()); + if (origin == nullptr) { + warnings.push_back(TTR("XRCamera3D must have an XROrigin3D node as its parent.")); + }; } - String warning = Camera3D::get_configuration_warning(); - - // must be child node of XROrigin3D! - XROrigin3D *origin = Object::cast_to(get_parent()); - if (origin == nullptr) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("XRCamera3D must have an XROrigin3D node as its parent."); - }; - - return warning; + return warnings; }; Vector3 XRCamera3D::project_local_ray_normal(const Point2 &p_pos) const { @@ -265,7 +260,7 @@ void XRController3D::set_controller_id(int p_controller_id) { // We don't check any bounds here, this controller may not yet be active and just be a place holder until it is. // Note that setting this to 0 means this node is not bound to a controller yet. controller_id = p_controller_id; - update_configuration_warning(); + update_configuration_warnings(); }; int XRController3D::get_controller_id() const { @@ -362,30 +357,22 @@ XRPositionalTracker::TrackerHand XRController3D::get_tracker_hand() const { return tracker->get_tracker_hand(); }; -String XRController3D::get_configuration_warning() const { - if (!is_visible() || !is_inside_tree()) { - return String(); +TypedArray XRController3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); + + if (is_visible() && is_inside_tree()) { + // must be child node of XROrigin! + XROrigin3D *origin = Object::cast_to(get_parent()); + if (origin == nullptr) { + warnings.push_back(TTR("XRController3D must have an XROrigin3D node as its parent.")); + } + + if (controller_id == 0) { + warnings.push_back(TTR("The controller ID must not be 0 or this controller won't be bound to an actual controller.")); + } } - String warning = Node3D::get_configuration_warning(); - - // must be child node of XROrigin! - XROrigin3D *origin = Object::cast_to(get_parent()); - if (origin == nullptr) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("XRController3D must have an XROrigin3D node as its parent."); - }; - - if (controller_id == 0) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("The controller ID must not be 0 or this controller won't be bound to an actual controller."); - }; - - return warning; + return warnings; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -459,7 +446,7 @@ void XRAnchor3D::set_anchor_id(int p_anchor_id) { // We don't check any bounds here, this anchor may not yet be active and just be a place holder until it is. // Note that setting this to 0 means this node is not bound to an anchor yet. anchor_id = p_anchor_id; - update_configuration_warning(); + update_configuration_warnings(); }; int XRAnchor3D::get_anchor_id() const { @@ -487,30 +474,22 @@ bool XRAnchor3D::get_is_active() const { return is_active; }; -String XRAnchor3D::get_configuration_warning() const { - if (!is_visible() || !is_inside_tree()) { - return String(); +TypedArray XRAnchor3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); + + if (is_visible() && is_inside_tree()) { + // must be child node of XROrigin3D! + XROrigin3D *origin = Object::cast_to(get_parent()); + if (origin == nullptr) { + warnings.push_back(TTR("XRAnchor3D must have an XROrigin3D node as its parent.")); + } + + if (anchor_id == 0) { + warnings.push_back(TTR("The anchor ID must not be 0 or this anchor won't be bound to an actual anchor.")); + } } - String warning = Node3D::get_configuration_warning(); - - // must be child node of XROrigin3D! - XROrigin3D *origin = Object::cast_to(get_parent()); - if (origin == nullptr) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("XRAnchor3D must have an XROrigin3D node as its parent."); - }; - - if (anchor_id == 0) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("The anchor ID must not be 0 or this anchor won't be bound to an actual anchor."); - }; - - return warning; + return warnings; }; Plane XRAnchor3D::get_plane() const { @@ -528,21 +507,16 @@ Ref XRAnchor3D::get_mesh() const { //////////////////////////////////////////////////////////////////////////////////////////////////// -String XROrigin3D::get_configuration_warning() const { - if (!is_visible() || !is_inside_tree()) { - return String(); - } +TypedArray XROrigin3D::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); - String warning = Node3D::get_configuration_warning(); - - if (tracked_camera == nullptr) { - if (!warning.is_empty()) { - warning += "\n\n"; + if (is_visible() && is_inside_tree()) { + if (tracked_camera == nullptr) { + warnings.push_back(TTR("XROrigin3D requires an XRCamera3D child node.")); } - warning += TTR("XROrigin3D requires an XRCamera3D child node."); } - return warning; + return warnings; }; void XROrigin3D::_bind_methods() { diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h index 7cd6e2ac57c..90079f5fe91 100644 --- a/scene/3d/xr_nodes.h +++ b/scene/3d/xr_nodes.h @@ -50,7 +50,7 @@ protected: void _notification(int p_what); public: - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; virtual Vector3 project_local_ray_normal(const Point2 &p_pos) const override; virtual Point2 unproject_position(const Vector3 &p_pos) const override; @@ -97,7 +97,7 @@ public: Ref get_mesh() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; XRController3D() {} ~XRController3D() {} @@ -133,7 +133,7 @@ public: Ref get_mesh() const; - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; XRAnchor3D() {} ~XRAnchor3D() {} @@ -158,7 +158,7 @@ protected: static void _bind_methods(); public: - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; void set_tracked_camera(XRCamera3D *p_tracked_camera); void clear_tracked_camera_if(XRCamera3D *p_tracked_camera); diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 4b4d3943c92..44f2d38a842 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -458,7 +458,7 @@ void AnimationTree::set_tree_root(const Ref &p_root) { properties_dirty = true; - update_configuration_warning(); + update_configuration_warnings(); } Ref AnimationTree::get_tree_root() const { @@ -1262,7 +1262,7 @@ void AnimationTree::_notification(int p_what) { void AnimationTree::set_animation_player(const NodePath &p_player) { animation_player = p_player; - update_configuration_warning(); + update_configuration_warnings(); } NodePath AnimationTree::get_animation_player() const { @@ -1281,38 +1281,26 @@ uint64_t AnimationTree::get_last_process_pass() const { return process_pass; } -String AnimationTree::get_configuration_warning() const { - String warning = Node::get_configuration_warning(); +TypedArray AnimationTree::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!root.is_valid()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("No root AnimationNode for the graph is set."); + warnings.push_back(TTR("No root AnimationNode for the graph is set.")); } if (!has_node(animation_player)) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Path to an AnimationPlayer node containing animations is not set."); + warnings.push_back(TTR("Path to an AnimationPlayer node containing animations is not set.")); } else { AnimationPlayer *player = Object::cast_to(get_node(animation_player)); if (!player) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Path set for AnimationPlayer does not lead to an AnimationPlayer node."); + warnings.push_back(TTR("Path set for AnimationPlayer does not lead to an AnimationPlayer node.")); } else if (!player->has_node(player->get_root())) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("The AnimationPlayer root node is not a valid node."); + warnings.push_back(TTR("The AnimationPlayer root node is not a valid node.")); } } - return warning; + return warnings; } void AnimationTree::set_root_motion_track(const NodePath &p_track) { diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 1c5aec26ab7..700ff1cb5bf 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -300,7 +300,7 @@ public: void set_animation_player(const NodePath &p_player); NodePath get_animation_player() const; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; bool is_state_invalid() const; String get_invalid_state_reason() const; diff --git a/scene/gui/container.cpp b/scene/gui/container.cpp index 2e6b798eeaa..dea69aae6b3 100644 --- a/scene/gui/container.cpp +++ b/scene/gui/container.cpp @@ -159,16 +159,14 @@ void Container::_notification(int p_what) { } } -String Container::get_configuration_warning() const { - String warning = Control::get_configuration_warning(); +TypedArray Container::get_configuration_warnings() const { + TypedArray warnings = Control::get_configuration_warnings(); if (get_class() == "Container" && get_script().is_null()) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Container by itself serves no purpose unless a script configures its children placement behavior.\nIf you don't intend to add a script, use a plain Control node instead."); + warnings.push_back(TTR("Container by itself serves no purpose unless a script configures its children placement behavior.\nIf you don't intend to add a script, use a plain Control node instead.")); } - return warning; + + return warnings; } void Container::_bind_methods() { diff --git a/scene/gui/container.h b/scene/gui/container.h index a4f392a3ae1..bce3085f0c4 100644 --- a/scene/gui/container.h +++ b/scene/gui/container.h @@ -56,7 +56,7 @@ public: void fit_child_in_rect(Control *p_child, const Rect2 &p_rect); - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; Container(); }; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 300201c0dbe..f569fbc420a 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2183,7 +2183,7 @@ Ref Control::get_theme() const { void Control::set_tooltip(const String &p_tooltip) { data.tooltip = p_tooltip; - update_configuration_warning(); + update_configuration_warnings(); } String Control::get_tooltip(const Point2 &p_pos) const { @@ -2468,7 +2468,7 @@ int Control::get_v_size_flags() const { void Control::set_mouse_filter(MouseFilter p_filter) { ERR_FAIL_INDEX(p_filter, 3); data.mouse_filter = p_filter; - update_configuration_warning(); + update_configuration_warnings(); } Control::MouseFilter Control::get_mouse_filter() const { @@ -2707,17 +2707,14 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List } } -String Control::get_configuration_warning() const { - String warning = CanvasItem::get_configuration_warning(); +TypedArray Control::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (data.mouse_filter == MOUSE_FILTER_IGNORE && data.tooltip != "") { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("The Hint Tooltip won't be displayed as the control's Mouse Filter is set to \"Ignore\". To solve this, set the Mouse Filter to \"Stop\" or \"Pass\"."); + warnings.push_back(TTR("The Hint Tooltip won't be displayed as the control's Mouse Filter is set to \"Ignore\". To solve this, set the Mouse Filter to \"Stop\" or \"Pass\".")); } - return warning; + return warnings; } void Control::set_clip_contents(bool p_clip) { diff --git a/scene/gui/control.h b/scene/gui/control.h index 184b2df6d3c..1f397df5899 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -524,7 +524,7 @@ public: bool is_visibility_clip_disabled() const; virtual void get_argument_options(const StringName &p_function, int p_idx, List *r_options) const override; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; Control() {} }; diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index 86b775e7954..adc1ed67cac 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -30,17 +30,14 @@ #include "range.h" -String Range::get_configuration_warning() const { - String warning = Control::get_configuration_warning(); +TypedArray Range::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (shared->exp_ratio && shared->min <= 0) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0."); + warnings.push_back(TTR("If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0.")); } - return warning; + return warnings; } void Range::_value_changed_notify() { @@ -106,7 +103,7 @@ void Range::set_min(double p_min) { shared->emit_changed("min"); - update_configuration_warning(); + update_configuration_warnings(); } void Range::set_max(double p_max) { @@ -181,7 +178,6 @@ double Range::get_as_ratio() const { double v = Math::log(value) / Math::log((double)2); return CLAMP((v - exp_min) / (exp_max - exp_min), 0, 1); - } else { float value = CLAMP(get_value(), shared->min, shared->max); return CLAMP((value - get_min()) / (get_max() - get_min()), 0, 1); @@ -287,7 +283,7 @@ bool Range::is_using_rounded_values() const { void Range::set_exp_ratio(bool p_enable) { shared->exp_ratio = p_enable; - update_configuration_warning(); + update_configuration_warnings(); } bool Range::is_ratio_exp() const { diff --git a/scene/gui/range.h b/scene/gui/range.h index 1072a109c62..7a129e88d6d 100644 --- a/scene/gui/range.h +++ b/scene/gui/range.h @@ -97,7 +97,7 @@ public: void share(Range *p_range); void unshare(); - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; Range(); ~Range(); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 757a0841eaa..73c63716585 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -544,8 +544,8 @@ void ScrollContainer::set_follow_focus(bool p_follow) { follow_focus = p_follow; } -String ScrollContainer::get_configuration_warning() const { - String warning = Container::get_configuration_warning(); +TypedArray ScrollContainer::get_configuration_warnings() const { + TypedArray warnings = Container::get_configuration_warnings(); int found = 0; @@ -565,12 +565,10 @@ String ScrollContainer::get_configuration_warning() const { } if (found != 1) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("ScrollContainer is intended to work with a single child control.\nUse a container as child (VBox, HBox, etc.), or a Control and set the custom minimum size manually."); + warnings.push_back(TTR("ScrollContainer is intended to work with a single child control.\nUse a container as child (VBox, HBox, etc.), or a Control and set the custom minimum size manually.")); } - return warning; + + return warnings; } HScrollBar *ScrollContainer::get_h_scrollbar() { diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h index 9d3ce39345e..e7d73bab0a9 100644 --- a/scene/gui/scroll_container.h +++ b/scene/gui/scroll_container.h @@ -103,7 +103,7 @@ public: virtual bool clips_input() const override; - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; ScrollContainer(); }; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 27712242d14..b7313749d69 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2634,15 +2634,27 @@ void Node::clear_internal_tree_resource_paths() { } } -String Node::get_configuration_warning() const { +TypedArray Node::get_configuration_warnings() const { if (get_script_instance() && get_script_instance()->get_script().is_valid() && - get_script_instance()->get_script()->is_tool() && get_script_instance()->has_method("_get_configuration_warning")) { - return get_script_instance()->call("_get_configuration_warning"); + get_script_instance()->get_script()->is_tool() && get_script_instance()->has_method("_get_configuration_warnings")) { + return get_script_instance()->call("_get_configuration_warnings"); } - return String(); + return Array(); } -void Node::update_configuration_warning() { +String Node::get_configuration_warnings_as_string() const { + TypedArray warnings = get_configuration_warnings(); + String all_warnings = String(); + for (int i = 0; i < warnings.size(); i++) { + if (i > 0) { + all_warnings += "\n\n"; + } + all_warnings += String(warnings[i]); + } + return all_warnings; +} + +void Node::update_configuration_warnings() { #ifdef TOOLS_ENABLED if (!is_inside_tree()) { return; @@ -2798,7 +2810,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("rset_unreliable", "property", "value"), &Node::rset_unreliable); ClassDB::bind_method(D_METHOD("rset_unreliable_id", "peer_id", "property", "value"), &Node::rset_unreliable_id); - ClassDB::bind_method(D_METHOD("update_configuration_warning"), &Node::update_configuration_warning); + ClassDB::bind_method(D_METHOD("update_configuration_warnings"), &Node::update_configuration_warnings); BIND_CONSTANT(NOTIFICATION_ENTER_TREE); BIND_CONSTANT(NOTIFICATION_EXIT_TREE); @@ -2874,7 +2886,7 @@ void Node::_bind_methods() { BIND_VMETHOD(MethodInfo("_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); BIND_VMETHOD(MethodInfo("_unhandled_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); BIND_VMETHOD(MethodInfo("_unhandled_key_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEventKey"))); - BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_configuration_warning")); + BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, "String"), "_get_configuration_warnings")); } String Node::_get_name_num_separator() { diff --git a/scene/main/node.h b/scene/main/node.h index b1e51d2aee7..6ca2317d9e5 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -412,9 +412,10 @@ public: _FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; } - virtual String get_configuration_warning() const; + virtual TypedArray get_configuration_warnings() const; + String get_configuration_warnings_as_string() const; - void update_configuration_warning(); + void update_configuration_warnings(); void set_display_folded(bool p_folded); bool is_displayed_folded() const; diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp index b6b29821552..cb3b2cb3925 100644 --- a/scene/main/shader_globals_override.cpp +++ b/scene/main/shader_globals_override.cpp @@ -232,7 +232,7 @@ void ShaderGlobalsOverride::_activate() { } } - update_configuration_warning(); //may have activated + update_configuration_warnings(); //may have activated } } @@ -260,17 +260,14 @@ void ShaderGlobalsOverride::_notification(int p_what) { } } -String ShaderGlobalsOverride::get_configuration_warning() const { - String warning = Node::get_configuration_warning(); +TypedArray ShaderGlobalsOverride::get_configuration_warnings() const { + TypedArray warnings = Node::get_configuration_warnings(); if (!active) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("ShaderGlobalsOverride is not active because another node of the same type is in the scene."); + warnings.push_back(TTR("ShaderGlobalsOverride is not active because another node of the same type is in the scene.")); } - return warning; + return warnings; } void ShaderGlobalsOverride::_bind_methods() { diff --git a/scene/main/shader_globals_override.h b/scene/main/shader_globals_override.h index 8d8794d465d..2d9c3c76bda 100644 --- a/scene/main/shader_globals_override.h +++ b/scene/main/shader_globals_override.h @@ -58,7 +58,7 @@ protected: static void _bind_methods(); public: - String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; ShaderGlobalsOverride(); }; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index a3effef99a5..4c9ebe016ec 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -3175,20 +3175,17 @@ Variant Viewport::gui_get_drag_data() const { return gui.drag_data; } -String Viewport::get_configuration_warning() const { +TypedArray Viewport::get_configuration_warnings() const { /*if (get_parent() && !Object::cast_to(get_parent()) && !render_target) { return TTR("This viewport is not set as render target. If you intend for it to display its contents directly to the screen, make it a child of a Control so it can obtain a size. Otherwise, make it a RenderTarget and assign its internal texture to some node for display."); }*/ - String warning = Node::get_configuration_warning(); + TypedArray warnings = Node::get_configuration_warnings(); if (size.x == 0 || size.y == 0) { - if (!warning.is_empty()) { - warning += "\n\n"; - } - warning += TTR("Viewport size must be greater than 0 to render anything."); + warnings.push_back(TTR("Viewport size must be greater than 0 to render anything.")); } - return warning; + return warnings; } void Viewport::gui_reset_canvas_sort_index() { diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 8e79b503858..e8a88debf11 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -580,7 +580,7 @@ public: void gui_reset_canvas_sort_index(); int gui_get_canvas_sort_index(); - virtual String get_configuration_warning() const override; + TypedArray get_configuration_warnings() const override; void set_debug_draw(DebugDraw p_debug_draw); DebugDraw get_debug_draw() const;