diff options
Diffstat (limited to 'scene/3d')
48 files changed, 1724 insertions, 296 deletions
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index a024757927..b1ffe76662 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -180,26 +180,20 @@ void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, i E->get().shapes.erase(ShapePair(p_body_shape, p_area_shape)); } - bool eraseit = false; - + bool in_tree = E->get().in_tree; if (E->get().rc == 0) { + body_map.erase(E); if (node) { node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree)); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree)); - if (E->get().in_tree) { + if (in_tree) { emit_signal(SceneStringNames::get_singleton()->body_exited, obj); } } - - eraseit = true; } - if (node && E->get().in_tree) { + if (node && in_tree) { emit_signal(SceneStringNames::get_singleton()->body_shape_exited, objid, obj, p_body_shape, p_area_shape); } - - if (eraseit) { - body_map.erase(E); - } } locked = false; @@ -222,6 +216,9 @@ void Area3D::_clear_monitoring() { } //ERR_CONTINUE(!node); + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree)); + if (!E->get().in_tree) { continue; } @@ -231,9 +228,6 @@ void Area3D::_clear_monitoring() { } emit_signal(SceneStringNames::get_singleton()->body_exited, node); - - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_body_exit_tree)); } } @@ -251,6 +245,9 @@ void Area3D::_clear_monitoring() { } //ERR_CONTINUE(!node); + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree)); + if (!E->get().in_tree) { continue; } @@ -260,9 +257,6 @@ void Area3D::_clear_monitoring() { } emit_signal(SceneStringNames::get_singleton()->area_exited, obj); - - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree)); } } } @@ -366,26 +360,20 @@ void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, i E->get().shapes.erase(AreaShapePair(p_area_shape, p_self_shape)); } - bool eraseit = false; - + bool in_tree = E->get().in_tree; if (E->get().rc == 0) { + area_map.erase(E); if (node) { node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &Area3D::_area_enter_tree)); node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &Area3D::_area_exit_tree)); - if (E->get().in_tree) { + if (in_tree) { emit_signal(SceneStringNames::get_singleton()->area_exited, obj); } } - - eraseit = true; } - if (!node || E->get().in_tree) { + if (!node || in_tree) { emit_signal(SceneStringNames::get_singleton()->area_shape_exited, objid, obj, p_area_shape, p_self_shape); } - - if (eraseit) { - area_map.erase(E); - } } locked = false; diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h index 07d24f39a7..7d1f030baf 100644 --- a/scene/3d/area_3d.h +++ b/scene/3d/area_3d.h @@ -31,7 +31,7 @@ #ifndef AREA_3D_H #define AREA_3D_H -#include "core/vset.h" +#include "core/templates/vset.h" #include "scene/3d/collision_object_3d.h" class Area3D : public CollisionObject3D { diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 6e4db8f382..37bc032356 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -30,7 +30,7 @@ #include "audio_stream_player_3d.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "scene/3d/area_3d.h" #include "scene/3d/camera_3d.h" #include "scene/3d/listener_3d.h" @@ -327,9 +327,6 @@ float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const { return att; } -void _update_sound() { -} - void AudioStreamPlayer3D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { velocity_tracker->reset(get_global_transform().origin); diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index e867891ec0..38c9e96fbc 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -37,7 +37,7 @@ #include "core/os/dir_access.h" #include "core/os/file_access.h" #include "core/os/os.h" -#include "core/sort_array.h" +#include "core/templates/sort_array.h" #include "lightmap_probe.h" void BakedLightmapData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) { diff --git a/scene/3d/baked_lightmap.h b/scene/3d/baked_lightmap.h index bebb579252..8808569215 100644 --- a/scene/3d/baked_lightmap.h +++ b/scene/3d/baked_lightmap.h @@ -31,7 +31,7 @@ #ifndef BAKED_LIGHTMAP_H #define BAKED_LIGHTMAP_H -#include "core/local_vector.h" +#include "core/templates/local_vector.h" #include "scene/3d/light_3d.h" #include "scene/3d/lightmapper.h" #include "scene/3d/mesh_instance_3d.h" diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index ecbaca7bd1..191159448a 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -31,7 +31,7 @@ #include "camera_3d.h" #include "collision_object_3d.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "core/math/camera_matrix.h" #include "scene/resources/material.h" #include "scene/resources/surface_tool.h" @@ -519,8 +519,8 @@ void Camera3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1"), "set_fov", "get_fov"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_znear", "get_znear"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_zfar", "get_zfar"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_EXP_RANGE, "0.001,8192,0.001,or_greater"), "set_znear", "get_znear"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_zfar", "get_zfar"); BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE); BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL); diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h index 6a778d45a2..04cec92b14 100644 --- a/scene/3d/camera_3d.h +++ b/scene/3d/camera_3d.h @@ -42,7 +42,6 @@ class Camera3D : public Node3D { public: enum Projection { - PROJECTION_PERSPECTIVE, PROJECTION_ORTHOGONAL, PROJECTION_FRUSTUM @@ -103,7 +102,6 @@ protected: public: enum { - NOTIFICATION_BECAME_CURRENT = 50, NOTIFICATION_LOST_CURRENT = 51 }; diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp index e2d11c740a..b8a4ab74ee 100644 --- a/scene/3d/collision_polygon_3d.cpp +++ b/scene/3d/collision_polygon_3d.cpp @@ -156,15 +156,23 @@ bool CollisionPolygon3D::is_disabled() const { } String CollisionPolygon3D::get_configuration_warning() const { + String warning = Node3D::get_configuration_warning(); + if (!Object::cast_to<CollisionObject3D>(get_parent())) { - return TTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape."); } if (polygon.empty()) { - return TTR("An empty CollisionPolygon3D has no effect on collision."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("An empty CollisionPolygon3D has no effect on collision."); } - return String(); + return warning; } bool CollisionPolygon3D::_is_editable_3d_polygon() const { diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index 56367e9bdd..e1c691b89a 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -44,23 +44,36 @@ //TODO: Implement CylinderShape and HeightMapShape? -void CollisionShape3D::make_convex_from_brothers() { +void CollisionShape3D::make_convex_from_siblings() { Node *p = get_parent(); if (!p) { return; } + Vector<Vector3> vertices; + for (int i = 0; i < p->get_child_count(); i++) { Node *n = p->get_child(i); MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(n); if (mi) { Ref<Mesh> m = mi->get_mesh(); if (m.is_valid()) { - Ref<Shape3D> s = m->create_convex_shape(); - set_shape(s); + for (int j = 0; j < m->get_surface_count(); j++) { + Array a = m->surface_get_arrays(j); + if (!a.empty()) { + Vector<Vector3> v = a[RenderingServer::ARRAY_VERTEX]; + for (int k = 0; k < v.size(); k++) { + vertices.append(mi->get_transform().xform(v[k])); + } + } + } } } } + + Ref<ConvexPolygonShape3D> shape = memnew(ConvexPolygonShape3D); + shape->set_points(vertices); + set_shape(shape); } void CollisionShape3D::_update_in_shape_owner(bool p_xform_only) { @@ -111,23 +124,33 @@ void CollisionShape3D::resource_changed(RES res) { } String CollisionShape3D::get_configuration_warning() const { + String warning = Node3D::get_configuration_warning(); + if (!Object::cast_to<CollisionObject3D>(get_parent())) { - return TTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, KinematicBody3D, etc. to give them a shape."); } if (!shape.is_valid()) { - return TTR("A shape must be provided for CollisionShape3D to function. Please create a shape resource for it."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("A shape must be provided for CollisionShape3D to function. Please create a shape resource for it."); } - if (Object::cast_to<RigidBody3D>(get_parent())) { - if (Object::cast_to<ConcavePolygonShape3D>(*shape)) { - if (Object::cast_to<RigidBody3D>(get_parent())->get_mode() != RigidBody3D::MODE_STATIC) { - return TTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static."); - } + if (shape.is_valid() && + Object::cast_to<RigidBody3D>(get_parent()) && + Object::cast_to<ConcavePolygonShape3D>(*shape) && + Object::cast_to<RigidBody3D>(get_parent())->get_mode() != RigidBody3D::MODE_STATIC) { + if (!warning.empty()) { + warning += "\n\n"; } + warning += TTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static."); } - return String(); + return warning; } void CollisionShape3D::_bind_methods() { @@ -137,8 +160,8 @@ void CollisionShape3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape3D::get_shape); ClassDB::bind_method(D_METHOD("set_disabled", "enable"), &CollisionShape3D::set_disabled); ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape3D::is_disabled); - ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape3D::make_convex_from_brothers); - ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + 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); diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h index a32a3efeb6..35f40d27b1 100644 --- a/scene/3d/collision_shape_3d.h +++ b/scene/3d/collision_shape_3d.h @@ -60,7 +60,7 @@ protected: static void _bind_methods(); public: - void make_convex_from_brothers(); + void make_convex_from_siblings(); void set_shape(const Ref<Shape3D> &p_shape); Ref<Shape3D> get_shape() const; diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index 4244a11592..215d9e062c 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -39,7 +39,7 @@ AABB CPUParticles3D::get_aabb() const { return AABB(); } -Vector<Face3> CPUParticles3D::get_faces(uint32_t p_usage_flags) const { +Vector<Face3> CPUParticles3D::get_faces(uint32_t p_usage_particle_flags) const { return Vector<Face3>(); } @@ -189,7 +189,7 @@ bool CPUParticles3D::get_fractional_delta() const { } String CPUParticles3D::get_configuration_warning() const { - String warnings; + String warnings = GeometryInstance3D::get_configuration_warning(); bool mesh_found = false; bool anim_material_found = false; @@ -368,17 +368,17 @@ Ref<Gradient> CPUParticles3D::get_color_ramp() const { return color_ramp; } -void CPUParticles3D::set_particle_flag(Flags p_flag, bool p_enable) { - ERR_FAIL_INDEX(p_flag, FLAG_MAX); - flags[p_flag] = p_enable; - if (p_flag == FLAG_DISABLE_Z) { +void CPUParticles3D::set_particle_flag(ParticleFlags p_particle_flag, bool p_enable) { + ERR_FAIL_INDEX(p_particle_flag, PARTICLE_FLAG_MAX); + particle_flags[p_particle_flag] = p_enable; + if (p_particle_flag == PARTICLE_FLAG_DISABLE_Z) { _change_notify(); } } -bool CPUParticles3D::get_particle_flag(Flags p_flag) const { - ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); - return flags[p_flag]; +bool CPUParticles3D::get_particle_flag(ParticleFlags p_particle_flag) const { + ERR_FAIL_INDEX_V(p_particle_flag, PARTICLE_FLAG_MAX, false); + return particle_flags[p_particle_flag]; } void CPUParticles3D::set_emission_shape(EmissionShape p_shape) { @@ -459,7 +459,7 @@ void CPUParticles3D::_validate_property(PropertyInfo &property) const { property.usage = 0; } - if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) { + if (property.name.begins_with("orbit_") && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) { property.usage = 0; } } @@ -675,7 +675,7 @@ void CPUParticles3D::_particles_process(float p_delta) { p.hue_rot_rand = Math::randf(); p.anim_offset_rand = Math::randf(); - if (flags[FLAG_DISABLE_Z]) { + if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { float angle1_rad = Math::atan2(direction.y, direction.x) + (Math::randf() * 2.0 - 1.0) * Math_PI * spread / 180.0; Vector3 rot = Vector3(Math::cos(angle1_rad), Math::sin(angle1_rad), 0.0); p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]); @@ -725,14 +725,16 @@ void CPUParticles3D::_particles_process(float p_delta) { p.transform.origin = emission_points.get(random_idx); if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS && emission_normals.size() == pc) { - if (flags[FLAG_DISABLE_Z]) { - /* - mat2 rotm; - "; - rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy; - rotm[1] = rotm[0].yx * vec2(1.0, -1.0); - VELOCITY.xy = rotm * VELOCITY.xy; - */ + if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { + Vector3 normal = emission_normals.get(random_idx); + Vector2 normal_2d(normal.x, normal.y); + Transform2D m2; + m2.set_axis(0, normal_2d); + m2.set_axis(1, normal_2d.tangent()); + Vector2 velocity_2d(p.velocity.x, p.velocity.y); + velocity_2d = m2.basis_xform(velocity_2d); + p.velocity.x = velocity_2d.x; + p.velocity.y = velocity_2d.y; } else { Vector3 normal = emission_normals.get(random_idx); Vector3 v0 = Math::abs(normal.z) < 0.999 ? Vector3(0.0, 0.0, 1.0) : Vector3(0, 1.0, 0.0); @@ -760,7 +762,7 @@ void CPUParticles3D::_particles_process(float p_delta) { p.transform = emission_xform * p.transform; } - if (flags[FLAG_DISABLE_Z]) { + if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { p.velocity.z = 0.0; p.transform.origin.z = 0.0; } @@ -781,7 +783,7 @@ void CPUParticles3D::_particles_process(float p_delta) { } float tex_orbit_velocity = 0.0; - if (flags[FLAG_DISABLE_Z]) { + if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { if (curve_parameters[PARAM_ORBIT_VELOCITY].is_valid()) { tex_orbit_velocity = curve_parameters[PARAM_ORBIT_VELOCITY]->interpolate(p.custom[1]); } @@ -828,7 +830,7 @@ void CPUParticles3D::_particles_process(float p_delta) { Vector3 force = gravity; Vector3 position = p.transform.origin; - if (flags[FLAG_DISABLE_Z]) { + if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { position.z = 0.0; } //apply linear acceleration @@ -838,7 +840,7 @@ void CPUParticles3D::_particles_process(float p_delta) { Vector3 diff = position - org; force += diff.length() > 0.0 ? diff.normalized() * (parameters[PARAM_RADIAL_ACCEL] + tex_radial_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_RADIAL_ACCEL]) : Vector3(); //apply tangential acceleration; - if (flags[FLAG_DISABLE_Z]) { + if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { Vector2 yx = Vector2(diff.y, diff.x); Vector2 yx2 = (yx * Vector2(-1.0, 1.0)).normalized(); force += yx.length() > 0.0 ? Vector3(yx2.x, yx2.y, 0.0) * ((parameters[PARAM_TANGENTIAL_ACCEL] + tex_tangential_accel) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_TANGENTIAL_ACCEL])) : Vector3(); @@ -850,7 +852,7 @@ void CPUParticles3D::_particles_process(float p_delta) { //apply attractor forces p.velocity += force * local_delta; //orbit velocity - if (flags[FLAG_DISABLE_Z]) { + if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { float orbit_amount = (parameters[PARAM_ORBIT_VELOCITY] + tex_orbit_velocity) * Math::lerp(1.0f, rand_from_seed(alt_seed), randomness[PARAM_ORBIT_VELOCITY]); if (orbit_amount != 0.0) { float ang = orbit_amount * local_delta * Math_PI * 2.0; @@ -921,8 +923,8 @@ void CPUParticles3D::_particles_process(float p_delta) { p.color *= p.base_color; - if (flags[FLAG_DISABLE_Z]) { - if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { + if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { + if (particle_flags[PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY]) { if (p.velocity.length() > 0.0) { p.transform.basis.set_axis(1, p.velocity.normalized()); } else { @@ -939,7 +941,7 @@ void CPUParticles3D::_particles_process(float p_delta) { } else { //orient particle Y towards velocity - if (flags[FLAG_ALIGN_Y_TO_VELOCITY]) { + if (particle_flags[PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY]) { if (p.velocity.length() > 0.0) { p.transform.basis.set_axis(1, p.velocity.normalized()); } else { @@ -957,7 +959,7 @@ void CPUParticles3D::_particles_process(float p_delta) { } //turn particle by rotation in Y - if (flags[FLAG_ROTATE_Y]) { + if (particle_flags[PARTICLE_FLAG_ROTATE_Y]) { Basis rot_y(Vector3(0, 1, 0), p.custom[0]); p.transform.basis = p.transform.basis * rot_y; } @@ -971,7 +973,7 @@ void CPUParticles3D::_particles_process(float p_delta) { p.transform.basis.scale(Vector3(1, 1, 1) * base_scale); - if (flags[FLAG_DISABLE_Z]) { + if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { p.velocity.z = 0.0; p.transform.origin.z = 0.0; } @@ -1197,9 +1199,9 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) { set_color_ramp(gt->get_gradient()); } - set_particle_flag(FLAG_ALIGN_Y_TO_VELOCITY, material->get_flag(ParticlesMaterial::FLAG_ALIGN_Y_TO_VELOCITY)); - set_particle_flag(FLAG_ROTATE_Y, material->get_flag(ParticlesMaterial::FLAG_ROTATE_Y)); - set_particle_flag(FLAG_DISABLE_Z, material->get_flag(ParticlesMaterial::FLAG_DISABLE_Z)); + set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY)); + set_particle_flag(PARTICLE_FLAG_ROTATE_Y, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_ROTATE_Y)); + set_particle_flag(PARTICLE_FLAG_DISABLE_Z, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_DISABLE_Z)); set_emission_shape(EmissionShape(material->get_emission_shape())); set_emission_sphere_radius(material->get_emission_sphere_radius()); @@ -1316,8 +1318,8 @@ void CPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &CPUParticles3D::set_color_ramp); ClassDB::bind_method(D_METHOD("get_color_ramp"), &CPUParticles3D::get_color_ramp); - ClassDB::bind_method(D_METHOD("set_particle_flag", "flag", "enable"), &CPUParticles3D::set_particle_flag); - ClassDB::bind_method(D_METHOD("get_particle_flag", "flag"), &CPUParticles3D::get_particle_flag); + ClassDB::bind_method(D_METHOD("set_particle_flag", "particle_flag", "enable"), &CPUParticles3D::set_particle_flag); + ClassDB::bind_method(D_METHOD("get_particle_flag", "particle_flag"), &CPUParticles3D::get_particle_flag); ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &CPUParticles3D::set_emission_shape); ClassDB::bind_method(D_METHOD("get_emission_shape"), &CPUParticles3D::get_emission_shape); @@ -1343,16 +1345,16 @@ void CPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles3D::convert_from_particles); ADD_GROUP("Emission Shape", "emission_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_points"), "set_emission_points", "get_emission_points"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals"); ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors"); - ADD_GROUP("Flags", "flag_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_align_y"), "set_particle_flag", "get_particle_flag", FLAG_ALIGN_Y_TO_VELOCITY); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_rotate_y"), "set_particle_flag", "get_particle_flag", FLAG_ROTATE_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flag_disable_z"), "set_particle_flag", "get_particle_flag", FLAG_DISABLE_Z); + ADD_GROUP("Particle Flags", "particle_flag_"); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_align_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_rotate_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ROTATE_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_disable_z"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_DISABLE_Z); ADD_GROUP("Direction", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "direction"), "set_direction", "get_direction"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "spread", PROPERTY_HINT_RANGE, "0,180,0.01"), "set_spread", "get_spread"); @@ -1424,10 +1426,10 @@ void CPUParticles3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_ANIM_OFFSET); BIND_ENUM_CONSTANT(PARAM_MAX); - BIND_ENUM_CONSTANT(FLAG_ALIGN_Y_TO_VELOCITY); - BIND_ENUM_CONSTANT(FLAG_ROTATE_Y); - BIND_ENUM_CONSTANT(FLAG_DISABLE_Z); - BIND_ENUM_CONSTANT(FLAG_MAX); + BIND_ENUM_CONSTANT(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY); + BIND_ENUM_CONSTANT(PARTICLE_FLAG_ROTATE_Y); + BIND_ENUM_CONSTANT(PARTICLE_FLAG_DISABLE_Z); + BIND_ENUM_CONSTANT(PARTICLE_FLAG_MAX); BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINT); BIND_ENUM_CONSTANT(EMISSION_SHAPE_SPHERE); @@ -1491,8 +1493,8 @@ CPUParticles3D::CPUParticles3D() { set_param_randomness(Parameter(i), 0); } - for (int i = 0; i < FLAG_MAX; i++) { - flags[i] = false; + for (int i = 0; i < PARTICLE_FLAG_MAX; i++) { + particle_flags[i] = false; } can_update = false; diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h index f44d0dfcfa..8c1b8a684c 100644 --- a/scene/3d/cpu_particles_3d.h +++ b/scene/3d/cpu_particles_3d.h @@ -31,7 +31,7 @@ #ifndef CPU_PARTICLES_H #define CPU_PARTICLES_H -#include "core/rid.h" +#include "core/templates/rid.h" #include "scene/3d/visual_instance_3d.h" class CPUParticles3D : public GeometryInstance3D { @@ -46,7 +46,6 @@ public: }; enum Parameter { - PARAM_INITIAL_LINEAR_VELOCITY, PARAM_ANGULAR_VELOCITY, PARAM_ORBIT_VELOCITY, @@ -62,11 +61,11 @@ public: PARAM_MAX }; - enum Flags { - FLAG_ALIGN_Y_TO_VELOCITY, - FLAG_ROTATE_Y, - FLAG_DISABLE_Z, - FLAG_MAX + enum ParticleFlags { + PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, + PARTICLE_FLAG_ROTATE_Y, + PARTICLE_FLAG_DISABLE_Z, + PARTICLE_FLAG_MAX }; enum EmissionShape { @@ -161,7 +160,7 @@ private: Color color; Ref<Gradient> color_ramp; - bool flags[FLAG_MAX]; + bool particle_flags[PARTICLE_FLAG_MAX]; EmissionShape emission_shape; float emission_sphere_radius; @@ -257,8 +256,8 @@ public: void set_color_ramp(const Ref<Gradient> &p_ramp); Ref<Gradient> get_color_ramp() const; - void set_particle_flag(Flags p_flag, bool p_enable); - bool get_particle_flag(Flags p_flag) const; + void set_particle_flag(ParticleFlags p_particle_flag, bool p_enable); + bool get_particle_flag(ParticleFlags p_particle_flag) const; void set_emission_shape(EmissionShape p_shape); void set_emission_sphere_radius(float p_radius); @@ -291,7 +290,7 @@ public: VARIANT_ENUM_CAST(CPUParticles3D::DrawOrder) VARIANT_ENUM_CAST(CPUParticles3D::Parameter) -VARIANT_ENUM_CAST(CPUParticles3D::Flags) +VARIANT_ENUM_CAST(CPUParticles3D::ParticleFlags) VARIANT_ENUM_CAST(CPUParticles3D::EmissionShape) #endif // CPU_PARTICLES_H diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index 1b6f9b45b9..fd592012f8 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -32,7 +32,6 @@ #include "core/os/os.h" -#include "core/method_bind_ext.gen.inc" #include "mesh_instance_3d.h" #include "voxelizer.h" @@ -514,10 +513,15 @@ Vector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const { } String GIProbe::get_configuration_warning() const { + String warning = VisualInstance3D::get_configuration_warning(); + if (RenderingServer::get_singleton()->is_low_end()) { - return TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead."); } - return String(); + return warning; } void GIProbe::_bind_methods() { diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index c4480e3ed2..ec33d7bcab 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -124,6 +124,11 @@ void GPUParticles3D::set_speed_scale(float p_scale) { RS::get_singleton()->particles_set_speed_scale(particles, p_scale); } +void GPUParticles3D::set_collision_base_size(float p_size) { + collision_base_size = p_size; + RS::get_singleton()->particles_set_collision_base_size(particles, p_size); +} + bool GPUParticles3D::is_emitting() const { return RS::get_singleton()->particles_get_emitting(particles); } @@ -168,6 +173,10 @@ float GPUParticles3D::get_speed_scale() const { return speed_scale; } +float GPUParticles3D::get_collision_base_size() const { + return collision_base_size; +} + void GPUParticles3D::set_draw_order(DrawOrder p_order) { draw_order = p_order; RS::get_singleton()->particles_set_draw_order(particles, RS::ParticlesDrawOrder(p_order)); @@ -232,7 +241,7 @@ String GPUParticles3D::get_configuration_warning() const { return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles3D node instead. You can use the \"Convert to CPUParticles3D\" option for this purpose."); } - String warnings; + String warnings = GeometryInstance3D::get_configuration_warning(); bool meshes_found = false; bool anim_material_found = false; @@ -301,6 +310,36 @@ void GPUParticles3D::_validate_property(PropertyInfo &property) const { } } +void GPUParticles3D::emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { + RS::get_singleton()->particles_emit(particles, p_transform, p_velocity, p_color, p_custom, p_emit_flags); +} + +void GPUParticles3D::_attach_sub_emitter() { + Node *n = get_node_or_null(sub_emitter); + if (n) { + GPUParticles3D *sen = Object::cast_to<GPUParticles3D>(n); + if (sen && sen != this) { + RS::get_singleton()->particles_set_subemitter(particles, sen->particles); + } + } +} + +void GPUParticles3D::set_sub_emitter(const NodePath &p_path) { + if (is_inside_tree()) { + RS::get_singleton()->particles_set_subemitter(particles, RID()); + } + + sub_emitter = p_path; + + if (is_inside_tree() && sub_emitter != NodePath()) { + _attach_sub_emitter(); + } +} + +NodePath GPUParticles3D::get_sub_emitter() const { + return sub_emitter; +} + void GPUParticles3D::_notification(int p_what) { if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { if (can_process()) { @@ -319,6 +358,16 @@ void GPUParticles3D::_notification(int p_what) { } } + if (p_what == NOTIFICATION_ENTER_TREE) { + if (sub_emitter != NodePath()) { + _attach_sub_emitter(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + RS::get_singleton()->particles_set_subemitter(particles, RID()); + } + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { // make sure particles are updated before rendering occurs if they were active before if (is_visible_in_tree() && !RS::get_singleton()->particles_is_inactive(particles)) { @@ -341,6 +390,7 @@ void GPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &GPUParticles3D::set_fractional_delta); ClassDB::bind_method(D_METHOD("set_process_material", "material"), &GPUParticles3D::set_process_material); ClassDB::bind_method(D_METHOD("set_speed_scale", "scale"), &GPUParticles3D::set_speed_scale); + ClassDB::bind_method(D_METHOD("set_collision_base_size", "size"), &GPUParticles3D::set_collision_base_size); ClassDB::bind_method(D_METHOD("is_emitting"), &GPUParticles3D::is_emitting); ClassDB::bind_method(D_METHOD("get_amount"), &GPUParticles3D::get_amount); @@ -355,6 +405,7 @@ void GPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_fractional_delta"), &GPUParticles3D::get_fractional_delta); ClassDB::bind_method(D_METHOD("get_process_material"), &GPUParticles3D::get_process_material); ClassDB::bind_method(D_METHOD("get_speed_scale"), &GPUParticles3D::get_speed_scale); + ClassDB::bind_method(D_METHOD("get_collision_base_size"), &GPUParticles3D::get_collision_base_size); ClassDB::bind_method(D_METHOD("set_draw_order", "order"), &GPUParticles3D::set_draw_order); @@ -369,8 +420,14 @@ void GPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("restart"), &GPUParticles3D::restart); ClassDB::bind_method(D_METHOD("capture_aabb"), &GPUParticles3D::capture_aabb); + ClassDB::bind_method(D_METHOD("set_sub_emitter", "path"), &GPUParticles3D::set_sub_emitter); + ClassDB::bind_method(D_METHOD("get_sub_emitter"), &GPUParticles3D::get_sub_emitter); + + ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles3D::emit_particle); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter"); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); @@ -380,6 +437,8 @@ void GPUParticles3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_fps", PROPERTY_HINT_RANGE, "0,1000,1"), "set_fixed_fps", "get_fixed_fps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fract_delta"), "set_fractional_delta", "get_fractional_delta"); + ADD_GROUP("Collision", "collision_"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision_base_size", PROPERTY_HINT_RANGE, "0,128,0.01,or_greater"), "set_collision_base_size", "get_collision_base_size"); ADD_GROUP("Drawing", ""); ADD_PROPERTY(PropertyInfo(Variant::AABB, "visibility_aabb"), "set_visibility_aabb", "get_visibility_aabb"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "local_coords"), "set_use_local_coordinates", "get_use_local_coordinates"); @@ -396,6 +455,12 @@ void GPUParticles3D::_bind_methods() { BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME); BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH); + BIND_ENUM_CONSTANT(EMIT_FLAG_POSITION); + BIND_ENUM_CONSTANT(EMIT_FLAG_ROTATION_SCALE); + BIND_ENUM_CONSTANT(EMIT_FLAG_VELOCITY); + BIND_ENUM_CONSTANT(EMIT_FLAG_COLOR); + BIND_ENUM_CONSTANT(EMIT_FLAG_CUSTOM); + BIND_CONSTANT(MAX_DRAW_PASSES); } @@ -417,6 +482,7 @@ GPUParticles3D::GPUParticles3D() { set_draw_passes(1); set_draw_order(DRAW_ORDER_INDEX); set_speed_scale(1); + set_collision_base_size(0.01); } GPUParticles3D::~GPUParticles3D() { diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h index e04473727d..f0e5f05e5b 100644 --- a/scene/3d/gpu_particles_3d.h +++ b/scene/3d/gpu_particles_3d.h @@ -31,7 +31,7 @@ #ifndef PARTICLES_H #define PARTICLES_H -#include "core/rid.h" +#include "core/templates/rid.h" #include "scene/3d/visual_instance_3d.h" #include "scene/resources/material.h" @@ -64,6 +64,8 @@ private: bool local_coords; int fixed_fps; bool fractional_delta; + NodePath sub_emitter; + float collision_base_size; Ref<Material> process_material; @@ -71,6 +73,8 @@ private: Vector<Ref<Mesh>> draw_passes; + void _attach_sub_emitter(); + protected: static void _bind_methods(); void _notification(int p_what); @@ -91,6 +95,7 @@ public: void set_use_local_coordinates(bool p_enable); void set_process_material(const Ref<Material> &p_material); void set_speed_scale(float p_scale); + void set_collision_base_size(float p_ratio); bool is_emitting() const; int get_amount() const; @@ -103,6 +108,7 @@ public: bool get_use_local_coordinates() const; Ref<Material> get_process_material() const; float get_speed_scale() const; + float get_collision_base_size() const; void set_fixed_fps(int p_count); int get_fixed_fps() const; @@ -121,13 +127,27 @@ public: virtual String get_configuration_warning() const override; + void set_sub_emitter(const NodePath &p_path); + NodePath get_sub_emitter() const; + void restart(); + enum EmitFlags { + EMIT_FLAG_POSITION = RS::PARTICLES_EMIT_FLAG_POSITION, + EMIT_FLAG_ROTATION_SCALE = RS::PARTICLES_EMIT_FLAG_ROTATION_SCALE, + EMIT_FLAG_VELOCITY = RS::PARTICLES_EMIT_FLAG_VELOCITY, + EMIT_FLAG_COLOR = RS::PARTICLES_EMIT_FLAG_COLOR, + EMIT_FLAG_CUSTOM = RS::PARTICLES_EMIT_FLAG_CUSTOM + }; + + void emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags); + AABB capture_aabb() const; GPUParticles3D(); ~GPUParticles3D(); }; VARIANT_ENUM_CAST(GPUParticles3D::DrawOrder) +VARIANT_ENUM_CAST(GPUParticles3D::EmitFlags) #endif // PARTICLES_H diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp new file mode 100644 index 0000000000..1f0d5d587d --- /dev/null +++ b/scene/3d/gpu_particles_collision_3d.cpp @@ -0,0 +1,901 @@ +/*************************************************************************/ +/* gpu_particles_collision_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "gpu_particles_collision_3d.h" + +#include "core/templates/thread_work_pool.h" +#include "mesh_instance_3d.h" +#include "scene/3d/camera_3d.h" +#include "scene/main/viewport.h" + +void GPUParticlesCollision3D::set_cull_mask(uint32_t p_cull_mask) { + cull_mask = p_cull_mask; + RS::get_singleton()->particles_collision_set_cull_mask(collision, p_cull_mask); +} + +uint32_t GPUParticlesCollision3D::get_cull_mask() const { + return cull_mask; +} + +void GPUParticlesCollision3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &GPUParticlesCollision3D::set_cull_mask); + ClassDB::bind_method(D_METHOD("get_cull_mask"), &GPUParticlesCollision3D::get_cull_mask); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); +} + +GPUParticlesCollision3D::GPUParticlesCollision3D(RS::ParticlesCollisionType p_type) { + collision = RS::get_singleton()->particles_collision_create(); + RS::get_singleton()->particles_collision_set_collision_type(collision, p_type); + set_base(collision); +} + +GPUParticlesCollision3D::~GPUParticlesCollision3D() { + RS::get_singleton()->free(collision); +} + +///////////////////////////////// + +void GPUParticlesCollisionSphere::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &GPUParticlesCollisionSphere::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &GPUParticlesCollisionSphere::get_radius); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_radius", "get_radius"); +} + +void GPUParticlesCollisionSphere::set_radius(float p_radius) { + radius = p_radius; + RS::get_singleton()->particles_collision_set_sphere_radius(_get_collision(), radius); + update_gizmo(); +} + +float GPUParticlesCollisionSphere::get_radius() const { + return radius; +} + +AABB GPUParticlesCollisionSphere::get_aabb() const { + return AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2, radius * 2, radius * 2)); +} + +GPUParticlesCollisionSphere::GPUParticlesCollisionSphere() : + GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE) { +} + +GPUParticlesCollisionSphere::~GPUParticlesCollisionSphere() { +} + +/////////////////////////// + +void GPUParticlesCollisionBox::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionBox::set_extents); + ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionBox::get_extents); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); +} + +void GPUParticlesCollisionBox::set_extents(const Vector3 &p_extents) { + extents = p_extents; + RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); + update_gizmo(); +} + +Vector3 GPUParticlesCollisionBox::get_extents() const { + return extents; +} + +AABB GPUParticlesCollisionBox::get_aabb() const { + return AABB(-extents, extents * 2); +} + +GPUParticlesCollisionBox::GPUParticlesCollisionBox() : + GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE) { +} + +GPUParticlesCollisionBox::~GPUParticlesCollisionBox() { +} + +/////////////////////////////// +/////////////////////////// + +void GPUParticlesCollisionSDF::_find_meshes(const AABB &p_aabb, Node *p_at_node, List<PlotMesh> &plot_meshes) { + MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node); + if (mi && mi->is_visible_in_tree()) { + Ref<Mesh> mesh = mi->get_mesh(); + if (mesh.is_valid()) { + AABB aabb = mesh->get_aabb(); + + Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform(); + + if (p_aabb.intersects(xf.xform(aabb))) { + PlotMesh pm; + pm.local_xform = xf; + pm.mesh = mesh; + plot_meshes.push_back(pm); + } + } + } + + Node3D *s = Object::cast_to<Node3D>(p_at_node); + if (s) { + if (s->is_visible_in_tree()) { + Array meshes = p_at_node->call("get_meshes"); + for (int i = 0; i < meshes.size(); i += 2) { + Transform mxf = meshes[i]; + Ref<Mesh> mesh = meshes[i + 1]; + if (!mesh.is_valid()) { + continue; + } + + AABB aabb = mesh->get_aabb(); + + Transform xf = get_global_transform().affine_inverse() * (s->get_global_transform() * mxf); + + if (p_aabb.intersects(xf.xform(aabb))) { + PlotMesh pm; + pm.local_xform = xf; + pm.mesh = mesh; + plot_meshes.push_back(pm); + } + } + } + } + + for (int i = 0; i < p_at_node->get_child_count(); i++) { + Node *child = p_at_node->get_child(i); + _find_meshes(p_aabb, child, plot_meshes); + } +} + +uint32_t GPUParticlesCollisionSDF::_create_bvh(LocalVector<BVH> &bvh_tree, FacePos *p_faces, uint32_t p_face_count, const Face3 *p_triangles, float p_thickness) { + if (p_face_count == 1) { + return BVH::LEAF_BIT | p_faces[0].index; + } + + uint32_t index = bvh_tree.size(); + { + BVH bvh; + + for (uint32_t i = 0; i < p_face_count; i++) { + const Face3 &f = p_triangles[p_faces[i].index]; + AABB aabb(f.vertex[0], Vector3()); + aabb.expand_to(f.vertex[1]); + aabb.expand_to(f.vertex[2]); + if (p_thickness > 0.0) { + Vector3 normal = p_triangles[p_faces[i].index].get_plane().normal; + aabb.expand_to(f.vertex[0] - normal * p_thickness); + aabb.expand_to(f.vertex[1] - normal * p_thickness); + aabb.expand_to(f.vertex[2] - normal * p_thickness); + } + if (i == 0) { + bvh.bounds = aabb; + } else { + bvh.bounds.merge_with(aabb); + } + } + bvh_tree.push_back(bvh); + } + + uint32_t middle = p_face_count / 2; + + SortArray<FacePos, FaceSort> s; + s.compare.axis = bvh_tree[index].bounds.get_longest_axis_index(); + s.sort(p_faces, p_face_count); + + uint32_t left = _create_bvh(bvh_tree, p_faces, middle, p_triangles, p_thickness); + uint32_t right = _create_bvh(bvh_tree, p_faces + middle, p_face_count - middle, p_triangles, p_thickness); + + bvh_tree[index].children[0] = left; + bvh_tree[index].children[1] = right; + + return index; +} + +static _FORCE_INLINE_ float Vector3_dot2(const Vector3 &p_vec3) { + return p_vec3.dot(p_vec3); +} + +void GPUParticlesCollisionSDF::_find_closest_distance(const Vector3 &p_pos, const BVH *bvh, uint32_t p_bvh_cell, const Face3 *triangles, float thickness, float &closest_distance) { + if (p_bvh_cell & BVH::LEAF_BIT) { + p_bvh_cell &= BVH::LEAF_MASK; //remove bit + + Vector3 point = p_pos; + Plane p = triangles[p_bvh_cell].get_plane(); + float d = p.distance_to(point); + float inside_d = 1e20; + if (d < 0 && d > -thickness) { + //inside planes, do this in 2D + + Vector3 x_axis = (triangles[p_bvh_cell].vertex[0] - triangles[p_bvh_cell].vertex[1]).normalized(); + Vector3 y_axis = p.normal.cross(x_axis).normalized(); + + Vector2 points[3]; + for (int i = 0; i < 3; i++) { + points[i] = Vector2(x_axis.dot(triangles[p_bvh_cell].vertex[i]), y_axis.dot(triangles[p_bvh_cell].vertex[i])); + } + + Vector2 p2d = Vector2(x_axis.dot(point), y_axis.dot(point)); + + { + // https://www.shadertoy.com/view/XsXSz4 + + Vector2 e0 = points[1] - points[0]; + Vector2 e1 = points[2] - points[1]; + Vector2 e2 = points[0] - points[2]; + + Vector2 v0 = p2d - points[0]; + Vector2 v1 = p2d - points[1]; + Vector2 v2 = p2d - points[2]; + + Vector2 pq0 = v0 - e0 * CLAMP(v0.dot(e0) / e0.dot(e0), 0.0, 1.0); + Vector2 pq1 = v1 - e1 * CLAMP(v1.dot(e1) / e1.dot(e1), 0.0, 1.0); + Vector2 pq2 = v2 - e2 * CLAMP(v2.dot(e2) / e2.dot(e2), 0.0, 1.0); + + float s = SGN(e0.x * e2.y - e0.y * e2.x); + Vector2 d2 = Vector2(pq0.dot(pq0), s * (v0.x * e0.y - v0.y * e0.x)).min(Vector2(pq1.dot(pq1), s * (v1.x * e1.y - v1.y * e1.x))).min(Vector2(pq2.dot(pq2), s * (v2.x * e2.y - v2.y * e2.x))); + + inside_d = -Math::sqrt(d2.x) * SGN(d2.y); + } + + //make sure distance to planes is not shorter if inside + if (inside_d < 0) { + inside_d = MAX(inside_d, d); + inside_d = MAX(inside_d, -(thickness + d)); + } + + closest_distance = MIN(closest_distance, inside_d); + } else { + if (d < 0) { + point -= p.normal * thickness; //flatten + } + + // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm + Vector3 a = triangles[p_bvh_cell].vertex[0]; + Vector3 b = triangles[p_bvh_cell].vertex[1]; + Vector3 c = triangles[p_bvh_cell].vertex[2]; + + Vector3 ba = b - a; + Vector3 pa = point - a; + Vector3 cb = c - b; + Vector3 pb = point - b; + Vector3 ac = a - c; + Vector3 pc = point - c; + Vector3 nor = ba.cross(ac); + + inside_d = Math::sqrt( + (SGN(ba.cross(nor).dot(pa)) + + SGN(cb.cross(nor).dot(pb)) + + SGN(ac.cross(nor).dot(pc)) < + 2.0) ? + MIN(MIN( + Vector3_dot2(ba * CLAMP(ba.dot(pa) / Vector3_dot2(ba), 0.0, 1.0) - pa), + Vector3_dot2(cb * CLAMP(cb.dot(pb) / Vector3_dot2(cb), 0.0, 1.0) - pb)), + Vector3_dot2(ac * CLAMP(ac.dot(pc) / Vector3_dot2(ac), 0.0, 1.0) - pc)) : + nor.dot(pa) * nor.dot(pa) / Vector3_dot2(nor)); + + closest_distance = MIN(closest_distance, inside_d); + } + + } else { + bool pass = true; + if (!bvh[p_bvh_cell].bounds.has_point(p_pos)) { + //outside, find closest point + Vector3 he = bvh[p_bvh_cell].bounds.size * 0.5; + Vector3 center = bvh[p_bvh_cell].bounds.position + he; + + Vector3 rel = (p_pos - center).abs(); + Vector3 closest(MIN(rel.x, he.x), MIN(rel.y, he.y), MIN(rel.z, he.z)); + float d = rel.distance_to(closest); + + if (d >= closest_distance) { + pass = false; //already closer than this aabb, discard + } + } + + if (pass) { + _find_closest_distance(p_pos, bvh, bvh[p_bvh_cell].children[0], triangles, thickness, closest_distance); + _find_closest_distance(p_pos, bvh, bvh[p_bvh_cell].children[1], triangles, thickness, closest_distance); + } + } +} + +void GPUParticlesCollisionSDF::_compute_sdf_z(uint32_t p_z, ComputeSDFParams *params) { + int32_t z_ofs = p_z * params->size.y * params->size.x; + for (int32_t y = 0; y < params->size.y; y++) { + int32_t y_ofs = z_ofs + y * params->size.x; + for (int32_t x = 0; x < params->size.x; x++) { + int32_t x_ofs = y_ofs + x; + float &cell = params->cells[x_ofs]; + + Vector3 pos = params->cell_offset + Vector3(x, y, p_z) * params->cell_size; + + cell = 1e20; + + _find_closest_distance(pos, params->bvh, 0, params->triangles, params->thickness, cell); + } + } +} + +void GPUParticlesCollisionSDF::_compute_sdf(ComputeSDFParams *params) { + ThreadWorkPool work_pool; + work_pool.init(); + work_pool.begin_work(params->size.z, this, &GPUParticlesCollisionSDF::_compute_sdf_z, params); + while (work_pool.get_work_index() < (uint32_t)params->size.z) { + OS::get_singleton()->delay_usec(10000); + bake_step_function(work_pool.get_work_index() * 100 / params->size.z, "Baking SDF"); + } + work_pool.end_work(); + work_pool.finish(); +} + +Vector3i GPUParticlesCollisionSDF::get_estimated_cell_size() const { + static const int subdivs[RESOLUTION_MAX] = { 16, 32, 64, 128, 256, 512 }; + int subdiv = subdivs[get_resolution()]; + + AABB aabb(-extents, extents * 2); + + float cell_size = aabb.get_longest_axis_size() / float(subdiv); + + Vector3i sdf_size = Vector3i(aabb.size / cell_size); + sdf_size.x = MAX(1, sdf_size.x); + sdf_size.y = MAX(1, sdf_size.y); + sdf_size.z = MAX(1, sdf_size.z); + return sdf_size; +} + +Ref<Image> GPUParticlesCollisionSDF::bake() { + static const int subdivs[RESOLUTION_MAX] = { 16, 32, 64, 128, 256, 512 }; + int subdiv = subdivs[get_resolution()]; + + AABB aabb(-extents, extents * 2); + + float cell_size = aabb.get_longest_axis_size() / float(subdiv); + + Vector3i sdf_size = Vector3i(aabb.size / cell_size); + sdf_size.x = MAX(1, sdf_size.x); + sdf_size.y = MAX(1, sdf_size.y); + sdf_size.z = MAX(1, sdf_size.z); + + if (bake_begin_function) { + bake_begin_function(100); + } + + aabb.size = Vector3(sdf_size) * cell_size; + + List<PlotMesh> plot_meshes; + _find_meshes(aabb, get_parent(), plot_meshes); + + LocalVector<Face3> faces; + + if (bake_step_function) { + bake_step_function(0, "Finding Meshes"); + } + + for (List<PlotMesh>::Element *E = plot_meshes.front(); E; E = E->next()) { + const PlotMesh &pm = E->get(); + + for (int i = 0; i < pm.mesh->get_surface_count(); i++) { + if (pm.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) { + continue; //only triangles + } + + Array a = pm.mesh->surface_get_arrays(i); + + Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; + const Vector3 *vr = vertices.ptr(); + Vector<int> index = a[Mesh::ARRAY_INDEX]; + + if (index.size()) { + int facecount = index.size() / 3; + const int *ir = index.ptr(); + + for (int j = 0; j < facecount; j++) { + Face3 face; + + for (int k = 0; k < 3; k++) { + face.vertex[k] = pm.local_xform.xform(vr[ir[j * 3 + k]]); + } + + //test against original bounds + if (!Geometry3D::triangle_box_overlap(aabb.position + aabb.size * 0.5, aabb.size * 0.5, face.vertex)) { + continue; + } + + faces.push_back(face); + } + + } else { + int facecount = vertices.size() / 3; + + for (int j = 0; j < facecount; j++) { + Face3 face; + + for (int k = 0; k < 3; k++) { + face.vertex[k] = pm.local_xform.xform(vr[j * 3 + k]); + } + + //test against original bounds + if (!Geometry3D::triangle_box_overlap(aabb.position + aabb.size * 0.5, aabb.size * 0.5, face.vertex)) { + continue; + } + + faces.push_back(face); + } + } + } + } + + //compute bvh + + ERR_FAIL_COND_V(faces.size() <= 1, Ref<Image>()); + + LocalVector<FacePos> face_pos; + + face_pos.resize(faces.size()); + + float th = cell_size * thickness; + + for (uint32_t i = 0; i < faces.size(); i++) { + face_pos[i].index = i; + face_pos[i].center = (faces[i].vertex[0] + faces[i].vertex[1] + faces[i].vertex[2]) / 2; + if (th > 0.0) { + face_pos[i].center -= faces[i].get_plane().normal * th * 0.5; + } + } + + if (bake_step_function) { + bake_step_function(0, "Creating BVH"); + } + + LocalVector<BVH> bvh; + + _create_bvh(bvh, face_pos.ptr(), face_pos.size(), faces.ptr(), th); + + Vector<uint8_t> data; + data.resize(sdf_size.z * sdf_size.y * sdf_size.x * sizeof(float)); + + if (bake_step_function) { + bake_step_function(0, "Baking SDF"); + } + + ComputeSDFParams params; + params.cells = (float *)data.ptrw(); + params.size = sdf_size; + params.cell_size = cell_size; + params.cell_offset = aabb.position + Vector3(cell_size * 0.5, cell_size * 0.5, cell_size * 0.5); + params.bvh = bvh.ptr(); + params.triangles = faces.ptr(); + params.thickness = th; + _compute_sdf(¶ms); + + Ref<Image> ret; + ret.instance(); + ret->create(sdf_size.x, sdf_size.y * sdf_size.z, false, Image::FORMAT_RF, data); + ret->convert(Image::FORMAT_RH); //convert to half, save space + ret->set_meta("depth", sdf_size.z); //hack, make sure to add to the docs of this function + + if (bake_end_function) { + bake_end_function(); + } + + return ret; +} + +void GPUParticlesCollisionSDF::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionSDF::set_extents); + ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionSDF::get_extents); + + ClassDB::bind_method(D_METHOD("set_resolution", "resolution"), &GPUParticlesCollisionSDF::set_resolution); + ClassDB::bind_method(D_METHOD("get_resolution"), &GPUParticlesCollisionSDF::get_resolution); + + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &GPUParticlesCollisionSDF::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &GPUParticlesCollisionSDF::get_texture); + + ClassDB::bind_method(D_METHOD("set_thickness", "thickness"), &GPUParticlesCollisionSDF::set_thickness); + ClassDB::bind_method(D_METHOD("get_thickness"), &GPUParticlesCollisionSDF::get_thickness); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "16,32,64,128,256,512"), "set_resolution", "get_resolution"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "thickness", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_thickness", "get_thickness"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture"); + + BIND_ENUM_CONSTANT(RESOLUTION_16); + BIND_ENUM_CONSTANT(RESOLUTION_32); + BIND_ENUM_CONSTANT(RESOLUTION_64); + BIND_ENUM_CONSTANT(RESOLUTION_128); + BIND_ENUM_CONSTANT(RESOLUTION_256); + BIND_ENUM_CONSTANT(RESOLUTION_512); + BIND_ENUM_CONSTANT(RESOLUTION_MAX); +} + +void GPUParticlesCollisionSDF::set_thickness(float p_thickness) { + thickness = p_thickness; +} + +float GPUParticlesCollisionSDF::get_thickness() const { + return thickness; +} + +void GPUParticlesCollisionSDF::set_extents(const Vector3 &p_extents) { + extents = p_extents; + RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); + update_gizmo(); +} + +Vector3 GPUParticlesCollisionSDF::get_extents() const { + return extents; +} + +void GPUParticlesCollisionSDF::set_resolution(Resolution p_resolution) { + resolution = p_resolution; + update_gizmo(); +} + +GPUParticlesCollisionSDF::Resolution GPUParticlesCollisionSDF::get_resolution() const { + return resolution; +} + +void GPUParticlesCollisionSDF::set_texture(const Ref<Texture3D> &p_texture) { + texture = p_texture; + RID tex = texture.is_valid() ? texture->get_rid() : RID(); + RS::get_singleton()->particles_collision_set_field_texture(_get_collision(), tex); +} + +Ref<Texture3D> GPUParticlesCollisionSDF::get_texture() const { + return texture; +} + +AABB GPUParticlesCollisionSDF::get_aabb() const { + return AABB(-extents, extents * 2); +} + +GPUParticlesCollisionSDF::BakeBeginFunc GPUParticlesCollisionSDF::bake_begin_function = nullptr; +GPUParticlesCollisionSDF::BakeStepFunc GPUParticlesCollisionSDF::bake_step_function = nullptr; +GPUParticlesCollisionSDF::BakeEndFunc GPUParticlesCollisionSDF::bake_end_function = nullptr; + +GPUParticlesCollisionSDF::GPUParticlesCollisionSDF() : + GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE) { +} + +GPUParticlesCollisionSDF::~GPUParticlesCollisionSDF() { +} + +//////////////////////////// +//////////////////////////// + +void GPUParticlesCollisionHeightField::_notification(int p_what) { + if (p_what == NOTIFICATION_INTERNAL_PROCESS) { + if (update_mode == UPDATE_MODE_ALWAYS) { + RS::get_singleton()->particles_collision_height_field_update(_get_collision()); + } + + if (follow_camera_mode && get_viewport()) { + Camera3D *cam = get_viewport()->get_camera(); + if (cam) { + Transform xform = get_global_transform(); + Vector3 x_axis = xform.basis.get_axis(Vector3::AXIS_X).normalized(); + Vector3 z_axis = xform.basis.get_axis(Vector3::AXIS_Z).normalized(); + float x_len = xform.basis.get_scale().x; + float z_len = xform.basis.get_scale().z; + + Vector3 cam_pos = cam->get_global_transform().origin; + Transform new_xform = xform; + + while (x_axis.dot(cam_pos - new_xform.origin) > x_len) { + new_xform.origin += x_axis * x_len; + } + while (x_axis.dot(cam_pos - new_xform.origin) < -x_len) { + new_xform.origin -= x_axis * x_len; + } + + while (z_axis.dot(cam_pos - new_xform.origin) > z_len) { + new_xform.origin += z_axis * z_len; + } + while (z_axis.dot(cam_pos - new_xform.origin) < -z_len) { + new_xform.origin -= z_axis * z_len; + } + + if (new_xform != xform) { + set_global_transform(new_xform); + RS::get_singleton()->particles_collision_height_field_update(_get_collision()); + } + } + } + } + + if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { + RS::get_singleton()->particles_collision_height_field_update(_get_collision()); + } +} + +void GPUParticlesCollisionHeightField::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesCollisionHeightField::set_extents); + ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesCollisionHeightField::get_extents); + + ClassDB::bind_method(D_METHOD("set_resolution", "resolution"), &GPUParticlesCollisionHeightField::set_resolution); + ClassDB::bind_method(D_METHOD("get_resolution"), &GPUParticlesCollisionHeightField::get_resolution); + + ClassDB::bind_method(D_METHOD("set_update_mode", "update_mode"), &GPUParticlesCollisionHeightField::set_update_mode); + ClassDB::bind_method(D_METHOD("get_update_mode"), &GPUParticlesCollisionHeightField::get_update_mode); + + ClassDB::bind_method(D_METHOD("set_follow_camera_mode", "enabled"), &GPUParticlesCollisionHeightField::set_follow_camera_mode); + ClassDB::bind_method(D_METHOD("is_follow_camera_mode_enabled"), &GPUParticlesCollisionHeightField::is_follow_camera_mode_enabled); + + ClassDB::bind_method(D_METHOD("set_follow_camera_push_ratio", "ratio"), &GPUParticlesCollisionHeightField::set_follow_camera_push_ratio); + ClassDB::bind_method(D_METHOD("get_follow_camera_push_ratio"), &GPUParticlesCollisionHeightField::get_follow_camera_push_ratio); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096,8192"), "set_resolution", "get_resolution"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "WhenMoved,Always"), "set_update_mode", "get_update_mode"); + ADD_GROUP("Folow Camera", "follow_camera_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_camera_enabled"), "set_follow_camera_mode", "is_follow_camera_mode_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "follow_camera_push_ratio", PROPERTY_HINT_RANGE, "0.01,1,0.01"), "set_follow_camera_push_ratio", "get_follow_camera_push_ratio"); + + BIND_ENUM_CONSTANT(RESOLUTION_256); + BIND_ENUM_CONSTANT(RESOLUTION_512); + BIND_ENUM_CONSTANT(RESOLUTION_1024); + BIND_ENUM_CONSTANT(RESOLUTION_2048); + BIND_ENUM_CONSTANT(RESOLUTION_4096); + BIND_ENUM_CONSTANT(RESOLUTION_8192); + BIND_ENUM_CONSTANT(RESOLUTION_MAX); + + BIND_ENUM_CONSTANT(UPDATE_MODE_WHEN_MOVED); + BIND_ENUM_CONSTANT(UPDATE_MODE_ALWAYS); +} + +void GPUParticlesCollisionHeightField::set_follow_camera_push_ratio(float p_follow_camera_push_ratio) { + follow_camera_push_ratio = p_follow_camera_push_ratio; +} + +float GPUParticlesCollisionHeightField::get_follow_camera_push_ratio() const { + return follow_camera_push_ratio; +} + +void GPUParticlesCollisionHeightField::set_extents(const Vector3 &p_extents) { + extents = p_extents; + RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); + update_gizmo(); + RS::get_singleton()->particles_collision_height_field_update(_get_collision()); +} + +Vector3 GPUParticlesCollisionHeightField::get_extents() const { + return extents; +} + +void GPUParticlesCollisionHeightField::set_resolution(Resolution p_resolution) { + resolution = p_resolution; + RS::get_singleton()->particles_collision_set_height_field_resolution(_get_collision(), RS::ParticlesCollisionHeightfieldResolution(resolution)); + update_gizmo(); + RS::get_singleton()->particles_collision_height_field_update(_get_collision()); +} + +GPUParticlesCollisionHeightField::Resolution GPUParticlesCollisionHeightField::get_resolution() const { + return resolution; +} + +void GPUParticlesCollisionHeightField::set_update_mode(UpdateMode p_update_mode) { + update_mode = p_update_mode; + set_process_internal(follow_camera_mode || update_mode == UPDATE_MODE_ALWAYS); +} + +GPUParticlesCollisionHeightField::UpdateMode GPUParticlesCollisionHeightField::get_update_mode() const { + return update_mode; +} + +void GPUParticlesCollisionHeightField::set_follow_camera_mode(bool p_enabled) { + follow_camera_mode = p_enabled; + set_process_internal(follow_camera_mode || update_mode == UPDATE_MODE_ALWAYS); +} + +bool GPUParticlesCollisionHeightField::is_follow_camera_mode_enabled() const { + return follow_camera_mode; +} + +AABB GPUParticlesCollisionHeightField::get_aabb() const { + return AABB(-extents, extents * 2); +} + +GPUParticlesCollisionHeightField::GPUParticlesCollisionHeightField() : + GPUParticlesCollision3D(RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE) { +} + +GPUParticlesCollisionHeightField::~GPUParticlesCollisionHeightField() { +} + +//////////////////////////// +//////////////////////////// + +void GPUParticlesAttractor3D::set_cull_mask(uint32_t p_cull_mask) { + cull_mask = p_cull_mask; + RS::get_singleton()->particles_collision_set_cull_mask(collision, p_cull_mask); +} + +uint32_t GPUParticlesAttractor3D::get_cull_mask() const { + return cull_mask; +} + +void GPUParticlesAttractor3D::set_strength(float p_strength) { + strength = p_strength; + RS::get_singleton()->particles_collision_set_attractor_strength(collision, p_strength); +} + +float GPUParticlesAttractor3D::get_strength() const { + return strength; +} + +void GPUParticlesAttractor3D::set_attenuation(float p_attenuation) { + attenuation = p_attenuation; + RS::get_singleton()->particles_collision_set_attractor_attenuation(collision, p_attenuation); +} + +float GPUParticlesAttractor3D::get_attenuation() const { + return attenuation; +} + +void GPUParticlesAttractor3D::set_directionality(float p_directionality) { + directionality = p_directionality; + RS::get_singleton()->particles_collision_set_attractor_directionality(collision, p_directionality); + update_gizmo(); +} + +float GPUParticlesAttractor3D::get_directionality() const { + return directionality; +} + +void GPUParticlesAttractor3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_cull_mask", "mask"), &GPUParticlesAttractor3D::set_cull_mask); + ClassDB::bind_method(D_METHOD("get_cull_mask"), &GPUParticlesAttractor3D::get_cull_mask); + + ClassDB::bind_method(D_METHOD("set_strength", "strength"), &GPUParticlesAttractor3D::set_strength); + ClassDB::bind_method(D_METHOD("get_strength"), &GPUParticlesAttractor3D::get_strength); + + ClassDB::bind_method(D_METHOD("set_attenuation", "attenuation"), &GPUParticlesAttractor3D::set_attenuation); + ClassDB::bind_method(D_METHOD("get_attenuation"), &GPUParticlesAttractor3D::get_attenuation); + + ClassDB::bind_method(D_METHOD("set_directionality", "amount"), &GPUParticlesAttractor3D::set_directionality); + ClassDB::bind_method(D_METHOD("get_directionality"), &GPUParticlesAttractor3D::get_directionality); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "-128,128,0.01,or_greater,or_lesser"), "set_strength", "get_strength"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attenuation", PROPERTY_HINT_EXP_EASING, "0,8,0.01"), "set_attenuation", "get_attenuation"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "directionality", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_directionality", "get_directionality"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); +} + +GPUParticlesAttractor3D::GPUParticlesAttractor3D(RS::ParticlesCollisionType p_type) { + collision = RS::get_singleton()->particles_collision_create(); + RS::get_singleton()->particles_collision_set_collision_type(collision, p_type); + set_base(collision); +} +GPUParticlesAttractor3D::~GPUParticlesAttractor3D() { + RS::get_singleton()->free(collision); +} + +///////////////////////////////// + +void GPUParticlesAttractorSphere::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_radius", "radius"), &GPUParticlesAttractorSphere::set_radius); + ClassDB::bind_method(D_METHOD("get_radius"), &GPUParticlesAttractorSphere::get_radius); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_radius", "get_radius"); +} + +void GPUParticlesAttractorSphere::set_radius(float p_radius) { + radius = p_radius; + RS::get_singleton()->particles_collision_set_sphere_radius(_get_collision(), radius); + update_gizmo(); +} + +float GPUParticlesAttractorSphere::get_radius() const { + return radius; +} + +AABB GPUParticlesAttractorSphere::get_aabb() const { + return AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2, radius * 2, radius * 2)); +} + +GPUParticlesAttractorSphere::GPUParticlesAttractorSphere() : + GPUParticlesAttractor3D(RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT) { +} + +GPUParticlesAttractorSphere::~GPUParticlesAttractorSphere() { +} + +/////////////////////////// + +void GPUParticlesAttractorBox::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesAttractorBox::set_extents); + ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesAttractorBox::get_extents); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); +} + +void GPUParticlesAttractorBox::set_extents(const Vector3 &p_extents) { + extents = p_extents; + RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); + update_gizmo(); +} + +Vector3 GPUParticlesAttractorBox::get_extents() const { + return extents; +} + +AABB GPUParticlesAttractorBox::get_aabb() const { + return AABB(-extents, extents * 2); +} + +GPUParticlesAttractorBox::GPUParticlesAttractorBox() : + GPUParticlesAttractor3D(RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT) { +} + +GPUParticlesAttractorBox::~GPUParticlesAttractorBox() { +} + +/////////////////////////// + +void GPUParticlesAttractorVectorField::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_extents", "extents"), &GPUParticlesAttractorVectorField::set_extents); + ClassDB::bind_method(D_METHOD("get_extents"), &GPUParticlesAttractorVectorField::get_extents); + + ClassDB::bind_method(D_METHOD("set_texture", "texture"), &GPUParticlesAttractorVectorField::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &GPUParticlesAttractorVectorField::get_texture); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater"), "set_extents", "get_extents"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture"); +} + +void GPUParticlesAttractorVectorField::set_extents(const Vector3 &p_extents) { + extents = p_extents; + RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents); + update_gizmo(); +} + +Vector3 GPUParticlesAttractorVectorField::get_extents() const { + return extents; +} + +void GPUParticlesAttractorVectorField::set_texture(const Ref<Texture3D> &p_texture) { + texture = p_texture; + RID tex = texture.is_valid() ? texture->get_rid() : RID(); + RS::get_singleton()->particles_collision_set_field_texture(_get_collision(), tex); +} + +Ref<Texture3D> GPUParticlesAttractorVectorField::get_texture() const { + return texture; +} + +AABB GPUParticlesAttractorVectorField::get_aabb() const { + return AABB(-extents, extents * 2); +} + +GPUParticlesAttractorVectorField::GPUParticlesAttractorVectorField() : + GPUParticlesAttractor3D(RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) { +} + +GPUParticlesAttractorVectorField::~GPUParticlesAttractorVectorField() { +} diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h new file mode 100644 index 0000000000..9b644ade6b --- /dev/null +++ b/scene/3d/gpu_particles_collision_3d.h @@ -0,0 +1,342 @@ +/*************************************************************************/ +/* gpu_particles_collision_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef GPU_PARTICLES_COLLISION_3D_H +#define GPU_PARTICLES_COLLISION_3D_H + +#include "core/templates/local_vector.h" +#include "core/templates/rid.h" +#include "scene/3d/visual_instance_3d.h" +#include "scene/resources/material.h" + +class GPUParticlesCollision3D : public VisualInstance3D { + GDCLASS(GPUParticlesCollision3D, VisualInstance3D); + + uint32_t cull_mask = 0xFFFFFFFF; + RID collision; + +protected: + _FORCE_INLINE_ RID _get_collision() { return collision; } + static void _bind_methods(); + + GPUParticlesCollision3D(RS::ParticlesCollisionType p_type); + +public: + void set_cull_mask(uint32_t p_cull_mask); + uint32_t get_cull_mask() const; + + virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); } + + ~GPUParticlesCollision3D(); +}; + +class GPUParticlesCollisionSphere : public GPUParticlesCollision3D { + GDCLASS(GPUParticlesCollisionSphere, GPUParticlesCollision3D); + + float radius = 1.0; + +protected: + static void _bind_methods(); + +public: + void set_radius(float p_radius); + float get_radius() const; + + virtual AABB get_aabb() const override; + + GPUParticlesCollisionSphere(); + ~GPUParticlesCollisionSphere(); +}; + +class GPUParticlesCollisionBox : public GPUParticlesCollision3D { + GDCLASS(GPUParticlesCollisionBox, GPUParticlesCollision3D); + + Vector3 extents = Vector3(1, 1, 1); + +protected: + static void _bind_methods(); + +public: + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + virtual AABB get_aabb() const override; + + GPUParticlesCollisionBox(); + ~GPUParticlesCollisionBox(); +}; + +class GPUParticlesCollisionSDF : public GPUParticlesCollision3D { + GDCLASS(GPUParticlesCollisionSDF, GPUParticlesCollision3D); + +public: + enum Resolution { + RESOLUTION_16, + RESOLUTION_32, + RESOLUTION_64, + RESOLUTION_128, + RESOLUTION_256, + RESOLUTION_512, + RESOLUTION_MAX, + }; + + typedef void (*BakeBeginFunc)(int); + typedef void (*BakeStepFunc)(int, const String &); + typedef void (*BakeEndFunc)(); + +private: + Vector3 extents = Vector3(1, 1, 1); + Resolution resolution = RESOLUTION_64; + Ref<Texture3D> texture; + float thickness = 1.0; + + struct PlotMesh { + Ref<Mesh> mesh; + Transform local_xform; + }; + + void _find_meshes(const AABB &p_aabb, Node *p_at_node, List<PlotMesh> &plot_meshes); + + struct BVH { + enum { + LEAF_BIT = 1 << 30, + LEAF_MASK = LEAF_BIT - 1 + }; + AABB bounds; + uint32_t children[2]; + }; + + struct FacePos { + Vector3 center; + uint32_t index; + }; + + struct FaceSort { + uint32_t axis; + bool operator()(const FacePos &p_left, const FacePos &p_right) const { + return p_left.center[axis] < p_right.center[axis]; + } + }; + + uint32_t _create_bvh(LocalVector<BVH> &bvh_tree, FacePos *p_faces, uint32_t p_face_count, const Face3 *p_triangles, float p_thickness); + + struct ComputeSDFParams { + float *cells; + Vector3i size; + float cell_size; + Vector3 cell_offset; + const BVH *bvh; + const Face3 *triangles; + float thickness; + }; + + void _find_closest_distance(const Vector3 &p_pos, const BVH *bvh, uint32_t p_bvh_cell, const Face3 *triangles, float thickness, float &closest_distance); + void _compute_sdf_z(uint32_t p_z, ComputeSDFParams *params); + void _compute_sdf(ComputeSDFParams *params); + +protected: + static void _bind_methods(); + +public: + void set_thickness(float p_thickness); + float get_thickness() const; + + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + void set_resolution(Resolution p_resolution); + Resolution get_resolution() const; + + void set_texture(const Ref<Texture3D> &p_texture); + Ref<Texture3D> get_texture() const; + + Vector3i get_estimated_cell_size() const; + Ref<Image> bake(); + + virtual AABB get_aabb() const override; + + static BakeBeginFunc bake_begin_function; + static BakeStepFunc bake_step_function; + static BakeEndFunc bake_end_function; + + GPUParticlesCollisionSDF(); + ~GPUParticlesCollisionSDF(); +}; + +VARIANT_ENUM_CAST(GPUParticlesCollisionSDF::Resolution) + +class GPUParticlesCollisionHeightField : public GPUParticlesCollision3D { + GDCLASS(GPUParticlesCollisionHeightField, GPUParticlesCollision3D); + +public: + enum Resolution { + RESOLUTION_256, + RESOLUTION_512, + RESOLUTION_1024, + RESOLUTION_2048, + RESOLUTION_4096, + RESOLUTION_8192, + RESOLUTION_MAX, + }; + + enum UpdateMode { + UPDATE_MODE_WHEN_MOVED, + UPDATE_MODE_ALWAYS, + }; + +private: + Vector3 extents = Vector3(1, 1, 1); + Resolution resolution = RESOLUTION_1024; + bool follow_camera_mode = false; + float follow_camera_push_ratio = 0.1; + + UpdateMode update_mode = UPDATE_MODE_WHEN_MOVED; + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + void set_resolution(Resolution p_resolution); + Resolution get_resolution() const; + + void set_update_mode(UpdateMode p_update_mode); + UpdateMode get_update_mode() const; + + void set_follow_camera_mode(bool p_enabled); + bool is_follow_camera_mode_enabled() const; + + void set_follow_camera_push_ratio(float p_ratio); + float get_follow_camera_push_ratio() const; + + virtual AABB get_aabb() const override; + + GPUParticlesCollisionHeightField(); + ~GPUParticlesCollisionHeightField(); +}; + +VARIANT_ENUM_CAST(GPUParticlesCollisionHeightField::Resolution) +VARIANT_ENUM_CAST(GPUParticlesCollisionHeightField::UpdateMode) + +class GPUParticlesAttractor3D : public VisualInstance3D { + GDCLASS(GPUParticlesAttractor3D, VisualInstance3D); + + uint32_t cull_mask = 0xFFFFFFFF; + RID collision; + float strength = 1.0; + float attenuation = 1.0; + float directionality = 0.0; + +protected: + _FORCE_INLINE_ RID _get_collision() { return collision; } + static void _bind_methods(); + + GPUParticlesAttractor3D(RS::ParticlesCollisionType p_type); + +public: + void set_cull_mask(uint32_t p_cull_mask); + uint32_t get_cull_mask() const; + + void set_strength(float p_strength); + float get_strength() const; + + void set_attenuation(float p_attenuation); + float get_attenuation() const; + + void set_directionality(float p_directionality); + float get_directionality() const; + + virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); } + + ~GPUParticlesAttractor3D(); +}; + +class GPUParticlesAttractorSphere : public GPUParticlesAttractor3D { + GDCLASS(GPUParticlesAttractorSphere, GPUParticlesAttractor3D); + + float radius = 1.0; + +protected: + static void _bind_methods(); + +public: + void set_radius(float p_radius); + float get_radius() const; + + virtual AABB get_aabb() const override; + + GPUParticlesAttractorSphere(); + ~GPUParticlesAttractorSphere(); +}; + +class GPUParticlesAttractorBox : public GPUParticlesAttractor3D { + GDCLASS(GPUParticlesAttractorBox, GPUParticlesAttractor3D); + + Vector3 extents = Vector3(1, 1, 1); + +protected: + static void _bind_methods(); + +public: + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + virtual AABB get_aabb() const override; + + GPUParticlesAttractorBox(); + ~GPUParticlesAttractorBox(); +}; + +class GPUParticlesAttractorVectorField : public GPUParticlesAttractor3D { + GDCLASS(GPUParticlesAttractorVectorField, GPUParticlesAttractor3D); + + Vector3 extents = Vector3(1, 1, 1); + Ref<Texture3D> texture; + +protected: + static void _bind_methods(); + +public: + void set_extents(const Vector3 &p_extents); + Vector3 get_extents() const; + + void set_texture(const Ref<Texture3D> &p_texture); + Ref<Texture3D> get_texture() const; + + virtual AABB get_aabb() const override; + + GPUParticlesAttractorVectorField(); + ~GPUParticlesAttractorVectorField(); +}; + +#endif // GPU_PARTICLES_COLLISION_3D_H diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index cc1622722e..3f816535f5 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -30,8 +30,8 @@ #include "light_3d.h" -#include "core/engine.h" -#include "core/project_settings.h" +#include "core/config/engine.h" +#include "core/config/project_settings.h" #include "scene/resources/surface_tool.h" bool Light3D::_can_gizmo_scale() const { @@ -270,6 +270,7 @@ void Light3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_normal_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_transmittance_bias", PROPERTY_HINT_RANGE, "-16,16,0.01"), "set_param", "get_param", PARAM_TRANSMITTANCE_BIAS); + ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_fog_fade", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_param", "get_param", PARAM_SHADOW_VOLUMETRIC_FOG_FADE); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_blur", PROPERTY_HINT_RANGE, "0.1,8,0.01"), "set_param", "get_param", PARAM_SHADOW_BLUR); ADD_GROUP("Editor", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_only"), "set_editor_only", "is_editor_only"); @@ -292,6 +293,7 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_SHADOW_BIAS); BIND_ENUM_CONSTANT(PARAM_SHADOW_PANCAKE_SIZE); BIND_ENUM_CONSTANT(PARAM_SHADOW_BLUR); + BIND_ENUM_CONSTANT(PARAM_SHADOW_VOLUMETRIC_FOG_FADE); BIND_ENUM_CONSTANT(PARAM_TRANSMITTANCE_BIAS); BIND_ENUM_CONSTANT(PARAM_MAX); @@ -345,6 +347,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) { set_param(PARAM_SHADOW_BIAS, 0.02); set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0); set_param(PARAM_TRANSMITTANCE_BIAS, 0.05); + set_param(PARAM_SHADOW_VOLUMETRIC_FOG_FADE, 1.0); set_param(PARAM_SHADOW_FADE_START, 1); set_disable_scale(true); } @@ -391,6 +394,15 @@ bool DirectionalLight3D::is_blend_splits_enabled() const { return blend_splits; } +void DirectionalLight3D::set_sky_only(bool p_sky_only) { + sky_only = p_sky_only; + RS::get_singleton()->light_directional_set_sky_only(light, p_sky_only); +} + +bool DirectionalLight3D::is_sky_only() const { + return sky_only; +} + void DirectionalLight3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shadow_mode", "mode"), &DirectionalLight3D::set_shadow_mode); ClassDB::bind_method(D_METHOD("get_shadow_mode"), &DirectionalLight3D::get_shadow_mode); @@ -401,6 +413,9 @@ void DirectionalLight3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_blend_splits", "enabled"), &DirectionalLight3D::set_blend_splits); ClassDB::bind_method(D_METHOD("is_blend_splits_enabled"), &DirectionalLight3D::is_blend_splits_enabled); + ClassDB::bind_method(D_METHOD("set_sky_only", "priority"), &DirectionalLight3D::set_sky_only); + ClassDB::bind_method(D_METHOD("is_sky_only"), &DirectionalLight3D::is_sky_only); + ADD_GROUP("Directional Shadow", "directional_shadow_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "directional_shadow_mode", PROPERTY_HINT_ENUM, "Orthogonal (Fast),PSSM 2 Splits (Average),PSSM 4 Splits (Slow)"), "set_shadow_mode", "get_shadow_mode"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_split_1", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_param", "get_param", PARAM_SHADOW_SPLIT_1_OFFSET); @@ -412,6 +427,8 @@ void DirectionalLight3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_max_distance", PROPERTY_HINT_EXP_RANGE, "0,8192,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_MAX_DISTANCE); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "directional_shadow_pancake_size", PROPERTY_HINT_EXP_RANGE, "0,1024,0.1,or_greater"), "set_param", "get_param", PARAM_SHADOW_PANCAKE_SIZE); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_in_sky_only"), "set_sky_only", "is_sky_only"); + BIND_ENUM_CONSTANT(SHADOW_ORTHOGONAL); BIND_ENUM_CONSTANT(SHADOW_PARALLEL_2_SPLITS); BIND_ENUM_CONSTANT(SHADOW_PARALLEL_4_SPLITS); @@ -445,7 +462,7 @@ String OmniLight3D::get_configuration_warning() const { String warning = Light3D::get_configuration_warning(); if (!has_shadow() && get_projector().is_valid()) { - if (warning != String()) { + if (!warning.empty()) { warning += "\n\n"; } warning += TTR("Projector texture only works with shadows active."); @@ -479,15 +496,14 @@ String SpotLight3D::get_configuration_warning() const { String warning = Light3D::get_configuration_warning(); if (has_shadow() && get_param(PARAM_SPOT_ANGLE) >= 90.0) { - if (warning != String()) { + if (!warning.empty()) { warning += "\n\n"; } - warning += TTR("A SpotLight3D with an angle wider than 90 degrees cannot cast shadows."); } if (!has_shadow() && get_projector().is_valid()) { - if (warning != String()) { + if (!warning.empty()) { warning += "\n\n"; } warning += TTR("Projector texture only works with shadows active."); diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index f106151472..08287a3313 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -58,6 +58,7 @@ public: PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS, PARAM_SHADOW_PANCAKE_SIZE = RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE, PARAM_SHADOW_BLUR = RS::LIGHT_PARAM_SHADOW_BLUR, + PARAM_SHADOW_VOLUMETRIC_FOG_FADE = RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE, PARAM_TRANSMITTANCE_BIAS = RS::LIGHT_PARAM_TRANSMITTANCE_BIAS, PARAM_MAX = RS::LIGHT_PARAM_MAX }; @@ -157,6 +158,7 @@ private: bool blend_splits; ShadowMode shadow_mode; ShadowDepthRange shadow_depth_range; + bool sky_only = false; protected: static void _bind_methods(); @@ -171,6 +173,9 @@ public: void set_blend_splits(bool p_enable); bool is_blend_splits_enabled() const; + void set_sky_only(bool p_sky_only); + bool is_sky_only() const; + DirectionalLight3D(); }; diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index e179261002..f9f8f276a3 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -30,7 +30,7 @@ #include "navigation_agent_3d.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "scene/3d/navigation_3d.h" #include "servers/navigation_server_3d.h" @@ -287,11 +287,16 @@ void NavigationAgent3D::_avoidance_done(Vector3 p_new_velocity) { } String NavigationAgent3D::get_configuration_warning() const { + String warning = Node::get_configuration_warning(); + if (!Object::cast_to<Node3D>(get_parent())) { - return TTR("The NavigationAgent3D can be used only under a spatial node."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("The NavigationAgent3D can be used only under a spatial node."); } - return String(); + return warning; } void NavigationAgent3D::update_navigation() { diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h index e80367ea50..dcfd302561 100644 --- a/scene/3d/navigation_agent_3d.h +++ b/scene/3d/navigation_agent_3d.h @@ -31,7 +31,7 @@ #ifndef NAVIGATION_AGENT_H #define NAVIGATION_AGENT_H -#include "core/vector.h" +#include "core/templates/vector.h" #include "scene/main/node.h" class Node3D; diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index 69fd5b02fc..adbff06ed6 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -113,11 +113,16 @@ Node *NavigationObstacle3D::get_navigation_node() const { } String NavigationObstacle3D::get_configuration_warning() const { + String warning = Node::get_configuration_warning(); + if (!Object::cast_to<Node3D>(get_parent())) { - return TTR("The NavigationObstacle3D only serves to provide collision avoidance to a spatial object."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("The NavigationObstacle3D only serves to provide collision avoidance to a spatial object."); } - return String(); + return warning; } void NavigationObstacle3D::update_agent_shape() { diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 15ed448a65..2ae01c7ab8 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -182,6 +182,7 @@ void NavigationRegion3D::bake_navigation_mesh() { void NavigationRegion3D::_bake_finished(Ref<NavigationMesh> p_nav_mesh) { set_navigation_mesh(p_nav_mesh); bake_thread = nullptr; + emit_signal("bake_finished"); } String NavigationRegion3D::get_configuration_warning() const { @@ -189,19 +190,28 @@ String NavigationRegion3D::get_configuration_warning() const { return String(); } + String warning = Node3D::get_configuration_warning(); + if (!navmesh.is_valid()) { - return TTR("A NavigationMesh resource must be set or created for this node to work."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("A NavigationMesh resource must be set or created for this node to work."); } + const Node3D *c = this; while (c) { if (Object::cast_to<Navigation3D>(c)) { - return String(); + return warning; } c = Object::cast_to<Node3D>(c->get_parent()); } - return TTR("NavigationRegion3D must be a child or grandchild to a Navigation3D node. It only provides navigation data."); + if (!warning.empty()) { + warning += "\n\n"; + } + return warning + TTR("NavigationRegion3D must be a child or grandchild to a Navigation3D node. It only provides navigation data."); } void NavigationRegion3D::_bind_methods() { diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index bd9e4f5bde..e8005f38ed 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -30,8 +30,8 @@ #include "node_3d.h" -#include "core/engine.h" -#include "core/message_queue.h" +#include "core/config/engine.h" +#include "core/object/message_queue.h" #include "scene/main/scene_tree.h" #include "scene/main/window.h" #include "scene/scene_string_names.h" @@ -103,8 +103,8 @@ void Node3D::_propagate_transform_changed(Node3D *p_origin) { data.children_lock++; for (List<Node3D *>::Element *E = data.children.front(); E; E = E->next()) { - if (E->get()->data.toplevel_active) { - continue; //don't propagate to a toplevel + if (E->get()->data.top_level_active) { + continue; //don't propagate to a top_level } E->get()->_propagate_transform_changed(p_origin); } @@ -136,12 +136,12 @@ void Node3D::_notification(int p_what) { data.C = nullptr; } - if (data.toplevel && !Engine::get_singleton()->is_editor_hint()) { + if (data.top_level && !Engine::get_singleton()->is_editor_hint()) { if (data.parent) { data.local_transform = data.parent->get_global_transform() * get_transform(); data.dirty = DIRTY_VECTORS; //global is always dirty upon entering a scene } - data.toplevel_active = true; + data.top_level_active = true; } data.dirty |= DIRTY_GLOBAL; //global is always dirty upon entering a scene @@ -160,7 +160,7 @@ void Node3D::_notification(int p_what) { } data.parent = nullptr; data.C = nullptr; - data.toplevel_active = false; + data.top_level_active = false; } break; case NOTIFICATION_ENTER_WORLD: { data.inside_world = true; @@ -238,7 +238,7 @@ void Node3D::set_transform(const Transform &p_transform) { void Node3D::set_global_transform(const Transform &p_transform) { Transform xform = - (data.parent && !data.toplevel_active) ? + (data.parent && !data.top_level_active) ? data.parent->get_global_transform().affine_inverse() * p_transform : p_transform; @@ -261,7 +261,7 @@ Transform Node3D::get_global_transform() const { _update_local_transform(); } - if (data.parent && !data.toplevel_active) { + if (data.parent && !data.top_level_active) { data.global_transform = data.parent->get_global_transform() * data.local_transform; } else { data.global_transform = data.local_transform; @@ -462,8 +462,8 @@ bool Node3D::is_scale_disabled() const { return data.disable_scale; } -void Node3D::set_as_toplevel(bool p_enabled) { - if (data.toplevel == p_enabled) { +void Node3D::set_as_top_level(bool p_enabled) { + if (data.top_level == p_enabled) { return; } if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) { @@ -473,16 +473,16 @@ void Node3D::set_as_toplevel(bool p_enabled) { set_transform(data.parent->get_global_transform().affine_inverse() * get_global_transform()); } - data.toplevel = p_enabled; - data.toplevel_active = p_enabled; + data.top_level = p_enabled; + data.top_level_active = p_enabled; } else { - data.toplevel = p_enabled; + data.top_level = p_enabled; } } -bool Node3D::is_set_as_toplevel() const { - return data.toplevel; +bool Node3D::is_set_as_top_level() const { + return data.top_level; } Ref<World3D> Node3D::get_world_3d() const { @@ -715,8 +715,8 @@ void Node3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_global_transform"), &Node3D::get_global_transform); ClassDB::bind_method(D_METHOD("get_parent_spatial"), &Node3D::get_parent_spatial); ClassDB::bind_method(D_METHOD("set_ignore_transform_notification", "enabled"), &Node3D::set_ignore_transform_notification); - ClassDB::bind_method(D_METHOD("set_as_toplevel", "enable"), &Node3D::set_as_toplevel); - ClassDB::bind_method(D_METHOD("is_set_as_toplevel"), &Node3D::is_set_as_toplevel); + ClassDB::bind_method(D_METHOD("set_as_top_level", "enable"), &Node3D::set_as_top_level); + ClassDB::bind_method(D_METHOD("is_set_as_top_level"), &Node3D::is_set_as_top_level); ClassDB::bind_method(D_METHOD("set_disable_scale", "disable"), &Node3D::set_disable_scale); ClassDB::bind_method(D_METHOD("is_scale_disabled"), &Node3D::is_scale_disabled); ClassDB::bind_method(D_METHOD("get_world_3d"), &Node3D::get_world_3d); @@ -773,6 +773,7 @@ void Node3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_rotation_degrees", "get_rotation_degrees"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_NONE, "", 0), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_scale", "get_scale"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level"); ADD_GROUP("Matrix", ""); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform"); ADD_GROUP("Visibility", ""); @@ -788,8 +789,8 @@ Node3D::Node3D() : data.children_lock = 0; data.ignore_notification = false; - data.toplevel = false; - data.toplevel_active = false; + data.top_level = false; + data.top_level_active = false; data.scale = Vector3(1, 1, 1); data.viewport = nullptr; data.inside_world = false; diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h index 327d4671e9..5fb421c930 100644 --- a/scene/3d/node_3d.h +++ b/scene/3d/node_3d.h @@ -71,8 +71,8 @@ class Node3D : public Node { Viewport *viewport; - bool toplevel_active; - bool toplevel; + bool top_level_active; + bool top_level; bool inside_world; int children_lock; @@ -111,7 +111,6 @@ protected: public: enum { - NOTIFICATION_TRANSFORM_CHANGED = SceneTree::NOTIFICATION_TRANSFORM_CHANGED, NOTIFICATION_ENTER_WORLD = 41, NOTIFICATION_EXIT_WORLD = 42, @@ -144,8 +143,8 @@ public: virtual Transform get_local_gizmo_transform() const; #endif - void set_as_toplevel(bool p_enabled); - bool is_set_as_toplevel() const; + void set_as_top_level(bool p_enabled); + bool is_set_as_top_level() const; void set_disable_scale(bool p_enabled); bool is_scale_disabled() const; diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp index bf69a8598d..f25a64c567 100644 --- a/scene/3d/path_3d.cpp +++ b/scene/3d/path_3d.cpp @@ -30,7 +30,7 @@ #include "path_3d.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "scene/scene_string_names.h" void Path3D::_notification(int p_what) { @@ -250,16 +250,24 @@ String PathFollow3D::get_configuration_warning() const { return String(); } + String warning = Node3D::get_configuration_warning(); + if (!Object::cast_to<Path3D>(get_parent())) { - return TTR("PathFollow3D only works when set as a child of a Path3D node."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("PathFollow3D only works when set as a child of a Path3D node."); } else { Path3D *path = Object::cast_to<Path3D>(get_parent()); if (path->get_curve().is_valid() && !path->get_curve()->is_up_vector_enabled() && rotation_mode == ROTATION_ORIENTED) { - return TTR("PathFollow3D's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its parent Path3D's Curve resource."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("PathFollow3D's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its parent Path3D's Curve resource."); } } - return String(); + return warning; } void PathFollow3D::_bind_methods() { diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h index 1aa9f7ffd2..1b0f5fa4e0 100644 --- a/scene/3d/path_3d.h +++ b/scene/3d/path_3d.h @@ -57,7 +57,6 @@ class PathFollow3D : public Node3D { public: enum RotationMode { - ROTATION_NONE, ROTATION_Y, ROTATION_XY, diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index fc021e5532..15cd2238e1 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -30,12 +30,11 @@ #include "physics_body_3d.h" +#include "core/config/engine.h" #include "core/core_string_names.h" -#include "core/engine.h" -#include "core/list.h" -#include "core/method_bind_ext.gen.inc" -#include "core/object.h" -#include "core/rid.h" +#include "core/object/class_db.h" +#include "core/templates/list.h" +#include "core/templates/rid.h" #include "scene/3d/collision_shape_3d.h" #include "scene/scene_string_names.h" #include "servers/navigation_server_3d.h" @@ -130,15 +129,6 @@ void PhysicsBody3D::remove_collision_exception_with(Node *p_node) { PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid()); } -void PhysicsBody3D::_set_layers(uint32_t p_mask) { - set_collision_layer(p_mask); - set_collision_mask(p_mask); -} - -uint32_t PhysicsBody3D::_get_layers() const { - return get_collision_layer(); -} - void PhysicsBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collision_layer", "layer"), &PhysicsBody3D::set_collision_layer); ClassDB::bind_method(D_METHOD("get_collision_layer"), &PhysicsBody3D::get_collision_layer); @@ -152,9 +142,6 @@ void PhysicsBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_collision_layer_bit", "bit", "value"), &PhysicsBody3D::set_collision_layer_bit); ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &PhysicsBody3D::get_collision_layer_bit); - ClassDB::bind_method(D_METHOD("_set_layers", "mask"), &PhysicsBody3D::_set_layers); - ClassDB::bind_method(D_METHOD("_get_layers"), &PhysicsBody3D::_get_layers); - ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); @@ -491,8 +478,6 @@ RigidBody3D::Mode RigidBody3D::get_mode() const { void RigidBody3D::set_mass(real_t p_mass) { ERR_FAIL_COND(p_mass <= 0); mass = p_mass; - _change_notify("mass"); - _change_notify("weight"); PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass); } @@ -500,14 +485,6 @@ real_t RigidBody3D::get_mass() const { return mass; } -void RigidBody3D::set_weight(real_t p_weight) { - set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8))); -} - -real_t RigidBody3D::get_weight() const { - return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); -} - void RigidBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { if (physics_material_override.is_valid()) { if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody3D::_reload_physics_characteristics))) { @@ -737,7 +714,7 @@ String RigidBody3D::get_configuration_warning() const { String warning = CollisionObject3D::get_configuration_warning(); if ((get_mode() == MODE_RIGID || get_mode() == MODE_CHARACTER) && (ABS(t.basis.get_axis(0).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(1).length() - 1.0) > 0.05 || ABS(t.basis.get_axis(2).length() - 1.0) > 0.05)) { - if (warning != String()) { + if (!warning.empty()) { warning += "\n\n"; } warning += TTR("Size changes to RigidBody3D (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."); @@ -753,9 +730,6 @@ void RigidBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody3D::set_mass); ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody3D::get_mass); - ClassDB::bind_method(D_METHOD("set_weight", "weight"), &RigidBody3D::set_weight); - ClassDB::bind_method(D_METHOD("get_weight"), &RigidBody3D::get_weight); - ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody3D::set_physics_material_override); ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody3D::get_physics_material_override); @@ -815,7 +789,6 @@ void RigidBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Rigid,Static,Character,Kinematic"), "set_mode", "get_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01", PROPERTY_USAGE_EDITOR), "set_weight", "get_weight"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "custom_integrator"), "set_use_custom_integrator", "is_using_custom_integrator"); @@ -2134,9 +2107,6 @@ void PhysicalBone3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mass", "mass"), &PhysicalBone3D::set_mass); ClassDB::bind_method(D_METHOD("get_mass"), &PhysicalBone3D::get_mass); - ClassDB::bind_method(D_METHOD("set_weight", "weight"), &PhysicalBone3D::set_weight); - ClassDB::bind_method(D_METHOD("get_weight"), &PhysicalBone3D::get_weight); - ClassDB::bind_method(D_METHOD("set_friction", "friction"), &PhysicalBone3D::set_friction); ClassDB::bind_method(D_METHOD("get_friction"), &PhysicalBone3D::get_friction); @@ -2167,7 +2137,6 @@ void PhysicalBone3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "body_offset"), "set_body_offset", "get_body_offset"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_weight", "get_weight"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity_scale", PROPERTY_HINT_RANGE, "-10,10,0.01"), "set_gravity_scale", "get_gravity_scale"); @@ -2469,14 +2438,6 @@ real_t PhysicalBone3D::get_mass() const { return mass; } -void PhysicalBone3D::set_weight(real_t p_weight) { - set_mass(p_weight / real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8))); -} - -real_t PhysicalBone3D::get_weight() const { - return mass * real_t(GLOBAL_DEF("physics/3d/default_gravity", 9.8)); -} - void PhysicalBone3D::set_friction(real_t p_friction) { ERR_FAIL_COND(p_friction < 0 || p_friction > 1); @@ -2606,7 +2567,7 @@ void PhysicalBone3D::_start_physics_simulation() { PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); - set_as_toplevel(true); + set_as_top_level(true); _internal_simulate_physics = true; } @@ -2626,7 +2587,7 @@ void PhysicalBone3D::_stop_physics_simulation() { if (_internal_simulate_physics) { PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), nullptr, ""); parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); - set_as_toplevel(false); + set_as_top_level(false); _internal_simulate_physics = false; } } diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 9830a55183..58eebc90ce 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -31,7 +31,7 @@ #ifndef PHYSICS_BODY_3D_H #define PHYSICS_BODY_3D_H -#include "core/vset.h" +#include "core/templates/vset.h" #include "scene/3d/collision_object_3d.h" #include "scene/resources/physics_material.h" #include "servers/physics_server_3d.h" @@ -43,9 +43,6 @@ class PhysicsBody3D : public CollisionObject3D { uint32_t collision_layer; uint32_t collision_mask; - void _set_layers(uint32_t p_mask); - uint32_t _get_layers() const; - protected: static void _bind_methods(); PhysicsBody3D(PhysicsServer3D::BodyMode p_mode); @@ -188,9 +185,6 @@ public: virtual float get_inverse_mass() const override { return 1.0 / mass; } - void set_weight(real_t p_weight); - real_t get_weight() const; - void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override); Ref<PhysicsMaterial> get_physics_material_override() const; @@ -575,9 +569,6 @@ public: void set_mass(real_t p_mass); real_t get_mass() const; - void set_weight(real_t p_weight); - real_t get_weight() const; - void set_friction(real_t p_friction); real_t get_friction() const; diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp index af4d6ae152..ab9cdb9fd8 100644 --- a/scene/3d/physics_joint_3d.cpp +++ b/scene/3d/physics_joint_3d.cpp @@ -43,6 +43,7 @@ void Joint3D::_update_joint(bool p_only_free) { } if (p_only_free || !is_inside_tree()) { + warning = String(); return; } @@ -52,20 +53,47 @@ void Joint3D::_update_joint(bool p_only_free) { PhysicsBody3D *body_a = Object::cast_to<PhysicsBody3D>(node_a); PhysicsBody3D *body_b = Object::cast_to<PhysicsBody3D>(node_b); - if (!body_a && body_b) { - SWAP(body_a, body_b); + if (node_a && !body_a && node_b && !body_b) { + warning = TTR("Node A and Node B must be PhysicsBody3Ds"); + update_configuration_warning(); + return; } - if (!body_a) { + if (node_a && !body_a) { + warning = TTR("Node A must be a PhysicsBody3D"); + update_configuration_warning(); return; } - joint = _configure_joint(body_a, body_b); + if (node_b && !body_b) { + warning = TTR("Node B must be a PhysicsBody3D"); + update_configuration_warning(); + return; + } - if (!joint.is_valid()) { + if (!body_a && !body_b) { + warning = TTR("Joint is not connected to any PhysicsBody3Ds"); + update_configuration_warning(); return; } + if (body_a == body_b) { + warning = TTR("Node A and Node B must be different PhysicsBody3Ds"); + update_configuration_warning(); + return; + } + + if (!body_a) { + SWAP(body_a, body_b); + } + + warning = String(); + update_configuration_warning(); + + joint = _configure_joint(body_a, body_b); + + ERR_FAIL_COND_MSG(!joint.is_valid(), "Failed to configure the joint."); + PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority); ba = body_a->get_rid(); @@ -137,6 +165,19 @@ bool Joint3D::get_exclude_nodes_from_collision() const { return exclude_from_collision; } +String Joint3D::get_configuration_warning() const { + String node_warning = Node3D::get_configuration_warning(); + + if (!warning.empty()) { + if (!node_warning.empty()) { + node_warning += "\n\n"; + } + node_warning += warning; + } + + return node_warning; +} + void Joint3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_node_a", "node"), &Joint3D::set_node_a); ClassDB::bind_method(D_METHOD("get_node_a"), &Joint3D::get_node_a); @@ -150,8 +191,8 @@ void Joint3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_exclude_nodes_from_collision", "enable"), &Joint3D::set_exclude_nodes_from_collision); ClassDB::bind_method(D_METHOD("get_exclude_nodes_from_collision"), &Joint3D::get_exclude_nodes_from_collision); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject3D"), "set_node_a", "get_node_a"); - ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "CollisionObject3D"), "set_node_b", "get_node_b"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_a", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody3D"), "set_node_a", "get_node_a"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "nodes/node_b", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "PhysicsBody3D"), "set_node_b", "get_node_b"); ADD_PROPERTY(PropertyInfo(Variant::INT, "solver/priority", PROPERTY_HINT_RANGE, "1,8,1"), "set_solver_priority", "get_solver_priority"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision/exclude_nodes"), "set_exclude_nodes_from_collision", "get_exclude_nodes_from_collision"); diff --git a/scene/3d/physics_joint_3d.h b/scene/3d/physics_joint_3d.h index 8e2de82527..a65f6db3bf 100644 --- a/scene/3d/physics_joint_3d.h +++ b/scene/3d/physics_joint_3d.h @@ -46,6 +46,7 @@ class Joint3D : public Node3D { int solver_priority; bool exclude_from_collision; + String warning; protected: void _update_joint(bool p_only_free = false); @@ -57,6 +58,8 @@ protected: static void _bind_methods(); public: + virtual String get_configuration_warning() const override; + void set_node_a(const NodePath &p_node_a); NodePath get_node_a() const; @@ -203,7 +206,6 @@ class ConeTwistJoint3D : public Joint3D { public: enum Param { - PARAM_SWING_SPAN, PARAM_TWIST_SPAN, PARAM_BIAS, @@ -237,7 +239,6 @@ class Generic6DOFJoint3D : public Joint3D { public: enum Param { - PARAM_LINEAR_LOWER_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT, PARAM_LINEAR_UPPER_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT, PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp index 2a922e3cda..811e8a331b 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -31,12 +31,12 @@ #include "ray_cast_3d.h" #include "collision_object_3d.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "mesh_instance_3d.h" #include "servers/physics_server_3d.h" -void RayCast3D::set_cast_to(const Vector3 &p_point) { - cast_to = p_point; +void RayCast3D::set_target_position(const Vector3 &p_point) { + target_position = p_point; if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) { update_gizmo(); } @@ -45,8 +45,8 @@ void RayCast3D::set_cast_to(const Vector3 &p_point) { } } -Vector3 RayCast3D::get_cast_to() const { - return cast_to; +Vector3 RayCast3D::get_target_position() const { + return target_position; } void RayCast3D::set_collision_mask(uint32_t p_mask) { @@ -202,7 +202,7 @@ void RayCast3D::_update_raycast_state() { Transform gt = get_global_transform(); - Vector3 to = cast_to; + Vector3 to = target_position; if (to == Vector3()) { to = Vector3(0, 0.01, 0); } @@ -276,8 +276,8 @@ void RayCast3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast3D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast3D::is_enabled); - ClassDB::bind_method(D_METHOD("set_cast_to", "local_point"), &RayCast3D::set_cast_to); - ClassDB::bind_method(D_METHOD("get_cast_to"), &RayCast3D::get_cast_to); + ClassDB::bind_method(D_METHOD("set_target_position", "local_point"), &RayCast3D::set_target_position); + ClassDB::bind_method(D_METHOD("get_target_position"), &RayCast3D::get_target_position); ClassDB::bind_method(D_METHOD("is_colliding"), &RayCast3D::is_colliding); ClassDB::bind_method(D_METHOD("force_raycast_update"), &RayCast3D::force_raycast_update); @@ -312,7 +312,7 @@ void RayCast3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cast_to"), "set_cast_to", "get_cast_to"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_GROUP("Collide With", "collide_with"); @@ -360,7 +360,7 @@ void RayCast3D::_update_debug_shape() { Vector<Vector3> verts; verts.push_back(Vector3()); - verts.push_back(cast_to); + verts.push_back(target_position); a[Mesh::ARRAY_VERTEX] = verts; mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a); @@ -387,7 +387,7 @@ RayCast3D::RayCast3D() { collided = false; against_shape = 0; collision_mask = 1; - cast_to = Vector3(0, -1, 0); + target_position = Vector3(0, -1, 0); debug_shape = nullptr; exclude_parent_body = true; collide_with_areas = false; diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h index 8f617e5491..f4fe7ba621 100644 --- a/scene/3d/ray_cast_3d.h +++ b/scene/3d/ray_cast_3d.h @@ -43,7 +43,7 @@ class RayCast3D : public Node3D { Vector3 collision_point; Vector3 collision_normal; - Vector3 cast_to; + Vector3 target_position; Set<RID> exclude; uint32_t collision_mask; @@ -74,8 +74,8 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const; - void set_cast_to(const Vector3 &p_point); - Vector3 get_cast_to() const; + void set_target_position(const Vector3 &p_point); + Vector3 get_target_position() const; void set_collision_mask(uint32_t p_mask); uint32_t get_collision_mask() const; diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp index 95fce6b802..358f9346f8 100644 --- a/scene/3d/remote_transform_3d.cpp +++ b/scene/3d/remote_transform_3d.cpp @@ -180,11 +180,16 @@ void RemoteTransform3D::force_update_cache() { } String RemoteTransform3D::get_configuration_warning() const { + String warning = Node3D::get_configuration_warning(); + if (!has_node(remote_node) || !Object::cast_to<Node3D>(get_node(remote_node))) { - return TTR("The \"Remote Path\" property must point to a valid Node3D or Node3D-derived node to work."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("The \"Remote Path\" property must point to a valid Node3D or Node3D-derived node to work."); } - return String(); + return warning; } void RemoteTransform3D::_bind_methods() { diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 6723ca04b9..4425af26f9 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -30,10 +30,10 @@ #include "skeleton_3d.h" -#include "core/engine.h" -#include "core/message_queue.h" -#include "core/project_settings.h" -#include "core/type_info.h" +#include "core/config/engine.h" +#include "core/config/project_settings.h" +#include "core/object/message_queue.h" +#include "core/variant/type_info.h" #include "scene/3d/physics_body_3d.h" #include "scene/resources/surface_tool.h" #include "scene/scene_string_names.h" @@ -848,7 +848,7 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { skin_bindings.insert(skin_ref.operator->()); - skin->connect_compat("changed", skin_ref.operator->(), "_skin_changed"); + skin->connect("changed", Callable(skin_ref.operator->(), "_skin_changed")); _make_dirty(); //skin needs to be updated, so update skeleton diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index a21891a32e..c54f89d3ce 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -31,7 +31,7 @@ #ifndef SKELETON_3D_H #define SKELETON_3D_H -#include "core/rid.h" +#include "core/templates/rid.h" #include "scene/3d/node_3d.h" #include "scene/resources/skin.h" @@ -149,7 +149,6 @@ protected: public: enum { - NOTIFICATION_UPDATE_SKELETON = 50 }; diff --git a/scene/3d/skeleton_ik_3d.h b/scene/3d/skeleton_ik_3d.h index 80acc3e937..6c1db6dd33 100644 --- a/scene/3d/skeleton_ik_3d.h +++ b/scene/3d/skeleton_ik_3d.h @@ -76,10 +76,6 @@ class FabrikInverseKinematic { ChainTip(ChainItem *p_chain_item, const EndEffector *p_end_effector) : chain_item(p_chain_item), end_effector(p_end_effector) {} - - ChainTip(const ChainTip &p_other_ct) : - chain_item(p_other_ct.chain_item), - end_effector(p_other_ct.end_effector) {} }; struct Chain { diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index a267c57f5e..d811b2e852 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -30,10 +30,10 @@ #include "soft_body_3d.h" -#include "core/list.h" -#include "core/object.h" +#include "core/object/class_db.h" #include "core/os/os.h" -#include "core/rid.h" +#include "core/templates/list.h" +#include "core/templates/rid.h" #include "scene/3d/collision_object_3d.h" #include "scene/3d/physics_body_3d.h" #include "scene/3d/skeleton_3d.h" @@ -106,7 +106,7 @@ SoftBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { offset = obj_tocopy.offset; } -SoftBody3D::PinnedPoint SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { +SoftBody3D::PinnedPoint &SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { point_index = obj.point_index; spatial_attachment_path = obj.spatial_attachment_path; spatial_attachment = obj.spatial_attachment; @@ -282,7 +282,7 @@ void SoftBody3D::_notification(int p_what) { set_notify_transform(false); // Required to be top level with Transform at center of world in order to modify RenderingServer only to support custom Transform - set_as_toplevel(true); + set_as_top_level(true); set_transform(Transform()); set_notify_transform(true); @@ -425,7 +425,7 @@ void SoftBody3D::_draw_soft_mesh() { /// Necessary in order to render the mesh correctly (Soft body nodes are in global space) simulation_started = true; - call_deferred("set_as_toplevel", true); + call_deferred("set_as_top_level", true); call_deferred("set_transform", Transform()); } @@ -480,7 +480,6 @@ void SoftBody3D::become_mesh_owner() { Dictionary surface_lods = mesh->surface_get_lods(0); uint32_t surface_format = mesh->surface_get_format(0); - surface_format &= ~(Mesh::ARRAY_COMPRESS_NORMAL); surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE; Ref<ArrayMesh> soft_mesh; @@ -725,7 +724,7 @@ void SoftBody3D::_update_cache_pin_points_datas() { w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(w[i].spatial_attachment_path)); } if (!w[i].spatial_attachment) { - ERR_PRINT("Node3D node not defined in the pinned point, Softbody undefined behaviour!"); + ERR_PRINT("Node3D node not defined in the pinned point, this is undefined behavior for SoftBody3D!"); } } } diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h index 85cfb81637..c59a0b3aa3 100644 --- a/scene/3d/soft_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -74,7 +74,7 @@ public: PinnedPoint(); PinnedPoint(const PinnedPoint &obj_tocopy); - PinnedPoint operator=(const PinnedPoint &obj); + PinnedPoint &operator=(const PinnedPoint &obj); }; private: diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp index 9775ecc6c6..287d760db0 100644 --- a/scene/3d/spring_arm_3d.cpp +++ b/scene/3d/spring_arm_3d.cpp @@ -30,7 +30,7 @@ #include "spring_arm_3d.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "scene/3d/collision_object_3d.h" #include "scene/resources/sphere_shape_3d.h" #include "servers/physics_server_3d.h" diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 3b76cb6499..1d20a9cd3b 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -204,7 +204,6 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const { float pixel_size = get_pixel_size(); Vector2 vertices[4] = { - (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, (final_rect.position + final_rect.size) * pixel_size, (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, @@ -414,7 +413,6 @@ void Sprite3D::_draw() { float pixel_size = get_pixel_size(); Vector2 vertices[4] = { - (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, (final_rect.position + final_rect.size) * pixel_size, (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, @@ -488,7 +486,7 @@ void Sprite3D::_draw() { RS::get_singleton()->immediate_normal(immediate, normal); RS::get_singleton()->immediate_tangent(immediate, tangent); RS::get_singleton()->immediate_color(immediate, color); - RS::get_singleton()->immediate_uv(immediate, uvs[i]); + RS::get_singleton()->immediate_uv(immediate, uvs[index[i]]); Vector3 vtx; vtx[x_axis] = vertices[index[i]][0]; @@ -667,8 +665,8 @@ void Sprite3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); ADD_GROUP("Animation", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); ADD_GROUP("Region", "region_"); @@ -740,7 +738,6 @@ void AnimatedSprite3D::_draw() { float pixel_size = get_pixel_size(); Vector2 vertices[4] = { - (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, (final_rect.position + final_rect.size) * pixel_size, (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, @@ -818,7 +815,7 @@ void AnimatedSprite3D::_draw() { RS::get_singleton()->immediate_normal(immediate, normal); RS::get_singleton()->immediate_tangent(immediate, tangent); RS::get_singleton()->immediate_color(immediate, color); - RS::get_singleton()->immediate_uv(immediate, uvs[i]); + RS::get_singleton()->immediate_uv(immediate, uvs[indices[i]]); Vector3 vtx; vtx[x_axis] = vertices[indices[i]][0]; @@ -1074,11 +1071,16 @@ StringName AnimatedSprite3D::get_animation() const { } String AnimatedSprite3D::get_configuration_warning() const { + String warning = SpriteBase3D::get_configuration_warning(); + if (frames.is_null()) { - return TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames."); } - return String(); + return warning; } void AnimatedSprite3D::_bind_methods() { diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index 4c71ab470b..e27307e75f 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -103,11 +103,16 @@ void VehicleWheel3D::_notification(int p_what) { } String VehicleWheel3D::get_configuration_warning() const { + String warning = Node3D::get_configuration_warning(); + if (!Object::cast_to<VehicleBody3D>(get_parent())) { - return TTR("VehicleWheel3D serves to provide a wheel system to a VehicleBody3D. Please use it as a child of a VehicleBody3D."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("VehicleWheel3D serves to provide a wheel system to a VehicleBody3D. Please use it as a child of a VehicleBody3D."); } - return String(); + return warning; } void VehicleWheel3D::_update(PhysicsDirectBodyState3D *s) { @@ -629,7 +634,6 @@ VehicleBody3D::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDir /* TODO: Why is this code unused? if (body1) { - Vector3 r0 = frictionPosWorld - body1->get_global_transform().origin; Vector3 c0 = (r0).cross(frictionDirectionWorld); Vector3 vec = s->get_inverse_inertia_tensor().xform_inv(c0).cross(r0); diff --git a/scene/3d/velocity_tracker_3d.cpp b/scene/3d/velocity_tracker_3d.cpp index db10f3273b..eba7d44c16 100644 --- a/scene/3d/velocity_tracker_3d.cpp +++ b/scene/3d/velocity_tracker_3d.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "velocity_tracker_3d.h" -#include "core/engine.h" +#include "core/config/engine.h" void VelocityTracker3D::set_track_physics_step(bool p_track_physics_step) { physics_step = p_track_physics_step; diff --git a/scene/3d/visibility_notifier_3d.cpp b/scene/3d/visibility_notifier_3d.cpp index a64b0df1cc..9f5c40caf4 100644 --- a/scene/3d/visibility_notifier_3d.cpp +++ b/scene/3d/visibility_notifier_3d.cpp @@ -30,7 +30,7 @@ #include "visibility_notifier_3d.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "scene/3d/camera_3d.h" #include "scene/3d/physics_body_3d.h" #include "scene/animation/animation_player.h" diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index 195674f62d..51bcb411da 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -32,7 +32,7 @@ #define VISUAL_INSTANCE_H #include "core/math/face3.h" -#include "core/rid.h" +#include "core/templates/rid.h" #include "scene/3d/node_3d.h" #include "scene/resources/material.h" diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp index de5496ee35..c570fc7b7c 100644 --- a/scene/3d/voxelizer.cpp +++ b/scene/3d/voxelizer.cpp @@ -580,7 +580,6 @@ void Voxelizer::_fixup_plot(int p_idx, int p_level) { /*if (bake_light.size()) { for(int i=0;i<6;i++) { - } }*/ diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index 5e73e460ed..3c12d4991e 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -110,22 +110,30 @@ Ref<CameraEffects> WorldEnvironment::get_camera_effects() const { } String WorldEnvironment::get_configuration_warning() const { + String warning = Node::get_configuration_warning(); + if (!environment.is_valid()) { - return TTR("WorldEnvironment requires its \"Environment\" property to contain an Environment to have a visible effect."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("WorldEnvironment requires its \"Environment\" property to contain an Environment to have a visible effect."); } if (!is_inside_tree()) { - return String(); + 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 (nodes.size() > 1) { - return TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes)."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("Only one WorldEnvironment is allowed per scene (or set of instanced scenes)."); } - return String(); + return warning; } void WorldEnvironment::_bind_methods() { diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index f4a514cdd6..763461880f 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -60,13 +60,18 @@ String XRCamera3D::get_configuration_warning() const { return String(); } + String warning = Camera3D::get_configuration_warning(); + // must be child node of XROrigin3D! XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent()); if (origin == nullptr) { - return TTR("XRCamera3D must have an XROrigin3D node as its parent."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("XRCamera3D must have an XROrigin3D node as its parent."); }; - return String(); + return warning; }; Vector3 XRCamera3D::project_local_ray_normal(const Point2 &p_pos) const { @@ -206,7 +211,7 @@ void XRController3D::_notification(int p_what) { emit_signal("button_pressed", i); button_states += mask; } else if (was_pressed && !is_pressed) { - emit_signal("button_release", i); + emit_signal("button_released", i); button_states -= mask; }; @@ -252,7 +257,7 @@ void XRController3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_mesh"), &XRController3D::get_mesh); ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::INT, "button"))); - ADD_SIGNAL(MethodInfo("button_release", PropertyInfo(Variant::INT, "button"))); + ADD_SIGNAL(MethodInfo("button_released", PropertyInfo(Variant::INT, "button"))); ADD_SIGNAL(MethodInfo("mesh_updated", PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"))); }; @@ -277,7 +282,7 @@ String XRController3D::get_controller_name() const { return String("Not connected"); }; - return tracker->get_name(); + return tracker->get_tracker_name(); }; int XRController3D::get_joystick_id() const { @@ -362,17 +367,25 @@ String XRController3D::get_configuration_warning() const { return String(); } + String warning = Node3D::get_configuration_warning(); + // must be child node of XROrigin! XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent()); if (origin == nullptr) { - return TTR("XRController3D must have an XROrigin3D node as its parent."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("XRController3D must have an XROrigin3D node as its parent."); }; if (controller_id == 0) { - return TTR("The controller ID must not be 0 or this controller won't be bound to an actual controller."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("The controller ID must not be 0 or this controller won't be bound to an actual controller."); }; - return String(); + return warning; }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -467,7 +480,7 @@ String XRAnchor3D::get_anchor_name() const { return String("Not connected"); }; - return tracker->get_name(); + return tracker->get_tracker_name(); }; bool XRAnchor3D::get_is_active() const { @@ -479,17 +492,25 @@ String XRAnchor3D::get_configuration_warning() const { return String(); } + String warning = Node3D::get_configuration_warning(); + // must be child node of XROrigin3D! XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent()); if (origin == nullptr) { - return TTR("XRAnchor3D must have an XROrigin3D node as its parent."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("XRAnchor3D must have an XROrigin3D node as its parent."); }; if (anchor_id == 0) { - return TTR("The anchor ID must not be 0 or this anchor won't be bound to an actual anchor."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("The anchor ID must not be 0 or this anchor won't be bound to an actual anchor."); }; - return String(); + return warning; }; Plane XRAnchor3D::get_plane() const { @@ -512,11 +533,16 @@ String XROrigin3D::get_configuration_warning() const { return String(); } + String warning = Node3D::get_configuration_warning(); + if (tracked_camera == nullptr) { - return TTR("XROrigin3D requires an XRCamera3D child node."); + if (!warning.empty()) { + warning += "\n\n"; + } + warning += TTR("XROrigin3D requires an XRCamera3D child node."); } - return String(); + return warning; }; void XROrigin3D::_bind_methods() { |