Use Array for node configuration warnings

Previously, the warnings were passed as a string and delimitation of which were hard coded at each implementation.
This commit is contained in:
Nathan Franke 2020-10-29 05:01:28 -05:00
parent 4a1f2dcb74
commit 2a8c59c171
No known key found for this signature in database
GPG Key ID: 92164DCCF3B1F723
96 changed files with 426 additions and 674 deletions

View File

@ -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].
</description>
</method>
<method name="_get_configuration_warning" qualifiers="virtual">
<return type="String">
<method name="_get_configuration_warnings" qualifiers="virtual">
<return type="Array">
</return>
<description>
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.
</description>
</method>
<method name="_input" qualifiers="virtual">
@ -856,12 +856,12 @@
Sets whether this is an instance load placeholder. See [InstancePlaceholder].
</description>
</method>
<method name="update_configuration_warning">
<method name="update_configuration_warnings">
<return type="void">
</return>
<description>
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.
</description>
</method>
</methods>

View File

@ -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();

View File

@ -272,7 +272,7 @@ void AnimatedSprite2D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
notify_property_list_changed();
_reset_timeout();
update();
update_configuration_warning();
update_configuration_warnings();
}
Ref<SpriteFrames> 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<String> AnimatedSprite2D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -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<String> get_configuration_warnings() const override;
AnimatedSprite2D();
};

View File

@ -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<String> CanvasModulate::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
String warning = Node2D::get_configuration_warning();
if (is_visible_in_tree() && is_inside_tree()) {
List<Node *> nodes;
get_tree()->get_nodes_in_group("_canvas_modulate_" + itos(get_canvas().get_id()), &nodes);
List<Node *> 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() {

View File

@ -46,7 +46,7 @@ public:
void set_color(const Color &p_color);
Color get_color() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
CanvasModulate();
~CanvasModulate();

View File

@ -363,17 +363,14 @@ void CollisionObject2D::_update_pickable() {
}
}
String CollisionObject2D::get_configuration_warning() const {
String warning = Node2D::get_configuration_warning();
TypedArray<String> CollisionObject2D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -107,7 +107,7 @@ public:
void set_pickable(bool p_enabled);
bool is_pickable() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
_FORCE_INLINE_ RID get_rid() const { return rid; }

View File

@ -204,7 +204,7 @@ void CollisionPolygon2D::set_polygon(const Vector<Point2> &p_polygon) {
_update_in_shape_owner();
}
update();
update_configuration_warning();
update_configuration_warnings();
}
Vector<Point2> 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<String> CollisionPolygon2D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<CollisionObject2D>(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) {

View File

@ -78,7 +78,7 @@ public:
void set_polygon(const Vector<Point2> &p_polygon);
Vector<Point2> get_polygon() const;
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
void set_disabled(bool p_disabled);
bool is_disabled() const;

View File

@ -162,7 +162,7 @@ void CollisionShape2D::set_shape(const Ref<Shape2D> &p_shape) {
shape->connect("changed", callable_mp(this, &CollisionShape2D::_shape_changed));
}
update_configuration_warning();
update_configuration_warnings();
}
Ref<Shape2D> 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<String> CollisionShape2D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<CollisionObject2D>(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<ConvexPolygonShape2D> convex = shape;
Ref<ConcavePolygonShape2D> 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) {

View File

@ -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<String> get_configuration_warnings() const override;
CollisionShape2D();
};

View File

@ -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<String> CPUParticles2D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
CanvasItemMaterial *mat = Object::cast_to<CanvasItemMaterial>(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."));
}
}

View File

@ -275,7 +275,7 @@ public:
void set_gravity(const Vector2 &p_gravity);
Vector2 get_gravity() const;
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
void restart();

View File

@ -137,7 +137,7 @@ void GPUParticles2D::set_process_material(const Ref<Material> &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<String> GPUParticles2D::get_configuration_warnings() const {
TypedArray<String> 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<CanvasItemMaterial>(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."));
}
}
}

View File

@ -110,7 +110,7 @@ public:
void set_texture(const Ref<Texture2D> &p_texture);
Ref<Texture2D> get_texture() const;
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
void restart();
Rect2 capture_rect() const;

View File

