summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/area_3d.cpp69
-rw-r--r--scene/3d/area_3d.h14
-rw-r--r--scene/3d/audio_stream_player_3d.cpp6
-rw-r--r--scene/3d/collision_object_3d.cpp8
-rw-r--r--scene/3d/collision_object_3d.h4
-rw-r--r--scene/3d/physics_body_3d.cpp59
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;
}