diff options
Diffstat (limited to 'scene/3d')
-rw-r--r-- | scene/3d/area_3d.cpp | 69 | ||||
-rw-r--r-- | scene/3d/area_3d.h | 14 | ||||
-rw-r--r-- | scene/3d/audio_stream_player_3d.cpp | 6 | ||||
-rw-r--r-- | scene/3d/collision_object_3d.cpp | 8 | ||||
-rw-r--r-- | scene/3d/collision_object_3d.h | 4 | ||||
-rw-r--r-- | scene/3d/physics_body_3d.cpp | 59 |
6 files changed, 123 insertions, 37 deletions
diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index 2e917c4a42..943586f43c 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -105,6 +105,61 @@ real_t Area3D::get_priority() const { return priority; } +void Area3D::set_wind_force_magnitude(real_t p_wind_force_magnitude) { + wind_force_magnitude = p_wind_force_magnitude; + if (is_inside_tree()) { + _initialize_wind(); + } +} + +real_t Area3D::get_wind_force_magnitude() const { + return wind_force_magnitude; +} + +void Area3D::set_wind_attenuation_factor(real_t p_wind_force_attenuation_factor) { + wind_attenuation_factor = p_wind_force_attenuation_factor; + if (is_inside_tree()) { + _initialize_wind(); + } +} + +real_t Area3D::get_wind_attenuation_factor() const { + return wind_attenuation_factor; +} + +void Area3D::set_wind_source_path(const NodePath &p_wind_source_path) { + wind_source_path = p_wind_source_path; + if (is_inside_tree()) { + _initialize_wind(); + } +} + +const NodePath &Area3D::get_wind_source_path() const { + return wind_source_path; +} + +void Area3D::_initialize_wind() { + real_t temp_magnitude = 0.0; + Vector3 wind_direction(0., 0., 0.); + Vector3 wind_source(0., 0., 0.); + + // Overwrite with area-specified info if available + if (!wind_source_path.is_empty()) { + Node3D *p_wind_source = Object::cast_to<Node3D>(get_node(wind_source_path)); + ERR_FAIL_NULL(p_wind_source); + Transform3D global_transform = p_wind_source->get_transform(); + wind_direction = -global_transform.basis.get_axis(Vector3::AXIS_Z).normalized(); + wind_source = global_transform.origin; + temp_magnitude = wind_force_magnitude; + } + + // Set force, source and direction in the physics server. + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_WIND_ATTENUATION_FACTOR, wind_attenuation_factor); + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_WIND_SOURCE, wind_source); + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_WIND_DIRECTION, wind_direction); + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_WIND_FORCE_MAGNITUDE, temp_magnitude); +} + void Area3D::_body_enter_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); @@ -264,6 +319,8 @@ void Area3D::_clear_monitoring() { void Area3D::_notification(int p_what) { if (p_what == NOTIFICATION_EXIT_TREE) { _clear_monitoring(); + } else if (p_what == NOTIFICATION_ENTER_TREE) { + _initialize_wind(); } } @@ -550,6 +607,15 @@ void Area3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_priority", "priority"), &Area3D::set_priority); ClassDB::bind_method(D_METHOD("get_priority"), &Area3D::get_priority); + ClassDB::bind_method(D_METHOD("set_wind_force_magnitude", "wind_force_magnitude"), &Area3D::set_wind_force_magnitude); + ClassDB::bind_method(D_METHOD("get_wind_force_magnitude"), &Area3D::get_wind_force_magnitude); + + ClassDB::bind_method(D_METHOD("set_wind_attenuation_factor", "wind_attenuation_factor"), &Area3D::set_wind_attenuation_factor); + ClassDB::bind_method(D_METHOD("get_wind_attenuation_factor"), &Area3D::get_wind_attenuation_factor); + + ClassDB::bind_method(D_METHOD("set_wind_source_path", "wind_source_path"), &Area3D::set_wind_source_path); + ClassDB::bind_method(D_METHOD("get_wind_source_path"), &Area3D::get_wind_source_path); + ClassDB::bind_method(D_METHOD("set_monitorable", "enable"), &Area3D::set_monitorable); ClassDB::bind_method(D_METHOD("is_monitorable"), &Area3D::is_monitorable); @@ -605,6 +671,9 @@ void Area3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravity", PROPERTY_HINT_RANGE, "-32,32,0.001,or_lesser,or_greater"), "set_gravity", "get_gravity"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), "set_angular_damp", "get_angular_damp"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wind_force_magnitude", PROPERTY_HINT_RANGE, "0,10,0.001,or_greater"), "set_wind_force_magnitude", "get_wind_force_magnitude"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wind_attenuation_factor", PROPERTY_HINT_RANGE, "0.0,3.0,0.001,or_greater"), "set_wind_attenuation_factor", "get_wind_attenuation_factor"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "wind_source_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node3D"), "set_wind_source_path", "get_wind_source_path"); ADD_GROUP("Audio Bus", "audio_bus_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus"); diff --git a/scene/3d/area_3d.h b/scene/3d/area_3d.h index 5b8d612717..847d1c5966 100644 --- a/scene/3d/area_3d.h +++ b/scene/3d/area_3d.h @@ -55,6 +55,9 @@ private: real_t angular_damp = 0.1; real_t linear_damp = 0.1; int priority = 0; + real_t wind_force_magnitude = 0.0; + real_t wind_attenuation_factor = 0.0; + NodePath wind_source_path; bool monitoring = false; bool monitorable = false; bool locked = false; @@ -134,6 +137,8 @@ private: void _validate_property(PropertyInfo &property) const override; + void _initialize_wind(); + protected: void _notification(int p_what); static void _bind_methods(); @@ -163,6 +168,15 @@ public: void set_priority(real_t p_priority); real_t get_priority() const; + void set_wind_force_magnitude(real_t p_wind_force_magnitude); + real_t get_wind_force_magnitude() const; + + void set_wind_attenuation_factor(real_t p_wind_attenuation_factor); + real_t get_wind_attenuation_factor() const; + + void set_wind_source_path(const NodePath &p_wind_source_path); + const NodePath &get_wind_source_path() const; + void set_monitoring(bool p_enable); bool is_monitoring() const; diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index d2424c9a3b..3b44580264 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -624,8 +624,12 @@ void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) { } if (p_stream.is_valid()) { - stream = p_stream; stream_playback = p_stream->instance_playback(); + if (stream_playback.is_valid()) { + stream = p_stream; + } else { + stream.unref(); + } } AudioServer::get_singleton()->unlock(); diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 36d9bfba82..e2f953974a 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -254,10 +254,8 @@ void CollisionObject3D::_apply_enabled() { } } -void CollisionObject3D::_input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { - if (get_script_instance()) { - get_script_instance()->call(SceneStringNames::get_singleton()->_input_event, p_camera, p_input_event, p_pos, p_normal, p_shape); - } +void CollisionObject3D::_input_event_call(Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { + GDVIRTUAL_CALL(_input_event, p_camera, p_input_event, p_pos, p_normal, p_shape); emit_signal(SceneStringNames::get_singleton()->input_event, p_camera, p_input_event, p_pos, p_normal, p_shape); } @@ -453,7 +451,7 @@ void CollisionObject3D::_bind_methods() { ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject3D::shape_owner_clear_shapes); ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject3D::shape_find_owner); - BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "position"), PropertyInfo(Variant::VECTOR3, "normal"), PropertyInfo(Variant::INT, "shape_idx"))); + GDVIRTUAL_BIND(_input_event, "camera", "event", "position", "normal", "shape_idx"); ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "position"), PropertyInfo(Variant::VECTOR3, "normal"), PropertyInfo(Variant::INT, "shape_idx"))); ADD_SIGNAL(MethodInfo("mouse_entered")); diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index c066960eb4..1c7e205888 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -31,6 +31,7 @@ #ifndef COLLISION_OBJECT_3D_H #define COLLISION_OBJECT_3D_H +#include "scene/3d/camera_3d.h" #include "scene/3d/node_3d.h" class CollisionObject3D : public Node3D { @@ -101,7 +102,7 @@ protected: void _on_transform_changed(); friend class Viewport; - virtual void _input_event(Node *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape); + virtual void _input_event_call(Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape); virtual void _mouse_enter(); virtual void _mouse_exit(); @@ -110,6 +111,7 @@ protected: void set_only_update_transform_changes(bool p_enable); bool is_only_update_transform_changes_enabled() const; + GDVIRTUAL5(_input_event, Camera3D *, Ref<InputEvent>, Vector3, Vector3, int) public: void set_collision_layer(uint32_t p_layer); uint32_t get_collision_layer() const; diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 4c36618c99..d34331e1d8 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -1080,8 +1080,6 @@ void RigidBody3D::_reload_physics_characteristics() { #define FLOOR_ANGLE_THRESHOLD 0.01 bool CharacterBody3D::move_and_slide() { - Vector3 body_velocity_normal = linear_velocity.normalized(); - bool was_on_floor = on_floor; // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky @@ -1111,7 +1109,7 @@ bool CharacterBody3D::move_and_slide() { floor_normal = Vector3(); floor_velocity = Vector3(); - if (current_floor_velocity != Vector3() && on_floor_body.is_valid()) { + if (!current_floor_velocity.is_equal_approx(Vector3()) && on_floor_body.is_valid()) { PhysicsServer3D::MotionResult floor_result; Set<RID> exclude; exclude.insert(on_floor_body); @@ -1130,39 +1128,35 @@ bool CharacterBody3D::move_and_slide() { for (int iteration = 0; iteration < max_slides; ++iteration) { PhysicsServer3D::MotionResult result; - bool found_collision = false; - bool collided = move_and_collide(motion, result, margin, false, !sliding_enabled); - if (!collided) { - motion = Vector3(); //clear because no collision happened and motion completed - } else { - found_collision = true; - + if (collided) { motion_results.push_back(result); _set_collision_direction(result); - if (on_floor && floor_stop_on_slope) { - if ((body_velocity_normal + up_direction).length() < 0.01) { - Transform3D gt = get_global_transform(); - if (result.travel.length() > margin) { - gt.origin -= result.travel.slide(up_direction); - } else { - gt.origin -= result.travel; - } - set_global_transform(gt); - linear_velocity = Vector3(); - return true; + if (on_floor && floor_stop_on_slope && (linear_velocity.normalized() + up_direction).length() < 0.01) { + Transform3D gt = get_global_transform(); + if (result.travel.length() > margin) { + gt.origin -= result.travel.slide(up_direction); + } else { + gt.origin -= result.travel; } + set_global_transform(gt); + linear_velocity = Vector3(); + motion = Vector3(); + break; } - if (sliding_enabled || !on_floor) { - motion = result.remainder.slide(result.collision_normal); - linear_velocity = linear_velocity.slide(result.collision_normal); + if (result.remainder.is_equal_approx(Vector3())) { + motion = Vector3(); + break; + } - for (int j = 0; j < 3; j++) { - if (locked_axis & (1 << j)) { - linear_velocity[j] = 0.0; - } + if (sliding_enabled || !on_floor) { + Vector3 slide_motion = result.remainder.slide(result.collision_normal); + if (slide_motion.dot(linear_velocity) > 0.0) { + motion = slide_motion; + } else { + motion = Vector3(); } } else { motion = result.remainder; @@ -1171,12 +1165,12 @@ bool CharacterBody3D::move_and_slide() { sliding_enabled = true; - if (!found_collision || motion == Vector3()) { + if (!collided || motion.is_equal_approx(Vector3())) { break; } } - if (was_on_floor && snap != Vector3()) { + if (was_on_floor && !on_floor && !snap.is_equal_approx(Vector3())) { // Apply snap. Transform3D gt = get_global_transform(); PhysicsServer3D::MotionResult result; @@ -1213,6 +1207,11 @@ bool CharacterBody3D::move_and_slide() { linear_velocity += current_floor_velocity; } + // Reset the gravity accumulation when touching the ground. + if (on_floor && linear_velocity.dot(up_direction) <= 0) { + linear_velocity = linear_velocity.slide(up_direction); + } + return motion_results.size() > 0; } |