@ -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<PhysicsBody2D>(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<String> Joint2D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -62,7 +62,7 @@ protected:
_FORCE_INLINE_ bool is_configured() const { return configured; }
public:
virtual String get_configuration_warning() const override;
virtual TypedArray<String> get_configuration_warnings() const override;
void set_node_a(const NodePath &p_node_a);
NodePath get_node_a() const;

View File

@ -373,7 +373,7 @@ void PointLight2D::set_texture(const Ref<Texture2D> &p_texture) {
RS::get_singleton()->canvas_light_set_texture(_get_light(), RID());
}
update_configuration_warning();
update_configuration_warnings();
}
Ref<Texture2D> 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<String> PointLight2D::get_configuration_warnings() const {
TypedArray<String> 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) {

View File

@ -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<String> get_configuration_warnings() const override;
PointLight2D();
};

View File

@ -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<String> LightOccluder2D::get_configuration_warnings() const {
TypedArray<String> 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) {

View File

@ -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<String> get_configuration_warnings() const override;
LightOccluder2D();
~LightOccluder2D();

View File

@ -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<String> NavigationAgent2D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<Node2D>(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() {

View File

@ -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<String> get_configuration_warnings() const override;
private:
void update_navigation();

View File

@ -69,17 +69,14 @@ NavigationObstacle2D::~NavigationObstacle2D() {
agent = RID(); // Pointless
}
String NavigationObstacle2D::get_configuration_warning() const {
String warning = Node::get_configuration_warning();
TypedArray<String> NavigationObstacle2D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<Node2D>(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() {

View File

@ -52,7 +52,7 @@ public:
return agent;
}
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
private:
void update_agent_shape();

View File

@ -491,7 +491,7 @@ void NavigationRegion2D::set_navigation_polygon(const Ref<NavigationPolygon> &p_
}
_navpoly_changed();
update_configuration_warning();
update_configuration_warnings();
}
Ref<NavigationPolygon> 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<String> NavigationRegion2D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -120,7 +120,7 @@ public:
void set_navigation_polygon(const Ref<NavigationPolygon> &p_navpoly);
Ref<NavigationPolygon> get_navigation_polygon() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
NavigationRegion2D();
~NavigationRegion2D();

View File

@ -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<String> ParallaxLayer::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<ParallaxBackground>(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() {

View File

@ -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<String> get_configuration_warnings() const override;
ParallaxLayer();
};

View File

@ -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<String> PathFollow2D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
String warning = Node2D::get_configuration_warning();
if (!Object::cast_to<Path2D>(get_parent())) {
if (!warning.is_empty()) {
warning += "\n\n";
if (is_visible_in_tree() && is_inside_tree()) {
if (!Object::cast_to<Path2D>(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() {

View File

@ -105,7 +105,7 @@ public:
void set_cubic_interpolation(bool p_enable);
bool get_cubic_interpolation() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
PathFollow2D() {}
};

View File

@ -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<String> RigidBody2D::get_configuration_warnings() const {
Transform2D t = get_transform();
String warning = CollisionObject2D::get_configuration_warning();
TypedArray<String> 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() {

View File

@ -246,7 +246,7 @@ public:
TypedArray<Node2D> get_colliding_bodies() const; //function for script
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
RigidBody2D();
~RigidBody2D();

View File

@ -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<String> RemoteTransform2D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!has_node(remote_node) || !Object::cast_to<Node2D>(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() {

View File

@ -70,7 +70,7 @@ public:
void force_update_cache();
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
RemoteTransform2D();
};

View File

@ -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<String> Bone2D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -60,7 +60,7 @@ public:
void apply_rest();
Transform2D get_skeleton_rest() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
void set_default_length(real_t p_length);
real_t get_default_length() const;

View File

@ -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<String> TileMap::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -340,7 +340,7 @@ public:
void set_clip_uv(bool p_enable);
bool get_clip_uv() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
virtual void set_texture_filter(CanvasItem::TextureFilter p_texture_filter) override;

View File

@ -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<String> VisibilityEnabler2D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -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<String> get_configuration_warnings() const override;
VisibilityEnabler2D();
};

View File

@ -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<String> CollisionObject3D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -110,7 +110,7 @@ public:
_FORCE_INLINE_ RID get_rid() const { return rid; }
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
CollisionObject3D();
~CollisionObject3D();

View File

@ -121,7 +121,7 @@ void CollisionPolygon3D::set_polygon(const Vector<Point2> &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<String> CollisionPolygon3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<CollisionObject3D>(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 {

View File

@ -74,7 +74,7 @@ public:
real_t get_margin() const;
void set_margin(real_t p_margin);
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
CollisionPolygon3D();
};

View File

@ -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<String> CollisionShape3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<CollisionObject3D>(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<RigidBody3D>(get_parent()) &&
Object::cast_to<ConcavePolygonShape3D>(*shape) &&
Object::cast_to<RigidBody3D>(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<Shape3D> &p_shape) {
if (is_inside_tree()) {
_shape_changed();
}
update_configuration_warning();
update_configuration_warnings();
}
Ref<Shape3D> CollisionShape3D::get_shape() const {

View File

@ -64,7 +64,7 @@ public:
void set_disabled(bool p_disabled);
bool is_disabled() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
CollisionShape3D();
~CollisionShape3D();

View File

@ -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<String> CPUParticles3D::get_configuration_warnings() const {
TypedArray<String> 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;

View File

@ -280,7 +280,7 @@ public:
void set_gravity(const Vector3 &p_gravity);
Vector3 get_gravity() const;
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
void restart();

View File

@ -503,19 +503,15 @@ Vector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
return Vector<Face3>();
}
String GIProbe::get_configuration_warning() const {
String warning = VisualInstance3D::get_configuration_warning();
TypedArray<String> GIProbe::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -165,7 +165,7 @@ public:
virtual AABB get_aabb() const override;
virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
GIProbe();
~GIProbe();

View File

@ -115,7 +115,7 @@ void GPUParticles3D::set_process_material(const Ref<Material> &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<Mesh> &p_mesh) {
RS::get_singleton()->particles_set_draw_pass_mesh(particles, p_pass, mesh_rid);
update_configuration_warning();
update_configuration_warnings();
}
Ref<Mesh> 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<String> GPUParticles3D::get_configuration_warnings() const {
TypedArray<String> 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<ParticlesMaterial>(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\"."));
}
}

View File

@ -125,7 +125,7 @@ public:
void set_draw_pass_mesh(int p_pass, const Ref<Mesh> &p_mesh);
Ref<Mesh> get_draw_pass_mesh(int p_pass) const;
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
void set_sub_emitter(const NodePath &p_path);
NodePath get_sub_emitter() const;

View File

@ -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<Texture2D> &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<Texture2D> 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<String> OmniLight3D::get_configuration_warnings() const {
TypedArray<String> 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<String> SpotLight3D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -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<String> get_configuration_warnings() const override;
OmniLight3D();
};
@ -216,7 +216,7 @@ protected:
static void _bind_methods();
public:
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
SpotLight3D() :
Light3D(RenderingServer::LIGHT_SPOT) {}

View File

@ -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<String> NavigationAgent3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<Node3D>(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() {

View File

@ -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<String> get_configuration_warnings() const override;
private:
void update_navigation();

View File

@ -76,17 +76,14 @@ NavigationObstacle3D::~NavigationObstacle3D() {
agent = RID(); // Pointless
}
String NavigationObstacle3D::get_configuration_warning() const {
String warning = Node::get_configuration_warning();
TypedArray<String> NavigationObstacle3D::get_configuration_warnings() const {
TypedArray<String> 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<Node3D>(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() {

View File

@ -52,7 +52,7 @@ public:
return agent;
}
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
private:
void update_agent_shape();

View File

@ -135,7 +135,7 @@ void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmes
emit_signal("navigation_mesh_changed");
update_gizmo();
update_configuration_warning();
update_configuration_warnings();
}
Ref<NavigationMesh> NavigationRegion3D::get_navigation_mesh() const {
@ -177,21 +177,16 @@ void NavigationRegion3D::_bake_finished(Ref<NavigationMesh> p_nav_mesh) {
emit_signal("bake_finished");
}
String NavigationRegion3D::get_configuration_warning() const {
if (!is_visible_in_tree() || !is_inside_tree()) {
return String();
}
TypedArray<String> NavigationRegion3D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -66,7 +66,7 @@ public:
void bake_navigation_mesh();
void _bake_finished(Ref<NavigationMesh> p_nav_mesh);
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
NavigationRegion3D();
~NavigationRegion3D();

View File

@ -50,7 +50,7 @@ void Path3D::_curve_changed() {
for (int i = 0; i < get_child_count(); i++) {
PathFollow3D *child = Object::cast_to<PathFollow3D>(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<String> PathFollow3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
String warning = Node3D::get_configuration_warning();
if (!Object::cast_to<Path3D>(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<Path3D>(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<Path3D>(get_parent())) {
warnings.push_back(TTR("PathFollow3D only works when set as a child of a Path3D node."));
} else {
Path3D *path = Object::cast_to<Path3D>(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();
}

View File

@ -104,7 +104,7 @@ public:
void set_cubic_interpolation(bool p_enable);
bool get_cubic_interpolation() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
PathFollow3D() {}
};

View File

@ -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<String> RigidBody3D::get_configuration_warnings() const {
Transform t = get_transform();
String warning = CollisionObject3D::get_configuration_warning();
TypedArray<String> 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() {

View File

@ -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<String> get_configuration_warnings() const override;
RigidBody3D();
~RigidBody3D();

View File

@ -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<PhysicsBody3D>(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<String> Joint3D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -63,7 +63,7 @@ protected:
_FORCE_INLINE_ bool is_configured() const { return configured; }
public:
virtual String get_configuration_warning() const override;
virtual TypedArray<String> get_configuration_warnings() const override;
void set_node_a(const NodePath &p_node_a);
NodePath get_node_a() const;

View File

@ -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<String> RemoteTransform3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!has_node(remote_node) || !Object::cast_to<Node3D>(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() {

View File

@ -70,7 +70,7 @@ public:
void force_update_cache();
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
RemoteTransform3D();
};

View File

@ -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<String> SoftBody3D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -113,7 +113,7 @@ protected:
void _notification(int p_what);
static void _bind_methods();
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
protected:
void _update_physics_server();

View File

@ -928,7 +928,7 @@ void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) {
notify_property_list_changed();
_reset_timeout();
_queue_update();
update_configuration_warning();
update_configuration_warnings();
}
Ref<SpriteFrames> 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<String> AnimatedSprite3D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -236,7 +236,7 @@ public:
virtual Rect2 get_item_rect() const override;
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
AnimatedSprite3D();
};

View File

@ -102,17 +102,14 @@ void VehicleWheel3D::_notification(int p_what) {
}
}
String VehicleWheel3D::get_configuration_warning() const {
String warning = Node3D::get_configuration_warning();
TypedArray<String> VehicleWheel3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (!Object::cast_to<VehicleBody3D>(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) {

View File

@ -145,7 +145,7 @@ public:
void set_steering(real_t p_steering);
real_t get_steering() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
VehicleWheel3D();
};

View File

@ -65,7 +65,7 @@ void WorldEnvironment::_update_current_environment() {
} else {
get_viewport()->find_world_3d()->set_environment(Ref<Environment>());
}
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<CameraEffects>());
}
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<Environment> &p_environment) {
@ -96,7 +96,7 @@ void WorldEnvironment::set_environment(const Ref<Environment> &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<CameraEffects> &p_camera_eff
if (is_inside_tree()) {
_update_current_camera_effects();
} else {
update_configuration_warning();
update_configuration_warnings();
}
}
@ -129,35 +129,26 @@ Ref<CameraEffects> WorldEnvironment::get_camera_effects() const {
return camera_effects;
}
String WorldEnvironment::get_configuration_warning() const {
String warning = Node::get_configuration_warning();
TypedArray<String> WorldEnvironment::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -55,7 +55,7 @@ public:
void set_camera_effects(const Ref<CameraEffects> &p_camera_effects);
Ref<CameraEffects> get_camera_effects() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
WorldEnvironment();
};

View File

@ -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<String> XRCamera3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (is_visible() && is_inside_tree()) {
// must be child node of XROrigin3D!
XROrigin3D *origin = Object::cast_to<XROrigin3D>(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<XROrigin3D>(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<String> XRController3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (is_visible() && is_inside_tree()) {
// must be child node of XROrigin!
XROrigin3D *origin = Object::cast_to<XROrigin3D>(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<XROrigin3D>(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<String> XRAnchor3D::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
if (is_visible() && is_inside_tree()) {
// must be child node of XROrigin3D!
XROrigin3D *origin = Object::cast_to<XROrigin3D>(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<XROrigin3D>(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<Mesh> XRAnchor3D::get_mesh() const {
////////////////////////////////////////////////////////////////////////////////////////////////////
String XROrigin3D::get_configuration_warning() const {
if (!is_visible() || !is_inside_tree()) {
return String();
}
TypedArray<String> XROrigin3D::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -50,7 +50,7 @@ protected:
void _notification(int p_what);
public:
String get_configuration_warning() const override;
TypedArray<String> 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<Mesh> get_mesh() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
XRController3D() {}
~XRController3D() {}
@ -133,7 +133,7 @@ public:
Ref<Mesh> get_mesh() const;
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
XRAnchor3D() {}
~XRAnchor3D() {}
@ -158,7 +158,7 @@ protected:
static void _bind_methods();
public:
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
void set_tracked_camera(XRCamera3D *p_tracked_camera);
void clear_tracked_camera_if(XRCamera3D *p_tracked_camera);

View File

@ -458,7 +458,7 @@ void AnimationTree::set_tree_root(const Ref<AnimationNode> &p_root) {
properties_dirty = true;
update_configuration_warning();
update_configuration_warnings();
}
Ref<AnimationNode> 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<String> AnimationTree::get_configuration_warnings() const {
TypedArray<String> 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<AnimationPlayer>(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) {

View File

@ -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<String> get_configuration_warnings() const override;
bool is_state_invalid() const;
String get_invalid_state_reason() const;

View File

@ -159,16 +159,14 @@ void Container::_notification(int p_what) {
}
}
String Container::get_configuration_warning() const {
String warning = Control::get_configuration_warning();
TypedArray<String> Container::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -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<String> get_configuration_warnings() const override;
Container();
};

View File

@ -2183,7 +2183,7 @@ Ref<Theme> 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<String> Control::get_configuration_warnings() const {
TypedArray<String> 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) {

View File

@ -524,7 +524,7 @@ public:
bool is_visibility_clip_disabled() const;
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override;
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
Control() {}
};

View File

@ -30,17 +30,14 @@
#include "range.h"
String Range::get_configuration_warning() const {
String warning = Control::get_configuration_warning();
TypedArray<String> Range::get_configuration_warnings() const {
TypedArray<String> 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 {

View File

@ -97,7 +97,7 @@ public:
void share(Range *p_range);
void unshare();
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
Range();
~Range();

View File

@ -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<String> ScrollContainer::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -103,7 +103,7 @@ public:
virtual bool clips_input() const override;
virtual String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
ScrollContainer();
};

View File

@ -2634,15 +2634,27 @@ void Node::clear_internal_tree_resource_paths() {
}
}
String Node::get_configuration_warning() const {
TypedArray<String> 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<String> 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() {

View File

@ -412,9 +412,10 @@ public:
_FORCE_INLINE_ Viewport *get_viewport() const { return data.viewport; }
virtual String get_configuration_warning() const;
virtual TypedArray<String> 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;

View File

@ -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<String> ShaderGlobalsOverride::get_configuration_warnings() const {
TypedArray<String> 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() {

View File

@ -58,7 +58,7 @@ protected:
static void _bind_methods();
public:
String get_configuration_warning() const override;
TypedArray<String> get_configuration_warnings() const override;
ShaderGlobalsOverride();
};

View File

@ -3175,20 +3175,17 @@ Variant Viewport::gui_get_drag_data() const {
return gui.drag_data;
}
String Viewport::get_configuration_warning() const {
TypedArray<String> Viewport::get_configuration_warnings() const {
/*if (get_parent() && !Object::cast_to<Control>(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<String> 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() {

View File

@ -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<String> get_configuration_warnings() const override;
void set_debug_draw(DebugDraw p_debug_draw);
DebugDraw get_debug_draw() const;