summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/area_3d.cpp12
-rw-r--r--scene/3d/area_3d.h7
-rw-r--r--scene/3d/audio_stream_player_3d.cpp23
-rw-r--r--scene/3d/audio_stream_player_3d.h8
-rw-r--r--scene/3d/bone_attachment_3d.cpp6
-rw-r--r--scene/3d/bone_attachment_3d.h2
-rw-r--r--scene/3d/camera_3d.cpp11
-rw-r--r--scene/3d/collision_object_3d.cpp3
-rw-r--r--scene/3d/cpu_particles_3d.cpp2
-rw-r--r--scene/3d/gpu_particles_3d.cpp24
-rw-r--r--scene/3d/gpu_particles_3d.h8
-rw-r--r--scene/3d/gpu_particles_collision_3d.cpp10
-rw-r--r--scene/3d/light_3d.cpp28
-rw-r--r--scene/3d/light_3d.h4
-rw-r--r--scene/3d/lightmap_gi.cpp9
-rw-r--r--scene/3d/marker_3d.cpp19
-rw-r--r--scene/3d/marker_3d.h8
-rw-r--r--scene/3d/mesh_instance_3d.cpp30
-rw-r--r--scene/3d/mesh_instance_3d.h1
-rw-r--r--scene/3d/navigation_agent_3d.cpp10
-rw-r--r--scene/3d/navigation_link_3d.cpp2
-rw-r--r--scene/3d/navigation_link_3d.h6
-rw-r--r--scene/3d/navigation_region_3d.cpp2
-rw-r--r--scene/3d/node_3d.cpp31
-rw-r--r--scene/3d/node_3d.h21
-rw-r--r--scene/3d/path_3d.cpp177
-rw-r--r--scene/3d/path_3d.h7
-rw-r--r--scene/3d/physics_body_3d.cpp16
-rw-r--r--scene/3d/physics_body_3d.h4
-rw-r--r--scene/3d/ray_cast_3d.cpp2
-rw-r--r--scene/3d/remote_transform_3d.cpp4
-rw-r--r--scene/3d/shape_cast_3d.cpp8
-rw-r--r--scene/3d/shape_cast_3d.h1
-rw-r--r--scene/3d/skeleton_3d.cpp18
-rw-r--r--scene/3d/soft_body_3d.cpp4
-rw-r--r--scene/3d/spring_arm_3d.cpp1
-rw-r--r--scene/3d/sprite_3d.cpp11
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.cpp2
-rw-r--r--scene/3d/visual_instance_3d.cpp46
-rw-r--r--scene/3d/visual_instance_3d.h10
-rw-r--r--scene/3d/voxel_gi.cpp4
-rw-r--r--scene/3d/xr_nodes.cpp187
-rw-r--r--scene/3d/xr_nodes.h15
43 files changed, 439 insertions, 365 deletions
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp
index cefa9eceff..c6433e773d 100644
--- a/scene/3d/area_3d.cpp
+++ b/scene/3d/area_3d.cpp
@@ -578,11 +578,11 @@ bool Area3D::is_using_reverb_bus() const {
return use_reverb_bus;
}
-void Area3D::set_reverb_bus(const StringName &p_audio_bus) {
+void Area3D::set_reverb_bus_name(const StringName &p_audio_bus) {
reverb_bus = p_audio_bus;
}
-StringName Area3D::get_reverb_bus() const {
+StringName Area3D::get_reverb_bus_name() const {
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
if (AudioServer::get_singleton()->get_bus_name(i) == reverb_bus) {
return reverb_bus;
@@ -711,8 +711,8 @@ void Area3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_reverb_bus", "enable"), &Area3D::set_use_reverb_bus);
ClassDB::bind_method(D_METHOD("is_using_reverb_bus"), &Area3D::is_using_reverb_bus);
- ClassDB::bind_method(D_METHOD("set_reverb_bus", "name"), &Area3D::set_reverb_bus);
- ClassDB::bind_method(D_METHOD("get_reverb_bus"), &Area3D::get_reverb_bus);
+ ClassDB::bind_method(D_METHOD("set_reverb_bus_name", "name"), &Area3D::set_reverb_bus_name);
+ ClassDB::bind_method(D_METHOD("get_reverb_bus_name"), &Area3D::get_reverb_bus_name);
ClassDB::bind_method(D_METHOD("set_reverb_amount", "amount"), &Area3D::set_reverb_amount);
ClassDB::bind_method(D_METHOD("get_reverb_amount"), &Area3D::get_reverb_amount);
@@ -760,8 +760,8 @@ void Area3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus_name", "get_audio_bus_name");
ADD_GROUP("Reverb Bus", "reverb_bus_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reverb_bus_enable"), "set_use_reverb_bus", "is_using_reverb_bus");
- ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "reverb_bus_name", PROPERTY_HINT_ENUM, ""), "set_reverb_bus", "get_reverb_bus");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "reverb_bus_enabled"), "set_use_reverb_bus", "is_using_reverb_bus");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "reverb_bus_name", PROPERTY_HINT_ENUM, ""), "set_reverb_bus_name", "get_reverb_bus_name");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "reverb_bus_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_amount", "get_reverb_amount");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "reverb_bus_uniformity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_uniformity", "get_reverb_uniformity");
diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h
index 0f0bcc7ce0..195f9f0d9e 100644
--- a/scene/3d/area_3d.h
+++ b/scene/3d/area_3d.h
@@ -141,13 +141,12 @@ private:
float reverb_amount = 0.0;
float reverb_uniformity = 0.0;
- void _validate_property(PropertyInfo &p_property) const;
-
void _initialize_wind();
protected:
void _notification(int p_what);
static void _bind_methods();
+ void _validate_property(PropertyInfo &p_property) const;
public:
void set_gravity_space_override_mode(SpaceOverride p_mode);
@@ -216,8 +215,8 @@ public:
void set_use_reverb_bus(bool p_enable);
bool is_using_reverb_bus() const;
- void set_reverb_bus(const StringName &p_audio_bus);
- StringName get_reverb_bus() const;
+ void set_reverb_bus_name(const StringName &p_audio_bus);
+ StringName get_reverb_bus_name() const;
void set_reverb_amount(float p_amount);
float get_reverb_amount() const;
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 21cf3bdb3b..75e840c24b 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -231,7 +231,7 @@ float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const {
}
}
- att += unit_db;
+ att += volume_db;
if (att > max_db) {
att = max_db;
}
@@ -485,7 +485,7 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() {
}
if (area->is_using_reverb_bus()) {
- StringName reverb_bus_name = area->get_reverb_bus();
+ StringName reverb_bus_name = area->get_reverb_bus_name();
Vector<AudioFrame> reverb_vol;
_calc_reverb_vol(area, listener_area_pos, output_volume_vector, reverb_vol);
bus_volumes[reverb_bus_name] = reverb_vol;
@@ -538,12 +538,12 @@ Ref<AudioStream> AudioStreamPlayer3D::get_stream() const {
return stream;
}
-void AudioStreamPlayer3D::set_unit_db(float p_volume) {
- unit_db = p_volume;
+void AudioStreamPlayer3D::set_volume_db(float p_volume) {
+ volume_db = p_volume;
}
-float AudioStreamPlayer3D::get_unit_db() const {
- return unit_db;
+float AudioStreamPlayer3D::get_volume_db() const {
+ return volume_db;
}
void AudioStreamPlayer3D::set_unit_size(float p_volume) {
@@ -606,6 +606,9 @@ bool AudioStreamPlayer3D::is_playing() const {
return true;
}
}
+ if (setplay.get() >= 0) {
+ return true; // play() has been called this frame, but no playback exists just yet.
+ }
return false;
}
@@ -810,8 +813,8 @@ void AudioStreamPlayer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stream", "stream"), &AudioStreamPlayer3D::set_stream);
ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer3D::get_stream);
- ClassDB::bind_method(D_METHOD("set_unit_db", "unit_db"), &AudioStreamPlayer3D::set_unit_db);
- ClassDB::bind_method(D_METHOD("get_unit_db"), &AudioStreamPlayer3D::get_unit_db);
+ ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer3D::set_volume_db);
+ ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer3D::get_volume_db);
ClassDB::bind_method(D_METHOD("set_unit_size", "unit_size"), &AudioStreamPlayer3D::set_unit_size);
ClassDB::bind_method(D_METHOD("get_unit_size"), &AudioStreamPlayer3D::get_unit_size);
@@ -878,7 +881,7 @@ void AudioStreamPlayer3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream");
ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,Inverse Square,Logarithmic,Disabled"), "set_attenuation_model", "get_attenuation_model");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_db", PROPERTY_HINT_RANGE, "-80,80,suffix:dB"), "set_unit_db", "get_unit_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volume_db", PROPERTY_HINT_RANGE, "-80,80,suffix:dB"), "set_volume_db", "get_volume_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.01,or_greater"), "set_unit_size", "get_unit_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_db", PROPERTY_HINT_RANGE, "-24,6,suffix:dB"), "set_max_db", "get_max_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pitch_scale", PROPERTY_HINT_RANGE, "0.01,4,0.01,or_greater"), "set_pitch_scale", "get_pitch_scale");
@@ -916,7 +919,7 @@ AudioStreamPlayer3D::AudioStreamPlayer3D() {
velocity_tracker.instantiate();
AudioServer::get_singleton()->connect("bus_layout_changed", callable_mp(this, &AudioStreamPlayer3D::_bus_layout_changed));
set_disable_scale(true);
- cached_global_panning_strength = ProjectSettings::get_singleton()->get("audio/general/3d_panning_strength");
+ cached_global_panning_strength = GLOBAL_GET("audio/general/3d_panning_strength");
}
AudioStreamPlayer3D::~AudioStreamPlayer3D() {
diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h
index ef48269544..806b250ba7 100644
--- a/scene/3d/audio_stream_player_3d.h
+++ b/scene/3d/audio_stream_player_3d.h
@@ -71,7 +71,7 @@ private:
SafeNumeric<float> setplay{ -1.0 };
AttenuationModel attenuation_model = ATTENUATION_INVERSE_DISTANCE;
- float unit_db = 0.0;
+ float volume_db = 0.0;
float unit_size = 10.0;
float max_db = 3.0;
float pitch_scale = 1.0;
@@ -117,7 +117,7 @@ private:
float _get_attenuation_db(float p_distance) const;
float panning_strength = 1.0f;
- float cached_global_panning_strength = 1.0f;
+ float cached_global_panning_strength = 0.5f;
protected:
void _validate_property(PropertyInfo &p_property) const;
@@ -128,8 +128,8 @@ public:
void set_stream(Ref<AudioStream> p_stream);
Ref<AudioStream> get_stream() const;
- void set_unit_db(float p_volume);
- float get_unit_db() const;
+ void set_volume_db(float p_volume);
+ float get_volume_db() const;
void set_unit_size(float p_volume);
float get_unit_size() const;
diff --git a/scene/3d/bone_attachment_3d.cpp b/scene/3d/bone_attachment_3d.cpp
index 7b0a6c7e3e..9cf10dbef1 100644
--- a/scene/3d/bone_attachment_3d.cpp
+++ b/scene/3d/bone_attachment_3d.cpp
@@ -91,7 +91,7 @@ bool BoneAttachment3D::_get(const StringName &p_path, Variant &r_ret) const {
void BoneAttachment3D::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::BOOL, "override_pose", PROPERTY_HINT_NONE, ""));
if (override_pose) {
- p_list->push_back(PropertyInfo(Variant::INT, "override_mode", PROPERTY_HINT_ENUM, "Global Pose Override, Local Pose Override, Custom Pose"));
+ p_list->push_back(PropertyInfo(Variant::INT, "override_mode", PROPERTY_HINT_ENUM, "Global Pose Override,Local Pose Override,Custom Pose"));
}
p_list->push_back(PropertyInfo(Variant::BOOL, "use_external_skeleton", PROPERTY_HINT_NONE, ""));
@@ -375,7 +375,7 @@ void BoneAttachment3D::on_bone_pose_update(int p_bone_index) {
}
}
#ifdef TOOLS_ENABLED
-void BoneAttachment3D::_notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Ref<BoneMap> p_bone_map) {
+void BoneAttachment3D::_notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map) {
const Skeleton3D *parent = nullptr;
if (use_external_skeleton) {
if (external_skeleton_node_cache.is_valid()) {
@@ -385,7 +385,7 @@ void BoneAttachment3D::_notify_skeleton_bones_renamed(Node *p_base_scene, Skelet
parent = Object::cast_to<Skeleton3D>(get_parent());
}
if (parent && parent == p_skeleton) {
- StringName bn = p_bone_map->find_profile_bone_name(bone_name);
+ StringName bn = p_rename_map[bone_name];
if (bn) {
set_bone_name(bn);
}
diff --git a/scene/3d/bone_attachment_3d.h b/scene/3d/bone_attachment_3d.h
index 2db6ba6268..81338b30e9 100644
--- a/scene/3d/bone_attachment_3d.h
+++ b/scene/3d/bone_attachment_3d.h
@@ -72,7 +72,7 @@ protected:
static void _bind_methods();
#ifdef TOOLS_ENABLED
- virtual void _notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Ref<BoneMap> p_bone_map);
+ virtual void _notify_skeleton_bones_renamed(Node *p_base_scene, Skeleton3D *p_skeleton, Dictionary p_rename_map);
#endif // TOOLS_ENABLED
public:
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 304e56326d..2a50575749 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -112,6 +112,12 @@ void Camera3D::_notification(int p_what) {
if (current || first_camera) {
viewport->_camera_3d_set(this);
}
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ viewport->connect(SNAME("size_changed"), callable_mp((Node3D *)this, &Camera3D::update_gizmos));
+ }
+#endif
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -133,6 +139,11 @@ void Camera3D::_notification(int p_what) {
}
if (viewport) {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ viewport->disconnect(SNAME("size_changed"), callable_mp((Node3D *)this, &Camera3D::update_gizmos));
+ }
+#endif
viewport->_camera_3d_remove(this);
viewport = nullptr;
}
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index a98be62dfa..66546092f2 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -30,6 +30,7 @@
#include "collision_object_3d.h"
+#include "scene/resources/shape_3d.h"
#include "scene/scene_string_names.h"
void CollisionObject3D::_notification(int p_what) {
@@ -330,7 +331,7 @@ bool CollisionObject3D::_are_collision_shapes_visible() {
void CollisionObject3D::_update_shape_data(uint32_t p_owner) {
if (_are_collision_shapes_visible()) {
if (debug_shapes_to_update.is_empty()) {
- callable_mp(this, &CollisionObject3D::_update_debug_shapes).call_deferredp({}, 0);
+ callable_mp(this, &CollisionObject3D::_update_debug_shapes).call_deferred();
}
debug_shapes_to_update.insert(p_owner);
}
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 7de685b469..5ac8535bb6 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -867,7 +867,7 @@ void CPUParticles3D::_particles_process(double p_delta) {
real_t ring_random_angle = Math::randf() * Math_TAU;
real_t ring_random_radius = Math::randf() * (emission_ring_radius - emission_ring_inner_radius) + emission_ring_inner_radius;
Vector3 axis = emission_ring_axis.normalized();
- Vector3 ortho_axis = Vector3();
+ Vector3 ortho_axis;
if (axis == Vector3(1.0, 0.0, 0.0)) {
ortho_axis = Vector3(0.0, 1.0, 0.0).cross(axis);
} else {
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index dbbf196f7a..17dfe2610e 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -176,22 +176,22 @@ void GPUParticles3D::set_draw_order(DrawOrder p_order) {
void GPUParticles3D::set_trail_enabled(bool p_enabled) {
trail_enabled = p_enabled;
- RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length);
+ RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_lifetime);
update_configuration_warnings();
}
-void GPUParticles3D::set_trail_length(double p_seconds) {
+void GPUParticles3D::set_trail_lifetime(double p_seconds) {
ERR_FAIL_COND(p_seconds < 0.001);
- trail_length = p_seconds;
- RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_length);
+ trail_lifetime = p_seconds;
+ RS::get_singleton()->particles_set_trails(particles, trail_enabled, trail_lifetime);
}
bool GPUParticles3D::is_trail_enabled() const {
return trail_enabled;
}
-double GPUParticles3D::get_trail_length() const {
- return trail_length;
+double GPUParticles3D::get_trail_lifetime() const {
+ return trail_lifetime;
}
GPUParticles3D::DrawOrder GPUParticles3D::get_draw_order() const {
@@ -272,10 +272,6 @@ bool GPUParticles3D::get_interpolate() const {
PackedStringArray GPUParticles3D::get_configuration_warnings() const {
PackedStringArray warnings = GeometryInstance3D::get_configuration_warnings();
- if (RenderingServer::get_singleton()->is_low_end()) {
- warnings.push_back(RTR("GPU-based particles are not supported by the OpenGL video driver.\nUse the CPUParticles3D node instead. You can use the \"Convert to CPUParticles3D\" option for this purpose."));
- }
-
bool meshes_found = false;
bool anim_material_found = false;
@@ -552,10 +548,10 @@ void GPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles3D::emit_particle);
ClassDB::bind_method(D_METHOD("set_trail_enabled", "enabled"), &GPUParticles3D::set_trail_enabled);
- ClassDB::bind_method(D_METHOD("set_trail_length", "secs"), &GPUParticles3D::set_trail_length);
+ ClassDB::bind_method(D_METHOD("set_trail_lifetime", "secs"), &GPUParticles3D::set_trail_lifetime);
ClassDB::bind_method(D_METHOD("is_trail_enabled"), &GPUParticles3D::is_trail_enabled);
- ClassDB::bind_method(D_METHOD("get_trail_length"), &GPUParticles3D::get_trail_length);
+ ClassDB::bind_method(D_METHOD("get_trail_lifetime"), &GPUParticles3D::get_trail_lifetime);
ClassDB::bind_method(D_METHOD("set_transform_align", "align"), &GPUParticles3D::set_transform_align);
ClassDB::bind_method(D_METHOD("get_transform_align"), &GPUParticles3D::get_transform_align);
@@ -583,7 +579,7 @@ void GPUParticles3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_align", PROPERTY_HINT_ENUM, "Disabled,Z-Billboard,Y to Velocity,Z-Billboard + Y to Velocity"), "set_transform_align", "get_transform_align");
ADD_GROUP("Trails", "trail_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trail_enabled"), "set_trail_enabled", "is_trail_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_length_secs", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_trail_length", "get_trail_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_lifetime", PROPERTY_HINT_RANGE, "0.01,10,0.01,or_greater,suffix:s"), "set_trail_lifetime", "get_trail_lifetime");
ADD_GROUP("Process Material", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticleProcessMaterial"), "set_process_material", "get_process_material");
ADD_GROUP("Draw Passes", "draw_");
@@ -627,7 +623,7 @@ GPUParticles3D::GPUParticles3D() {
set_pre_process_time(0);
set_explosiveness_ratio(0);
set_randomness_ratio(0);
- set_trail_length(0.3);
+ set_trail_lifetime(0.3);
set_visibility_aabb(AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8)));
set_use_local_coordinates(false);
set_draw_passes(1);
diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h
index ef92218e4d..d1768436e5 100644
--- a/scene/3d/gpu_particles_3d.h
+++ b/scene/3d/gpu_particles_3d.h
@@ -76,13 +76,13 @@ private:
real_t collision_base_size = 0.01;
bool trail_enabled = false;
- double trail_length = 0.3;
+ double trail_lifetime = 0.3;
TransformAlign transform_align = TRANSFORM_ALIGN_DISABLED;
Ref<Material> process_material;
- DrawOrder draw_order;
+ DrawOrder draw_order = DRAW_ORDER_INDEX;
Vector<Ref<Mesh>> draw_passes;
Ref<Skin> skin;
@@ -112,7 +112,7 @@ public:
void set_speed_scale(double p_scale);
void set_collision_base_size(real_t p_ratio);
void set_trail_enabled(bool p_enabled);
- void set_trail_length(double p_seconds);
+ void set_trail_lifetime(double p_seconds);
bool is_emitting() const;
int get_amount() const;
@@ -127,7 +127,7 @@ public:
double get_speed_scale() const;
real_t get_collision_base_size() const;
bool is_trail_enabled() const;
- double get_trail_length() const;
+ double get_trail_lifetime() const;
void set_fixed_fps(int p_count);
int get_fixed_fps() const;
diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp
index b3437c4810..476820b1c4 100644
--- a/scene/3d/gpu_particles_collision_3d.cpp
+++ b/scene/3d/gpu_particles_collision_3d.cpp
@@ -347,7 +347,9 @@ void GPUParticlesCollisionSDF3D::_compute_sdf(ComputeSDFParams *params) {
WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GPUParticlesCollisionSDF3D::_compute_sdf_z, params, params->size.z);
while (!WorkerThreadPool::get_singleton()->is_group_task_completed(group_task)) {
OS::get_singleton()->delay_usec(10000);
- bake_step_function(WorkerThreadPool::get_singleton()->get_group_processed_element_count(group_task) * 100 / params->size.z, "Baking SDF");
+ if (bake_step_function) {
+ bake_step_function(WorkerThreadPool::get_singleton()->get_group_processed_element_count(group_task) * 100 / params->size.z, "Baking SDF");
+ }
}
WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
}
@@ -490,9 +492,7 @@ Ref<Image> GPUParticlesCollisionSDF3D::bake() {
params.thickness = th;
_compute_sdf(&params);
- Ref<Image> ret;
- ret.instantiate();
- ret->create(sdf_size.x, sdf_size.y * sdf_size.z, false, Image::FORMAT_RF, cells_data);
+ Ref<Image> ret = Image::create_from_data(sdf_size.x, sdf_size.y * sdf_size.z, false, Image::FORMAT_RF, cells_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
@@ -532,7 +532,7 @@ void GPUParticlesCollisionSDF3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bake_mask_value", "layer_number"), &GPUParticlesCollisionSDF3D::get_bake_mask_value);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents", PROPERTY_HINT_RANGE, "0.01,1024,0.01,or_greater,suffix:m"), "set_extents", "get_extents");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution", PROPERTY_HINT_ENUM, "16,32,64,128,256,512,suffix:px"), "set_resolution", "get_resolution");
+ 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,suffix:m"), "set_thickness", "get_thickness");
ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_bake_mask", "get_bake_mask");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture");
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 23fd091be6..3f43e718b8 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -165,6 +165,16 @@ AABB Light3D::get_aabb() const {
return AABB();
}
+PackedStringArray Light3D::get_configuration_warnings() const {
+ PackedStringArray warnings = VisualInstance3D::get_configuration_warnings();
+
+ if (!get_scale().is_equal_approx(Vector3(1, 1, 1))) {
+ warnings.push_back(RTR("A light's scale does not affect the visual size of the light."));
+ }
+
+ return warnings;
+}
+
void Light3D::set_bake_mode(BakeMode p_mode) {
bake_mode = p_mode;
RS::get_singleton()->light_set_bake_mode(light, RS::LightBakeMode(p_mode));
@@ -451,7 +461,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) {
set_param(PARAM_SHADOW_PANCAKE_SIZE, 20.0);
set_param(PARAM_SHADOW_OPACITY, 1.0);
set_param(PARAM_SHADOW_BLUR, 1.0);
- set_param(PARAM_SHADOW_BIAS, 0.03);
+ set_param(PARAM_SHADOW_BIAS, 0.1);
set_param(PARAM_SHADOW_NORMAL_BIAS, 1.0);
set_param(PARAM_TRANSMITTANCE_BIAS, 0.05);
set_param(PARAM_SHADOW_FADE_START, 1);
@@ -561,8 +571,8 @@ DirectionalLight3D::DirectionalLight3D() :
Light3D(RenderingServer::LIGHT_DIRECTIONAL) {
set_param(PARAM_SHADOW_MAX_DISTANCE, 100);
set_param(PARAM_SHADOW_FADE_START, 0.8);
- // Increase the default shadow bias to better suit most scenes.
- set_param(PARAM_SHADOW_BIAS, 0.1);
+ // Increase the default shadow normal bias to better suit most scenes.
+ set_param(PARAM_SHADOW_NORMAL_BIAS, 2.0);
set_param(PARAM_INTENSITY, 100000.0); // Specified in Lux, approximate mid-day sun.
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
blend_splits = false;
@@ -579,7 +589,7 @@ OmniLight3D::ShadowMode OmniLight3D::get_shadow_mode() const {
}
PackedStringArray OmniLight3D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Light3D::get_configuration_warnings();
if (!has_shadow() && get_projector().is_valid()) {
warnings.push_back(RTR("Projector texture only works with shadows active."));
@@ -604,12 +614,10 @@ void OmniLight3D::_bind_methods() {
OmniLight3D::OmniLight3D() :
Light3D(RenderingServer::LIGHT_OMNI) {
set_shadow_mode(SHADOW_CUBE);
- // Increase the default shadow biases to better suit most scenes.
- set_param(PARAM_SHADOW_BIAS, 0.2);
}
PackedStringArray SpotLight3D::get_configuration_warnings() const {
- PackedStringArray warnings = Node::get_configuration_warnings();
+ PackedStringArray warnings = Light3D::get_configuration_warnings();
if (has_shadow() && get_param(PARAM_SPOT_ANGLE) >= 90.0) {
warnings.push_back(RTR("A SpotLight3D with an angle wider than 90 degrees cannot cast shadows."));
@@ -629,3 +637,9 @@ void SpotLight3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle", PROPERTY_HINT_RANGE, "0,180,0.01,degrees"), "set_param", "get_param", PARAM_SPOT_ANGLE);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "spot_angle_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), "set_param", "get_param", PARAM_SPOT_ATTENUATION);
}
+
+SpotLight3D::SpotLight3D() :
+ Light3D(RenderingServer::LIGHT_SPOT) {
+ // Decrease the default shadow bias to better suit most scenes.
+ set_param(PARAM_SHADOW_BIAS, 0.03);
+}
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index 8da45bee79..d2dfa32aac 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -147,6 +147,7 @@ public:
Color get_correlated_color() const;
virtual AABB get_aabb() const override;
+ virtual PackedStringArray get_configuration_warnings() const override;
Light3D();
~Light3D();
@@ -232,8 +233,7 @@ protected:
public:
PackedStringArray get_configuration_warnings() const override;
- SpotLight3D() :
- Light3D(RenderingServer::LIGHT_SPOT) {}
+ SpotLight3D();
};
#endif // LIGHT_3D_H
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index 3ea1de57cd..1b5427c80d 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -145,10 +145,7 @@ Array LightmapGIData::_get_light_textures_data() const {
for (int i = 0; i < texture_count; i++) {
int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture;
- Ref<Image> texture_image;
- texture_image.instantiate();
-
- texture_image->create(slice_width, slice_height * texture_slice_count, false, images[0]->get_format());
+ Ref<Image> texture_image = Image::create_empty(slice_width, slice_height * texture_slice_count, false, images[0]->get_format());
for (int j = 0; j < texture_slice_count; j++) {
texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j));
@@ -818,7 +815,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
}
md.albedo_on_uv2.instantiate();
- md.albedo_on_uv2->create(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom);
+ md.albedo_on_uv2->set_data(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom);
}
md.emission_on_uv2 = images[RS::BAKE_CHANNEL_EMISSION];
@@ -1054,7 +1051,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
} break;
case ENVIRONMENT_MODE_CUSTOM_COLOR: {
environment_image.instantiate();
- environment_image->create(128, 64, false, Image::FORMAT_RGBAF);
+ environment_image->initialize_data(128, 64, false, Image::FORMAT_RGBAF);
Color c = environment_custom_color;
c.r *= environment_custom_energy;
c.g *= environment_custom_energy;
diff --git a/scene/3d/marker_3d.cpp b/scene/3d/marker_3d.cpp
index 3987172561..8e5998d14f 100644
--- a/scene/3d/marker_3d.cpp
+++ b/scene/3d/marker_3d.cpp
@@ -30,5 +30,24 @@
#include "marker_3d.h"
+void Marker3D::set_gizmo_extents(real_t p_extents) {
+ if (Math::is_equal_approx(gizmo_extents, p_extents)) {
+ return;
+ }
+ gizmo_extents = p_extents;
+ update_gizmos();
+}
+
+real_t Marker3D::get_gizmo_extents() const {
+ return gizmo_extents;
+}
+
+void Marker3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_gizmo_extents", "extents"), &Marker3D::set_gizmo_extents);
+ ClassDB::bind_method(D_METHOD("get_gizmo_extents"), &Marker3D::get_gizmo_extents);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gizmo_extents", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater,suffix:m"), "set_gizmo_extents", "get_gizmo_extents");
+}
+
Marker3D::Marker3D() {
}
diff --git a/scene/3d/marker_3d.h b/scene/3d/marker_3d.h
index 95caa101c5..a9bd993476 100644
--- a/scene/3d/marker_3d.h
+++ b/scene/3d/marker_3d.h
@@ -36,7 +36,15 @@
class Marker3D : public Node3D {
GDCLASS(Marker3D, Node3D);
+ real_t gizmo_extents = 0.25;
+
+protected:
+ static void _bind_methods();
+
public:
+ void set_gizmo_extents(real_t p_extents);
+ real_t get_gizmo_extents() const;
+
Marker3D();
};
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index d4f60503c2..10f3ab5c79 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -33,6 +33,8 @@
#include "collision_shape_3d.h"
#include "core/core_string_names.h"
#include "physics_body_3d.h"
+#include "scene/resources/concave_polygon_shape_3d.h"
+#include "scene/resources/convex_polygon_shape_3d.h"
bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) {
//this is not _too_ bad performance wise, really. it only arrives here if the property was not set anywhere else.
@@ -50,11 +52,22 @@ bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) {
if (p_name.operator String().begins_with("surface_material_override/")) {
int idx = p_name.operator String().get_slicec('/', 1).to_int();
- if (idx >= surface_override_materials.size() || idx < 0) {
+
+ // This is a bit of a hack to ensure compatibility with older material
+ // overrides that start indexing at 0.
+ // We assume that idx 0 is always read first, if its not, this won't work.
+ if (idx == 0) {
+ old_surface_index = true;
+ }
+ if (old_surface_index) {
+ idx++;
+ }
+
+ if (idx > surface_override_materials.size() || idx < 0) {
return false;
}
- set_surface_override_material(idx, p_value);
+ set_surface_override_material(idx - 1, p_value);
return true;
}
@@ -73,7 +86,7 @@ bool MeshInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
}
if (p_name.operator String().begins_with("surface_material_override/")) {
- int idx = p_name.operator String().get_slicec('/', 1).to_int();
+ int idx = p_name.operator String().get_slicec('/', 1).to_int() - 1;
if (idx >= surface_override_materials.size() || idx < 0) {
return false;
}
@@ -96,7 +109,7 @@ void MeshInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
}
if (mesh.is_valid()) {
- for (int i = 0; i < mesh->get_surface_count(); i++) {
+ for (int i = 1; i <= mesh->get_surface_count(); i++) {
p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("%s/%d", PNAME("surface_material_override"), i), PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE));
}
}
@@ -224,7 +237,7 @@ Node *MeshInstance3D::create_trimesh_collision_node() {
return nullptr;
}
- Ref<Shape3D> shape = mesh->create_trimesh_shape();
+ Ref<ConcavePolygonShape3D> shape = mesh->create_trimesh_shape();
if (shape.is_null()) {
return nullptr;
}
@@ -254,7 +267,7 @@ Node *MeshInstance3D::create_convex_collision_node(bool p_clean, bool p_simplify
return nullptr;
}
- Ref<Shape3D> shape = mesh->create_convex_shape(p_clean, p_simplify);
+ Ref<ConvexPolygonShape3D> shape = mesh->create_convex_shape(p_clean, p_simplify);
if (shape.is_null()) {
return nullptr;
}
@@ -320,6 +333,11 @@ void MeshInstance3D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
_resolve_skeleton_path();
} break;
+ case NOTIFICATION_TRANSLATION_CHANGED: {
+ if (mesh.is_valid()) {
+ mesh->notification(NOTIFICATION_TRANSLATION_CHANGED);
+ }
+ } break;
}
}
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index caf7d25616..9e6dbaf160 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -57,6 +57,7 @@ protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ bool old_surface_index = false;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index 39068fe83c..e907b9f66f 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -79,6 +79,7 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_target_location", "location"), &NavigationAgent3D::set_target_location);
ClassDB::bind_method(D_METHOD("get_target_location"), &NavigationAgent3D::get_target_location);
+
ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent3D::get_next_location);
ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent3D::distance_to_target);
ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent3D::set_velocity);
@@ -92,6 +93,7 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_avoidance_done", "new_velocity"), &NavigationAgent3D::_avoidance_done);
ADD_GROUP("Pathfinding", "");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_location", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_target_location", "get_target_location");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_path_desired_distance", "get_path_desired_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:m"), "set_target_desired_distance", "get_target_desired_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height_offset", PROPERTY_HINT_RANGE, "-100.0,100,0.01,suffix:m"), "set_agent_height_offset", "get_agent_height_offset");
@@ -202,9 +204,9 @@ NavigationAgent3D::~NavigationAgent3D() {
void NavigationAgent3D::set_avoidance_enabled(bool p_enabled) {
avoidance_enabled = p_enabled;
if (avoidance_enabled) {
- NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, get_instance_id(), "_avoidance_done");
} else {
- NavigationServer3D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
}
}
@@ -214,7 +216,7 @@ bool NavigationAgent3D::get_avoidance_enabled() const {
void NavigationAgent3D::set_agent_parent(Node *p_agent_parent) {
// remove agent from any avoidance map before changing parent or there will be leftovers on the RVO map
- NavigationServer3D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
if (Object::cast_to<Node3D>(p_agent_parent) != nullptr) {
// place agent on navigation map first or else the RVO agent callback creation fails silently later
agent_parent = Object::cast_to<Node3D>(p_agent_parent);
@@ -495,8 +497,8 @@ void NavigationAgent3D::_request_repath() {
void NavigationAgent3D::_check_distance_to_target() {
if (!target_reached) {
if (distance_to_target() < target_desired_distance) {
- emit_signal(SNAME("target_reached"));
target_reached = true;
+ emit_signal(SNAME("target_reached"));
}
}
}
diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp
index 78fe4754ea..bee7c7f39b 100644
--- a/scene/3d/navigation_link_3d.cpp
+++ b/scene/3d/navigation_link_3d.cpp
@@ -221,6 +221,8 @@ void NavigationLink3D::_notification(int p_what) {
NavigationLink3D::NavigationLink3D() {
link = NavigationServer3D::get_singleton()->link_create();
+ NavigationServer3D::get_singleton()->link_set_owner_id(link, get_instance_id());
+
set_notify_transform(true);
}
diff --git a/scene/3d/navigation_link_3d.h b/scene/3d/navigation_link_3d.h
index 1fc03546fa..46bc6318b8 100644
--- a/scene/3d/navigation_link_3d.h
+++ b/scene/3d/navigation_link_3d.h
@@ -37,11 +37,11 @@ class NavigationLink3D : public Node3D {
GDCLASS(NavigationLink3D, Node3D);
bool enabled = true;
- RID link = RID();
+ RID link;
bool bidirectional = true;
uint32_t navigation_layers = 1;
- Vector3 end_location = Vector3();
- Vector3 start_location = Vector3();
+ Vector3 end_location;
+ Vector3 start_location;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index 06182d921c..bd96c55512 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -339,7 +339,9 @@ void NavigationRegion3D::_navigation_map_changed(RID p_map) {
NavigationRegion3D::NavigationRegion3D() {
set_notify_transform(true);
+
region = NavigationServer3D::get_singleton()->region_create();
+ NavigationServer3D::get_singleton()->region_set_owner_id(region, get_instance_id());
NavigationServer3D::get_singleton()->region_set_enter_cost(region, get_enter_cost());
NavigationServer3D::get_singleton()->region_set_travel_cost(region, get_travel_cost());
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 5f515acead..a60ccd2169 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -188,7 +188,7 @@ void Node3D::_notification(int p_what) {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SNAME("_request_gizmo_for_id"), get_instance_id());
}
#endif
} break;
@@ -253,9 +253,7 @@ Vector3 Node3D::get_global_rotation() const {
void Node3D::set_global_rotation(const Vector3 &p_euler_rad) {
Transform3D transform = get_global_transform();
- Basis new_basis = transform.get_basis();
- new_basis.set_euler(p_euler_rad);
- transform.set_basis(new_basis);
+ transform.basis = Basis::from_euler(p_euler_rad);
set_global_transform(transform);
}
@@ -394,27 +392,25 @@ Node3D::RotationEditMode Node3D::get_rotation_edit_mode() const {
return data.rotation_edit_mode;
}
-void Node3D::set_rotation_order(RotationOrder p_order) {
- Basis::EulerOrder order = Basis::EulerOrder(p_order);
-
- if (data.euler_rotation_order == order) {
+void Node3D::set_rotation_order(EulerOrder p_order) {
+ if (data.euler_rotation_order == p_order) {
return;
}
- ERR_FAIL_INDEX(int32_t(order), 6);
+ ERR_FAIL_INDEX(int32_t(p_order), 6);
bool transform_changed = false;
if (data.dirty & DIRTY_EULER_ROTATION_AND_SCALE) {
_update_rotation_and_scale();
} else if (data.dirty & DIRTY_LOCAL_TRANSFORM) {
- data.euler_rotation = Basis::from_euler(data.euler_rotation, data.euler_rotation_order).get_euler_normalized(order);
+ data.euler_rotation = Basis::from_euler(data.euler_rotation, data.euler_rotation_order).get_euler_normalized(p_order);
transform_changed = true;
} else {
data.dirty |= DIRTY_LOCAL_TRANSFORM;
transform_changed = true;
}
- data.euler_rotation_order = order;
+ data.euler_rotation_order = p_order;
if (transform_changed) {
_propagate_transform_changed(this);
@@ -425,8 +421,8 @@ void Node3D::set_rotation_order(RotationOrder p_order) {
notify_property_list_changed(); // Will change the rotation property.
}
-Node3D::RotationOrder Node3D::get_rotation_order() const {
- return RotationOrder(data.euler_rotation_order);
+EulerOrder Node3D::get_rotation_order() const {
+ return data.euler_rotation_order;
}
void Node3D::set_rotation(const Vector3 &p_euler_rad) {
@@ -486,7 +482,7 @@ void Node3D::update_gizmos() {
}
if (data.gizmos.is_empty()) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
+ get_tree()->call_group_flags(SceneTree::GROUP_CALL_DEFERRED, SceneStringNames::get_singleton()->_spatial_editor_group, SNAME("_request_gizmo_for_id"), get_instance_id());
return;
}
if (data.gizmos_dirty) {
@@ -1044,13 +1040,6 @@ void Node3D::_bind_methods() {
BIND_ENUM_CONSTANT(ROTATION_EDIT_MODE_QUATERNION);
BIND_ENUM_CONSTANT(ROTATION_EDIT_MODE_BASIS);
- BIND_ENUM_CONSTANT(ROTATION_ORDER_XYZ);
- BIND_ENUM_CONSTANT(ROTATION_ORDER_XZY);
- BIND_ENUM_CONSTANT(ROTATION_ORDER_YXZ);
- BIND_ENUM_CONSTANT(ROTATION_ORDER_YZX);
- BIND_ENUM_CONSTANT(ROTATION_ORDER_ZXY);
- BIND_ENUM_CONSTANT(ROTATION_ORDER_ZYX);
-
ADD_GROUP("Transform", "");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, "suffix:m", PROPERTY_USAGE_NO_EDITOR), "set_transform", "get_transform");
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "suffix:m", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform");
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index 90c7bc89ef..76c1e3e22c 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -61,18 +61,9 @@ public:
ROTATION_EDIT_MODE_BASIS,
};
- enum RotationOrder {
- ROTATION_ORDER_XYZ,
- ROTATION_ORDER_XZY,
- ROTATION_ORDER_YXZ,
- ROTATION_ORDER_YZX,
- ROTATION_ORDER_ZXY,
- ROTATION_ORDER_ZYX
- };
-
private:
- // For the sake of ease of use, Node3D can operate with Transforms (Basis+Origin), Quaterinon/Scale and Euler Rotation/Scale.
- // Transform and Quaterinon are stored in data.local_transform Basis (so quaternion is not really stored, but converted back/forth from 3x3 matrix on demand).
+ // For the sake of ease of use, Node3D can operate with Transforms (Basis+Origin), Quaternion/Scale and Euler Rotation/Scale.
+ // Transform and Quaternion are stored in data.local_transform Basis (so quaternion is not really stored, but converted back/forth from 3x3 matrix on demand).
// Euler needs to be kept separate because converting to Basis and back may result in a different vector (which is troublesome for users
// editing in the inspector, not only because of the numerical precision loss but because they expect these rotations to be consistent, or support
// "redundant" rotations for animation interpolation, like going from 0 to 720 degrees).
@@ -96,10 +87,11 @@ private:
mutable SelfList<Node> xform_change;
+ // This Data struct is to avoid namespace pollution in derived classes.
struct Data {
mutable Transform3D global_transform;
mutable Transform3D local_transform;
- mutable Basis::EulerOrder euler_rotation_order = Basis::EULER_ORDER_YXZ;
+ mutable EulerOrder euler_rotation_order = EulerOrder::YXZ;
mutable Vector3 euler_rotation;
mutable Vector3 scale = Vector3(1, 1, 1);
mutable RotationEditMode rotation_edit_mode = ROTATION_EDIT_MODE_EULER;
@@ -178,7 +170,7 @@ public:
void set_rotation_edit_mode(RotationEditMode p_mode);
RotationEditMode get_rotation_edit_mode() const;
- void set_rotation_order(RotationOrder p_order);
+ void set_rotation_order(EulerOrder p_order);
void set_rotation(const Vector3 &p_euler_rad);
void set_scale(const Vector3 &p_scale);
@@ -187,7 +179,7 @@ public:
Vector3 get_position() const;
- RotationOrder get_rotation_order() const;
+ EulerOrder get_rotation_order() const;
Vector3 get_rotation() const;
Vector3 get_scale() const;
@@ -276,6 +268,5 @@ public:
};
VARIANT_ENUM_CAST(Node3D::RotationEditMode)
-VARIANT_ENUM_CAST(Node3D::RotationOrder)
#endif // NODE_3D_H
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index ab4cba86fb..02ab297d8e 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -182,125 +182,31 @@ void PathFollow3D::_update_transform(bool p_update_xyz_rot) {
if (bl == 0.0) {
return;
}
- real_t bi = c->get_bake_interval();
- real_t o_next = progress + bi;
- real_t o_prev = progress - bi;
-
- if (loop) {
- o_next = Math::fposmod(o_next, bl);
- o_prev = Math::fposmod(o_prev, bl);
- } else if (rotation_mode == ROTATION_ORIENTED) {
- if (o_next >= bl) {
- o_next = bl;
- }
- if (o_prev <= 0) {
- o_prev = 0;
- }
- }
-
- Vector3 pos = c->sample_baked(progress, cubic);
- Transform3D t = get_transform();
- // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases
- // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formerly used
-
- if (rotation_mode == ROTATION_ORIENTED) {
- Vector3 forward = c->sample_baked(o_next, cubic) - pos;
-
- // Try with the previous position
- if (forward.length_squared() < CMP_EPSILON2) {
- forward = pos - c->sample_baked(o_prev, cubic);
- }
-
- if (forward.length_squared() < CMP_EPSILON2) {
- forward = Vector3(0, 0, 1);
- } else {
- forward.normalize();
- }
-
- Vector3 up = c->sample_baked_up_vector(progress, true);
- if (o_next < progress) {
- Vector3 up1 = c->sample_baked_up_vector(o_next, true);
- Vector3 axis = up.cross(up1);
-
- if (axis.length_squared() < CMP_EPSILON2) {
- axis = forward;
- } else {
- axis.normalize();
- }
-
- up.rotate(axis, up.angle_to(up1) * 0.5f);
- }
-
- Vector3 scale = t.basis.get_scale();
- Vector3 sideways = up.cross(forward).normalized();
- up = forward.cross(sideways).normalized();
-
- t.basis.set_columns(sideways, up, forward);
- t.basis.scale_local(scale);
-
- t.origin = pos + sideways * h_offset + up * v_offset;
- } else if (rotation_mode != ROTATION_NONE) {
- // perform parallel transport
- //
- // see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example
- // for a discussion about why not Frenet frame.
+ Transform3D t;
+ if (rotation_mode == ROTATION_NONE) {
+ Vector3 pos = c->sample_baked(progress, cubic);
t.origin = pos;
- if (p_update_xyz_rot && prev_offset != progress) { // Only update rotation if some parameter has changed - i.e. not on addition to scene tree.
- real_t sample_distance = bi * 0.01;
- Vector3 t_prev_pos_a = c->sample_baked(prev_offset - sample_distance, cubic);
- Vector3 t_prev_pos_b = c->sample_baked(prev_offset + sample_distance, cubic);
- Vector3 t_cur_pos_a = c->sample_baked(progress - sample_distance, cubic);
- Vector3 t_cur_pos_b = c->sample_baked(progress + sample_distance, cubic);
- Vector3 t_prev = (t_prev_pos_a - t_prev_pos_b).normalized();
- Vector3 t_cur = (t_cur_pos_a - t_cur_pos_b).normalized();
-
- Vector3 axis = t_prev.cross(t_cur);
- real_t dot = t_prev.dot(t_cur);
- real_t angle = Math::acos(CLAMP(dot, -1, 1));
-
- if (likely(!Math::is_zero_approx(angle))) {
- if (rotation_mode == ROTATION_Y) {
- // assuming we're referring to global Y-axis. is this correct?
- axis.x = 0;
- axis.z = 0;
- } else if (rotation_mode == ROTATION_XY) {
- axis.z = 0;
- } else if (rotation_mode == ROTATION_XYZ) {
- // all components are allowed
- }
+ } else {
+ t = c->sample_baked_with_rotation(progress, cubic, false);
+ Vector3 forward = t.basis.get_column(2); // Retain tangent for applying tilt
+ t = PathFollow3D::correct_posture(t, rotation_mode);
- if (likely(!Math::is_zero_approx(axis.length()))) {
- t.rotate_basis(axis.normalized(), angle);
- }
- }
+ // Apply tilt *after* correct_posture
+ if (tilt_enabled) {
+ const real_t tilt = c->sample_baked_tilt(progress);
- // do the additional tilting
- real_t tilt_angle = c->sample_baked_tilt(progress);
- Vector3 tilt_axis = t_cur; // not sure what tilt is supposed to do, is this correct??
-
- if (likely(!Math::is_zero_approx(Math::abs(tilt_angle)))) {
- if (rotation_mode == ROTATION_Y) {
- tilt_axis.x = 0;
- tilt_axis.z = 0;
- } else if (rotation_mode == ROTATION_XY) {
- tilt_axis.z = 0;
- } else if (rotation_mode == ROTATION_XYZ) {
- // all components are allowed
- }
-
- if (likely(!Math::is_zero_approx(tilt_axis.length()))) {
- t.rotate_basis(tilt_axis.normalized(), tilt_angle);
- }
- }
+ const Basis twist(forward, tilt);
+ t.basis = twist * t.basis;
}
-
- t.translate_local(Vector3(h_offset, v_offset, 0));
- } else {
- t.origin = pos + Vector3(h_offset, v_offset, 0);
}
+ Vector3 scale = get_transform().basis.get_scale();
+
+ t.translate_local(Vector3(h_offset, v_offset, 0));
+ t.basis.scale_local(scale);
+
set_transform(t);
}
@@ -358,6 +264,38 @@ PackedStringArray PathFollow3D::get_configuration_warnings() const {
return warnings;
}
+Transform3D PathFollow3D::correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode) {
+ Transform3D t = p_transform;
+
+ // Modify frame according to rotation mode.
+ if (p_rotation_mode == PathFollow3D::ROTATION_NONE) {
+ // Clear rotation.
+ t.basis = Basis();
+ } else if (p_rotation_mode == PathFollow3D::ROTATION_ORIENTED) {
+ // Y-axis always straight up.
+ Vector3 up(0.0, 1.0, 0.0);
+ Vector3 forward = t.basis.get_column(2);
+
+ t.basis = Basis::looking_at(-forward, up);
+ } else {
+ // Lock some euler axes.
+ Vector3 euler = t.basis.get_euler_normalized(EulerOrder::YXZ);
+ if (p_rotation_mode == PathFollow3D::ROTATION_Y) {
+ // Only Y-axis allowed.
+ euler[0] = 0;
+ euler[2] = 0;
+ } else if (p_rotation_mode == PathFollow3D::ROTATION_XY) {
+ // XY allowed.
+ euler[2] = 0;
+ }
+
+ Basis locked = Basis::from_euler(euler, EulerOrder::YXZ);
+ t.basis = locked;
+ }
+
+ return t;
+}
+
void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_progress", "progress"), &PathFollow3D::set_progress);
ClassDB::bind_method(D_METHOD("get_progress"), &PathFollow3D::get_progress);
@@ -380,6 +318,11 @@ void PathFollow3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_loop", "loop"), &PathFollow3D::set_loop);
ClassDB::bind_method(D_METHOD("has_loop"), &PathFollow3D::has_loop);
+ ClassDB::bind_method(D_METHOD("set_tilt_enabled", "enabled"), &PathFollow3D::set_tilt_enabled);
+ ClassDB::bind_method(D_METHOD("is_tilt_enabled"), &PathFollow3D::is_tilt_enabled);
+
+ ClassDB::bind_static_method("PathFollow3D", D_METHOD("correct_posture", "transform", "rotation_mode"), &PathFollow3D::correct_posture);
+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress", PROPERTY_HINT_RANGE, "0,10000,0.01,or_less,or_greater,suffix:m"), "set_progress", "get_progress");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "progress_ratio", PROPERTY_HINT_RANGE, "0,1,0.0001,or_less,or_greater", PROPERTY_USAGE_EDITOR), "set_progress_ratio", "get_progress_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "h_offset", PROPERTY_HINT_NONE, "suffix:m"), "set_h_offset", "get_h_offset");
@@ -387,6 +330,7 @@ void PathFollow3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tilt_enabled"), "set_tilt_enabled", "is_tilt_enabled");
BIND_ENUM_CONSTANT(ROTATION_NONE);
BIND_ENUM_CONSTANT(ROTATION_Y);
@@ -397,7 +341,6 @@ void PathFollow3D::_bind_methods() {
void PathFollow3D::set_progress(real_t p_progress) {
ERR_FAIL_COND(!isfinite(p_progress));
- prev_offset = progress;
progress = p_progress;
if (path) {
@@ -409,8 +352,6 @@ void PathFollow3D::set_progress(real_t p_progress) {
if (!Math::is_zero_approx(p_progress) && Math::is_zero_approx(progress)) {
progress = path_length;
}
- } else {
- progress = CLAMP(progress, 0, path_length);
}
}
@@ -476,3 +417,11 @@ void PathFollow3D::set_loop(bool p_loop) {
bool PathFollow3D::has_loop() const {
return loop;
}
+
+void PathFollow3D::set_tilt_enabled(bool p_enable) {
+ tilt_enabled = p_enable;
+}
+
+bool PathFollow3D::is_tilt_enabled() const {
+ return tilt_enabled;
+}
diff --git a/scene/3d/path_3d.h b/scene/3d/path_3d.h
index b161b12185..9d5f694247 100644
--- a/scene/3d/path_3d.h
+++ b/scene/3d/path_3d.h
@@ -72,14 +72,16 @@ public:
ROTATION_ORIENTED
};
+ static Transform3D correct_posture(Transform3D p_transform, PathFollow3D::RotationMode p_rotation_mode);
+
private:
Path3D *path = nullptr;
- real_t prev_offset = 0.0; // Offset during the last _update_transform.
real_t progress = 0.0;
real_t h_offset = 0.0;
real_t v_offset = 0.0;
bool cubic = true;
bool loop = true;
+ bool tilt_enabled = true;
RotationMode rotation_mode = ROTATION_XYZ;
void _update_transform(bool p_update_xyz_rot = true);
@@ -106,6 +108,9 @@ public:
void set_loop(bool p_loop);
bool has_loop() const;
+ void set_tilt_enabled(bool p_enable);
+ bool is_tilt_enabled() const;
+
void set_rotation_mode(RotationMode p_rotation_mode);
RotationMode get_rotation_mode() const;
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index d9fa37ce74..d29f337fc8 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -34,8 +34,8 @@
#include "scene/scene_string_names.h"
void PhysicsBody3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "distance", "test_only", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
- ClassDB::bind_method(D_METHOD("test_move", "from", "distance", "collision", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("move_and_collide", "motion", "test_only", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::_move, DEFVAL(false), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("test_move", "from", "motion", "collision", "safe_margin", "recovery_as_collision", "max_collisions"), &PhysicsBody3D::test_move, DEFVAL(Variant()), DEFVAL(0.001), DEFVAL(false), DEFVAL(1));
ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &PhysicsBody3D::set_axis_lock);
ClassDB::bind_method(D_METHOD("get_axis_lock", "axis"), &PhysicsBody3D::get_axis_lock);
@@ -80,19 +80,19 @@ TypedArray<PhysicsBody3D> PhysicsBody3D::get_collision_exceptions() {
void PhysicsBody3D::add_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid());
}
void PhysicsBody3D::remove_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid());
}
-Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_distance, bool p_test_only, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
- PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_distance, p_margin);
+Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_motion, bool p_test_only, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
+ PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_motion, p_margin);
parameters.max_collisions = p_max_collisions;
parameters.recovery_as_collision = p_recovery_as_collision;
@@ -169,7 +169,7 @@ bool PhysicsBody3D::move_and_collide(const PhysicsServer3D::MotionParameters &p_
return colliding;
}
-bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_distance, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
+bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision, real_t p_margin, bool p_recovery_as_collision, int p_max_collisions) {
ERR_FAIL_COND_V(!is_inside_tree(), false);
PhysicsServer3D::MotionResult *r = nullptr;
@@ -181,7 +181,7 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_distan
r = &temp_result;
}
- PhysicsServer3D::MotionParameters parameters(p_from, p_distance, p_margin);
+ PhysicsServer3D::MotionParameters parameters(p_from, p_motion, p_margin);
parameters.recovery_as_collision = p_recovery_as_collision;
return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r);
diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h
index 4b874b91d9..36b7ce774c 100644
--- a/scene/3d/physics_body_3d.h
+++ b/scene/3d/physics_body_3d.h
@@ -50,11 +50,11 @@ protected:
uint16_t locked_axis = 0;
- Ref<KinematicCollision3D> _move(const Vector3 &p_distance, bool p_test_only = false, real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
+ Ref<KinematicCollision3D> _move(const Vector3 &p_motion, bool p_test_only = false, real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
public:
bool move_and_collide(const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true);
- bool test_move(const Transform3D &p_from, const Vector3 &p_distance, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
+ bool test_move(const Transform3D &p_from, const Vector3 &p_motion, const Ref<KinematicCollision3D> &r_collision = Ref<KinematicCollision3D>(), real_t p_margin = 0.001, bool p_recovery_as_collision = false, int p_max_collisions = 1);
void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock);
bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const;
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp
index a45ef52452..45ff0a4b45 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/ray_cast_3d.cpp
@@ -516,7 +516,7 @@ void RayCast3D::_clear_debug_shape() {
MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
if (mi->is_inside_tree()) {
- mi->queue_delete();
+ mi->queue_free();
} else {
memdelete(mi);
}
diff --git a/scene/3d/remote_transform_3d.cpp b/scene/3d/remote_transform_3d.cpp
index ff05e88241..817ffbfec8 100644
--- a/scene/3d/remote_transform_3d.cpp
+++ b/scene/3d/remote_transform_3d.cpp
@@ -68,7 +68,7 @@ void RemoteTransform3D::_update_remote() {
Transform3D our_trans = get_global_transform();
if (update_remote_rotation) {
- n->set_rotation(our_trans.basis.get_euler_normalized(Basis::EulerOrder(n->get_rotation_order())));
+ n->set_rotation(our_trans.basis.get_euler_normalized(EulerOrder(n->get_rotation_order())));
}
if (update_remote_scale) {
@@ -90,7 +90,7 @@ void RemoteTransform3D::_update_remote() {
Transform3D our_trans = get_transform();
if (update_remote_rotation) {
- n->set_rotation(our_trans.basis.get_euler_normalized(Basis::EulerOrder(n->get_rotation_order())));
+ n->set_rotation(our_trans.basis.get_euler_normalized(EulerOrder(n->get_rotation_order())));
}
if (update_remote_scale) {
diff --git a/scene/3d/shape_cast_3d.cpp b/scene/3d/shape_cast_3d.cpp
index e7d1a8ec7d..267139c7d0 100644
--- a/scene/3d/shape_cast_3d.cpp
+++ b/scene/3d/shape_cast_3d.cpp
@@ -115,6 +115,7 @@ void ShapeCast3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("force_shapecast_update"), &ShapeCast3D::force_shapecast_update);
ClassDB::bind_method(D_METHOD("get_collider", "index"), &ShapeCast3D::get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_rid", "index"), &ShapeCast3D::get_collider_rid);
ClassDB::bind_method(D_METHOD("get_collider_shape", "index"), &ShapeCast3D::get_collider_shape);
ClassDB::bind_method(D_METHOD("get_collision_point", "index"), &ShapeCast3D::get_collision_point);
ClassDB::bind_method(D_METHOD("get_collision_normal", "index"), &ShapeCast3D::get_collision_normal);
@@ -282,6 +283,11 @@ Object *ShapeCast3D::get_collider(int p_idx) const {
return ObjectDB::get_instance(result[p_idx].collider_id);
}
+RID ShapeCast3D::get_collider_rid(int p_idx) const {
+ ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), RID(), "No collider RID found.");
+ return result[p_idx].rid;
+}
+
int ShapeCast3D::get_collider_shape(int p_idx) const {
ERR_FAIL_INDEX_V_MSG(p_idx, result.size(), -1, "No collider shape found.");
return result[p_idx].shape;
@@ -619,7 +625,7 @@ void ShapeCast3D::_clear_debug_shape() {
MeshInstance3D *mi = static_cast<MeshInstance3D *>(debug_shape);
if (mi->is_inside_tree()) {
- mi->queue_delete();
+ mi->queue_free();
} else {
memdelete(mi);
}
diff --git a/scene/3d/shape_cast_3d.h b/scene/3d/shape_cast_3d.h
index 2526d8d32c..abe10c9b24 100644
--- a/scene/3d/shape_cast_3d.h
+++ b/scene/3d/shape_cast_3d.h
@@ -120,6 +120,7 @@ public:
int get_collision_count() const;
Object *get_collider(int p_idx) const;
+ RID get_collider_rid(int p_idx) const;
int get_collider_shape(int p_idx) const;
Vector3 get_collision_point(int p_idx) const;
Vector3 get_collision_normal(int p_idx) const;
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index 85b2c5154b..b205c2cde0 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -541,7 +541,7 @@ void Skeleton3D::set_bone_name(int p_bone, const String &p_name) {
for (int i = 0; i < bone_size; i++) {
if (i != p_bone) {
- ERR_FAIL_COND(bones[i].name == p_name);
+ ERR_FAIL_COND_MSG(bones[i].name == p_name, "Skeleton3D: '" + get_name() + "', bone name: '" + p_name + "' is already exist.");
}
}
@@ -888,10 +888,14 @@ void _pb_start_simulation(const Skeleton3D *p_skeleton, Node *p_node, const Vect
PhysicalBone3D *pb = Object::cast_to<PhysicalBone3D>(p_node);
if (pb) {
- for (int i = p_sim_bones.size() - 1; 0 <= i; --i) {
- if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) {
- pb->set_simulate_physics(true);
- break;
+ if (p_sim_bones.is_empty()) { // If no bones is specified, activate ragdoll on full body.
+ pb->set_simulate_physics(true);
+ } else {
+ for (int i = p_sim_bones.size() - 1; 0 <= i; --i) {
+ if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) {
+ pb->set_simulate_physics(true);
+ break;
+ }
}
}
}
@@ -901,9 +905,7 @@ void Skeleton3D::physical_bones_start_simulation_on(const TypedArray<StringName>
set_physics_process_internal(false);
Vector<int> sim_bones;
- if (p_bones.size() <= 0) {
- sim_bones.push_back(0); // If no bones is specified, activate ragdoll on full body.
- } else {
+ if (p_bones.size() > 0) {
sim_bones.resize(p_bones.size());
int c = 0;
for (int i = sim_bones.size() - 1; 0 <= i; --i) {
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index 83e3369423..1814baa9e9 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -607,14 +607,14 @@ TypedArray<PhysicsBody3D> SoftBody3D::get_collision_exceptions() {
void SoftBody3D::add_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid());
}
void SoftBody3D::remove_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node);
- ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds.");
+ ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two nodes that inherit from CollisionObject3D (such as Area3D or PhysicsBody3D).");
PhysicsServer3D::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid());
}
diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp
index f855fce318..6d8ce06524 100644
--- a/scene/3d/spring_arm_3d.cpp
+++ b/scene/3d/spring_arm_3d.cpp
@@ -31,6 +31,7 @@
#include "spring_arm_3d.h"
#include "scene/3d/camera_3d.h"
+#include "scene/resources/shape_3d.h"
void SpringArm3D::_notification(int p_what) {
switch (p_what) {
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index cc69a1cc51..e488ff3059 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -191,9 +191,7 @@ void SpriteBase3D::draw_texture_rect(Ref<Texture2D> p_texture, Rect2 p_dst_rect,
uint32_t v_normal;
{
- Vector3 n = normal * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
-
- Vector2 res = n.octahedron_encode();
+ Vector2 res = normal.octahedron_encode();
uint32_t value = 0;
value |= (uint16_t)CLAMP(res.x * 65535, 0, 65535);
value |= (uint16_t)CLAMP(res.y * 65535, 0, 65535) << 16;
@@ -680,6 +678,7 @@ void Sprite3D::set_region_enabled(bool p_region) {
region = p_region;
_queue_redraw();
+ notify_property_list_changed();
}
bool Sprite3D::is_region_enabled() const {
@@ -781,6 +780,10 @@ void Sprite3D::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "frame_coords") {
p_property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS;
}
+
+ if (!region && (p_property.name == "region_rect")) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
}
void Sprite3D::_bind_methods() {
@@ -810,7 +813,7 @@ void Sprite3D::_bind_methods() {
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, "suffix:px", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords");
ADD_GROUP("Region", "region_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled");
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect", PROPERTY_HINT_NONE, "suffix:px"), "set_region_rect", "get_region_rect");
diff --git a/scene/3d/visible_on_screen_notifier_3d.cpp b/scene/3d/visible_on_screen_notifier_3d.cpp
index 2013a93e26..6d4c18a69e 100644
--- a/scene/3d/visible_on_screen_notifier_3d.cpp
+++ b/scene/3d/visible_on_screen_notifier_3d.cpp
@@ -189,7 +189,7 @@ void VisibleOnScreenEnabler3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_enable_node_path"), &VisibleOnScreenEnabler3D::get_enable_node_path);
ADD_GROUP("Enabling", "enable_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "enable_mode", PROPERTY_HINT_ENUM, "Inherit,Always,WhenPaused"), "set_enable_mode", "get_enable_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "enable_mode", PROPERTY_HINT_ENUM, "Inherit,Always,When Paused"), "set_enable_mode", "get_enable_mode");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "enable_node_path"), "set_enable_node_path", "get_enable_node_path");
BIND_ENUM_CONSTANT(ENABLE_MODE_INHERIT);
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index e93ad5ecbf..b5b37bf837 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -34,14 +34,8 @@
AABB VisualInstance3D::get_aabb() const {
AABB ret;
- if (GDVIRTUAL_CALL(_get_aabb, ret)) {
- return ret;
- }
- return AABB();
-}
-
-AABB VisualInstance3D::get_transformed_aabb() const {
- return get_global_transform().xform(get_aabb());
+ GDVIRTUAL_CALL(_get_aabb, ret);
+ return ret;
}
void VisualInstance3D::_update_visibility() {
@@ -80,10 +74,6 @@ RID VisualInstance3D::get_instance() const {
return instance;
}
-RID VisualInstance3D::_get_visual_instance_rid() const {
- return instance;
-}
-
void VisualInstance3D::set_layer_mask(uint32_t p_mask) {
layers = p_mask;
RenderingServer::get_singleton()->instance_set_layer_mask(instance, p_mask);
@@ -112,7 +102,6 @@ bool VisualInstance3D::get_layer_mask_value(int p_layer_number) const {
}
void VisualInstance3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_get_visual_instance_rid"), &VisualInstance3D::_get_visual_instance_rid);
ClassDB::bind_method(D_METHOD("set_base", "base"), &VisualInstance3D::set_base);
ClassDB::bind_method(D_METHOD("get_base"), &VisualInstance3D::get_base);
ClassDB::bind_method(D_METHOD("get_instance"), &VisualInstance3D::get_instance);
@@ -121,8 +110,6 @@ void VisualInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_layer_mask_value", "layer_number", "value"), &VisualInstance3D::set_layer_mask_value);
ClassDB::bind_method(D_METHOD("get_layer_mask_value", "layer_number"), &VisualInstance3D::get_layer_mask_value);
- ClassDB::bind_method(D_METHOD("get_transformed_aabb"), &VisualInstance3D::get_transformed_aabb);
-
GDVIRTUAL_BIND(_get_aabb);
ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask");
}
@@ -164,7 +151,7 @@ Ref<Material> GeometryInstance3D::get_material_overlay() const {
return material_overlay;
}
-void GeometryInstance3D::set_transparecy(float p_transparency) {
+void GeometryInstance3D::set_transparency(float p_transparency) {
transparency = CLAMP(p_transparency, 0.0f, 1.0f);
RS::get_singleton()->instance_geometry_set_transparency(get_instance(), transparency);
}
@@ -224,15 +211,20 @@ GeometryInstance3D::VisibilityRangeFadeMode GeometryInstance3D::get_visibility_r
}
const StringName *GeometryInstance3D::_instance_uniform_get_remap(const StringName p_name) const {
- StringName *r = instance_uniform_property_remap.getptr(p_name);
+ StringName *r = instance_shader_parameter_property_remap.getptr(p_name);
if (!r) {
String s = p_name;
+#ifndef DISABLE_DEPRECATED
if (s.begins_with("shader_uniforms/")) {
- StringName name = s.replace("shader_uniforms/", "");
- instance_uniform_property_remap[p_name] = name;
- return instance_uniform_property_remap.getptr(p_name);
+ s = s.replace("shader_uniforms/", "instance_shader_parameters/");
+ }
+#endif // DISABLE_DEPRECATED
+ if (s.begins_with("instance_shader_parameters/")) {
+ StringName pname = StringName(s);
+ StringName name = s.replace("instance_shader_parameters/", "");
+ instance_shader_parameter_property_remap[pname] = name;
+ return instance_shader_parameter_property_remap.getptr(pname);
}
-
return nullptr;
}
@@ -255,7 +247,7 @@ bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value)
set_gi_mode(GI_MODE_DYNAMIC);
return true;
}
-#endif
+#endif // DISABLE_DEPRECATED
return false;
}
@@ -278,13 +270,13 @@ void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
if (def_value.get_type() != Variant::NIL) {
has_def_value = true;
}
- if (instance_uniforms.has(pi.name)) {
+ if (instance_shader_parameters.has(pi.name)) {
pi.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE | (has_def_value ? (PROPERTY_USAGE_CHECKABLE | PROPERTY_USAGE_CHECKED) : PROPERTY_USAGE_NONE);
} else {
pi.usage = PROPERTY_USAGE_EDITOR | (has_def_value ? PROPERTY_USAGE_CHECKABLE : PROPERTY_USAGE_NONE); //do not save if not changed
}
- pi.name = "shader_uniforms/" + pi.name;
+ pi.name = "instance_shader_parameters/" + pi.name;
p_list->push_back(pi);
}
}
@@ -323,9 +315,9 @@ void GeometryInstance3D::set_instance_shader_parameter(const StringName &p_name,
if (p_value.get_type() == Variant::NIL) {
Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), p_name);
RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_name, def_value);
- instance_uniforms.erase(p_value);
+ instance_shader_parameters.erase(p_value);
} else {
- instance_uniforms[p_name] = p_value;
+ instance_shader_parameters[p_name] = p_value;
if (p_value.get_type() == Variant::OBJECT) {
RID tex_id = p_value;
RS::get_singleton()->instance_geometry_set_shader_parameter(get_instance(), p_name, tex_id);
@@ -416,7 +408,7 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lod_bias", "bias"), &GeometryInstance3D::set_lod_bias);
ClassDB::bind_method(D_METHOD("get_lod_bias"), &GeometryInstance3D::get_lod_bias);
- ClassDB::bind_method(D_METHOD("set_transparency", "transparency"), &GeometryInstance3D::set_transparecy);
+ ClassDB::bind_method(D_METHOD("set_transparency", "transparency"), &GeometryInstance3D::set_transparency);
ClassDB::bind_method(D_METHOD("get_transparency"), &GeometryInstance3D::get_transparency);
ClassDB::bind_method(D_METHOD("set_visibility_range_end_margin", "distance"), &GeometryInstance3D::set_visibility_range_end_margin);
diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h
index 4755545516..f18bff2ddc 100644
--- a/scene/3d/visual_instance_3d.h
+++ b/scene/3d/visual_instance_3d.h
@@ -40,8 +40,6 @@ class VisualInstance3D : public Node3D {
RID instance;
uint32_t layers = 1;
- RID _get_visual_instance_rid() const;
-
protected:
void _update_visibility();
@@ -60,8 +58,6 @@ public:
RID get_instance() const;
virtual AABB get_aabb() const;
- virtual AABB get_transformed_aabb() const; // helper
-
void set_base(const RID &p_base);
RID get_base() const;
@@ -121,8 +117,8 @@ private:
float lod_bias = 1.0;
- mutable HashMap<StringName, Variant> instance_uniforms;
- mutable HashMap<StringName, StringName> instance_uniform_property_remap;
+ mutable HashMap<StringName, Variant> instance_shader_parameters;
+ mutable HashMap<StringName, StringName> instance_shader_parameter_property_remap;
float extra_cull_margin = 0.0;
LightmapScale lightmap_scale = LIGHTMAP_SCALE_1X;
@@ -142,7 +138,7 @@ public:
void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting);
ShadowCastingSetting get_cast_shadows_setting() const;
- void set_transparecy(float p_transparency);
+ void set_transparency(float p_transparency);
float get_transparency() const;
void set_visibility_range_begin(float p_dist);
diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp
index 3dba0221bb..7caf2f4874 100644
--- a/scene/3d/voxel_gi.cpp
+++ b/scene/3d/voxel_gi.cpp
@@ -77,9 +77,7 @@ Dictionary VoxelGIData::_get_data() const {
d["octree_cells"] = get_octree_cells();
d["octree_data"] = get_data_cells();
if (otsize != Vector3i()) {
- Ref<Image> img;
- img.instantiate();
- img->create(otsize.x * otsize.y, otsize.z, false, Image::FORMAT_L8, get_distance_field());
+ Ref<Image> img = Image::create_from_data(otsize.x * otsize.y, otsize.z, false, Image::FORMAT_L8, get_distance_field());
Vector<uint8_t> df_png = img->save_png_to_buffer();
ERR_FAIL_COND_V(df_png.size() == 0, Dictionary());
d["octree_df_png"] = df_png;
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index 4401d22f30..05fc73306c 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -36,49 +36,37 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
-void XRCamera3D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- // need to find our XROrigin3D parent and let it know we're its camera!
- XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent());
- if (origin != nullptr) {
- origin->set_tracked_camera(this);
- }
- } break;
+void XRCamera3D::_bind_tracker() {
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL(xr_server);
- case NOTIFICATION_EXIT_TREE: {
- // need to find our XROrigin3D parent and let it know we're no longer its camera!
- XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent());
- if (origin != nullptr && origin->get_tracked_camera() == this) {
- origin->set_tracked_camera(nullptr);
- }
- } break;
+ tracker = xr_server->get_tracker(tracker_name);
+ if (tracker.is_valid()) {
+ tracker->connect("pose_changed", callable_mp(this, &XRCamera3D::_pose_changed));
+
+ Ref<XRPose> pose = tracker->get_pose(pose_name);
+ if (pose.is_valid()) {
+ set_transform(pose->get_adjusted_transform());
+ }
}
}
+void XRCamera3D::_unbind_tracker() {
+ if (tracker.is_valid()) {
+ tracker->disconnect("pose_changed", callable_mp(this, &XRCamera3D::_pose_changed));
+ }
+ tracker.unref();
+}
+
void XRCamera3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_type) {
if (p_tracker_name == tracker_name) {
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL(xr_server);
-
- tracker = xr_server->get_tracker(p_tracker_name);
- if (tracker.is_valid()) {
- tracker->connect("pose_changed", callable_mp(this, &XRCamera3D::_pose_changed));
-
- Ref<XRPose> pose = tracker->get_pose(pose_name);
- if (pose.is_valid()) {
- set_transform(pose->get_adjusted_transform());
- }
- }
+ _bind_tracker();
}
}
void XRCamera3D::_removed_tracker(const StringName p_tracker_name, int p_tracker_type) {
if (p_tracker_name == tracker_name) {
- if (tracker.is_valid()) {
- tracker->disconnect("pose_changed", callable_mp(this, &XRCamera3D::_pose_changed));
- }
- tracker.unref();
+ _unbind_tracker();
}
}
@@ -213,6 +201,9 @@ XRCamera3D::XRCamera3D() {
xr_server->connect("tracker_added", callable_mp(this, &XRCamera3D::_changed_tracker));
xr_server->connect("tracker_updated", callable_mp(this, &XRCamera3D::_changed_tracker));
xr_server->connect("tracker_removed", callable_mp(this, &XRCamera3D::_removed_tracker));
+
+ // check if our tracker already exists and if so, bind it...
+ _bind_tracker();
}
XRCamera3D::~XRCamera3D() {
@@ -372,7 +363,7 @@ void XRNode3D::_unbind_tracker() {
}
void XRNode3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_type) {
- if (p_tracker_name == p_tracker_name) {
+ if (tracker_name == p_tracker_name) {
// just in case unref our current tracker
_unbind_tracker();
@@ -382,7 +373,7 @@ void XRNode3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_t
}
void XRNode3D::_removed_tracker(const StringName p_tracker_name, int p_tracker_type) {
- if (p_tracker_name == p_tracker_name) {
+ if (tracker_name == p_tracker_name) {
// unref our tracker, it's no longer available
_unbind_tracker();
}
@@ -582,11 +573,22 @@ Plane XRAnchor3D::get_plane() const {
////////////////////////////////////////////////////////////////////////////////////////////////////
+Vector<XROrigin3D *> XROrigin3D::origin_nodes;
+
PackedStringArray XROrigin3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
if (is_visible() && is_inside_tree()) {
- if (tracked_camera == nullptr) {
+ bool has_camera = false;
+ for (int i = 0; !has_camera && i < get_child_count(); i++) {
+ XRCamera3D *camera = Object::cast_to<XRCamera3D>(get_child(i));
+ if (camera) {
+ // found it!
+ has_camera = true;
+ }
+ }
+
+ if (!has_camera) {
warnings.push_back(RTR("XROrigin3D requires an XRCamera3D child node."));
}
}
@@ -603,14 +605,10 @@ void XROrigin3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_world_scale", "world_scale"), &XROrigin3D::set_world_scale);
ClassDB::bind_method(D_METHOD("get_world_scale"), &XROrigin3D::get_world_scale);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale");
-}
-
-void XROrigin3D::set_tracked_camera(XRCamera3D *p_tracked_camera) {
- tracked_camera = p_tracked_camera;
-}
-XRCamera3D *XROrigin3D::get_tracked_camera() const {
- return tracked_camera;
+ ClassDB::bind_method(D_METHOD("set_current", "enabled"), &XROrigin3D::set_current);
+ ClassDB::bind_method(D_METHOD("is_current"), &XROrigin3D::is_current);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
}
real_t XROrigin3D::get_world_scale() const {
@@ -629,6 +627,60 @@ void XROrigin3D::set_world_scale(real_t p_world_scale) {
xr_server->set_world_scale(p_world_scale);
}
+void XROrigin3D::_set_current(bool p_enabled, bool p_update_others) {
+ // We run this logic even if current already equals p_enabled as we may have set this previously before we entered our tree.
+ // This is then called a second time on NOTIFICATION_ENTER_TREE where we actually process activating this origin node.
+ current = p_enabled;
+
+ if (!is_inside_tree() || Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+
+ // Notify us of any transform changes
+ set_notify_local_transform(current);
+ set_notify_transform(current);
+
+ // update XRServer with our current position
+ if (current) {
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL(xr_server);
+
+ xr_server->set_world_origin(get_global_transform());
+ }
+
+ // Check if we need to update our other origin nodes accordingly
+ if (p_update_others) {
+ if (current) {
+ for (int i = 0; i < origin_nodes.size(); i++) {
+ if (origin_nodes[i] != this && origin_nodes[i]->current) {
+ origin_nodes[i]->_set_current(false, false);
+ }
+ }
+ } else {
+ // We no longer have a current origin so find the first one we can make current
+ for (int i = 0; i < origin_nodes.size(); i++) {
+ if (origin_nodes[i] != this) {
+ origin_nodes[i]->_set_current(true, false);
+ return; // we are done.
+ }
+ }
+ }
+ }
+}
+
+void XROrigin3D::set_current(bool p_enabled) {
+ _set_current(p_enabled, true);
+}
+
+bool XROrigin3D::is_current() const {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // return as is
+ return current;
+ } else {
+ return current && is_inside_tree();
+ }
+}
+
void XROrigin3D::_notification(int p_what) {
// get our XRServer
XRServer *xr_server = XRServer::get_singleton();
@@ -636,34 +688,47 @@ void XROrigin3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- set_process_internal(true);
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ if (origin_nodes.is_empty()) {
+ // first entry always becomes current
+ current = true;
+ }
+
+ origin_nodes.push_back(this);
+
+ if (current) {
+ // set this again so we do whatever setup is needed.
+ set_current(true);
+ }
+ }
} break;
case NOTIFICATION_EXIT_TREE: {
- set_process_internal(false);
- } break;
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ origin_nodes.erase(this);
- case NOTIFICATION_INTERNAL_PROCESS: {
- // set our world origin to our node transform
- xr_server->set_world_origin(get_global_transform());
-
- // check if we have a primary interface
- Ref<XRInterface> xr_interface = xr_server->get_primary_interface();
- if (xr_interface.is_valid() && tracked_camera != nullptr) {
- // get our positioning transform for our headset
- Transform3D t = xr_interface->get_camera_transform();
+ if (current) {
+ // We are no longer current
+ set_current(false);
+ }
+ }
+ } break;
- // now apply this to our camera
- tracked_camera->set_transform(t);
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED:
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+ if (current && !Engine::get_singleton()->is_editor_hint()) {
+ xr_server->set_world_origin(get_global_transform());
}
} break;
}
- // send our notification to all active XE interfaces, they may need to react to it also
- for (int i = 0; i < xr_server->get_interface_count(); i++) {
- Ref<XRInterface> interface = xr_server->get_interface(i);
- if (interface.is_valid() && interface->is_initialized()) {
- interface->notification(p_what);
+ if (current) {
+ // send our notification to all active XE interfaces, they may need to react to it also
+ for (int i = 0; i < xr_server->get_interface_count(); i++) {
+ Ref<XRInterface> interface = xr_server->get_interface(i);
+ if (interface.is_valid() && interface->is_initialized()) {
+ interface->notification(p_what);
+ }
}
}
}
diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h
index ef846cc3a3..ec8e151a08 100644
--- a/scene/3d/xr_nodes.h
+++ b/scene/3d/xr_nodes.h
@@ -48,8 +48,8 @@ protected:
StringName pose_name = "default";
Ref<XRPositionalTracker> tracker;
- void _notification(int p_what);
-
+ void _bind_tracker();
+ void _unbind_tracker();
void _changed_tracker(const StringName p_tracker_name, int p_tracker_type);
void _removed_tracker(const StringName p_tracker_name, int p_tracker_type);
void _pose_changed(const Ref<XRPose> &p_pose);
@@ -180,7 +180,10 @@ class XROrigin3D : public Node3D {
GDCLASS(XROrigin3D, Node3D);
private:
- XRCamera3D *tracked_camera = nullptr;
+ bool current = false;
+ static Vector<XROrigin3D *> origin_nodes; // all origin nodes in tree
+
+ void _set_current(bool p_enabled, bool p_update_others);
protected:
void _notification(int p_what);
@@ -189,12 +192,12 @@ protected:
public:
PackedStringArray get_configuration_warnings() const override;
- void set_tracked_camera(XRCamera3D *p_tracked_camera);
- XRCamera3D *get_tracked_camera() const;
-
real_t get_world_scale() const;
void set_world_scale(real_t p_world_scale);
+ void set_current(bool p_enabled);
+ bool is_current() const;
+
XROrigin3D() {}
~XROrigin3D() {}
};