diff options
Diffstat (limited to 'scene')
36 files changed, 365 insertions, 259 deletions
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index 902fba38bf..c175edb6cb 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -234,7 +234,7 @@ float AudioStreamPlayer2D::get_volume_db() const { } void AudioStreamPlayer2D::set_pitch_scale(float p_pitch_scale) { - ERR_FAIL_COND(p_pitch_scale <= 0.0); + ERR_FAIL_COND(!(p_pitch_scale > 0.0)); pitch_scale = p_pitch_scale; for (Ref<AudioStreamPlayback> &playback : stream_playbacks) { AudioServer::get_singleton()->set_playback_pitch_scale(playback, p_pitch_scale); diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index afd4763d74..04c7555306 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -1402,8 +1402,8 @@ void CPUParticles2D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel_max", PROPERTY_HINT_RANGE, "-100,100,0.01,or_less,or_greater"), "set_param_max", "get_param_max", PARAM_TANGENTIAL_ACCEL); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_TANGENTIAL_ACCEL); ADD_GROUP("Damping", ""); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_min", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param_min", "get_param_min", PARAM_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_max", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param_max", "get_param_max", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_min", PROPERTY_HINT_RANGE, "0,100,0.01,or_greater"), "set_param_min", "get_param_min", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_max", PROPERTY_HINT_RANGE, "0,100,0.01,or_greater"), "set_param_max", "get_param_max", PARAM_DAMPING); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING); ADD_GROUP("Angle", ""); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_min", PROPERTY_HINT_RANGE, "-720,720,0.1,or_less,or_greater,degrees"), "set_param_min", "get_param_min", PARAM_ANGLE); diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 52a1213a49..bfe2f6252e 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -31,6 +31,7 @@ #include "navigation_agent_2d.h" #include "core/math/geometry_2d.h" +#include "scene/2d/navigation_link_2d.h" #include "scene/resources/world_2d.h" #include "servers/navigation_server_2d.h" @@ -94,19 +95,19 @@ void NavigationAgent2D::_bind_methods() { ADD_GROUP("Pathfinding", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_target_position", "get_target_position"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,suffix:px"), "set_path_desired_distance", "get_path_desired_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,suffix:px"), "set_target_desired_distance", "get_target_desired_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,1000,1,suffix:px"), "set_path_max_distance", "get_path_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,or_greater,suffix:px"), "set_path_desired_distance", "get_path_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,1000,0.01,or_greater,suffix:px"), "set_target_desired_distance", "get_target_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,1000,1,or_greater,suffix:px"), "set_path_max_distance", "get_path_max_distance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags"); ADD_GROUP("Avoidance", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,500,0.01,suffix:px"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px"), "set_neighbor_distance", "get_neighbor_distance"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10,0.01,suffix:s"), "set_time_horizon", "get_time_horizon"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:px/s"), "set_max_speed", "get_max_speed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,500,0.01,or_greater,suffix:px"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,100000,0.01,or_greater,suffix:px"), "set_neighbor_distance", "get_neighbor_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,or_greater,1"), "set_max_neighbors", "get_max_neighbors"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10,0.01,or_greater,suffix:s"), "set_time_horizon", "get_time_horizon"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,or_greater,suffix:px/s"), "set_max_speed", "get_max_speed"); ClassDB::bind_method(D_METHOD("set_debug_enabled", "enabled"), &NavigationAgent2D::set_debug_enabled); ClassDB::bind_method(D_METHOD("get_debug_enabled"), &NavigationAgent2D::get_debug_enabled); @@ -623,6 +624,21 @@ void NavigationAgent2D::update_navigation() { } details[SNAME("owner")] = owner; + + if (waypoint_type == NavigationPathQueryResult2D::PATH_SEGMENT_TYPE_LINK) { + const NavigationLink2D *navlink = Object::cast_to<NavigationLink2D>(owner); + if (navlink) { + Vector2 link_global_start_position = navlink->get_global_start_position(); + Vector2 link_global_end_position = navlink->get_global_end_position(); + if (waypoint.distance_to(link_global_start_position) < waypoint.distance_to(link_global_end_position)) { + details[SNAME("link_entry_position")] = link_global_start_position; + details[SNAME("link_exit_position")] = link_global_end_position; + } else { + details[SNAME("link_entry_position")] = link_global_end_position; + details[SNAME("link_exit_position")] = link_global_start_position; + } + } + } } // Emit a signal for the waypoint diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp index 26dca40176..8adb7c6305 100644 --- a/scene/2d/navigation_link_2d.cpp +++ b/scene/2d/navigation_link_2d.cpp @@ -54,6 +54,12 @@ void NavigationLink2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_end_position", "position"), &NavigationLink2D::set_end_position); ClassDB::bind_method(D_METHOD("get_end_position"), &NavigationLink2D::get_end_position); + ClassDB::bind_method(D_METHOD("set_global_start_position", "position"), &NavigationLink2D::set_global_start_position); + ClassDB::bind_method(D_METHOD("get_global_start_position"), &NavigationLink2D::get_global_start_position); + + ClassDB::bind_method(D_METHOD("set_global_end_position", "position"), &NavigationLink2D::set_global_end_position); + ClassDB::bind_method(D_METHOD("get_global_end_position"), &NavigationLink2D::get_global_end_position); + ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink2D::set_enter_cost); ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink2D::get_enter_cost); @@ -271,6 +277,38 @@ void NavigationLink2D::set_end_position(Vector2 p_position) { #endif // DEBUG_ENABLED } +void NavigationLink2D::set_global_start_position(Vector2 p_position) { + if (is_inside_tree()) { + set_start_position(to_local(p_position)); + } else { + set_start_position(p_position); + } +} + +Vector2 NavigationLink2D::get_global_start_position() const { + if (is_inside_tree()) { + return to_global(start_position); + } else { + return start_position; + } +} + +void NavigationLink2D::set_global_end_position(Vector2 p_position) { + if (is_inside_tree()) { + set_end_position(to_local(p_position)); + } else { + set_end_position(p_position); + } +} + +Vector2 NavigationLink2D::get_global_end_position() const { + if (is_inside_tree()) { + return to_global(end_position); + } else { + return end_position; + } +} + void NavigationLink2D::set_enter_cost(real_t p_enter_cost) { ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive."); if (Math::is_equal_approx(enter_cost, p_enter_cost)) { diff --git a/scene/2d/navigation_link_2d.h b/scene/2d/navigation_link_2d.h index 5bf2a72358..8a24d611c9 100644 --- a/scene/2d/navigation_link_2d.h +++ b/scene/2d/navigation_link_2d.h @@ -78,6 +78,12 @@ public: void set_end_position(Vector2 p_position); Vector2 get_end_position() const { return end_position; } + void set_global_start_position(Vector2 p_position); + Vector2 get_global_start_position() const; + + void set_global_end_position(Vector2 p_position); + Vector2 get_global_end_position() const; + void set_enter_cost(real_t p_enter_cost); real_t get_enter_cost() const { return enter_cost; } diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 96711bbe72..4fdc7b3584 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -378,9 +378,6 @@ void Bone2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_skeleton_rest"), &Bone2D::get_skeleton_rest); ClassDB::bind_method(D_METHOD("get_index_in_skeleton"), &Bone2D::get_index_in_skeleton); - ClassDB::bind_method(D_METHOD("set_default_length", "default_length"), &Bone2D::set_default_length); - ClassDB::bind_method(D_METHOD("get_default_length"), &Bone2D::get_default_length); - ClassDB::bind_method(D_METHOD("set_autocalculate_length_and_angle", "auto_calculate"), &Bone2D::set_autocalculate_length_and_angle); ClassDB::bind_method(D_METHOD("get_autocalculate_length_and_angle"), &Bone2D::get_autocalculate_length_and_angle); ClassDB::bind_method(D_METHOD("set_length", "length"), &Bone2D::set_length); @@ -416,16 +413,6 @@ void Bone2D::apply_rest() { set_transform(rest); } -void Bone2D::set_default_length(real_t p_length) { - WARN_DEPRECATED_MSG("set_default_length is deprecated. Please use set_length instead!"); - set_length(p_length); -} - -real_t Bone2D::get_default_length() const { - WARN_DEPRECATED_MSG("get_default_length is deprecated. Please use get_length instead!"); - return get_length(); -} - int Bone2D::get_index_in_skeleton() const { ERR_FAIL_COND_V(!skeleton, -1); skeleton->_update_bone_setup(); diff --git a/scene/2d/skeleton_2d.h b/scene/2d/skeleton_2d.h index 149ab64306..6a36a31552 100644 --- a/scene/2d/skeleton_2d.h +++ b/scene/2d/skeleton_2d.h @@ -80,9 +80,6 @@ public: PackedStringArray get_configuration_warnings() const override; - void set_default_length(real_t p_length); - real_t get_default_length() const; - void set_autocalculate_length_and_angle(bool p_autocalculate); bool get_autocalculate_length_and_angle() const; void set_length(real_t p_length); diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp index 54ed96f585..1c2903fe22 100644 --- a/scene/2d/touch_screen_button.cpp +++ b/scene/2d/touch_screen_button.cpp @@ -194,10 +194,6 @@ void TouchScreenButton::input(const Ref<InputEvent> &p_event) { return; } - if (p_event->get_device() != 0) { - return; - } - const InputEventScreenTouch *st = Object::cast_to<InputEventScreenTouch>(*p_event); if (passby_press) { diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 77bf15125e..ac626d0d2a 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -559,7 +559,7 @@ float AudioStreamPlayer3D::get_max_db() const { } void AudioStreamPlayer3D::set_pitch_scale(float p_pitch_scale) { - ERR_FAIL_COND(p_pitch_scale <= 0.0); + ERR_FAIL_COND(!(p_pitch_scale > 0.0)); pitch_scale = p_pitch_scale; } diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index b9a161e476..c88eb033de 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -1588,8 +1588,8 @@ void CPUParticles3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "tangential_accel_max", PROPERTY_HINT_RANGE, "-100,100,0.01,or_less,or_greater"), "set_param_max", "get_param_max", PARAM_TANGENTIAL_ACCEL); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "tangential_accel_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_TANGENTIAL_ACCEL); ADD_GROUP("Damping", ""); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_min", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param_min", "get_param_min", PARAM_DAMPING); - ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_max", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_param_max", "get_param_max", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_min", PROPERTY_HINT_RANGE, "0,100,0.01,or_greater"), "set_param_min", "get_param_min", PARAM_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "damping_max", PROPERTY_HINT_RANGE, "0,100,0.01,or_greater"), "set_param_max", "get_param_max", PARAM_DAMPING); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "damping_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_DAMPING); ADD_GROUP("Angle", ""); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "angle_min", PROPERTY_HINT_RANGE, "-720,720,0.1,or_less,or_greater,degrees"), "set_param_min", "get_param_min", PARAM_ANGLE); diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 16f357194e..396e4b72af 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -30,6 +30,7 @@ #include "navigation_agent_3d.h" +#include "scene/3d/navigation_link_3d.h" #include "servers/navigation_server_3d.h" void NavigationAgent3D::_bind_methods() { @@ -98,20 +99,20 @@ void NavigationAgent3D::_bind_methods() { ADD_GROUP("Pathfinding", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_target_position", "get_target_position"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_path_desired_distance", "get_path_desired_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_target_desired_distance", "get_target_desired_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01,suffix:m"), "set_agent_height_offset", "get_agent_height_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater,suffix:m"), "set_path_desired_distance", "get_path_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater,suffix:m"), "set_target_desired_distance", "get_target_desired_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01,or_greater,suffix:m"), "set_agent_height_offset", "get_agent_height_offset"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,or_greater,suffix:m"), "set_path_max_distance", "get_path_max_distance"); ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers"); ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags"); ADD_GROUP("Avoidance", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_radius", "get_radius"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m"), "set_neighbor_distance", "get_neighbor_distance"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1"), "set_max_neighbors", "get_max_neighbors"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,100,0.01,suffix:s"), "set_time_horizon", "get_time_horizon"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m/s"), "set_max_speed", "get_max_speed"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater,suffix:m"), "set_radius", "get_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "neighbor_distance", PROPERTY_HINT_RANGE, "0.1,10000,0.01,or_greater,suffix:m"), "set_neighbor_distance", "get_neighbor_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_neighbors", PROPERTY_HINT_RANGE, "1,10000,1,or_greater"), "set_max_neighbors", "get_max_neighbors"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.01,10,0.01,or_greater,suffix:s"), "set_time_horizon", "get_time_horizon"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,1000,0.01,or_greater,suffix:m/s"), "set_max_speed", "get_max_speed"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y"); ADD_SIGNAL(MethodInfo("path_changed")); @@ -649,6 +650,21 @@ void NavigationAgent3D::update_navigation() { } details[SNAME("owner")] = owner; + + if (waypoint_type == NavigationPathQueryResult3D::PATH_SEGMENT_TYPE_LINK) { + const NavigationLink3D *navlink = Object::cast_to<NavigationLink3D>(owner); + if (navlink) { + Vector3 link_global_start_position = navlink->get_global_start_position(); + Vector3 link_global_end_position = navlink->get_global_end_position(); + if (waypoint.distance_to(link_global_start_position) < waypoint.distance_to(link_global_end_position)) { + details[SNAME("link_entry_position")] = link_global_start_position; + details[SNAME("link_exit_position")] = link_global_end_position; + } else { + details[SNAME("link_entry_position")] = link_global_end_position; + details[SNAME("link_exit_position")] = link_global_start_position; + } + } + } } // Emit a signal for the waypoint diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index 072ca1d3e8..cde826ed5c 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -52,14 +52,14 @@ class NavigationAgent3D : public Node { real_t path_desired_distance = 1.0; real_t target_desired_distance = 1.0; - real_t radius = 1.0; + real_t radius = 0.5; real_t navigation_height_offset = 0.0; bool ignore_y = true; real_t neighbor_distance = 50.0; int max_neighbors = 10; - real_t time_horizon = 5.0; + real_t time_horizon = 1.0; real_t max_speed = 10.0; - real_t path_max_distance = 3.0; + real_t path_max_distance = 5.0; Vector3 target_position; bool target_position_submitted = false; diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp index f47fcfaf51..9c4b8e7905 100644 --- a/scene/3d/navigation_link_3d.cpp +++ b/scene/3d/navigation_link_3d.cpp @@ -163,6 +163,12 @@ void NavigationLink3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_end_position", "position"), &NavigationLink3D::set_end_position); ClassDB::bind_method(D_METHOD("get_end_position"), &NavigationLink3D::get_end_position); + ClassDB::bind_method(D_METHOD("set_global_start_position", "position"), &NavigationLink3D::set_global_start_position); + ClassDB::bind_method(D_METHOD("get_global_start_position"), &NavigationLink3D::get_global_start_position); + + ClassDB::bind_method(D_METHOD("set_global_end_position", "position"), &NavigationLink3D::set_global_end_position); + ClassDB::bind_method(D_METHOD("get_global_end_position"), &NavigationLink3D::get_global_end_position); + ClassDB::bind_method(D_METHOD("set_enter_cost", "enter_cost"), &NavigationLink3D::set_enter_cost); ClassDB::bind_method(D_METHOD("get_enter_cost"), &NavigationLink3D::get_enter_cost); @@ -386,6 +392,38 @@ void NavigationLink3D::set_end_position(Vector3 p_position) { update_configuration_warnings(); } +void NavigationLink3D::set_global_start_position(Vector3 p_position) { + if (is_inside_tree()) { + set_start_position(to_local(p_position)); + } else { + set_start_position(p_position); + } +} + +Vector3 NavigationLink3D::get_global_start_position() const { + if (is_inside_tree()) { + return to_global(start_position); + } else { + return start_position; + } +} + +void NavigationLink3D::set_global_end_position(Vector3 p_position) { + if (is_inside_tree()) { + set_end_position(to_local(p_position)); + } else { + set_end_position(p_position); + } +} + +Vector3 NavigationLink3D::get_global_end_position() const { + if (is_inside_tree()) { + return to_global(end_position); + } else { + return end_position; + } +} + void NavigationLink3D::set_enter_cost(real_t p_enter_cost) { ERR_FAIL_COND_MSG(p_enter_cost < 0.0, "The enter_cost must be positive."); if (Math::is_equal_approx(enter_cost, p_enter_cost)) { diff --git a/scene/3d/navigation_link_3d.h b/scene/3d/navigation_link_3d.h index 5c9ec36189..991f45c85d 100644 --- a/scene/3d/navigation_link_3d.h +++ b/scene/3d/navigation_link_3d.h @@ -83,6 +83,12 @@ public: void set_end_position(Vector3 p_position); Vector3 get_end_position() const { return end_position; } + void set_global_start_position(Vector3 p_position); + Vector3 get_global_start_position() const; + + void set_global_end_position(Vector3 p_position); + Vector3 get_global_end_position() const; + void set_enter_cost(real_t p_enter_cost); real_t get_enter_cost() const { return enter_cost; } diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index d169999de4..42b0748698 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -346,25 +346,29 @@ Voxelizer::MaterialCache Voxelizer::_get_material_cache(Ref<Material> p_material } else { mc.albedo = _get_bake_texture(img_albedo, Color(1, 1, 1), mat->get_albedo()); // no albedo texture, color is additive } + if (mat->get_feature(BaseMaterial3D::FEATURE_EMISSION)) { + Ref<Texture2D> emission_tex = mat->get_texture(BaseMaterial3D::TEXTURE_EMISSION); - Ref<Texture2D> emission_tex = mat->get_texture(BaseMaterial3D::TEXTURE_EMISSION); - - Color emission_col = mat->get_emission(); - float emission_energy = mat->get_emission_energy_multiplier() * exposure_normalization; - if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) { - emission_energy *= mat->get_emission_intensity(); - } + Color emission_col = mat->get_emission(); + float emission_energy = mat->get_emission_energy_multiplier() * exposure_normalization; + if (GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units")) { + emission_energy *= mat->get_emission_intensity(); + } - Ref<Image> img_emission; + Ref<Image> img_emission; - if (emission_tex.is_valid()) { - img_emission = emission_tex->get_image(); - } + if (emission_tex.is_valid()) { + img_emission = emission_tex->get_image(); + } - if (mat->get_emission_operator() == BaseMaterial3D::EMISSION_OP_ADD) { - mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy); + if (mat->get_emission_operator() == BaseMaterial3D::EMISSION_OP_ADD) { + mc.emission = _get_bake_texture(img_emission, Color(1, 1, 1) * emission_energy, emission_col * emission_energy); + } else { + mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0)); + } } else { - mc.emission = _get_bake_texture(img_emission, emission_col * emission_energy, Color(0, 0, 0)); + Ref<Image> empty; + mc.emission = _get_bake_texture(empty, Color(0, 0, 0), Color(0, 0, 0)); } } else { diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index 7533a56b59..6c37d6f81d 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -111,7 +111,7 @@ float AudioStreamPlayer::get_volume_db() const { } void AudioStreamPlayer::set_pitch_scale(float p_pitch_scale) { - ERR_FAIL_COND(p_pitch_scale <= 0.0); + ERR_FAIL_COND(!(p_pitch_scale > 0.0)); pitch_scale = p_pitch_scale; for (Ref<AudioStreamPlayback> &playback : stream_playbacks) { diff --git a/scene/gui/aspect_ratio_container.cpp b/scene/gui/aspect_ratio_container.cpp index 802189c374..94240ccead 100644 --- a/scene/gui/aspect_ratio_container.cpp +++ b/scene/gui/aspect_ratio_container.cpp @@ -30,6 +30,8 @@ #include "aspect_ratio_container.h" +#include "scene/gui/texture_rect.h" + Size2 AspectRatioContainer::get_minimum_size() const { Size2 ms; for (int i = 0; i < get_child_count(); i++) { @@ -113,6 +115,16 @@ void AspectRatioContainer::_notification(int p_what) { if (c->is_set_as_top_level()) { continue; } + + // Temporary fix for editor crash. + TextureRect *trect = Object::cast_to<TextureRect>(c); + if (trect) { + if (trect->get_expand_mode() == TextureRect::EXPAND_FIT_WIDTH_PROPORTIONAL || trect->get_expand_mode() == TextureRect::EXPAND_FIT_HEIGHT_PROPORTIONAL) { + WARN_PRINT_ONCE("Proportional TextureRect is currently not supported inside AspectRatioContainer"); + continue; + } + } + Size2 child_minsize = c->get_combined_minimum_size(); Size2 child_size = Size2(ratio, 1.0); float scale_factor = 1.0; diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index e2f7ec860c..ee39327d4d 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -896,6 +896,7 @@ void CodeEdit::indent_lines() { set_caret_column(get_caret_column(c) + selection_offset, false, c); } end_complex_operation(); + queue_redraw(); } void CodeEdit::unindent_lines() { @@ -973,6 +974,7 @@ void CodeEdit::unindent_lines() { set_caret_column(initial_cursor_column - removed_characters, false, c); } end_complex_operation(); + queue_redraw(); } int CodeEdit::_calculate_spaces_till_next_left_indent(int p_column) const { diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 0b0698188c..48e3759981 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -31,10 +31,12 @@ #include "color_picker.h" #include "core/input/input.h" +#include "core/io/image.h" #include "core/math/color.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "scene/gui/color_mode.h" +#include "servers/display_server.h" #include "thirdparty/misc/ok_color.h" #include "thirdparty/misc/ok_color_shader.h" @@ -90,8 +92,8 @@ void ColorPicker::_notification(int p_what) { } break; case NOTIFICATION_WM_CLOSE_REQUEST: { - if (screen != nullptr && screen->is_visible()) { - screen->hide(); + if (picker_window != nullptr && picker_window->is_visible()) { + picker_window->hide(); } } break; } @@ -1372,30 +1374,26 @@ void ColorPicker::_recent_preset_pressed(const bool p_pressed, ColorPresetButton emit_signal(SNAME("color_changed"), p_preset->get_preset_color()); } -void ColorPicker::_screen_input(const Ref<InputEvent> &p_event) { +void ColorPicker::_picker_texture_input(const Ref<InputEvent> &p_event) { if (!is_inside_tree()) { return; } Ref<InputEventMouseButton> bev = p_event; if (bev.is_valid() && bev->get_button_index() == MouseButton::LEFT && !bev->is_pressed()) { + set_pick_color(picker_color); emit_signal(SNAME("color_changed"), color); - screen->hide(); + picker_window->hide(); } Ref<InputEventMouseMotion> mev = p_event; if (mev.is_valid()) { - Viewport *r = get_tree()->get_root(); - if (!r->get_visible_rect().has_point(mev->get_global_position())) { - return; - } - - Ref<Image> img = r->get_texture()->get_image(); + Ref<Image> img = picker_texture_rect->get_texture()->get_image(); if (img.is_valid() && !img->is_empty()) { - Vector2 ofs = mev->get_global_position(); - Color c = img->get_pixel(ofs.x, ofs.y); - - set_pick_color(c); + Vector2 ofs = mev->get_position(); + picker_color = img->get_pixel(ofs.x, ofs.y); + picker_preview_style_box->set_bg_color(picker_color); + picker_preview_label->set_self_modulate(picker_color.get_luminance() < 0.5 ? Color(1.0f, 1.0f, 1.0f) : Color(0.0f, 0.0f, 0.0f)); } } } @@ -1409,27 +1407,79 @@ void ColorPicker::_add_preset_pressed() { emit_signal(SNAME("preset_added"), color); } -void ColorPicker::_screen_pick_pressed() { +void ColorPicker::_pick_button_pressed() { if (!is_inside_tree()) { return; } - Viewport *r = get_tree()->get_root(); - if (!screen) { - screen = memnew(Control); - r->add_child(screen); - screen->set_as_top_level(true); - screen->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - screen->set_default_cursor_shape(CURSOR_POINTING_HAND); - screen->connect("gui_input", callable_mp(this, &ColorPicker::_screen_input)); - // It immediately toggles off in the first press otherwise. - screen->call_deferred(SNAME("connect"), "hidden", Callable(btn_pick, "set_pressed").bind(false)); + if (!picker_window) { + picker_window = memnew(Popup); + picker_window->hide(); + picker_window->set_transient(true); + add_child(picker_window); + + picker_texture_rect = memnew(TextureRect); + picker_texture_rect->set_anchors_preset(Control::PRESET_FULL_RECT); + picker_window->add_child(picker_texture_rect); + picker_texture_rect->set_default_cursor_shape(CURSOR_POINTING_HAND); + picker_texture_rect->connect(SNAME("gui_input"), callable_mp(this, &ColorPicker::_picker_texture_input)); + + picker_preview = memnew(Panel); + picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP); + picker_preview->set_mouse_filter(MOUSE_FILTER_IGNORE); + picker_window->add_child(picker_preview); + + picker_preview_label = memnew(Label); + picker_preview->set_anchors_preset(Control::PRESET_CENTER_TOP); + picker_preview_label->set_text("Color Picking active"); + picker_preview->add_child(picker_preview_label); + + picker_preview_style_box = (Ref<StyleBoxFlat>)memnew(StyleBoxFlat); + picker_preview_style_box->set_bg_color(Color(1.0, 1.0, 1.0)); + picker_preview->add_theme_style_override("panel", picker_preview_style_box); + } + + Rect2i screen_rect; + if (picker_window->is_embedded()) { + screen_rect = picker_window->get_embedder()->get_visible_rect(); + picker_window->set_position(Point2i()); + picker_texture_rect->set_texture(ImageTexture::create_from_image(picker_window->get_embedder()->get_texture()->get_image())); } else { - screen->show(); + screen_rect = picker_window->get_parent_rect(); + picker_window->set_position(screen_rect.position); + + Ref<Image> target_image = Image::create_empty(screen_rect.size.x, screen_rect.size.y, false, Image::FORMAT_RGB8); + DisplayServer *ds = DisplayServer::get_singleton(); + + // Add the Texture of each Window to the Image. + Vector<DisplayServer::WindowID> wl = ds->get_window_list(); + // FIXME: sort windows by visibility. + for (int index = 0; index < wl.size(); index++) { + DisplayServer::WindowID wid = wl[index]; + if (wid == DisplayServer::INVALID_WINDOW_ID) { + continue; + } + + ObjectID woid = DisplayServer::get_singleton()->window_get_attached_instance_id(wid); + if (woid == ObjectID()) { + continue; + } + + Window *w = Object::cast_to<Window>(ObjectDB::get_instance(woid)); + Ref<Image> img = w->get_texture()->get_image(); + if (!img.is_valid() || img->is_empty()) { + continue; + } + img->convert(Image::FORMAT_RGB8); + target_image->blit_rect(img, Rect2i(Point2i(0, 0), img->get_size()), w->get_position()); + } + + picker_texture_rect->set_texture(ImageTexture::create_from_image(target_image)); } - screen->move_to_front(); - // TODO: show modal no longer works, needs to be converted to a popup. - //screen->show_modal(); + + picker_window->set_size(screen_rect.size); + picker_preview->set_size(screen_rect.size / 10.0); // 10% of size in each axis. + picker_window->popup(); } void ColorPicker::_html_focus_exit() { @@ -1595,9 +1645,8 @@ ColorPicker::ColorPicker() { btn_pick = memnew(Button); sample_hbc->add_child(btn_pick); - btn_pick->set_toggle_mode(true); - btn_pick->set_tooltip_text(RTR("Pick a color from the editor window.")); - btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed)); + btn_pick->set_tooltip_text(RTR("Pick a color from the application window.")); + btn_pick->connect(SNAME("pressed"), callable_mp(this, &ColorPicker::_pick_button_pressed)); sample = memnew(TextureRect); sample_hbc->add_child(sample); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index f7578612cd..d02c3278e6 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -40,6 +40,7 @@ #include "scene/gui/line_edit.h" #include "scene/gui/menu_button.h" #include "scene/gui/option_button.h" +#include "scene/gui/panel.h" #include "scene/gui/popup.h" #include "scene/gui/separator.h" #include "scene/gui/slider.h" @@ -111,7 +112,12 @@ private: Vector<ColorMode *> modes; - Control *screen = nullptr; + Popup *picker_window = nullptr; + TextureRect *picker_texture_rect = nullptr; + Panel *picker_preview = nullptr; + Label *picker_preview_label = nullptr; + Ref<StyleBoxFlat> picker_preview_style_box; + Color picker_color; Control *uv_edit = nullptr; Control *w_edit = nullptr; AspectRatioContainer *wheel_edit = nullptr; @@ -211,10 +217,10 @@ private: void _line_edit_input(const Ref<InputEvent> &p_event); void _preset_input(const Ref<InputEvent> &p_event, const Color &p_color); void _recent_preset_pressed(const bool pressed, ColorPresetButton *p_preset); - void _screen_input(const Ref<InputEvent> &p_event); + void _picker_texture_input(const Ref<InputEvent> &p_event); void _text_changed(const String &p_new_text); void _add_preset_pressed(); - void _screen_pick_pressed(); + void _pick_button_pressed(); void _html_focus_exit(); inline int _get_preset_size(); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 5dd8cde342..02abddaa43 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -35,7 +35,6 @@ #include "scene/gui/label.h" FileDialog::GetIconFunc FileDialog::get_icon_func = nullptr; -FileDialog::GetIconFunc FileDialog::get_large_icon_func = nullptr; FileDialog::RegisterFunc FileDialog::register_func = nullptr; FileDialog::RegisterFunc FileDialog::unregister_func = nullptr; @@ -347,14 +346,15 @@ void FileDialog::_action_pressed() { } } - if (!valid) { + String file_name = file_text.strip_edges().get_file(); + if (!valid || file_name.is_empty()) { exterr->popup_centered(Size2(250, 80)); return; } if (dir_access->file_exists(f)) { - confirm_save->set_text(RTR("File exists, overwrite?")); - confirm_save->popup_centered(Size2(200, 80)); + confirm_save->set_text(vformat(RTR("File \"%s\" already exists.\nDo you want to overwrite it?"), f)); + confirm_save->popup_centered(Size2(250, 80)); } else { emit_signal(SNAME("file_selected"), f); hide(); @@ -1136,7 +1136,7 @@ FileDialog::FileDialog() { add_child(mkdirerr, false, INTERNAL_MODE_FRONT); exterr = memnew(AcceptDialog); - exterr->set_text(RTR("Must use a valid extension.")); + exterr->set_text(RTR("Invalid extension, or empty filename.")); add_child(exterr, false, INTERNAL_MODE_FRONT); update_filters(); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index d85cdcac90..7f80caf01d 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -60,7 +60,6 @@ public: typedef void (*RegisterFunc)(FileDialog *); static GetIconFunc get_icon_func; - static GetIconFunc get_large_icon_func; static RegisterFunc register_func; static RegisterFunc unregister_func; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 25a27d5e1a..d367a8d281 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -801,8 +801,9 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { search_string = ""; //any mousepress cancels for (int i = 4; i > 0; i--) { - if (current - current_columns * i >= 0 && CAN_SELECT(current - current_columns * i)) { - set_current(current - current_columns * i); + int index = current - current_columns * i; + if (index >= 0 && index < items.size() && CAN_SELECT(index)) { + set_current(index); ensure_current_is_visible(); if (select_mode == SELECT_SINGLE) { emit_signal(SNAME("item_selected"), current); @@ -815,8 +816,9 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { search_string = ""; //any mousepress cancels for (int i = 4; i > 0; i--) { - if (current + current_columns * i < items.size() && CAN_SELECT(current + current_columns * i)) { - set_current(current + current_columns * i); + int index = current + current_columns * i; + if (index >= 0 && index < items.size() && CAN_SELECT(index)) { + set_current(index); ensure_current_is_visible(); if (select_mode == SELECT_SINGLE) { emit_signal(SNAME("item_selected"), current); @@ -832,7 +834,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { if (current % current_columns != 0) { int current_row = current / current_columns; int next = current - 1; - while (!CAN_SELECT(next)) { + while (next >= 0 && !CAN_SELECT(next)) { next = next - 1; } if (next < 0 || !IS_SAME_ROW(next, current_row)) { @@ -852,7 +854,7 @@ void ItemList::gui_input(const Ref<InputEvent> &p_event) { if (current % current_columns != (current_columns - 1) && current + 1 < items.size()) { int current_row = current / current_columns; int next = current + 1; - while (!CAN_SELECT(next)) { + while (next < items.size() && !CAN_SELECT(next)) { next = next + 1; } if (items.size() <= next || !IS_SAME_ROW(next, current_row)) { diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 45218773fe..b861d7af01 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -139,11 +139,14 @@ bool Label::_shape() { can_process_lines = true; lines_dirty = false; } else { - // With autowrap on, we won't compute the minimum size until width is stable (two shape requests in a - // row with the same width.) This avoids situations in which the initial width is very narrow and the label - // would break text into many very short lines, causing a very tall label that can leave a deformed container. - - can_process_lines = get_size().width == stable_width || autowrap_mode == TextServer::AUTOWRAP_OFF; + // With autowrap on or off with trimming enabled, we won't compute the minimum size until width is stable + // (two shape requests in a row with the same width.) This avoids situations in which the initial width is + // very narrow and the label would break text into many very short lines, causing a very tall label that can + // leave a deformed container. In the remaining case (namely, autowrap off and no trimming), the label is + // free to dictate its own width, something that will be taken advtantage of. + bool can_dictate_width = autowrap_mode == TextServer::AUTOWRAP_OFF && overrun_behavior == TextServer::OVERRUN_NO_TRIMMING; + bool is_width_stable = get_size().width == stable_width; + can_process_lines = can_dictate_width || is_width_stable; stable_width = get_size().width; if (can_process_lines) { @@ -171,14 +174,13 @@ bool Label::_shape() { } } - if (autowrap_mode == TextServer::AUTOWRAP_OFF) { + if (can_dictate_width) { for (int i = 0; i < lines_rid.size(); i++) { if (minsize.width < TS->shaped_text_get_size(lines_rid[i]).x) { minsize.width = TS->shaped_text_get_size(lines_rid[i]).x; } } - // With autowrap off, by now we already know the width the label will take. width = (minsize.width - style->get_minimum_size().width); } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 1a6adca121..cf73729c0a 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1715,12 +1715,12 @@ void PopupMenu::activate_item(int p_item) { need_hide = false; } + emit_signal(SNAME("id_pressed"), id); + emit_signal(SNAME("index_pressed"), p_item); + if (need_hide) { hide(); } - - emit_signal(SNAME("id_pressed"), id); - emit_signal(SNAME("index_pressed"), p_item); } void PopupMenu::remove_item(int p_idx) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 2c1c44322a..973b02b3a3 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1179,7 +1179,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o dot_ul_started = false; float y_off = TS->shaped_text_get_underline_position(rid); float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale; - draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2); + draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2)); } if (_find_strikethrough(it)) { if (!st_started) { @@ -1341,7 +1341,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o dot_ul_started = false; float y_off = TS->shaped_text_get_underline_position(rid); float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale; - draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2); + draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2)); } if (st_started) { st_started = false; @@ -1363,7 +1363,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o dot_ul_started = false; float y_off = TS->shaped_text_get_underline_position(rid); float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale; - draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2); + draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, MAX(2.0, underline_width * 2)); } if (st_started) { st_started = false; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index d785280701..ebca8296a0 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2681,6 +2681,7 @@ void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) { set_caret_line(get_caret_line(caret_idx), false, true, 0, caret_idx); set_caret_column(column, caret_idx == 0, caret_idx); + adjust_carets_after_edit(caret_idx, get_caret_line(caret_idx), column, get_caret_line(caret_idx), from_column); // Now we can clean up the overlapping caret. if (overlapping_caret_index != -1) { @@ -4362,7 +4363,9 @@ int TextEdit::get_minimap_line_at_pos(const Point2i &p_pos) const { if (first_vis_line > 0 && minimap_line >= 0) { minimap_line -= get_next_visible_line_index_offset_from(first_vis_line, 0, -num_lines_before).x; minimap_line -= (minimap_line > 0 && smooth_scroll_enabled ? 1 : 0); - } else { + } + + if (minimap_line < 0) { minimap_line = 0; } diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index e5dcdd2afd..b36353158b 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -513,14 +513,16 @@ bool CanvasItem::is_y_sort_enabled() const { void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, real_t p_dash, bool p_aligned) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + ERR_FAIL_COND(p_dash <= 0.0); float length = (p_to - p_from).length(); - if (length < p_dash) { + Vector2 step = p_dash * (p_to - p_from).normalized(); + + if (length < p_dash || step == Vector2()) { RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width); return; } - Vector2 step = p_dash * (p_to - p_from).normalized(); int steps = (p_aligned) ? Math::ceil(length / p_dash) : Math::floor(length / p_dash); if (steps % 2 == 0) { steps--; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 126b1d54fc..244e0d5b93 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1330,7 +1330,7 @@ void Viewport::_gui_show_tooltip() { Window *window = gui.tooltip_popup->get_parent_visible_window(); Rect2i vr; if (gui.tooltip_popup->is_embedded()) { - vr = gui.tooltip_popup->_get_embedder()->get_visible_rect(); + vr = gui.tooltip_popup->get_embedder()->get_visible_rect(); } else { vr = window->get_usable_parent_rect(); } @@ -1851,7 +1851,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Window *w = Object::cast_to<Window>(this); if (w) { if (w->is_embedded()) { - embedder = w->_get_embedder(); + embedder = w->get_embedder(); viewport_pos = get_final_transform().xform(mpos) + w->get_position(); // To parent coords. } diff --git a/scene/main/window.cpp b/scene/main/window.cpp index b79a9ba444..59e3d307c6 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -485,7 +485,7 @@ void Window::set_ime_position(const Point2i &p_pos) { bool Window::is_embedded() const { ERR_FAIL_COND_V(!is_inside_tree(), false); - return _get_embedder() != nullptr; + return get_embedder() != nullptr; } bool Window::is_in_edited_scene_root() const { @@ -710,7 +710,7 @@ void Window::set_visible(bool p_visible) { // Stop any queued resizing, as the window will be resized right now. updating_child_controls = false; - Viewport *embedder_vp = _get_embedder(); + Viewport *embedder_vp = get_embedder(); if (!embedder_vp) { if (!p_visible && window_id != DisplayServer::INVALID_WINDOW_ID) { @@ -1053,7 +1053,7 @@ void Window::_update_window_callbacks() { DisplayServer::get_singleton()->window_set_drop_files_callback(callable_mp(this, &Window::_window_drop_files), window_id); } -Viewport *Window::_get_embedder() const { +Viewport *Window::get_embedder() const { Viewport *vp = get_parent_viewport(); while (vp) { @@ -1088,7 +1088,7 @@ void Window::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { bool embedded = false; { - embedder = _get_embedder(); + embedder = get_embedder(); if (embedder) { embedded = true; if (!visible) { @@ -1431,7 +1431,7 @@ void Window::popup_centered_clamped(const Size2i &p_size, float p_fallback_ratio Rect2 parent_rect; if (is_embedded()) { - parent_rect = _get_embedder()->get_visible_rect(); + parent_rect = get_embedder()->get_visible_rect(); } else { DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); @@ -1462,7 +1462,7 @@ void Window::popup_centered(const Size2i &p_minsize) { Rect2 parent_rect; if (is_embedded()) { - parent_rect = _get_embedder()->get_visible_rect(); + parent_rect = get_embedder()->get_visible_rect(); } else { DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); @@ -1488,7 +1488,7 @@ void Window::popup_centered_ratio(float p_ratio) { Rect2 parent_rect; if (is_embedded()) { - parent_rect = _get_embedder()->get_visible_rect(); + parent_rect = get_embedder()->get_visible_rect(); } else { DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); @@ -1509,7 +1509,7 @@ void Window::popup_centered_ratio(float p_ratio) { void Window::popup(const Rect2i &p_screen_rect) { emit_signal(SNAME("about_to_popup")); - if (!_get_embedder() && get_flag(FLAG_POPUP)) { + if (!get_embedder() && get_flag(FLAG_POPUP)) { // Send a focus-out notification when opening a Window Manager Popup. SceneTree *scene_tree = get_tree(); if (scene_tree) { @@ -1545,7 +1545,7 @@ void Window::popup(const Rect2i &p_screen_rect) { Rect2i parent_rect; if (is_embedded()) { - parent_rect = _get_embedder()->get_visible_rect(); + parent_rect = get_embedder()->get_visible_rect(); } else { int screen_id = DisplayServer::get_singleton()->window_get_current_screen(get_window_id()); parent_rect = DisplayServer::get_singleton()->screen_get_usable_rect(screen_id); @@ -1587,7 +1587,7 @@ Rect2i Window::get_usable_parent_rect() const { ERR_FAIL_COND_V(!is_inside_tree(), Rect2()); Rect2i parent_rect; if (is_embedded()) { - parent_rect = _get_embedder()->get_visible_rect(); + parent_rect = get_embedder()->get_visible_rect(); } else { const Window *w = is_visible() ? this : get_parent_visible_window(); //find a parent that can contain us @@ -2154,9 +2154,9 @@ Transform2D Window::get_final_transform() const { Transform2D Window::get_screen_transform_internal(bool p_absolute_position) const { Transform2D embedder_transform; - if (_get_embedder()) { + if (get_embedder()) { embedder_transform.translate_local(get_position()); - embedder_transform = _get_embedder()->get_screen_transform_internal(p_absolute_position) * embedder_transform; + embedder_transform = get_embedder()->get_screen_transform_internal(p_absolute_position) * embedder_transform; } else if (p_absolute_position) { embedder_transform.translate_local(get_position()); } @@ -2170,8 +2170,8 @@ Transform2D Window::get_popup_base_transform() const { Transform2D popup_base_transform; popup_base_transform.set_origin(get_position()); popup_base_transform *= get_final_transform(); - if (_get_embedder()) { - return _get_embedder()->get_popup_base_transform() * popup_base_transform; + if (get_embedder()) { + return get_embedder()->get_popup_base_transform() * popup_base_transform; } return popup_base_transform; } diff --git a/scene/main/window.h b/scene/main/window.h index 5359c37e9a..40b629ed11 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -192,7 +192,6 @@ private: Ref<Shortcut> debugger_stop_shortcut; protected: - Viewport *_get_embedder() const; virtual Rect2i _popup_adjust_rect() const { return Rect2i(); } virtual void _update_theme_item_cache(); @@ -278,6 +277,7 @@ public: void set_ime_position(const Point2i &p_pos); bool is_embedded() const; + Viewport *get_embedder() const; void set_content_scale_size(const Size2i &p_size); Size2i get_content_scale_size() const; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 7e84814ab3..2627898f5f 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -369,7 +369,15 @@ void ShaderMaterial::set_shader_parameter(const StringName &p_param, const Varia param_cache.erase(p_param); RS::get_singleton()->material_set_param(_get_material(), p_param, Variant()); } else { - param_cache[p_param] = p_value; + Variant *v = param_cache.getptr(p_param); + if (!v) { + // Never assigned, also update the remap cache. + remap_cache["shader_parameter/" + p_param.operator String()] = p_param; + param_cache.insert(p_param, p_value); + } else { + *v = p_value; + } + if (p_value.get_type() == Variant::OBJECT) { RID tex_rid = p_value; if (tex_rid == RID()) { @@ -955,11 +963,14 @@ void BaseMaterial3D::_update_shader() { } break; case BILLBOARD_PARTICLES: { //make billboard - code += " mat4 mat_world = mat4(normalize(INV_VIEW_MATRIX[0]) * length(MODEL_MATRIX[0]), normalize(INV_VIEW_MATRIX[1]) * length(MODEL_MATRIX[0]),normalize(INV_VIEW_MATRIX[2]) * length(MODEL_MATRIX[2]), MODEL_MATRIX[3]);\n"; + code += " mat4 mat_world = mat4(normalize(INV_VIEW_MATRIX[0]), normalize(INV_VIEW_MATRIX[1]) ,normalize(INV_VIEW_MATRIX[2]), MODEL_MATRIX[3]);\n"; //rotate by rotation code += " mat_world = mat_world * mat4(vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; //set modelview code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat_world;\n"; + if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { + code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; + } //set modelview normal code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n"; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 7e3156d2ff..05be40c446 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -2566,73 +2566,6 @@ void GradientTexture2D::_bind_methods() { ////////////////////////////////////// -void ProxyTexture::set_base(const Ref<Texture2D> &p_texture) { - ERR_FAIL_COND(p_texture == this); - - base = p_texture; - if (base.is_valid()) { - ERR_FAIL_NULL(RenderingServer::get_singleton()); - if (proxy_ph.is_valid()) { - RS::get_singleton()->texture_proxy_update(proxy, base->get_rid()); - RS::get_singleton()->free(proxy_ph); - proxy_ph = RID(); - } else if (proxy.is_valid()) { - RS::get_singleton()->texture_proxy_update(proxy, base->get_rid()); - } else { - proxy = RS::get_singleton()->texture_proxy_create(base->get_rid()); - } - } -} - -Ref<Texture2D> ProxyTexture::get_base() const { - return base; -} - -int ProxyTexture::get_width() const { - if (base.is_valid()) { - return base->get_width(); - } - return 1; -} - -int ProxyTexture::get_height() const { - if (base.is_valid()) { - return base->get_height(); - } - return 1; -} - -RID ProxyTexture::get_rid() const { - if (proxy.is_null()) { - proxy_ph = RS::get_singleton()->texture_2d_placeholder_create(); - proxy = RS::get_singleton()->texture_proxy_create(proxy_ph); - } - return proxy; -} - -bool ProxyTexture::has_alpha() const { - if (base.is_valid()) { - return base->has_alpha(); - } - return false; -} - -ProxyTexture::ProxyTexture() { - //proxy = RS::get_singleton()->texture_create(); -} - -ProxyTexture::~ProxyTexture() { - ERR_FAIL_NULL(RenderingServer::get_singleton()); - if (proxy_ph.is_valid()) { - RS::get_singleton()->free(proxy_ph); - } - if (proxy.is_valid()) { - RS::get_singleton()->free(proxy); - } -} - -////////////////////////////////////////////// - void AnimatedTexture::_update_proxy() { RWLockRead r(rw_lock); @@ -2704,6 +2637,7 @@ void AnimatedTexture::set_current_frame(int p_frame) { RWLockWrite r(rw_lock); current_frame = p_frame; + time = 0; } int AnimatedTexture::get_current_frame() const { diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 7f74ae6941..7c4d479da8 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -892,29 +892,6 @@ public: VARIANT_ENUM_CAST(GradientTexture2D::Fill); VARIANT_ENUM_CAST(GradientTexture2D::Repeat); -class ProxyTexture : public Texture2D { -private: - mutable RID proxy_ph; - mutable RID proxy; - Ref<Texture2D> base; - -protected: - static void _bind_methods(); - -public: - void set_base(const Ref<Texture2D> &p_texture); - Ref<Texture2D> get_base() const; - - virtual int get_width() const override; - virtual int get_height() const override; - virtual RID get_rid() const override; - - virtual bool has_alpha() const override; - - ProxyTexture(); - ~ProxyTexture(); -}; - class AnimatedTexture : public Texture2D { GDCLASS(AnimatedTexture, Texture2D); diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index fee0a4a910..d4b2be355e 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -3308,7 +3308,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { PropertyInfo property_info; // Rendering. - p_list->push_back(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Rendering", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < occlusion_layers.size(); i++) { p_list->push_back(PropertyInfo(Variant::INT, vformat("occlusion_layer_%d/light_mask", i), PROPERTY_HINT_LAYERS_2D_RENDER)); @@ -3321,7 +3321,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { } // Physics. - p_list->push_back(PropertyInfo(Variant::NIL, "Physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Physics", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < physics_layers.size(); i++) { p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/collision_layer", i), PROPERTY_HINT_LAYERS_2D_PHYSICS)); @@ -3341,7 +3341,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { } // Terrains. - p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Terrains", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int terrain_set_index = 0; terrain_set_index < terrain_sets.size(); terrain_set_index++) { p_list->push_back(PropertyInfo(Variant::INT, vformat("terrain_set_%d/mode", terrain_set_index), PROPERTY_HINT_ENUM, "Match Corners and Sides,Match Corners,Match Sides")); p_list->push_back(PropertyInfo(Variant::NIL, vformat("terrain_set_%d/terrains", terrain_set_index), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_ARRAY, vformat("terrain_set_%d/terrain_", terrain_set_index))); @@ -3352,7 +3352,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { } // Navigation. - p_list->push_back(PropertyInfo(Variant::NIL, "Navigation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Navigation", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < navigation_layers.size(); i++) { p_list->push_back(PropertyInfo(Variant::INT, vformat("navigation_layer_%d/layers", i), PROPERTY_HINT_LAYERS_2D_NAVIGATION)); } @@ -3362,7 +3362,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { for (int i = 1; i < Variant::VARIANT_MAX; i++) { argt += "," + Variant::get_type_name(Variant::Type(i)); } - p_list->push_back(PropertyInfo(Variant::NIL, "Custom data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Custom Data", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < custom_data_layers.size(); i++) { p_list->push_back(PropertyInfo(Variant::STRING, vformat("custom_data_layer_%d/name", i))); p_list->push_back(PropertyInfo(Variant::INT, vformat("custom_data_layer_%d/type", i), PROPERTY_HINT_ENUM, argt)); @@ -3376,10 +3376,10 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { // Tile Proxies. // Note: proxies need to be set after sources are set. - p_list->push_back(PropertyInfo(Variant::NIL, "Tile Proxies", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); - p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); - p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Tile Proxies", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/source_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/coords_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); + p_list->push_back(PropertyInfo(Variant::ARRAY, PNAME("tile_proxies/alternative_level"), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR)); // Patterns. for (unsigned int pattern_index = 0; pattern_index < patterns.size(); pattern_index++) { @@ -4887,9 +4887,9 @@ bool TileSetScenesCollectionSource::_get(const StringName &p_name, Variant &r_re void TileSetScenesCollectionSource::_get_property_list(List<PropertyInfo> *p_list) const { for (int i = 0; i < scenes_ids.size(); i++) { - p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("scenes/%d/scene", scenes_ids[i]), PROPERTY_HINT_RESOURCE_TYPE, "TileSetScenesCollectionSource")); + p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("%s/%d/%s", PNAME("scenes"), scenes_ids[i], PNAME("scene")), PROPERTY_HINT_RESOURCE_TYPE, "TileSetScenesCollectionSource")); - PropertyInfo property_info = PropertyInfo(Variant::BOOL, vformat("scenes/%d/display_placeholder", scenes_ids[i])); + PropertyInfo property_info = PropertyInfo(Variant::BOOL, vformat("%s/%d/%s", PNAME("scenes"), scenes_ids[i], PNAME("display_placeholder"))); if (scenes[scenes_ids[i]].display_placeholder == false) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } @@ -5692,10 +5692,10 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { // Add the groups manually. if (tile_set) { // Occlusion layers. - p_list->push_back(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Rendering", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < occluders.size(); i++) { // occlusion_layer_%d/polygon - property_info = PropertyInfo(Variant::OBJECT, vformat("occlusion_layer_%d/polygon", i), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT); + property_info = PropertyInfo(Variant::OBJECT, vformat("occlusion_layer_%d/%s", i, PNAME("polygon")), PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D", PROPERTY_USAGE_DEFAULT); if (!occluders[i].is_valid()) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } @@ -5703,29 +5703,29 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { } // Physics layers. - p_list->push_back(PropertyInfo(Variant::NIL, "Physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Physics", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < physics.size(); i++) { - p_list->push_back(PropertyInfo(Variant::VECTOR2, vformat("physics_layer_%d/linear_velocity", i), PROPERTY_HINT_NONE)); - p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/angular_velocity", i), PROPERTY_HINT_NONE)); - p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/polygons_count", i), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); + p_list->push_back(PropertyInfo(Variant::VECTOR2, vformat("physics_layer_%d/%s", i, PNAME("linear_velocity")), PROPERTY_HINT_NONE)); + p_list->push_back(PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/%s", i, PNAME("angular_velocity")), PROPERTY_HINT_NONE)); + p_list->push_back(PropertyInfo(Variant::INT, vformat("physics_layer_%d/%s", i, PNAME("polygons_count")), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); for (int j = 0; j < physics[i].polygons.size(); j++) { // physics_layer_%d/points - property_info = PropertyInfo(Variant::ARRAY, vformat("physics_layer_%d/polygon_%d/points", i, j), PROPERTY_HINT_ARRAY_TYPE, "Vector2", PROPERTY_USAGE_DEFAULT); + property_info = PropertyInfo(Variant::ARRAY, vformat("physics_layer_%d/polygon_%d/%s", i, j, PNAME("points")), PROPERTY_HINT_ARRAY_TYPE, "Vector2", PROPERTY_USAGE_DEFAULT); if (physics[i].polygons[j].polygon.is_empty()) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } p_list->push_back(property_info); // physics_layer_%d/polygon_%d/one_way - property_info = PropertyInfo(Variant::BOOL, vformat("physics_layer_%d/polygon_%d/one_way", i, j)); + property_info = PropertyInfo(Variant::BOOL, vformat("physics_layer_%d/polygon_%d/%s", i, j, PNAME("one_way"))); if (physics[i].polygons[j].one_way == false) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } p_list->push_back(property_info); // physics_layer_%d/polygon_%d/one_way_margin - property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/polygon_%d/one_way_margin", i, j)); + property_info = PropertyInfo(Variant::FLOAT, vformat("physics_layer_%d/polygon_%d/%s", i, j, PNAME("one_way_margin"))); if (physics[i].polygons[j].one_way_margin == 1.0) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } @@ -5735,7 +5735,7 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { // Terrain data if (terrain_set >= 0) { - p_list->push_back(PropertyInfo(Variant::NIL, "Terrains", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Terrains", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < TileSet::CELL_NEIGHBOR_MAX; i++) { TileSet::CellNeighbor bit = TileSet::CellNeighbor(i); if (is_valid_terrain_peering_bit(bit)) { @@ -5749,9 +5749,9 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { } // Navigation layers. - p_list->push_back(PropertyInfo(Variant::NIL, "Navigation", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Navigation", ""), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); for (int i = 0; i < navigation.size(); i++) { - property_info = PropertyInfo(Variant::OBJECT, vformat("navigation_layer_%d/polygon", i), PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_DEFAULT); + property_info = PropertyInfo(Variant::OBJECT, vformat("navigation_layer_%d/%s", i, PNAME("polygon")), PROPERTY_HINT_RESOURCE_TYPE, "NavigationPolygon", PROPERTY_USAGE_DEFAULT); if (!navigation[i].is_valid()) { property_info.usage ^= PROPERTY_USAGE_STORAGE; } @@ -5759,7 +5759,7 @@ void TileData::_get_property_list(List<PropertyInfo> *p_list) const { } // Custom data layers. - p_list->push_back(PropertyInfo(Variant::NIL, "Custom data", PROPERTY_HINT_NONE, "custom_data_", PROPERTY_USAGE_GROUP)); + p_list->push_back(PropertyInfo(Variant::NIL, GNAME("Custom Data", "custom_data_"), PROPERTY_HINT_NONE, "custom_data_", PROPERTY_USAGE_GROUP)); for (int i = 0; i < custom_data.size(); i++) { Variant default_val; Callable::CallError error; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 7550f598f8..9f5a64597a 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -7606,8 +7606,11 @@ String VisualShaderNodeBillboard::generate_code(Shader::Mode p_mode, VisualShade break; case BILLBOARD_TYPE_PARTICLES: code += " {\n"; - code += " mat4 __wm = mat4(normalize(INV_VIEW_MATRIX[0]) * length(MODEL_MATRIX[0]), normalize(INV_VIEW_MATRIX[1]) * length(MODEL_MATRIX[0]), normalize(INV_VIEW_MATRIX[2]) * length(MODEL_MATRIX[2]), MODEL_MATRIX[3]);\n"; + code += " mat4 __wm = mat4(normalize(INV_VIEW_MATRIX[0]), normalize(INV_VIEW_MATRIX[1]), normalize(INV_VIEW_MATRIX[2]), MODEL_MATRIX[3]);\n"; code += " __wm = __wm * mat4(vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; + if (keep_scale) { + code += " __wm = __wm * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; + } code += " " + p_output_vars[0] + " = VIEW_MATRIX * __wm;\n"; code += " }\n"; break; @@ -7650,7 +7653,7 @@ bool VisualShaderNodeBillboard::is_keep_scale_enabled() const { Vector<StringName> VisualShaderNodeBillboard::get_editable_properties() const { Vector<StringName> props; props.push_back("billboard_type"); - if (billboard_type == BILLBOARD_TYPE_ENABLED || billboard_type == BILLBOARD_TYPE_FIXED_Y) { + if (billboard_type == BILLBOARD_TYPE_ENABLED || billboard_type == BILLBOARD_TYPE_FIXED_Y || billboard_type == BILLBOARD_TYPE_PARTICLES) { props.push_back("keep_scale"); } return props; |