diff options
Diffstat (limited to 'scene/3d')
-rw-r--r-- | scene/3d/SCsub | 10 | ||||
-rw-r--r-- | scene/3d/area.cpp | 4 | ||||
-rw-r--r-- | scene/3d/arvr_nodes.cpp | 2 | ||||
-rw-r--r-- | scene/3d/audio_stream_player_3d.cpp | 149 | ||||
-rw-r--r-- | scene/3d/audio_stream_player_3d.h | 1 | ||||
-rw-r--r-- | scene/3d/collision_object.cpp | 4 | ||||
-rw-r--r-- | scene/3d/collision_shape.cpp | 2 | ||||
-rw-r--r-- | scene/3d/cpu_particles.cpp | 23 | ||||
-rw-r--r-- | scene/3d/cpu_particles.h | 4 | ||||
-rw-r--r-- | scene/3d/light.cpp | 24 | ||||
-rw-r--r-- | scene/3d/light.h | 2 | ||||
-rw-r--r-- | scene/3d/path.cpp | 2 | ||||
-rw-r--r-- | scene/3d/physics_body.cpp | 6 | ||||
-rw-r--r-- | scene/3d/remote_transform.cpp | 9 | ||||
-rw-r--r-- | scene/3d/remote_transform.h | 2 | ||||
-rw-r--r-- | scene/3d/sprite_3d.cpp | 38 | ||||
-rw-r--r-- | scene/3d/sprite_3d.h | 3 | ||||
-rw-r--r-- | scene/3d/vehicle_body.cpp | 68 | ||||
-rw-r--r-- | scene/3d/vehicle_body.h | 11 | ||||
-rw-r--r-- | scene/3d/visual_instance.cpp | 13 | ||||
-rw-r--r-- | scene/3d/world_environment.cpp | 2 |
21 files changed, 268 insertions, 111 deletions
diff --git a/scene/3d/SCsub b/scene/3d/SCsub index 200cf4316f..31a443bad1 100644 --- a/scene/3d/SCsub +++ b/scene/3d/SCsub @@ -3,10 +3,10 @@ Import('env') if env['disable_3d']: - env.scene_sources.append("3d/spatial.cpp") - env.scene_sources.append("3d/skeleton.cpp") - env.scene_sources.append("3d/particles.cpp") - env.scene_sources.append("3d/visual_instance.cpp") - env.scene_sources.append("3d/world_environment.cpp") + env.add_source_files(env.scene_sources, "spatial.cpp") + env.add_source_files(env.scene_sources, "skeleton.cpp") + env.add_source_files(env.scene_sources, "particles.cpp") + env.add_source_files(env.scene_sources, "visual_instance.cpp") + env.add_source_files(env.scene_sources, "world_environment.cpp") else: env.add_source_files(env.scene_sources, "*.cpp") diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 4247266e3d..19f43dd274 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -718,8 +718,8 @@ void Area::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_distance_scale", PROPERTY_HINT_EXP_RANGE, "0,1024,0.001,or_greater"), "set_gravity_distance_scale", "get_gravity_distance_scale"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "gravity_vec"), "set_gravity_vector", "get_gravity_vector"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_gravity", "get_gravity"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "linear_damp", PROPERTY_HINT_RANGE, "0,1024,0.001"), "set_linear_damp", "get_linear_damp"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_damp", PROPERTY_HINT_RANGE, "0,1024,0.001"), "set_angular_damp", "get_angular_damp"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); ADD_PROPERTY(PropertyInfo(Variant::INT, "priority", PROPERTY_HINT_RANGE, "0,128,1"), "set_priority", "get_priority"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitoring"), "set_monitoring", "is_monitoring"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitorable"), "set_monitorable", "is_monitorable"); diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp index dfa8fce9be..263a2d8de6 100644 --- a/scene/3d/arvr_nodes.cpp +++ b/scene/3d/arvr_nodes.cpp @@ -61,7 +61,7 @@ String ARVRCamera::get_configuration_warning() const { // must be child node of ARVROrigin! ARVROrigin *origin = Object::cast_to<ARVROrigin>(get_parent()); if (origin == NULL) { - return TTR("ARVRCamera must have an ARVROrigin node as its parent"); + return TTR("ARVRCamera must have an ARVROrigin node as its parent."); }; return String(); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index ff28f60d4f..27f16f7601 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -35,6 +35,99 @@ #include "scene/3d/listener.h" #include "scene/main/viewport.h" +// Based on "A Novel Multichannel Panning Method for Standard and Arbitrary Loudspeaker Configurations" by Ramy Sadek and Chris Kyriakakis (2004) +// Speaker-Placement Correction Amplitude Panning (SPCAP) +class Spcap { +private: + struct Speaker { + Vector3 direction; + real_t effective_number_of_speakers; // precalculated + mutable real_t squared_gain; // temporary + }; + + PoolVector<Speaker> speakers; + +public: + Spcap(unsigned int speaker_count, const Vector3 *speaker_directions) { + this->speakers.resize(speaker_count); + PoolVector<Speaker>::Write w = this->speakers.write(); + for (unsigned int speaker_num = 0; speaker_num < speaker_count; speaker_num++) { + w[speaker_num].direction = speaker_directions[speaker_num]; + w[speaker_num].squared_gain = 0.0; + w[speaker_num].effective_number_of_speakers = 0.0; + for (unsigned int other_speaker_num = 0; other_speaker_num < speaker_count; other_speaker_num++) { + w[speaker_num].effective_number_of_speakers += 0.5 * (1.0 + w[speaker_num].direction.dot(w[other_speaker_num].direction)); + } + } + } + + unsigned int get_speaker_count() const { + return (unsigned int)this->speakers.size(); + } + + Vector3 get_speaker_direction(unsigned int index) const { + return this->speakers.read()[index].direction; + } + + void calculate(const Vector3 &source_direction, real_t tightness, unsigned int volume_count, real_t *volumes) const { + PoolVector<Speaker>::Read r = this->speakers.read(); + real_t sum_squared_gains = 0.0; + for (unsigned int speaker_num = 0; speaker_num < (unsigned int)this->speakers.size(); speaker_num++) { + real_t initial_gain = 0.5 * powf(1.0 + r[speaker_num].direction.dot(source_direction), tightness) / r[speaker_num].effective_number_of_speakers; + r[speaker_num].squared_gain = initial_gain * initial_gain; + sum_squared_gains += r[speaker_num].squared_gain; + } + + for (unsigned int speaker_num = 0; speaker_num < MIN(volume_count, (unsigned int)this->speakers.size()); speaker_num++) { + volumes[speaker_num] = sqrtf(r[speaker_num].squared_gain / sum_squared_gains); + } + } +}; + +//TODO: hardcoded main speaker directions for 2, 3.1, 5.1 and 7.1 setups - these are simplified and could also be made configurable +static const Vector3 speaker_directions[7] = { + Vector3(-1.0, 0.0, -1.0).normalized(), // front-left + Vector3(1.0, 0.0, -1.0).normalized(), // front-right + Vector3(0.0, 0.0, -1.0).normalized(), // center + Vector3(-1.0, 0.0, 1.0).normalized(), // rear-left + Vector3(1.0, 0.0, 1.0).normalized(), // rear-right + Vector3(-1.0, 0.0, 0.0).normalized(), // side-left + Vector3(1.0, 0.0, 0.0).normalized(), // side-right +}; + +void AudioStreamPlayer3D::_calc_output_vol(const Vector3 &source_dir, real_t tightness, AudioStreamPlayer3D::Output &output) { + unsigned int speaker_count; // only main speakers (no LFE) + switch (AudioServer::get_singleton()->get_speaker_mode()) { + default: //fallthrough + case AudioServer::SPEAKER_MODE_STEREO: speaker_count = 2; break; + case AudioServer::SPEAKER_SURROUND_31: speaker_count = 3; break; + case AudioServer::SPEAKER_SURROUND_51: speaker_count = 5; break; + case AudioServer::SPEAKER_SURROUND_71: speaker_count = 7; break; + } + + Spcap spcap(speaker_count, speaker_directions); //TODO: should only be created/recreated once the speaker mode / speaker positions changes + real_t volumes[7]; + spcap.calculate(source_dir, tightness, speaker_count, volumes); + + switch (AudioServer::get_singleton()->get_speaker_mode()) { + case AudioServer::SPEAKER_SURROUND_71: + output.vol[3].l = volumes[5]; // side-left + output.vol[3].r = volumes[6]; // side-right + //fallthrough + case AudioServer::SPEAKER_SURROUND_51: + output.vol[2].l = volumes[3]; // rear-left + output.vol[2].r = volumes[4]; // rear-right + //fallthrough + case AudioServer::SPEAKER_SURROUND_31: + output.vol[1].r = 1.0; // LFE - always full power + output.vol[1].l = volumes[2]; // center + //fallthrough + case AudioServer::SPEAKER_MODE_STEREO: + output.vol[0].r = volumes[1]; // front-right + output.vol[0].l = volumes[0]; // front-left + } +} + void AudioStreamPlayer3D::_mix_audio() { if (!stream_playback.is_valid() || !active || @@ -381,59 +474,11 @@ void AudioStreamPlayer3D::_notification(int p_what) { output.filter_gain = Math::db2linear(db_att); - Vector3 flat_pos = local_pos; - flat_pos.y = 0; - flat_pos.normalize(); + //TODO: The lower the second parameter (tightness) the more the sound will "enclose" the listener (more undirected / playing from + // speakers not facing the source) - this could be made distance dependent. + _calc_output_vol(local_pos.normalized(), 4.0, output); unsigned int cc = AudioServer::get_singleton()->get_channel_count(); - if (cc == 1) { - // Stereo pair - float c = flat_pos.x * 0.5 + 0.5; - - output.vol[0].l = 1.0 - c; - output.vol[0].r = c; - } else { - Vector3 listenertopos = global_pos - listener_node->get_global_transform().origin; - float c = listenertopos.normalized().dot(get_global_transform().basis.get_axis(2).normalized()); //it's z negative - float angle = Math::rad2deg(Math::acos(c)); - float av = angle * (flat_pos.x < 0 ? -1 : 1) / 180.0; - - if (cc >= 1) { - // Stereo pair - float fl = Math::abs(1.0 - Math::abs(-0.8 - av)); - float fr = Math::abs(1.0 - Math::abs(0.8 - av)); - - output.vol[0].l = fl; - output.vol[0].r = fr; - } - - if (cc >= 2) { - // Center pair - float center = 1.0 - Math::sin(Math::acos(c)); - - output.vol[1].l = center; - output.vol[1].r = center; - } - - if (cc >= 3) { - // Side pair - float sleft = Math::abs(1.0 - Math::abs(-0.4 - av)); - float sright = Math::abs(1.0 - Math::abs(0.4 - av)); - - output.vol[2].l = sleft; - output.vol[2].r = sright; - } - - if (cc >= 4) { - // Rear pair - float rleft = Math::abs(1.0 - Math::abs(-0.2 - av)); - float rright = Math::abs(1.0 - Math::abs(0.2 - av)); - - output.vol[3].l = rleft; - output.vol[3].r = rright; - } - } - for (unsigned int k = 0; k < cc; k++) { output.vol[k] *= multiplier; } @@ -974,7 +1019,7 @@ void AudioStreamPlayer3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_angle_degrees", PROPERTY_HINT_RANGE, "0.1,90,0.1"), "set_emission_angle", "get_emission_angle"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "emission_angle_filter_attenuation_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_emission_angle_filter_attenuation_db", "get_emission_angle_filter_attenuation_db"); ADD_GROUP("Attenuation Filter", "attenuation_filter_"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_cutoff_hz", PROPERTY_HINT_RANGE, "50,50000,1"), "set_attenuation_filter_cutoff_hz", "get_attenuation_filter_cutoff_hz"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_attenuation_filter_cutoff_hz", "get_attenuation_filter_cutoff_hz"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation_filter_db", PROPERTY_HINT_RANGE, "-80,0,0.1"), "set_attenuation_filter_db", "get_attenuation_filter_db"); ADD_GROUP("Doppler", "doppler_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking"); diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h index 93954e758a..494aa70097 100644 --- a/scene/3d/audio_stream_player_3d.h +++ b/scene/3d/audio_stream_player_3d.h @@ -115,6 +115,7 @@ private: bool stream_paused_fade_out; StringName bus; + static void _calc_output_vol(const Vector3 &source_dir, real_t tightness, Output &output); void _mix_audio(); static void _mix_audios(void *self) { reinterpret_cast<AudioStreamPlayer3D *>(self)->_mix_audio(); } diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index fc46cf5bdb..63301fc226 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -370,8 +370,8 @@ String CollisionObject::get_configuration_warning() const { String warning = Spatial::get_configuration_warning(); if (shapes.empty()) { - if (warning == String()) { - warning += "\n"; + if (!warning.empty()) { + warning += "\n\n"; } warning += TTR("This node has no shape, so it can't collide or interact with other objects.\nConsider adding a CollisionShape or CollisionPolygon as a child to define its shape."); } diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp index 219ea56681..2b030641eb 100644 --- a/scene/3d/collision_shape.cpp +++ b/scene/3d/collision_shape.cpp @@ -120,7 +120,7 @@ String CollisionShape::get_configuration_warning() const { } if (!shape.is_valid()) { - return TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it!"); + return TTR("A shape must be provided for CollisionShape to function. Please create a shape resource for it."); } if (shape->is_class("PlaneShape")) { diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index 86b407b9e6..fc16bc36cb 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -92,6 +92,10 @@ void CPUParticles::set_randomness_ratio(float p_ratio) { randomness_ratio = p_ratio; } +void CPUParticles::set_lifetime_randomness(float p_random) { + + lifetime_randomness = p_random; +} void CPUParticles::set_use_local_coordinates(bool p_enable) { local_coords = p_enable; @@ -130,6 +134,10 @@ float CPUParticles::get_randomness_ratio() const { return randomness_ratio; } +float CPUParticles::get_lifetime_randomness() const { + + return lifetime_randomness; +} bool CPUParticles::get_use_local_coordinates() const { @@ -583,6 +591,10 @@ void CPUParticles::_particles_process(float p_delta) { } } + if (p.time * (1.0 - explosiveness_ratio) > p.lifetime) { + restart = true; + } + if (restart) { if (!emitting) { @@ -636,6 +648,7 @@ void CPUParticles::_particles_process(float p_delta) { p.custom[2] = (parameters[PARAM_ANIM_OFFSET] + tex_anim_offset) * Math::lerp(1.0f, p.anim_offset_rand, randomness[PARAM_ANIM_OFFSET]); //animation offset (0-1) p.transform = Transform(); p.time = 0; + p.lifetime = lifetime * (1.0 - Math::randf() * lifetime_randomness); p.base_color = Color(1, 1, 1, 1); switch (emission_shape) { @@ -701,6 +714,8 @@ void CPUParticles::_particles_process(float p_delta) { } else if (!p.active) { continue; + } else if (p.time > p.lifetime) { + p.active = false; } else { uint32_t alt_seed = p.seed; @@ -1059,9 +1074,6 @@ void CPUParticles::_notification(int p_what) { _set_redraw(false); } - if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { - } - if (p_what == NOTIFICATION_INTERNAL_PROCESS) { if (particles.size() == 0 || !is_visible_in_tree()) { @@ -1221,6 +1233,7 @@ void CPUParticles::convert_from_particles(Node *p_particles) { set_emission_box_extents(material->get_emission_box_extents()); set_gravity(material->get_gravity()); + set_lifetime_randomness(material->get_lifetime_randomness()); #define CONVERT_PARAM(m_param) \ set_param(m_param, material->get_param(ParticlesMaterial::m_param)); \ @@ -1255,6 +1268,7 @@ void CPUParticles::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pre_process_time", "secs"), &CPUParticles::set_pre_process_time); ClassDB::bind_method(D_METHOD("set_explosiveness_ratio", "ratio"), &CPUParticles::set_explosiveness_ratio); ClassDB::bind_method(D_METHOD("set_randomness_ratio", "ratio"), &CPUParticles::set_randomness_ratio); + ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "random"), &CPUParticles::set_lifetime_randomness); ClassDB::bind_method(D_METHOD("set_use_local_coordinates", "enable"), &CPUParticles::set_use_local_coordinates); ClassDB::bind_method(D_METHOD("set_fixed_fps", "fps"), &CPUParticles::set_fixed_fps); ClassDB::bind_method(D_METHOD("set_fractional_delta", "enable"), &CPUParticles::set_fractional_delta); @@ -1267,6 +1281,7 @@ void CPUParticles::_bind_methods() { ClassDB::bind_method(D_METHOD("get_pre_process_time"), &CPUParticles::get_pre_process_time); ClassDB::bind_method(D_METHOD("get_explosiveness_ratio"), &CPUParticles::get_explosiveness_ratio); ClassDB::bind_method(D_METHOD("get_randomness_ratio"), &CPUParticles::get_randomness_ratio); + ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &CPUParticles::get_lifetime_randomness); ClassDB::bind_method(D_METHOD("get_use_local_coordinates"), &CPUParticles::get_use_local_coordinates); ClassDB::bind_method(D_METHOD("get_fixed_fps"), &CPUParticles::get_fixed_fps); ClassDB::bind_method(D_METHOD("get_fractional_delta"), &CPUParticles::get_fractional_delta); @@ -1290,6 +1305,7 @@ void CPUParticles::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "speed_scale", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_speed_scale", "get_speed_scale"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "explosiveness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_explosiveness_ratio", "get_explosiveness_ratio"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_randomness_ratio", "get_randomness_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness"); 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("Drawing", ""); @@ -1472,6 +1488,7 @@ CPUParticles::CPUParticles() { set_pre_process_time(0); set_explosiveness_ratio(0); set_randomness_ratio(0); + set_lifetime_randomness(0); set_use_local_coordinates(true); set_draw_order(DRAW_ORDER_INDEX); diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h index 517df8490d..71de56f59e 100644 --- a/scene/3d/cpu_particles.h +++ b/scene/3d/cpu_particles.h @@ -95,6 +95,7 @@ private: float hue_rot_rand; float anim_offset_rand; float time; + float lifetime; Color base_color; uint32_t seed; @@ -137,6 +138,7 @@ private: float pre_process_time; float explosiveness_ratio; float randomness_ratio; + float lifetime_randomness; float speed_scale; bool local_coords; int fixed_fps; @@ -200,6 +202,7 @@ public: void set_pre_process_time(float p_time); void set_explosiveness_ratio(float p_ratio); void set_randomness_ratio(float p_ratio); + void set_lifetime_randomness(float p_random); void set_visibility_aabb(const AABB &p_aabb); void set_use_local_coordinates(bool p_enable); void set_speed_scale(float p_scale); @@ -211,6 +214,7 @@ public: float get_pre_process_time() const; float get_explosiveness_ratio() const; float get_randomness_ratio() const; + float get_lifetime_randomness() const; AABB get_visibility_aabb() const; bool get_use_local_coordinates() const; float get_speed_scale() const; diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index 2e64872616..85ee925248 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -51,6 +51,7 @@ void Light::set_param(Param p_param, float p_value) { if (p_param == PARAM_SPOT_ANGLE) { _change_notify("spot_angle"); + update_configuration_warning(); } else if (p_param == PARAM_RANGE) { _change_notify("omni_range"); _change_notify("spot_range"); @@ -68,6 +69,10 @@ void Light::set_shadow(bool p_enable) { shadow = p_enable; VS::get_singleton()->light_set_shadow(light, p_enable); + + if (type == VisualServer::LIGHT_SPOT) { + update_configuration_warning(); + } } bool Light::has_shadow() const { @@ -195,9 +200,6 @@ void Light::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { _update_visibility(); } - - if (p_what == NOTIFICATION_EXIT_TREE) { - } } void Light::set_editor_only(bool p_editor_only) { @@ -408,7 +410,7 @@ DirectionalLight::DirectionalLight() : set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8); set_param(PARAM_SHADOW_BIAS, 0.1); - set_param(PARAM_SHADOW_MAX_DISTANCE, 200); + set_param(PARAM_SHADOW_MAX_DISTANCE, 100); set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE, 0.25); set_shadow_mode(SHADOW_PARALLEL_4_SPLITS); set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE); @@ -465,6 +467,20 @@ OmniLight::OmniLight() : set_shadow_detail(SHADOW_DETAIL_HORIZONTAL); } +String SpotLight::get_configuration_warning() const { + String warning = Light::get_configuration_warning(); + + if (has_shadow() && get_param(PARAM_SPOT_ANGLE) >= 90.0) { + if (warning != String()) { + warning += "\n\n"; + } + + warning += TTR("A SpotLight with an angle wider than 90 degrees cannot cast shadows."); + } + + return warning; +} + void SpotLight::_bind_methods() { ADD_GROUP("Spot", "spot_"); diff --git a/scene/3d/light.h b/scene/3d/light.h index ddd5bc6b3a..5d365758b5 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -221,6 +221,8 @@ protected: static void _bind_methods(); public: + virtual String get_configuration_warning() const; + SpotLight() : Light(VisualServer::LIGHT_SPOT) {} }; diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp index 84078911cb..d55c795d38 100644 --- a/scene/3d/path.cpp +++ b/scene/3d/path.cpp @@ -270,7 +270,7 @@ String PathFollow::get_configuration_warning() const { } else { Path *path = Object::cast_to<Path>(get_parent()); if (path->get_curve().is_valid() && !path->get_curve()->is_up_vector_enabled() && rotation_mode == ROTATION_ORIENTED) { - return TTR("PathFollow ROTATION_ORIENTED requires \"Up Vector\" enabled in its parent Path's Curve resource."); + return TTR("PathFollow's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its parent Path's Curve resource."); } } diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index d3aad7000d..fa2bb300fa 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -934,7 +934,7 @@ String RigidBody::get_configuration_warning() const { 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()) { - warning += "\n"; + warning += "\n\n"; } warning += TTR("Size changes to RigidBody (in character or rigid modes) will be overridden by the physics engine when running.\nChange the size in children collision shapes instead."); } @@ -1044,10 +1044,10 @@ void RigidBody::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Z); ADD_GROUP("Linear", "linear_"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "linear_damp", PROPERTY_HINT_RANGE, "-1,128,0.01"), "set_linear_damp", "get_linear_damp"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp"); ADD_GROUP("Angular", "angular_"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_damp", PROPERTY_HINT_RANGE, "-1,128,0.01"), "set_angular_damp", "get_angular_damp"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape"))); diff --git a/scene/3d/remote_transform.cpp b/scene/3d/remote_transform.cpp index add77e0272..76b0b0c92f 100644 --- a/scene/3d/remote_transform.cpp +++ b/scene/3d/remote_transform.cpp @@ -105,7 +105,7 @@ void RemoteTransform::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_READY: { + case NOTIFICATION_ENTER_TREE: { _update_cache(); @@ -174,10 +174,14 @@ bool RemoteTransform::get_update_scale() const { return update_remote_scale; } +void RemoteTransform::force_update_cache() { + _update_cache(); +} + String RemoteTransform::get_configuration_warning() const { if (!has_node(remote_node) || !Object::cast_to<Spatial>(get_node(remote_node))) { - return TTR("Path property must point to a valid Spatial node to work."); + return TTR("The \"Remote Path\" property must point to a valid Spatial or Spatial-derived node to work."); } return String(); @@ -187,6 +191,7 @@ void RemoteTransform::_bind_methods() { ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform::set_remote_node); ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform::get_remote_node); + ClassDB::bind_method(D_METHOD("force_update_cache"), &RemoteTransform::force_update_cache); ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform::set_use_global_coordinates); ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform::get_use_global_coordinates); diff --git a/scene/3d/remote_transform.h b/scene/3d/remote_transform.h index b737a4f858..07e01284e5 100644 --- a/scene/3d/remote_transform.h +++ b/scene/3d/remote_transform.h @@ -68,6 +68,8 @@ public: void set_update_scale(const bool p_update); bool get_update_scale() const; + void force_update_cache(); + virtual String get_configuration_warning() const; RemoteTransform(); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index d0f8799a64..fc5523633d 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -558,12 +558,15 @@ Rect2 Sprite3D::get_region_rect() const { void Sprite3D::set_frame(int p_frame) { - ERR_FAIL_INDEX(p_frame, vframes * hframes); + ERR_FAIL_INDEX(p_frame, int64_t(vframes) * hframes); if (frame != p_frame) frame = p_frame; _queue_update(); + + _change_notify("frame"); + _change_notify("frame_coords"); emit_signal(SceneStringNames::get_singleton()->frame_changed); } @@ -572,6 +575,17 @@ int Sprite3D::get_frame() const { return frame; } +void Sprite3D::set_frame_coords(const Vector2 &p_coord) { + ERR_FAIL_INDEX(int(p_coord.x), vframes); + ERR_FAIL_INDEX(int(p_coord.y), hframes); + + set_frame(int(p_coord.y) * hframes + int(p_coord.x)); +} + +Vector2 Sprite3D::get_frame_coords() const { + return Vector2(frame % hframes, frame / hframes); +} + void Sprite3D::set_vframes(int p_amount) { ERR_FAIL_COND(p_amount < 1); @@ -628,10 +642,9 @@ Rect2 Sprite3D::get_item_rect() const { void Sprite3D::_validate_property(PropertyInfo &property) const { if (property.name == "frame") { - - property.hint = PROPERTY_HINT_SPRITE_FRAME; - + property.hint = PROPERTY_HINT_RANGE; property.hint_string = "0," + itos(vframes * hframes - 1) + ",1"; + property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; } } @@ -649,6 +662,9 @@ void Sprite3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_frame", "frame"), &Sprite3D::set_frame); ClassDB::bind_method(D_METHOD("get_frame"), &Sprite3D::get_frame); + ClassDB::bind_method(D_METHOD("set_frame_coords", "coords"), &Sprite3D::set_frame_coords); + ClassDB::bind_method(D_METHOD("get_frame_coords"), &Sprite3D::get_frame_coords); + ClassDB::bind_method(D_METHOD("set_vframes", "vframes"), &Sprite3D::set_vframes); ClassDB::bind_method(D_METHOD("get_vframes"), &Sprite3D::get_vframes); @@ -659,7 +675,8 @@ void Sprite3D::_bind_methods() { 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, "frame", PROPERTY_HINT_SPRITE_FRAME), "set_frame", "get_frame"); + 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_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region", "is_region"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); @@ -851,14 +868,11 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &property) const { } if (property.name == "frame") { - property.hint = PROPERTY_HINT_RANGE; - - if (frames->has_animation(animation)) { + if (frames->has_animation(animation) && frames->get_frame_count(animation) > 1) { property.hint_string = "0," + itos(frames->get_frame_count(animation) - 1) + ",1"; - } else { - property.hint_string = "0,0,0"; } + property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; } } @@ -1061,7 +1075,7 @@ StringName AnimatedSprite3D::get_animation() const { String AnimatedSprite3D::get_configuration_warning() const { 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."); + return TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames."); } return String(); @@ -1091,7 +1105,7 @@ void AnimatedSprite3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation"), "set_animation", "get_animation"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "frame", PROPERTY_HINT_SPRITE_FRAME), "set_frame", "get_frame"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing"); } diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 0e086ef31e..5ae9b153f9 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -173,6 +173,9 @@ public: void set_frame(int p_frame); int get_frame() const; + void set_frame_coords(const Vector2 &p_row); + Vector2 get_frame_coords() const; + void set_vframes(int p_amount); int get_vframes() const; diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index 89e96e0227..98e68cfbda 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -272,6 +272,20 @@ void VehicleWheel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_rpm"), &VehicleWheel::get_rpm); + ClassDB::bind_method(D_METHOD("set_engine_force", "engine_force"), &VehicleWheel::set_engine_force); + ClassDB::bind_method(D_METHOD("get_engine_force"), &VehicleWheel::get_engine_force); + + ClassDB::bind_method(D_METHOD("set_brake", "brake"), &VehicleWheel::set_brake); + ClassDB::bind_method(D_METHOD("get_brake"), &VehicleWheel::get_brake); + + ClassDB::bind_method(D_METHOD("set_steering", "steering"), &VehicleWheel::set_steering); + ClassDB::bind_method(D_METHOD("get_steering"), &VehicleWheel::get_steering); + + ADD_GROUP("Per-Wheel Motion", ""); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "engine_force", PROPERTY_HINT_RANGE, "0.00,1024.0,0.01,or_greater"), "set_engine_force", "get_engine_force"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "brake", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_brake", "get_brake"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "steering", PROPERTY_HINT_RANGE, "-180,180.0,0.01"), "set_steering", "get_steering"); + ADD_GROUP("VehicleBody Motion", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_traction"), "set_use_as_traction", "is_used_as_traction"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_as_steering"), "set_use_as_steering", "is_used_as_steering"); ADD_GROUP("Wheel", "wheel_"); @@ -288,6 +302,34 @@ void VehicleWheel::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "damping_relaxation"), "set_damping_relaxation", "get_damping_relaxation"); } +void VehicleWheel::set_engine_force(float p_engine_force) { + + m_engineForce = p_engine_force; +} + +float VehicleWheel::get_engine_force() const { + + return m_engineForce; +} + +void VehicleWheel::set_brake(float p_brake) { + + m_brake = p_brake; +} +float VehicleWheel::get_brake() const { + + return m_brake; +} + +void VehicleWheel::set_steering(float p_steering) { + + m_steering = p_steering; +} +float VehicleWheel::get_steering() const { + + return m_steering; +} + void VehicleWheel::set_use_as_traction(bool p_enable) { engine_traction = p_enable; @@ -374,10 +416,7 @@ void VehicleBody::_update_wheel(int p_idx, PhysicsDirectBodyState *s) { Vector3 fwd = up.cross(right); fwd = fwd.normalized(); - //rotate around steering over de wheelAxleWS - real_t steering = wheel.steers ? m_steeringValue : 0.0; - - Basis steeringMat(up, steering); + Basis steeringMat(up, wheel.m_steering); Basis rotatingMat(right, wheel.m_rotation); @@ -723,12 +762,11 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) { real_t rollingFriction = 0.f; if (wheelInfo.m_raycastInfo.m_isInContact) { - if (engine_force != 0.f && wheelInfo.engine_traction) { - rollingFriction = -engine_force * s->get_step(); + if (wheelInfo.m_engineForce != 0.f) { + rollingFriction = -wheelInfo.m_engineForce * s->get_step(); } else { real_t defaultRollingFrictionImpulse = 0.f; - float cbrake = MAX(wheelInfo.m_brake, brake); - real_t maxImpulse = cbrake ? cbrake : defaultRollingFrictionImpulse; + real_t maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse; btVehicleWheelContactPoint contactPt(s, wheelInfo.m_raycastInfo.m_groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, m_forwardWS[wheel], maxImpulse); rollingFriction = _calc_rolling_friction(contactPt); } @@ -886,6 +924,11 @@ void VehicleBody::_direct_state_changed(Object *p_state) { void VehicleBody::set_engine_force(float p_engine_force) { engine_force = p_engine_force; + for (int i = 0; i < wheels.size(); i++) { + VehicleWheel &wheelInfo = *wheels[i]; + if (wheelInfo.engine_traction) + wheelInfo.m_engineForce = p_engine_force; + } } float VehicleBody::get_engine_force() const { @@ -896,6 +939,10 @@ float VehicleBody::get_engine_force() const { void VehicleBody::set_brake(float p_brake) { brake = p_brake; + for (int i = 0; i < wheels.size(); i++) { + VehicleWheel &wheelInfo = *wheels[i]; + wheelInfo.m_brake = p_brake; + } } float VehicleBody::get_brake() const { @@ -905,6 +952,11 @@ float VehicleBody::get_brake() const { void VehicleBody::set_steering(float p_steering) { m_steeringValue = p_steering; + for (int i = 0; i < wheels.size(); i++) { + VehicleWheel &wheelInfo = *wheels[i]; + if (wheelInfo.steers) + wheelInfo.m_steering = p_steering; + } } float VehicleBody::get_steering() const { diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h index 9e3fe72282..914bfd54bd 100644 --- a/scene/3d/vehicle_body.h +++ b/scene/3d/vehicle_body.h @@ -70,7 +70,7 @@ class VehicleWheel : public Spatial { real_t m_deltaRotation; real_t m_rpm; real_t m_rollInfluence; - //real_t m_engineForce; + real_t m_engineForce; real_t m_brake; real_t m_clippedInvContactDotSuspension; @@ -137,6 +137,15 @@ public: float get_rpm() const; + void set_engine_force(float p_engine_force); + float get_engine_force() const; + + void set_brake(float p_brake); + float get_brake() const; + + void set_steering(float p_steering); + float get_steering() const; + String get_configuration_warning() const; VehicleWheel(); diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index 5141c84803..d1de0c56a7 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -215,17 +215,6 @@ float GeometryInstance::get_lod_max_hysteresis() const { } void GeometryInstance::_notification(int p_what) { - - if (p_what == NOTIFICATION_ENTER_WORLD) { - - if (flags[FLAG_USE_BAKED_LIGHT]) { - } - - } else if (p_what == NOTIFICATION_EXIT_WORLD) { - - if (flags[FLAG_USE_BAKED_LIGHT]) { - } - } } void GeometryInstance::set_flag(Flags p_flag, bool p_value) { @@ -236,8 +225,6 @@ void GeometryInstance::set_flag(Flags p_flag, bool p_value) { flags[p_flag] = p_value; VS::get_singleton()->instance_geometry_set_flag(get_instance(), (VS::InstanceFlags)p_flag, p_value); - if (p_flag == FLAG_USE_BAKED_LIGHT) { - } } bool GeometryInstance::get_flag(Flags p_flag) const { diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index 3cd43cbf5b..8d46b4161d 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -80,7 +80,7 @@ Ref<Environment> WorldEnvironment::get_environment() const { String WorldEnvironment::get_configuration_warning() const { if (!environment.is_valid()) { - return TTR("WorldEnvironment needs an Environment resource."); + return TTR("WorldEnvironment requires its \"Environment\" property to contain an Environment to have a visible effect."); } if (/*!is_visible_in_tree() ||*/ !is_inside_tree()) |