diff options
Diffstat (limited to 'scene')
27 files changed, 357 insertions, 184 deletions
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 68d5b4b540..49d1654e3f 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -590,10 +590,10 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout); ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"))); + ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node2D"))); ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area2D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index 99c5276636..23eda379be 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -640,10 +640,10 @@ void Area3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_reverb_uniformity", "amount"), &Area3D::set_reverb_uniformity); ClassDB::bind_method(D_METHOD("get_reverb_uniformity"), &Area3D::get_reverb_uniformity); - ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); - ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); - ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); + ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); + ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); + ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); ADD_SIGNAL(MethodInfo("area_shape_entered", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); ADD_SIGNAL(MethodInfo("area_shape_exited", PropertyInfo(Variant::INT, "area_id"), PropertyInfo(Variant::OBJECT, "area", PROPERTY_HINT_RESOURCE_TYPE, "Area3D"), PropertyInfo(Variant::INT, "area_shape"), PropertyInfo(Variant::INT, "local_shape"))); diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index b7da4822e2..849ef7a2bf 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -30,6 +30,7 @@ #include "collision_object_3d.h" +#include "mesh_instance_3d.h" #include "scene/scene_string_names.h" #include "servers/physics_server_3d.h" @@ -110,6 +111,42 @@ void CollisionObject3D::_update_pickable() { } } +void CollisionObject3D::_update_debug_shapes() { + for (Set<uint32_t>::Element *shapedata_idx = debug_shapes_to_update.front(); shapedata_idx; shapedata_idx = shapedata_idx->next()) { + if (shapes.has(shapedata_idx->get())) { + ShapeData &shapedata = shapes[shapedata_idx->get()]; + for (int i = 0; i < shapedata.shapes.size(); i++) { + ShapeData::ShapeBase &s = shapedata.shapes.write[i]; + if (s.debug_shape) { + s.debug_shape->queue_delete(); + s.debug_shape = nullptr; + } + if (s.shape.is_null() || shapedata.disabled) { + continue; + } + + Ref<Mesh> mesh = s.shape->get_debug_mesh(); + MeshInstance3D *mi = memnew(MeshInstance3D); + mi->set_transform(shapedata.xform); + mi->set_mesh(mesh); + add_child(mi); + mi->force_update_transform(); + s.debug_shape = mi; + } + } + } + debug_shapes_to_update.clear(); +} + +void CollisionObject3D::_update_shape_data(uint32_t p_owner) { + if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) { + if (debug_shapes_to_update.is_empty()) { + call_deferred("_update_debug_shapes"); + } + debug_shapes_to_update.insert(p_owner); + } +} + void CollisionObject3D::set_ray_pickable(bool p_ray_pickable) { ray_pickable = p_ray_pickable; _update_pickable(); @@ -141,6 +178,8 @@ void CollisionObject3D::_bind_methods() { ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject3D::shape_owner_clear_shapes); ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject3D::shape_find_owner); + ClassDB::bind_method(D_METHOD("_update_debug_shapes"), &CollisionObject3D::_update_debug_shapes); + BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx"))); @@ -188,6 +227,7 @@ void CollisionObject3D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabl PhysicsServer3D::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); } } + _update_shape_data(p_owner); } bool CollisionObject3D::is_shape_owner_disabled(uint32_t p_owner) const { @@ -223,6 +263,8 @@ void CollisionObject3D::shape_owner_set_transform(uint32_t p_owner, const Transf PhysicsServer3D::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); } } + + _update_shape_data(p_owner); } Transform CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const { @@ -245,6 +287,7 @@ void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3 ShapeData::ShapeBase s; s.index = total_subshapes; s.shape = p_shape; + if (area) { PhysicsServer3D::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); } else { @@ -253,6 +296,8 @@ void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3 sd.shapes.push_back(s); total_subshapes++; + + _update_shape_data(p_owner); } int CollisionObject3D::shape_owner_get_shape_count(uint32_t p_owner) const { @@ -279,13 +324,19 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) ERR_FAIL_COND(!shapes.has(p_owner)); ERR_FAIL_INDEX(p_shape, shapes[p_owner].shapes.size()); - int index_to_remove = shapes[p_owner].shapes[p_shape].index; + const ShapeData::ShapeBase &s = shapes[p_owner].shapes[p_shape]; + int index_to_remove = s.index; + if (area) { PhysicsServer3D::get_singleton()->area_remove_shape(rid, index_to_remove); } else { PhysicsServer3D::get_singleton()->body_remove_shape(rid, index_to_remove); } + if (s.debug_shape) { + s.debug_shape->queue_delete(); + } + shapes[p_owner].shapes.remove(p_shape); for (Map<uint32_t, ShapeData>::Element *E = shapes.front(); E; E = E->next()) { diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index b7473ca12a..fe20176984 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -45,6 +45,7 @@ class CollisionObject3D : public Node3D { Object *owner = nullptr; Transform xform; struct ShapeBase { + Node *debug_shape = nullptr; Ref<Shape3D> shape; int index = 0; }; @@ -60,8 +61,12 @@ class CollisionObject3D : public Node3D { bool capture_input_on_drag = false; bool ray_pickable = true; + Set<uint32_t> debug_shapes_to_update; + void _update_pickable(); + void _update_shape_data(uint32_t p_owner); + protected: CollisionObject3D(RID p_rid, bool p_area); @@ -72,6 +77,8 @@ protected: virtual void _mouse_enter(); virtual void _mouse_exit(); + void _update_debug_shapes(); + public: uint32_t create_shape_owner(Object *p_owner); void remove_shape_owner(uint32_t owner); diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index 914c8eab7a..242d82ab4c 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -100,9 +100,6 @@ void CollisionShape3D::_notification(int p_what) { if (parent) { _update_in_shape_owner(); } - if (get_tree()->is_debugging_collisions_hint()) { - _update_debug_shape(); - } } break; case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { if (parent) { @@ -163,8 +160,6 @@ void CollisionShape3D::_bind_methods() { ClassDB::bind_method(D_METHOD("make_convex_from_siblings"), &CollisionShape3D::make_convex_from_siblings); ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_siblings", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); - ClassDB::bind_method(D_METHOD("_update_debug_shape"), &CollisionShape3D::_update_debug_shape); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); } @@ -224,34 +219,9 @@ CollisionShape3D::~CollisionShape3D() { //RenderingServer::get_singleton()->free(indicator); } -void CollisionShape3D::_update_debug_shape() { - debug_shape_dirty = false; - - if (debug_shape) { - debug_shape->queue_delete(); - debug_shape = nullptr; - } - - Ref<Shape3D> s = get_shape(); - if (s.is_null()) { - return; - } - - Ref<Mesh> mesh = s->get_debug_mesh(); - MeshInstance3D *mi = memnew(MeshInstance3D); - mi->set_mesh(mesh); - add_child(mi); - debug_shape = mi; -} - void CollisionShape3D::_shape_changed() { // If this is a heightfield shape our center may have changed if (parent) { _update_in_shape_owner(true); } - - if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !debug_shape_dirty) { - debug_shape_dirty = true; - call_deferred("_update_debug_shape"); - } } diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h index f55c09ffaa..5512417f75 100644 --- a/scene/3d/collision_shape_3d.h +++ b/scene/3d/collision_shape_3d.h @@ -43,14 +43,10 @@ class CollisionShape3D : public Node3D { uint32_t owner_id = 0; CollisionObject3D *parent = nullptr; - Node *debug_shape = nullptr; - bool debug_shape_dirty; - void resource_changed(RES res); bool disabled = false; protected: - void _update_debug_shape(); void _shape_changed(); void _update_in_shape_owner(bool p_xform_only = false); diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index cf1c319acc..214ffd6bd5 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -35,51 +35,69 @@ void WorldEnvironment::_notification(int p_what) { if (p_what == Node3D::NOTIFICATION_ENTER_WORLD || p_what == Node3D::NOTIFICATION_ENTER_TREE) { if (environment.is_valid()) { - if (get_viewport()->find_world_3d()->get_environment().is_valid()) { - WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding."); - } - get_viewport()->find_world_3d()->set_environment(environment); add_to_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + _update_current_environment(); } if (camera_effects.is_valid()) { - if (get_viewport()->find_world_3d()->get_camera_effects().is_valid()) { - WARN_PRINT("World already has a camera effects (Another WorldEnvironment?), overriding."); - } - get_viewport()->find_world_3d()->set_camera_effects(camera_effects); add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + _update_current_camera_effects(); } } else if (p_what == Node3D::NOTIFICATION_EXIT_WORLD || p_what == Node3D::NOTIFICATION_EXIT_TREE) { - if (environment.is_valid() && get_viewport()->find_world_3d()->get_environment() == environment) { - get_viewport()->find_world_3d()->set_environment(Ref<Environment>()); + if (environment.is_valid()) { remove_from_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + _update_current_environment(); } - if (camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) { - get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>()); + if (camera_effects.is_valid()) { remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); + _update_current_camera_effects(); } } } -void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) { - if (is_inside_tree() && environment.is_valid() && get_viewport()->find_world_3d()->get_environment() == environment) { +void WorldEnvironment::_update_current_environment() { + WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()))); + + if (first) { + get_viewport()->find_world_3d()->set_environment(first->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"); +} + +void WorldEnvironment::_update_current_camera_effects() { + WorldEnvironment *first = Object::cast_to<WorldEnvironment>(get_tree()->get_first_node_in_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()))); + if (first) { + get_viewport()->find_world_3d()->set_camera_effects(first->camera_effects); + } else { + 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"); +} + +void WorldEnvironment::set_environment(const Ref<Environment> &p_environment) { + if (environment == p_environment) { + return; + } + if (is_inside_tree() && environment.is_valid()) { remove_from_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); - //clean up } environment = p_environment; + if (is_inside_tree() && environment.is_valid()) { - if (get_viewport()->find_world_3d()->get_environment().is_valid()) { - WARN_PRINT("World already has an environment (Another WorldEnvironment?), overriding."); - } - get_viewport()->find_world_3d()->set_environment(environment); add_to_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); } - update_configuration_warning(); + if (is_inside_tree()) { + _update_current_environment(); + } else { + update_configuration_warning(); + } } Ref<Environment> WorldEnvironment::get_environment() const { @@ -87,22 +105,24 @@ Ref<Environment> WorldEnvironment::get_environment() const { } void WorldEnvironment::set_camera_effects(const Ref<CameraEffects> &p_camera_effects) { + if (camera_effects == p_camera_effects) { + return; + } + if (is_inside_tree() && camera_effects.is_valid() && get_viewport()->find_world_3d()->get_camera_effects() == camera_effects) { - get_viewport()->find_world_3d()->set_camera_effects(Ref<CameraEffects>()); remove_from_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); - //clean up } camera_effects = p_camera_effects; if (is_inside_tree() && camera_effects.is_valid()) { - if (get_viewport()->find_world_3d()->get_camera_effects().is_valid()) { - WARN_PRINT("World already has an camera_effects (Another WorldEnvironment?), overriding."); - } - get_viewport()->find_world_3d()->set_camera_effects(camera_effects); add_to_group("_world_camera_effects_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id())); } - update_configuration_warning(); + if (is_inside_tree()) { + _update_current_camera_effects(); + } else { + update_configuration_warning(); + } } Ref<CameraEffects> WorldEnvironment::get_camera_effects() const { @@ -123,14 +143,18 @@ String WorldEnvironment::get_configuration_warning() const { return warning; } - List<Node *> nodes; - get_tree()->get_nodes_in_group("_world_environment_" + itos(get_viewport()->find_world_3d()->get_scenario().get_id()), &nodes); + 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)."); + } - if (nodes.size() > 1) { + 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 one WorldEnvironment is allowed per scene (or set of instanced scenes)."); + warning += TTR("Only the first CameraEffects has an effect in a scene (or set of instantiated scenes)."); } return warning; diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h index 3dfba20bf0..e3f28d6d6b 100644 --- a/scene/3d/world_environment.h +++ b/scene/3d/world_environment.h @@ -41,6 +41,9 @@ class WorldEnvironment : public Node { Ref<Environment> environment; Ref<CameraEffects> camera_effects; + void _update_current_environment(); + void _update_current_camera_effects(); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 62d03ea80c..9b98f3d031 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -1350,6 +1350,9 @@ void Tween::interpolate_property(Object *p_object, NodePath p_property, Variant return; } + // Check that the target object is valid + ERR_FAIL_COND_MSG(p_object == nullptr, vformat("The Tween \"%s\"'s target node is `null`. Is the node reference correct?", get_name())); + // Get the property from the node path p_property = p_property.get_as_property_path(); @@ -1378,6 +1381,9 @@ void Tween::interpolate_method(Object *p_object, StringName p_method, Variant p_ return; } + // Check that the target object is valid + ERR_FAIL_COND_MSG(p_object == nullptr, vformat("The Tween \"%s\"'s target node is `null`. Is the node reference correct?", get_name())); + // Convert any integers into REALs as they are better for interpolation if (p_initial_val.get_type() == Variant::INT) { p_initial_val = p_initial_val.operator real_t(); diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 37bb17b47d..b0bcde8865 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -56,6 +56,11 @@ Size2 Button::get_minimum_size() const { } } + Ref<Font> font = get_theme_font("font"); + float font_height = font->get_height(get_theme_font_size("font_size")); + + minsize.height = MAX(font_height, minsize.height); + return get_theme_stylebox("normal")->get_minimum_size() + minsize; } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index a79c633502..682584d73f 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1578,11 +1578,11 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { if (k->is_pressed()) { bool handled = false; - if (k->is_action("ui_pageup") && vscroll->is_visible_in_tree()) { + if (k->is_action("ui_page_up") && vscroll->is_visible_in_tree()) { vscroll->set_value(vscroll->get_value() - vscroll->get_page()); handled = true; } - if (k->is_action("ui_pagedown") && vscroll->is_visible_in_tree()) { + if (k->is_action("ui_page_down") && vscroll->is_visible_in_tree()) { vscroll->set_value(vscroll->get_value() + vscroll->get_page()); handled = true; } diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index 8b07299e30..2239226c78 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -73,8 +73,10 @@ void Slider::_gui_input(Ref<InputEvent> p_event) { } } else if (scrollable) { if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_UP) { + grab_focus(); set_value(get_value() + get_step()); } else if (mb->is_pressed() && mb->get_button_index() == BUTTON_WHEEL_DOWN) { + grab_focus(); set_value(get_value() - get_step()); } } diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 9f32c65f7b..9aaddfd373 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -54,6 +54,7 @@ #include "window.h" #include <stdio.h> +#include <stdlib.h> void SceneTreeTimer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_time_left", "time"), &SceneTreeTimer::set_time_left); @@ -534,12 +535,7 @@ void SceneTree::finalize() { } void SceneTree::quit(int p_exit_code) { - if (p_exit_code >= 0) { - // Override the exit code if a positive argument is given (the default is `-1`). - // This is a shorthand for calling `set_exit_code()` on the OS singleton then quitting. - OS::get_singleton()->set_exit_code(p_exit_code); - } - + OS::get_singleton()->set_exit_code(p_exit_code); _quit = true; } @@ -956,6 +952,21 @@ bool SceneTree::has_group(const StringName &p_identifier) const { return group_map.has(p_identifier); } +Node *SceneTree::get_first_node_in_group(const StringName &p_group) { + Map<StringName, Group>::Element *E = group_map.find(p_group); + if (!E) { + return nullptr; //no group + } + + _update_group_order(E->get()); //update order just in case + + if (E->get().nodes.size() == 0) { + return nullptr; + } + + return E->get().nodes[0]; +} + void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_list) { Map<StringName, Group>::Element *E = group_map.find(p_group); if (!E) { @@ -1190,7 +1201,7 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count); ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame); - ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(EXIT_SUCCESS)); ClassDB::bind_method(D_METHOD("queue_delete", "obj"), &SceneTree::queue_delete); @@ -1216,6 +1227,7 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("set_group", "group", "property", "value"), &SceneTree::set_group); ClassDB::bind_method(D_METHOD("get_nodes_in_group", "group"), &SceneTree::_get_nodes_in_group); + ClassDB::bind_method(D_METHOD("get_first_node_in_group", "group"), &SceneTree::get_first_node_in_group); ClassDB::bind_method(D_METHOD("set_current_scene", "child_node"), &SceneTree::set_current_scene); ClassDB::bind_method(D_METHOD("get_current_scene"), &SceneTree::get_current_scene); @@ -1334,6 +1346,8 @@ SceneTree::SceneTree() { collision_debug_contacts = GLOBAL_DEF("debug/shapes/collision/max_contacts_displayed", 10000); ProjectSettings::get_singleton()->set_custom_property_info("debug/shapes/collision/max_contacts_displayed", PropertyInfo(Variant::INT, "debug/shapes/collision/max_contacts_displayed", PROPERTY_HINT_RANGE, "0,20000,1")); // No negative + GLOBAL_DEF("debug/shapes/collision/draw_2d_outlines", true); + // Create with mainloop. root = memnew(Window); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index f39780831f..a2f2adb8f8 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -245,7 +245,7 @@ public: void set_auto_accept_quit(bool p_enable); void set_quit_on_go_back(bool p_enable); - void quit(int p_exit_code = -1); + void quit(int p_exit_code = EXIT_SUCCESS); _FORCE_INLINE_ float get_physics_process_time() const { return physics_process_time; } _FORCE_INLINE_ float get_process_time() const { return process_time; } @@ -302,6 +302,7 @@ public: void queue_delete(Object *p_object); void get_nodes_in_group(const StringName &p_group, List<Node *> *p_list); + Node *get_first_node_in_group(const StringName &p_group); bool has_group(const StringName &p_identifier) const; //void change_scene(const String& p_path); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 54b670df6c..40b85e6d7b 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1770,19 +1770,22 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_ } } - if (!c) { + if (!c || c->data.mouse_filter == Control::MOUSE_FILTER_IGNORE) { return nullptr; } matrix.affine_invert(); + if (!c->has_point(matrix.xform(p_global))) { + return nullptr; + } - //conditions for considering this as a valid control for return - if (c->data.mouse_filter != Control::MOUSE_FILTER_IGNORE && c->has_point(matrix.xform(p_global)) && (!gui.drag_preview || (c != gui.drag_preview && !gui.drag_preview->is_a_parent_of(c)))) { + Control *drag_preview = _gui_get_drag_preview(); + if (!drag_preview || (c != drag_preview && !drag_preview->is_a_parent_of(c))) { r_inv_xform = matrix; return c; - } else { - return nullptr; } + + return nullptr; } bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check) { @@ -1920,9 +1923,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { gui.drag_data = Variant(); gui.dragging = false; - if (gui.drag_preview) { - memdelete(gui.drag_preview); - gui.drag_preview = nullptr; + Control *drag_preview = _gui_get_drag_preview(); + if (drag_preview) { + memdelete(drag_preview); + gui.drag_preview_id = ObjectID(); } _propagate_viewport_notification(this, NOTIFICATION_DRAG_END); //change mouse accordingly @@ -1935,9 +1939,10 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false); } - if (gui.drag_preview && mb->get_button_index() == BUTTON_LEFT) { - memdelete(gui.drag_preview); - gui.drag_preview = nullptr; + Control *drag_preview = _gui_get_drag_preview(); + if (drag_preview) { + memdelete(drag_preview); + gui.drag_preview_id = ObjectID(); } gui.drag_data = Variant(); @@ -2034,10 +2039,11 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { gui.mouse_focus_mask = 0; break; } else { - if (gui.drag_preview != nullptr) { + Control *drag_preview = _gui_get_drag_preview(); + if (drag_preview) { ERR_PRINT("Don't set a drag preview and return null data. Preview was deleted and drag request ignored."); - memdelete(gui.drag_preview); - gui.drag_preview = nullptr; + memdelete(drag_preview); + gui.drag_preview_id = ObjectID(); } gui.dragging = false; } @@ -2177,8 +2183,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.drag_data.get_type() != Variant::NIL) { //handle dragandrop - if (gui.drag_preview) { - gui.drag_preview->set_position(mpos); + Control *drag_preview = _gui_get_drag_preview(); + if (drag_preview) { + drag_preview->set_position(mpos); } gui.drag_mouse_over = over; @@ -2453,15 +2460,29 @@ void Viewport::_gui_set_drag_preview(Control *p_base, Control *p_control) { ERR_FAIL_COND(p_control->is_inside_tree()); ERR_FAIL_COND(p_control->get_parent() != nullptr); - if (gui.drag_preview) { - memdelete(gui.drag_preview); + Control *drag_preview = _gui_get_drag_preview(); + if (drag_preview) { + memdelete(drag_preview); } p_control->set_as_top_level(true); p_control->set_position(gui.last_mouse_pos); p_base->get_root_parent_control()->add_child(p_control); //add as child of viewport p_control->raise(); - gui.drag_preview = p_control; + gui.drag_preview_id = p_control->get_instance_id(); +} + +Control *Viewport::_gui_get_drag_preview() { + if (gui.drag_preview_id.is_null()) { + return nullptr; + } else { + Control *drag_preview = Object::cast_to<Control>(ObjectDB::get_instance(gui.drag_preview_id)); + if (!drag_preview) { + ERR_PRINT("Don't free the control set as drag preview."); + gui.drag_preview_id = ObjectID(); + } + return drag_preview; + } } void Viewport::_gui_remove_root_control(List<Control *>::Element *RI) { diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 2a0026a561..0f11e6fb19 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -357,7 +357,7 @@ private: Point2 drag_accum; bool drag_attempted = false; Variant drag_data; - Control *drag_preview = nullptr; + ObjectID drag_preview_id; float tooltip_timer = -1.0; float tooltip_delay = 0.0; Transform2D focus_inv_xform; @@ -415,6 +415,7 @@ private: void _gui_force_drag(Control *p_base, const Variant &p_data, Control *p_control); void _gui_set_drag_preview(Control *p_base, Control *p_control); + Control *_gui_get_drag_preview(); void _gui_remove_focus_for_window(Node *p_window); void _gui_remove_focus(); diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index acf7319339..e5edba8a67 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -85,9 +85,11 @@ void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector<Color> col; col.push_back(p_color); RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); - RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); - // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. - RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); + if (is_collision_outline_enabled()) { + RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); + // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. + RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); + } } Rect2 CapsuleShape2D::get_rect() const { diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index a8a9c42fbd..f06bc4248d 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -79,9 +79,11 @@ void CircleShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector<Color> col; col.push_back(p_color); RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); - RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); - // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. - RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); + if (is_collision_outline_enabled()) { + RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); + // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. + RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); + } } CircleShape2D::CircleShape2D() : diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp index 7271614995..d331f83daf 100644 --- a/scene/resources/convex_polygon_shape_2d.cpp +++ b/scene/resources/convex_polygon_shape_2d.cpp @@ -75,9 +75,11 @@ void ConvexPolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector<Color> col; col.push_back(p_color); RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); - RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); - // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. - RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); + if (is_collision_outline_enabled()) { + RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); + // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. + RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); + } } Rect2 ConvexPolygonShape2D::get_rect() const { diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 943176537b..a94209c75f 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -128,6 +128,38 @@ static Ref<Texture2D> flip_icon(Ref<Texture2D> p_texture, bool p_flip_y = false, return texture; } +static Ref<FontData> make_font(int p_height, int p_ascent, int p_charcount, const int *p_char_rects, int p_kerning_count, const int *p_kernings, int p_w, int p_h, const unsigned char *p_img) { + Ref<FontData> font(memnew(FontData)); + font->new_bitmap(p_height, p_ascent, p_height); + + Ref<Image> image = memnew(Image(p_img)); + Ref<ImageTexture> tex = memnew(ImageTexture); + tex->create_from_image(image); + + font->bitmap_add_texture(tex); + + for (int i = 0; i < p_charcount; i++) { + const int *c = &p_char_rects[i * 8]; + + int chr = c[0]; + Rect2 frect; + frect.position.x = c[1]; + frect.position.y = c[2]; + frect.size.x = c[3]; + frect.size.y = c[4]; + Point2 align(c[6], c[5]); + int advance = c[7]; + + font->bitmap_add_char(chr, 0, frect, align, advance); + } + + for (int i = 0; i < p_kerning_count; i++) { + font->bitmap_add_kerning_pair(p_kernings[i * 3 + 0], p_kernings[i * 3 + 1], p_kernings[i * 3 + 2]); + } + + return font; +} + static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { Ref<StyleBox> style(memnew(StyleBoxEmpty)); @@ -989,41 +1021,11 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) { if (p_font.is_valid()) { default_font = p_font; } else if (p_hidpi) { - TextServer::BitmapFontData data; - data.height = _hidpi_font_height; - data.ascent = _hidpi_font_ascent; - data.charcount = _hidpi_font_charcount; - data.char_rects = &_hidpi_font_charrects[0][0]; - data.kerning_count = _hidpi_font_kerning_pair_count; - data.kernings = &_hidpi_font_kerning_pairs[0][0]; - data.w = _hidpi_font_img_width; - data.h = _hidpi_font_img_height; - data.img = _hidpi_font_img_data; - - Ref<FontData> font_data; - font_data.instance(); - font_data->load_memory((const uint8_t *)&data, sizeof(data), "fnt"); - default_font_size = font_data->get_base_size(); - + Ref<FontData> font_data = make_font(_hidpi_font_height, _hidpi_font_ascent, _hidpi_font_charcount, &_hidpi_font_charrects[0][0], _hidpi_font_kerning_pair_count, &_hidpi_font_kerning_pairs[0][0], _hidpi_font_img_width, _hidpi_font_img_height, _hidpi_font_img_data); default_font.instance(); default_font->add_data(font_data); } else { - TextServer::BitmapFontData data; - data.height = _lodpi_font_height; - data.ascent = _lodpi_font_ascent; - data.charcount = _lodpi_font_charcount; - data.char_rects = &_lodpi_font_charrects[0][0]; - data.kerning_count = _lodpi_font_kerning_pair_count; - data.kernings = &_lodpi_font_kerning_pairs[0][0]; - data.w = _lodpi_font_img_width; - data.h = _lodpi_font_img_height; - data.img = _lodpi_font_img_data; - - Ref<FontData> font_data; - font_data.instance(); - font_data->load_memory((const uint8_t *)&data, sizeof(data), "fnt"); - default_font_size = font_data->get_base_size(); - + Ref<FontData> font_data = make_font(_lodpi_font_height, _lodpi_font_ascent, _lodpi_font_charcount, &_lodpi_font_charrects[0][0], _lodpi_font_kerning_pair_count, &_lodpi_font_kerning_pairs[0][0], _lodpi_font_img_width, _lodpi_font_img_height, _lodpi_font_img_data); default_font.instance(); default_font->add_data(font_data); } diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 702f2ed1c8..6f87c524d8 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -39,6 +39,11 @@ void FontData::_bind_methods() { ClassDB::bind_method(D_METHOD("load_resource", "filename", "base_size"), &FontData::load_resource, DEFVAL(16)); ClassDB::bind_method(D_METHOD("load_memory", "data", "type", "base_size"), &FontData::_load_memory, DEFVAL(16)); + ClassDB::bind_method(D_METHOD("new_bitmap", "height", "ascent", "base_size"), &FontData::new_bitmap); + + ClassDB::bind_method(D_METHOD("bitmap_add_texture", "texture"), &FontData::bitmap_add_texture); + ClassDB::bind_method(D_METHOD("bitmap_add_char", "char", "texture_idx", "rect", "align", "advance"), &FontData::bitmap_add_char); + ClassDB::bind_method(D_METHOD("bitmap_add_kerning_pair", "A", "B", "kerning"), &FontData::bitmap_add_kerning_pair); ClassDB::bind_method(D_METHOD("set_data_path", "path"), &FontData::set_data_path); ClassDB::bind_method(D_METHOD("get_data_path"), &FontData::get_data_path); @@ -229,6 +234,34 @@ void FontData::load_memory(const uint8_t *p_data, size_t p_size, const String &p emit_changed(); } +void FontData::new_bitmap(float p_height, float p_ascent, int p_base_size) { + if (rid != RID()) { + TS->free(rid); + } + rid = TS->create_font_bitmap(p_height, p_ascent, p_base_size); + path = TTR("(Bitmap: " + String::num_int64(rid.get_id(), 16, true) + ")"); + base_size = TS->font_get_base_size(rid); + emit_changed(); +} + +void FontData::bitmap_add_texture(const Ref<Texture> &p_texture) { + if (rid != RID()) { + TS->font_bitmap_add_texture(rid, p_texture); + } +} + +void FontData::bitmap_add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) { + if (rid != RID()) { + TS->font_bitmap_add_char(rid, p_char, p_texture_idx, p_rect, p_align, p_advance); + } +} + +void FontData::bitmap_add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) { + if (rid != RID()) { + TS->font_bitmap_add_kerning_pair(rid, p_A, p_B, p_kerning); + } +} + void FontData::set_data_path(const String &p_path) { load_resource(p_path, base_size); } diff --git a/scene/resources/font.h b/scene/resources/font.h index 56b5acde1a..200373aa8c 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -69,6 +69,12 @@ public: void load_memory(const uint8_t *p_data, size_t p_size, const String &p_type, int p_base_size = 16); void _load_memory(const PackedByteArray &p_data, const String &p_type, int p_base_size = 16); + void new_bitmap(float p_height, float p_ascent, int p_base_size = 16); + + void bitmap_add_texture(const Ref<Texture> &p_texture); + void bitmap_add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance); + void bitmap_add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning); + void set_data_path(const String &p_path); String get_data_path() const; diff --git a/scene/resources/mesh_data_tool.cpp b/scene/resources/mesh_data_tool.cpp index 1b82aca386..3fb4f8f211 100644 --- a/scene/resources/mesh_data_tool.cpp +++ b/scene/resources/mesh_data_tool.cpp @@ -50,6 +50,28 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf int vcount = varray.size(); ERR_FAIL_COND_V(vcount == 0, ERR_INVALID_PARAMETER); + Vector<int> indices; + + if (arrays[Mesh::ARRAY_INDEX].get_type() != Variant::NIL) { + indices = arrays[Mesh::ARRAY_INDEX]; + } else { + //make code simpler + indices.resize(vcount); + int *iw = indices.ptrw(); + for (int i = 0; i < vcount; i++) { + iw[i] = i; + } + } + + int icount = indices.size(); + const int *r = indices.ptr(); + + ERR_FAIL_COND_V(icount == 0, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(icount % 3, ERR_INVALID_PARAMETER); + for (int i = 0; i < icount; i++) { + ERR_FAIL_INDEX_V(r[i], vcount, ERR_INVALID_PARAMETER); + } + clear(); format = p_mesh->surface_get_format(p_surface); material = p_mesh->surface_get_material(p_surface); @@ -128,22 +150,6 @@ Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surf vertices.write[i] = v; } - Vector<int> indices; - - if (arrays[Mesh::ARRAY_INDEX].get_type() != Variant::NIL) { - indices = arrays[Mesh::ARRAY_INDEX]; - } else { - //make code simpler - indices.resize(vcount); - int *iw = indices.ptrw(); - for (int i = 0; i < vcount; i++) { - iw[i] = i; - } - } - - int icount = indices.size(); - const int *r = indices.ptr(); - Map<Point2i, int> edge_indices; for (int i = 0; i < icount; i += 3) { diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 5d351f51f7..ab8a4b7934 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -147,15 +147,20 @@ Node *SceneState::instance(GenEditState p_edit_state) const { } #endif } - } else if (ClassDB::is_class_enabled(snames[n.type])) { - //node belongs to this scene and must be created - Object *obj = ClassDB::instance(snames[n.type]); + } else { + Object *obj = nullptr; + + if (ClassDB::is_class_enabled(snames[n.type])) { + //node belongs to this scene and must be created + obj = ClassDB::instance(snames[n.type]); + } + if (!Object::cast_to<Node>(obj)) { if (obj) { memdelete(obj); obj = nullptr; } - WARN_PRINT(String("Warning node of type " + snames[n.type].operator String() + " does not exist.").ascii().get_data()); + WARN_PRINT(vformat("Node %s of type %s cannot be created. A placeholder will be created instead.", snames[n.name], snames[n.type]).ascii().get_data()); if (n.parent >= 0 && n.parent < nc && ret_nodes[n.parent]) { if (Object::cast_to<Node3D>(ret_nodes[n.parent])) { obj = memnew(Node3D); @@ -172,10 +177,6 @@ Node *SceneState::instance(GenEditState p_edit_state) const { } node = Object::cast_to<Node>(obj); - - } else { - //print_line("Class is disabled for: " + itos(n.type)); - //print_line("name: " + String(snames[n.type])); } if (node) { diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp index 0fd65d8c72..dc4c6dc2d7 100644 --- a/scene/resources/rectangle_shape_2d.cpp +++ b/scene/resources/rectangle_shape_2d.cpp @@ -47,23 +47,25 @@ Vector2 RectangleShape2D::get_size() const { } void RectangleShape2D::draw(const RID &p_to_rid, const Color &p_color) { - // Draw an outlined rectangle to make individual shapes easier to distinguish. - Vector<Vector2> stroke_points; - stroke_points.resize(5); - stroke_points.write[0] = -size * 0.5; - stroke_points.write[1] = Vector2(size.x, -size.y) * 0.5; - stroke_points.write[2] = size * 0.5; - stroke_points.write[3] = Vector2(-size.x, size.y) * 0.5; - stroke_points.write[4] = -size * 0.5; + RenderingServer::get_singleton()->canvas_item_add_rect(p_to_rid, Rect2(-size * 0.5, size), p_color); + if (is_collision_outline_enabled()) { + // Draw an outlined rectangle to make individual shapes easier to distinguish. + Vector<Vector2> stroke_points; + stroke_points.resize(5); + stroke_points.write[0] = -size * 0.5; + stroke_points.write[1] = Vector2(size.x, -size.y) * 0.5; + stroke_points.write[2] = size * 0.5; + stroke_points.write[3] = Vector2(-size.x, size.y) * 0.5; + stroke_points.write[4] = -size * 0.5; - Vector<Color> stroke_colors; - stroke_colors.resize(5); - for (int i = 0; i < 5; i++) { - stroke_colors.write[i] = (p_color); - } + Vector<Color> stroke_colors; + stroke_colors.resize(5); + for (int i = 0; i < 5; i++) { + stroke_colors.write[i] = (p_color); + } - RenderingServer::get_singleton()->canvas_item_add_rect(p_to_rid, Rect2(-size * 0.5, size), p_color); - RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, stroke_points, stroke_colors); + RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, stroke_points, stroke_colors); + } } Rect2 RectangleShape2D::get_rect() const { diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index f8a5855d33..013b1ef1a9 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -29,7 +29,11 @@ /*************************************************************************/ #include "shape_2d.h" + +#include "core/config/engine.h" +#include "core/config/project_settings.h" #include "servers/physics_server_2d.h" + RID Shape2D::get_rid() const { return shape; } @@ -105,6 +109,15 @@ void Shape2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_solver_bias", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_custom_solver_bias", "get_custom_solver_bias"); } +bool Shape2D::is_collision_outline_enabled() { +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + return true; + } +#endif + return GLOBAL_DEF("debug/shapes/collision/draw_2d_outlines", true); +} + Shape2D::Shape2D(const RID &p_rid) { shape = p_rid; } diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h index 7b00e7e426..14bdd60e4b 100644 --- a/scene/resources/shape_2d.h +++ b/scene/resources/shape_2d.h @@ -61,6 +61,9 @@ public: /// Returns the radius of a circle that fully enclose this shape virtual real_t get_enclosing_radius() const = 0; virtual RID get_rid() const override; + + static bool is_collision_outline_enabled(); + Shape2D(); ~Shape2D(); }; |