Add support for controlling physics nodes' behavior when disabled
New property disable_mode to set different behaviors: Remove: remove from physics simulation MakeStatic: change body mode to static (doesn't affect area and soft body) KeepActive: do nothing Extra change: Handle disable/enable node state with specific notifications, in order to differentiate global pause from disabled nodes.
This commit is contained in:
parent
92f20fd70e
commit
5cbdc7a0ac
16 changed files with 638 additions and 198 deletions
|
@ -266,6 +266,9 @@
|
|||
The physics layers this CollisionObject2D scans. Collision objects can scan one or more of 32 different layers. See also [member collision_layer].
|
||||
[b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
|
||||
</member>
|
||||
<member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="CollisionObject2D.DisableMode" default="0">
|
||||
Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes.
|
||||
</member>
|
||||
<member name="input_pickable" type="bool" setter="set_pickable" getter="is_pickable" default="true">
|
||||
If [code]true[/code], this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events. Requires at least one [code]collision_layer[/code] bit to be set.
|
||||
</member>
|
||||
|
@ -294,5 +297,16 @@
|
|||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
<constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode">
|
||||
When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [CollisionObject2D].
|
||||
Automatically re-added to the physics simulation when the [Node] is processed again.
|
||||
</constant>
|
||||
<constant name="DISABLE_MODE_MAKE_STATIC" value="1" enum="DisableMode">
|
||||
When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], make the body static. Doesn't affect [Area2D]. [PhysicsBody2D] can't be affected by forces or other bodies while static.
|
||||
Automatically set [PhysicsBody2D] back to its original mode when the [Node] is processed again.
|
||||
</constant>
|
||||
<constant name="DISABLE_MODE_KEEP_ACTIVE" value="2" enum="DisableMode">
|
||||
When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], do not affect the physics simulation.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -230,6 +230,9 @@
|
|||
The physics layers this CollisionObject3D scans. Collision objects can scan one or more of 32 different layers. See also [member collision_layer].
|
||||
[b]Note:[/b] A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
|
||||
</member>
|
||||
<member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="CollisionObject3D.DisableMode" default="0">
|
||||
Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes.
|
||||
</member>
|
||||
<member name="input_capture_on_drag" type="bool" setter="set_capture_input_on_drag" getter="get_capture_input_on_drag" default="false">
|
||||
If [code]true[/code], the [CollisionObject3D] will continue to receive input events as the mouse is dragged across its shapes.
|
||||
</member>
|
||||
|
@ -265,5 +268,16 @@
|
|||
</signal>
|
||||
</signals>
|
||||
<constants>
|
||||
<constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode">
|
||||
When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [CollisionObject3D].
|
||||
Automatically re-added to the physics simulation when the [Node] is processed again.
|
||||
</constant>
|
||||
<constant name="DISABLE_MODE_MAKE_STATIC" value="1" enum="DisableMode">
|
||||
When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], make the body static. Doesn't affect [Area2D]. [PhysicsBody3D] can't be affected by forces or other bodies while static.
|
||||
Automatically set [PhysicsBody3D] back to its original mode when the [Node] is processed again.
|
||||
</constant>
|
||||
<constant name="DISABLE_MODE_KEEP_ACTIVE" value="2" enum="DisableMode">
|
||||
When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], do not affect the physics simulation.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -894,6 +894,12 @@
|
|||
<constant name="NOTIFICATION_POST_ENTER_TREE" value="27">
|
||||
Notification received when the node is ready, just before [constant NOTIFICATION_READY] is received. Unlike the latter, it's sent every time the node enters tree, instead of only once.
|
||||
</constant>
|
||||
<constant name="NOTIFICATION_DISABLED" value="28">
|
||||
Notification received when the node is disabled. See [constant PROCESS_MODE_DISABLED].
|
||||
</constant>
|
||||
<constant name="NOTIFICATION_ENABLED" value="29">
|
||||
Notification received when the node is enabled again after being disabled. See [constant PROCESS_MODE_DISABLED].
|
||||
</constant>
|
||||
<constant name="NOTIFICATION_EDITOR_PRE_SAVE" value="9001">
|
||||
Notification received right before the scene with the node is saved in the editor. This notification is only sent in the Godot editor and will not occur in exported projects.
|
||||
</constant>
|
||||
|
|
|
@ -93,6 +93,9 @@
|
|||
</member>
|
||||
<member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01">
|
||||
</member>
|
||||
<member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="SoftBody3D.DisableMode" default="0">
|
||||
Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes.
|
||||
</member>
|
||||
<member name="drag_coefficient" type="float" setter="set_drag_coefficient" getter="get_drag_coefficient" default="0.0">
|
||||
</member>
|
||||
<member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.5">
|
||||
|
@ -113,5 +116,12 @@
|
|||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode">
|
||||
When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [SoftBody3D].
|
||||
Automatically re-added to the physics simulation when the [Node] is processed again.
|
||||
</constant>
|
||||
<constant name="DISABLE_MODE_KEEP_ACTIVE" value="1" enum="DisableMode">
|
||||
When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], do not affect the physics simulation.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "collision_object_2d.h"
|
||||
|
||||
#include "scene/scene_string_names.h"
|
||||
#include "servers/physics_server_2d.h"
|
||||
|
||||
void CollisionObject2D::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
|
@ -44,16 +43,22 @@ void CollisionObject2D::_notification(int p_what) {
|
|||
PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, global_transform);
|
||||
}
|
||||
|
||||
bool disabled = !is_enabled();
|
||||
|
||||
if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) {
|
||||
_apply_disabled();
|
||||
}
|
||||
|
||||
if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) {
|
||||
RID space = get_world_2d()->get_space();
|
||||
if (area) {
|
||||
PhysicsServer2D::get_singleton()->area_set_space(rid, space);
|
||||
} else {
|
||||
PhysicsServer2D::get_singleton()->body_set_space(rid, space);
|
||||
}
|
||||
}
|
||||
|
||||
_update_pickable();
|
||||
|
||||
//get space
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENTER_CANVAS: {
|
||||
|
@ -67,6 +72,7 @@ void CollisionObject2D::_notification(int p_what) {
|
|||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
_update_pickable();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
if (only_update_transform_changes) {
|
||||
return;
|
||||
|
@ -79,15 +85,22 @@ void CollisionObject2D::_notification(int p_what) {
|
|||
} else {
|
||||
PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, global_transform);
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
bool disabled = !is_enabled();
|
||||
|
||||
if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) {
|
||||
if (area) {
|
||||
PhysicsServer2D::get_singleton()->area_set_space(rid, RID());
|
||||
} else {
|
||||
PhysicsServer2D::get_singleton()->body_set_space(rid, RID());
|
||||
}
|
||||
}
|
||||
|
||||
if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) {
|
||||
_apply_enabled();
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_CANVAS: {
|
||||
|
@ -97,6 +110,14 @@ void CollisionObject2D::_notification(int p_what) {
|
|||
PhysicsServer2D::get_singleton()->body_attach_canvas_instance_id(rid, ObjectID());
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_DISABLED: {
|
||||
_apply_disabled();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENABLED: {
|
||||
_apply_enabled();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,6 +179,79 @@ bool CollisionObject2D::get_collision_mask_bit(int p_bit) const {
|
|||
return get_collision_mask() & (1 << p_bit);
|
||||
}
|
||||
|
||||
void CollisionObject2D::set_disable_mode(DisableMode p_mode) {
|
||||
if (disable_mode == p_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool disabled = is_inside_tree() && !is_enabled();
|
||||
|
||||
if (disabled) {
|
||||
// Cancel previous disable mode.
|
||||
_apply_enabled();
|
||||
}
|
||||
|
||||
disable_mode = p_mode;
|
||||
|
||||
if (disabled) {
|
||||
// Apply new disable mode.
|
||||
_apply_disabled();
|
||||
}
|
||||
}
|
||||
|
||||
CollisionObject2D::DisableMode CollisionObject2D::get_disable_mode() const {
|
||||
return disable_mode;
|
||||
}
|
||||
|
||||
void CollisionObject2D::_apply_disabled() {
|
||||
switch (disable_mode) {
|
||||
case DISABLE_MODE_REMOVE: {
|
||||
if (is_inside_tree()) {
|
||||
if (area) {
|
||||
PhysicsServer2D::get_singleton()->area_set_space(rid, RID());
|
||||
} else {
|
||||
PhysicsServer2D::get_singleton()->body_set_space(rid, RID());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case DISABLE_MODE_MAKE_STATIC: {
|
||||
if (!area && (body_mode != PhysicsServer2D::BODY_MODE_STATIC)) {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(rid, PhysicsServer2D::BODY_MODE_STATIC);
|
||||
}
|
||||
} break;
|
||||
|
||||
case DISABLE_MODE_KEEP_ACTIVE: {
|
||||
// Nothing to do.
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionObject2D::_apply_enabled() {
|
||||
switch (disable_mode) {
|
||||
case DISABLE_MODE_REMOVE: {
|
||||
if (is_inside_tree()) {
|
||||
RID space = get_world_2d()->get_space();
|
||||
if (area) {
|
||||
PhysicsServer2D::get_singleton()->area_set_space(rid, space);
|
||||
} else {
|
||||
PhysicsServer2D::get_singleton()->body_set_space(rid, space);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case DISABLE_MODE_MAKE_STATIC: {
|
||||
if (!area && (body_mode != PhysicsServer2D::BODY_MODE_STATIC)) {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(rid, body_mode);
|
||||
}
|
||||
} break;
|
||||
|
||||
case DISABLE_MODE_KEEP_ACTIVE: {
|
||||
// Nothing to do.
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CollisionObject2D::create_shape_owner(Object *p_owner) {
|
||||
ShapeData sd;
|
||||
uint32_t id;
|
||||
|
@ -412,6 +506,22 @@ bool CollisionObject2D::is_only_update_transform_changes_enabled() const {
|
|||
return only_update_transform_changes;
|
||||
}
|
||||
|
||||
void CollisionObject2D::set_body_mode(PhysicsServer2D::BodyMode p_mode) {
|
||||
ERR_FAIL_COND(area);
|
||||
|
||||
if (body_mode == p_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
body_mode = p_mode;
|
||||
|
||||
if (is_inside_tree() && !is_enabled() && (disable_mode == DISABLE_MODE_MAKE_STATIC)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(rid, p_mode);
|
||||
}
|
||||
|
||||
void CollisionObject2D::_update_pickable() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
|
@ -445,6 +555,8 @@ void CollisionObject2D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CollisionObject2D::get_collision_layer_bit);
|
||||
ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CollisionObject2D::set_collision_mask_bit);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CollisionObject2D::get_collision_mask_bit);
|
||||
ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &CollisionObject2D::set_disable_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_disable_mode"), &CollisionObject2D::get_disable_mode);
|
||||
ClassDB::bind_method(D_METHOD("set_pickable", "enabled"), &CollisionObject2D::set_pickable);
|
||||
ClassDB::bind_method(D_METHOD("is_pickable"), &CollisionObject2D::is_pickable);
|
||||
ClassDB::bind_method(D_METHOD("create_shape_owner", "owner"), &CollisionObject2D::create_shape_owner);
|
||||
|
@ -473,12 +585,18 @@ void CollisionObject2D::_bind_methods() {
|
|||
ADD_SIGNAL(MethodInfo("mouse_entered"));
|
||||
ADD_SIGNAL(MethodInfo("mouse_exited"));
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,MakeStatic,KeepActive"), "set_disable_mode", "get_disable_mode");
|
||||
|
||||
ADD_GROUP("Collision", "collision_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask");
|
||||
|
||||
ADD_GROUP("Input", "input_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_pickable"), "set_pickable", "is_pickable");
|
||||
|
||||
BIND_ENUM_CONSTANT(DISABLE_MODE_REMOVE);
|
||||
BIND_ENUM_CONSTANT(DISABLE_MODE_MAKE_STATIC);
|
||||
BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE);
|
||||
}
|
||||
|
||||
CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
|
||||
|
@ -493,6 +611,7 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) {
|
|||
PhysicsServer2D::get_singleton()->area_attach_object_instance_id(rid, get_instance_id());
|
||||
} else {
|
||||
PhysicsServer2D::get_singleton()->body_attach_object_instance_id(rid, get_instance_id());
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(rid, body_mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,10 +33,19 @@
|
|||
|
||||
#include "scene/2d/node_2d.h"
|
||||
#include "scene/resources/shape_2d.h"
|
||||
#include "servers/physics_server_2d.h"
|
||||
|
||||
class CollisionObject2D : public Node2D {
|
||||
GDCLASS(CollisionObject2D, Node2D);
|
||||
|
||||
public:
|
||||
enum DisableMode {
|
||||
DISABLE_MODE_REMOVE,
|
||||
DISABLE_MODE_MAKE_STATIC,
|
||||
DISABLE_MODE_KEEP_ACTIVE,
|
||||
};
|
||||
|
||||
private:
|
||||
uint32_t collision_layer = 1;
|
||||
uint32_t collision_mask = 1;
|
||||
|
||||
|
@ -44,6 +53,10 @@ class CollisionObject2D : public Node2D {
|
|||
RID rid;
|
||||
bool pickable = false;
|
||||
|
||||
DisableMode disable_mode = DISABLE_MODE_REMOVE;
|
||||
|
||||
PhysicsServer2D::BodyMode body_mode = PhysicsServer2D::BODY_MODE_STATIC;
|
||||
|
||||
struct ShapeData {
|
||||
Object *owner = nullptr;
|
||||
Transform2D xform;
|
||||
|
@ -64,6 +77,9 @@ class CollisionObject2D : public Node2D {
|
|||
Map<uint32_t, ShapeData> shapes;
|
||||
bool only_update_transform_changes = false; //this is used for sync physics in CharacterBody2D
|
||||
|
||||
void _apply_disabled();
|
||||
void _apply_enabled();
|
||||
|
||||
protected:
|
||||
CollisionObject2D(RID p_rid, bool p_area);
|
||||
|
||||
|
@ -79,6 +95,8 @@ protected:
|
|||
void set_only_update_transform_changes(bool p_enable);
|
||||
bool is_only_update_transform_changes_enabled() const;
|
||||
|
||||
void set_body_mode(PhysicsServer2D::BodyMode p_mode);
|
||||
|
||||
public:
|
||||
void set_collision_layer(uint32_t p_layer);
|
||||
uint32_t get_collision_layer() const;
|
||||
|
@ -92,6 +110,9 @@ public:
|
|||
void set_collision_mask_bit(int p_bit, bool p_value);
|
||||
bool get_collision_mask_bit(int p_bit) const;
|
||||
|
||||
void set_disable_mode(DisableMode p_mode);
|
||||
DisableMode get_disable_mode() const;
|
||||
|
||||
uint32_t create_shape_owner(Object *p_owner);
|
||||
void remove_shape_owner(uint32_t owner);
|
||||
void get_shape_owners(List<uint32_t> *r_owners);
|
||||
|
@ -131,4 +152,6 @@ public:
|
|||
~CollisionObject2D();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(CollisionObject2D::DisableMode);
|
||||
|
||||
#endif // COLLISION_OBJECT_2D_H
|
||||
|
|
|
@ -31,8 +31,9 @@
|
|||
#include "physical_bone_2d.h"
|
||||
|
||||
void PhysicalBone2D::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
|
||||
// Position the RigidBody in the correct position
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
// Position the RigidBody in the correct position.
|
||||
if (follow_bone_when_simulating) {
|
||||
_position_at_bone2d();
|
||||
}
|
||||
|
@ -41,16 +42,18 @@ void PhysicalBone2D::_notification(int p_what) {
|
|||
if (child_joint && auto_configure_joint) {
|
||||
child_joint->set_global_position(get_global_position());
|
||||
}
|
||||
} else if (p_what == NOTIFICATION_READY) {
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_READY: {
|
||||
_find_skeleton_parent();
|
||||
_find_joint_child();
|
||||
|
||||
// Configure joint
|
||||
// Configure joint.
|
||||
if (child_joint && auto_configure_joint) {
|
||||
_auto_configure_joint();
|
||||
}
|
||||
|
||||
// Simulate physics if set
|
||||
// Simulate physics if set.
|
||||
if (simulate_physics) {
|
||||
_start_physics_simulation();
|
||||
} else {
|
||||
|
@ -58,6 +61,7 @@ void PhysicalBone2D::_notification(int p_what) {
|
|||
}
|
||||
|
||||
set_physics_process_internal(true);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,16 +160,16 @@ void PhysicalBone2D::_start_physics_simulation() {
|
|||
// Apply the correct mode
|
||||
RigidBody2D::Mode rigid_mode = get_mode();
|
||||
if (rigid_mode == RigidBody2D::MODE_STATIC) {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC);
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
|
||||
} else if (rigid_mode == RigidBody2D::MODE_DYNAMIC) {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC);
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC);
|
||||
} else if (rigid_mode == RigidBody2D::MODE_KINEMATIC) {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_KINEMATIC);
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
|
||||
} else if (rigid_mode == RigidBody2D::MODE_DYNAMIC_LOCKED) {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC_LOCKED);
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED);
|
||||
} else {
|
||||
// Default to Rigid
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_DYNAMIC);
|
||||
// Default to Dynamic.
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC);
|
||||
}
|
||||
|
||||
_internal_simulate_physics = true;
|
||||
|
|
|
@ -49,7 +49,7 @@ void PhysicsBody2D::_bind_methods() {
|
|||
|
||||
PhysicsBody2D::PhysicsBody2D(PhysicsServer2D::BodyMode p_mode) :
|
||||
CollisionObject2D(PhysicsServer2D::get_singleton()->body_create(), false) {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), p_mode);
|
||||
set_body_mode(p_mode);
|
||||
set_pickable(false);
|
||||
}
|
||||
|
||||
|
@ -186,9 +186,9 @@ void StaticBody2D::set_kinematic_motion_enabled(bool p_enabled) {
|
|||
kinematic_motion = p_enabled;
|
||||
|
||||
if (kinematic_motion) {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_KINEMATIC);
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
|
||||
} else {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_STATIC);
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
|
||||
}
|
||||
|
||||
_update_kinematic_motion();
|
||||
|
@ -199,7 +199,8 @@ bool StaticBody2D::is_kinematic_motion_enabled() const {
|
|||
}
|
||||
|
||||
void StaticBody2D::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
return;
|
||||
|
@ -221,6 +222,7 @@ void StaticBody2D::_notification(int p_what) {
|
|||
set_block_transform_notify(true);
|
||||
set_global_transform(new_transform);
|
||||
set_block_transform_notify(false);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,18 +497,18 @@ void RigidBody2D::set_mode(Mode p_mode) {
|
|||
mode = p_mode;
|
||||
switch (p_mode) {
|
||||
case MODE_DYNAMIC: {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_DYNAMIC);
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC);
|
||||
} break;
|
||||
case MODE_STATIC: {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_STATIC);
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
|
||||
|
||||
} break;
|
||||
case MODE_KINEMATIC: {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_KINEMATIC);
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_KINEMATIC);
|
||||
|
||||
} break;
|
||||
case MODE_DYNAMIC_LOCKED: {
|
||||
PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED);
|
||||
set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC_LOCKED);
|
||||
|
||||
} break;
|
||||
}
|
||||
|
@ -762,18 +764,19 @@ bool RigidBody2D::is_contact_monitor_enabled() const {
|
|||
|
||||
void RigidBody2D::_notification(int p_what) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
set_notify_local_transform(true); //used for warnings and only in editor
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
|
||||
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
update_configuration_warnings();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1232,7 +1235,8 @@ void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) {
|
|||
}
|
||||
|
||||
void CharacterBody2D::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
last_valid_transform = get_global_transform();
|
||||
|
||||
// Reset move_and_slide() data.
|
||||
|
@ -1242,16 +1246,17 @@ void CharacterBody2D::_notification(int p_what) {
|
|||
on_wall = false;
|
||||
motion_results.clear();
|
||||
floor_velocity = Vector2();
|
||||
}
|
||||
} break;
|
||||
|
||||
if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
|
||||
//used by sync to physics, send the new transform to the physics
|
||||
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
|
||||
// Used by sync to physics, send the new transform to the physics.
|
||||
Transform2D new_transform = get_global_transform();
|
||||
PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
|
||||
//but then revert changes
|
||||
// But then revert changes.
|
||||
set_notify_local_transform(false);
|
||||
set_global_transform(last_valid_transform);
|
||||
set_notify_local_transform(true);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include "core/config/engine.h"
|
||||
#include "scene/scene_string_names.h"
|
||||
#include "servers/physics_server_3d.h"
|
||||
|
||||
void CollisionObject3D::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
|
@ -59,15 +58,22 @@ void CollisionObject3D::_notification(int p_what) {
|
|||
PhysicsServer3D::get_singleton()->body_set_state(rid, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
|
||||
}
|
||||
|
||||
bool disabled = !is_enabled();
|
||||
|
||||
if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) {
|
||||
_apply_disabled();
|
||||
}
|
||||
|
||||
if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) {
|
||||
RID space = get_world_3d()->get_space();
|
||||
if (area) {
|
||||
PhysicsServer3D::get_singleton()->area_set_space(rid, space);
|
||||
} else {
|
||||
PhysicsServer3D::get_singleton()->body_set_space(rid, space);
|
||||
}
|
||||
}
|
||||
|
||||
_update_pickable();
|
||||
//get space
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
@ -78,19 +84,34 @@ void CollisionObject3D::_notification(int p_what) {
|
|||
}
|
||||
|
||||
_on_transform_changed();
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
_update_pickable();
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
bool disabled = !is_enabled();
|
||||
|
||||
if (!disabled || (disable_mode != DISABLE_MODE_REMOVE)) {
|
||||
if (area) {
|
||||
PhysicsServer3D::get_singleton()->area_set_space(rid, RID());
|
||||
} else {
|
||||
PhysicsServer3D::get_singleton()->body_set_space(rid, RID());
|
||||
}
|
||||
}
|
||||
|
||||
if (disabled && (disable_mode != DISABLE_MODE_REMOVE)) {
|
||||
_apply_enabled();
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_DISABLED: {
|
||||
_apply_disabled();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENABLED: {
|
||||
_apply_enabled();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -153,6 +174,79 @@ bool CollisionObject3D::get_collision_mask_bit(int p_bit) const {
|
|||
return get_collision_mask() & (1 << p_bit);
|
||||
}
|
||||
|
||||
void CollisionObject3D::set_disable_mode(DisableMode p_mode) {
|
||||
if (disable_mode == p_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool disabled = is_inside_tree() && !is_enabled();
|
||||
|
||||
if (disabled) {
|
||||
// Cancel previous disable mode.
|
||||
_apply_enabled();
|
||||
}
|
||||
|
||||
disable_mode = p_mode;
|
||||
|
||||
if (disabled) {
|
||||
// Apply new disable mode.
|
||||
_apply_disabled();
|
||||
}
|
||||
}
|
||||
|
||||
CollisionObject3D::DisableMode CollisionObject3D::get_disable_mode() const {
|
||||
return disable_mode;
|
||||
}
|
||||
|
||||
void CollisionObject3D::_apply_disabled() {
|
||||
switch (disable_mode) {
|
||||
case DISABLE_MODE_REMOVE: {
|
||||
if (is_inside_tree()) {
|
||||
if (area) {
|
||||
PhysicsServer3D::get_singleton()->area_set_space(rid, RID());
|
||||
} else {
|
||||
PhysicsServer3D::get_singleton()->body_set_space(rid, RID());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case DISABLE_MODE_MAKE_STATIC: {
|
||||
if (!area && (body_mode != PhysicsServer3D::BODY_MODE_STATIC)) {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(rid, PhysicsServer3D::BODY_MODE_STATIC);
|
||||
}
|
||||
} break;
|
||||
|
||||
case DISABLE_MODE_KEEP_ACTIVE: {
|
||||
// Nothing to do.
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionObject3D::_apply_enabled() {
|
||||
switch (disable_mode) {
|
||||
case DISABLE_MODE_REMOVE: {
|
||||
if (is_inside_tree()) {
|
||||
RID space = get_world_3d()->get_space();
|
||||
if (area) {
|
||||
PhysicsServer3D::get_singleton()->area_set_space(rid, space);
|
||||
} else {
|
||||
PhysicsServer3D::get_singleton()->body_set_space(rid, space);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case DISABLE_MODE_MAKE_STATIC: {
|
||||
if (!area && (body_mode != PhysicsServer3D::BODY_MODE_STATIC)) {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(rid, body_mode);
|
||||
}
|
||||
} break;
|
||||
|
||||
case DISABLE_MODE_KEEP_ACTIVE: {
|
||||
// Nothing to do.
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -174,6 +268,22 @@ void CollisionObject3D::_mouse_exit() {
|
|||
emit_signal(SceneStringNames::get_singleton()->mouse_exited);
|
||||
}
|
||||
|
||||
void CollisionObject3D::set_body_mode(PhysicsServer3D::BodyMode p_mode) {
|
||||
ERR_FAIL_COND(area);
|
||||
|
||||
if (body_mode == p_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
body_mode = p_mode;
|
||||
|
||||
if (is_inside_tree() && !is_enabled() && (disable_mode == DISABLE_MODE_MAKE_STATIC)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(rid, p_mode);
|
||||
}
|
||||
|
||||
void CollisionObject3D::_update_pickable() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
|
@ -305,6 +415,8 @@ void CollisionObject3D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_collision_layer_bit", "bit"), &CollisionObject3D::get_collision_layer_bit);
|
||||
ClassDB::bind_method(D_METHOD("set_collision_mask_bit", "bit", "value"), &CollisionObject3D::set_collision_mask_bit);
|
||||
ClassDB::bind_method(D_METHOD("get_collision_mask_bit", "bit"), &CollisionObject3D::get_collision_mask_bit);
|
||||
ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &CollisionObject3D::set_disable_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_disable_mode"), &CollisionObject3D::get_disable_mode);
|
||||
ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &CollisionObject3D::set_ray_pickable);
|
||||
ClassDB::bind_method(D_METHOD("is_ray_pickable"), &CollisionObject3D::is_ray_pickable);
|
||||
ClassDB::bind_method(D_METHOD("set_capture_input_on_drag", "enable"), &CollisionObject3D::set_capture_input_on_drag);
|
||||
|
@ -332,6 +444,8 @@ void CollisionObject3D::_bind_methods() {
|
|||
ADD_SIGNAL(MethodInfo("mouse_entered"));
|
||||
ADD_SIGNAL(MethodInfo("mouse_exited"));
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,MakeStatic,KeepActive"), "set_disable_mode", "get_disable_mode");
|
||||
|
||||
ADD_GROUP("Collision", "collision_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask");
|
||||
|
@ -339,6 +453,10 @@ void CollisionObject3D::_bind_methods() {
|
|||
ADD_GROUP("Input", "input_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_ray_pickable"), "set_ray_pickable", "is_ray_pickable");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_capture_on_drag"), "set_capture_input_on_drag", "get_capture_input_on_drag");
|
||||
|
||||
BIND_ENUM_CONSTANT(DISABLE_MODE_REMOVE);
|
||||
BIND_ENUM_CONSTANT(DISABLE_MODE_MAKE_STATIC);
|
||||
BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE);
|
||||
}
|
||||
|
||||
uint32_t CollisionObject3D::create_shape_owner(Object *p_owner) {
|
||||
|
@ -540,8 +658,8 @@ CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) {
|
|||
PhysicsServer3D::get_singleton()->area_attach_object_instance_id(rid, get_instance_id());
|
||||
} else {
|
||||
PhysicsServer3D::get_singleton()->body_attach_object_instance_id(rid, get_instance_id());
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(rid, body_mode);
|
||||
}
|
||||
//set_transform_notify(true);
|
||||
}
|
||||
|
||||
void CollisionObject3D::set_capture_input_on_drag(bool p_capture) {
|
||||
|
|
|
@ -33,10 +33,19 @@
|
|||
|
||||
#include "scene/3d/node_3d.h"
|
||||
#include "scene/resources/shape_3d.h"
|
||||
#include "servers/physics_server_3d.h"
|
||||
|
||||
class CollisionObject3D : public Node3D {
|
||||
GDCLASS(CollisionObject3D, Node3D);
|
||||
|
||||
public:
|
||||
enum DisableMode {
|
||||
DISABLE_MODE_REMOVE,
|
||||
DISABLE_MODE_MAKE_STATIC,
|
||||
DISABLE_MODE_KEEP_ACTIVE,
|
||||
};
|
||||
|
||||
private:
|
||||
uint32_t collision_layer = 1;
|
||||
uint32_t collision_mask = 1;
|
||||
|
||||
|
@ -44,6 +53,10 @@ class CollisionObject3D : public Node3D {
|
|||
|
||||
RID rid;
|
||||
|
||||
DisableMode disable_mode = DISABLE_MODE_REMOVE;
|
||||
|
||||
PhysicsServer3D::BodyMode body_mode = PhysicsServer3D::BODY_MODE_STATIC;
|
||||
|
||||
struct ShapeData {
|
||||
Object *owner = nullptr;
|
||||
Transform3D xform;
|
||||
|
@ -76,6 +89,9 @@ class CollisionObject3D : public Node3D {
|
|||
void _update_debug_shapes();
|
||||
void _clear_debug_shapes();
|
||||
|
||||
void _apply_disabled();
|
||||
void _apply_enabled();
|
||||
|
||||
protected:
|
||||
CollisionObject3D(RID p_rid, bool p_area);
|
||||
|
||||
|
@ -89,6 +105,8 @@ protected:
|
|||
virtual void _mouse_enter();
|
||||
virtual void _mouse_exit();
|
||||
|
||||
void set_body_mode(PhysicsServer3D::BodyMode p_mode);
|
||||
|
||||
public:
|
||||
void set_collision_layer(uint32_t p_layer);
|
||||
uint32_t get_collision_layer() const;
|
||||
|
@ -102,6 +120,9 @@ public:
|
|||
void set_collision_mask_bit(int p_bit, bool p_value);
|
||||
bool get_collision_mask_bit(int p_bit) const;
|
||||
|
||||
void set_disable_mode(DisableMode p_mode);
|
||||
DisableMode get_disable_mode() const;
|
||||
|
||||
uint32_t create_shape_owner(Object *p_owner);
|
||||
void remove_shape_owner(uint32_t owner);
|
||||
void get_shape_owners(List<uint32_t> *r_owners);
|
||||
|
@ -138,4 +159,6 @@ public:
|
|||
~CollisionObject3D();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(CollisionObject3D::DisableMode);
|
||||
|
||||
#endif // COLLISION_OBJECT__H
|
||||
|
|
|
@ -65,7 +65,7 @@ void PhysicsBody3D::_bind_methods() {
|
|||
|
||||
PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) :
|
||||
CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(), false) {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), p_mode);
|
||||
set_body_mode(p_mode);
|
||||
}
|
||||
|
||||
PhysicsBody3D::~PhysicsBody3D() {
|
||||
|
@ -200,9 +200,9 @@ void StaticBody3D::set_kinematic_motion_enabled(bool p_enabled) {
|
|||
kinematic_motion = p_enabled;
|
||||
|
||||
if (kinematic_motion) {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC);
|
||||
set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
|
||||
} else {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC);
|
||||
set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
|
||||
}
|
||||
|
||||
_update_kinematic_motion();
|
||||
|
@ -249,7 +249,8 @@ Vector3 StaticBody3D::get_angular_velocity() const {
|
|||
}
|
||||
|
||||
void StaticBody3D::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
return;
|
||||
|
@ -278,6 +279,7 @@ void StaticBody3D::_notification(int p_what) {
|
|||
set_global_transform(new_transform);
|
||||
set_ignore_transform_notification(false);
|
||||
_on_transform_changed();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -565,18 +567,19 @@ void RigidBody3D::_direct_state_changed(Object *p_state) {
|
|||
|
||||
void RigidBody3D::_notification(int p_what) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
set_notify_local_transform(true); //used for warnings and only in editor
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
|
||||
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
update_configuration_warnings();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -584,18 +587,16 @@ void RigidBody3D::set_mode(Mode p_mode) {
|
|||
mode = p_mode;
|
||||
switch (p_mode) {
|
||||
case MODE_DYNAMIC: {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC);
|
||||
set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC);
|
||||
} break;
|
||||
case MODE_STATIC: {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC);
|
||||
|
||||
set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
|
||||
} break;
|
||||
case MODE_DYNAMIC_LOCKED: {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED);
|
||||
|
||||
set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC_LOCKED);
|
||||
} break;
|
||||
case MODE_KINEMATIC: {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC);
|
||||
set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
|
||||
} break;
|
||||
}
|
||||
update_configuration_warnings();
|
||||
|
@ -1233,7 +1234,8 @@ void CharacterBody3D::set_up_direction(const Vector3 &p_up_direction) {
|
|||
}
|
||||
|
||||
void CharacterBody3D::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
// Reset move_and_slide() data.
|
||||
on_floor = false;
|
||||
on_floor_body = RID();
|
||||
|
@ -1241,6 +1243,7 @@ void CharacterBody3D::_notification(int p_what) {
|
|||
on_wall = false;
|
||||
motion_results.clear();
|
||||
floor_velocity = Vector3();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2095,7 +2098,8 @@ void PhysicalBone3D::_notification(int p_what) {
|
|||
_reload_joint();
|
||||
}
|
||||
break;
|
||||
case NOTIFICATION_EXIT_TREE:
|
||||
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
if (parent_skeleton) {
|
||||
if (-1 != bone_id) {
|
||||
parent_skeleton->unbind_physical_bone_from_bone(bone_id);
|
||||
|
@ -2105,12 +2109,13 @@ void PhysicalBone3D::_notification(int p_what) {
|
|||
}
|
||||
parent_skeleton = nullptr;
|
||||
PhysicsServer3D::get_singleton()->joint_clear(joint);
|
||||
break;
|
||||
case NOTIFICATION_TRANSFORM_CHANGED:
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
update_offset();
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2605,7 +2610,7 @@ void PhysicalBone3D::_start_physics_simulation() {
|
|||
return;
|
||||
}
|
||||
reset_to_rest_position();
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_DYNAMIC);
|
||||
set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC);
|
||||
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
|
||||
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
|
||||
PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &PhysicalBone3D::_direct_state_changed));
|
||||
|
@ -2618,11 +2623,11 @@ void PhysicalBone3D::_stop_physics_simulation() {
|
|||
return;
|
||||
}
|
||||
if (parent_skeleton->get_animate_physical_bones()) {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC);
|
||||
set_body_mode(PhysicsServer3D::BODY_MODE_KINEMATIC);
|
||||
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer());
|
||||
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask());
|
||||
} else {
|
||||
PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC);
|
||||
set_body_mode(PhysicsServer3D::BODY_MODE_STATIC);
|
||||
PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), 0);
|
||||
PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), 0);
|
||||
}
|
||||
|
|
|
@ -266,12 +266,13 @@ void SoftBody3D::_notification(int p_what) {
|
|||
PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, space);
|
||||
prepare_physics_server();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_READY: {
|
||||
if (!parent_collision_ignore.is_empty()) {
|
||||
add_collision_exception_with(get_node(parent_collision_ignore));
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
_reset_points_offsets();
|
||||
|
@ -285,28 +286,37 @@ void SoftBody3D::_notification(int p_what) {
|
|||
set_as_top_level(true);
|
||||
set_transform(Transform3D());
|
||||
set_notify_transform(true);
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
_update_pickable();
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_WORLD: {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, RID());
|
||||
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_DISABLED: {
|
||||
if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) {
|
||||
prepare_physics_server();
|
||||
}
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENABLED: {
|
||||
if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) {
|
||||
prepare_physics_server();
|
||||
}
|
||||
} break;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
||||
if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
|
||||
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
update_configuration_warnings();
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBody3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_physics_rid"), &SoftBody3D::get_physics_rid);
|
||||
|
@ -326,6 +336,9 @@ void SoftBody3D::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftBody3D::set_parent_collision_ignore);
|
||||
ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftBody3D::get_parent_collision_ignore);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &SoftBody3D::set_disable_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_disable_mode"), &SoftBody3D::get_disable_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftBody3D::get_collision_exceptions);
|
||||
ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftBody3D::add_collision_exception_with);
|
||||
ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftBody3D::remove_collision_exception_with);
|
||||
|
@ -364,6 +377,11 @@ void SoftBody3D::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drag_coefficient", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_coefficient", "get_drag_coefficient");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ray_pickable"), "set_ray_pickable", "is_ray_pickable");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "disable_mode", PROPERTY_HINT_ENUM, "Remove,KeepActive"), "set_disable_mode", "get_disable_mode");
|
||||
|
||||
BIND_ENUM_CONSTANT(DISABLE_MODE_REMOVE);
|
||||
BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE);
|
||||
}
|
||||
|
||||
TypedArray<String> SoftBody3D::get_configuration_warnings() const {
|
||||
|
@ -421,6 +439,7 @@ void SoftBody3D::_draw_soft_mesh() {
|
|||
}
|
||||
|
||||
void SoftBody3D::prepare_physics_server() {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
if (get_mesh().is_valid()) {
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh());
|
||||
|
@ -430,8 +449,9 @@ void SoftBody3D::prepare_physics_server() {
|
|||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (get_mesh().is_valid()) {
|
||||
if (get_mesh().is_valid() && (is_enabled() || (disable_mode != DISABLE_MODE_REMOVE))) {
|
||||
become_mesh_owner();
|
||||
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh());
|
||||
RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh));
|
||||
|
@ -527,6 +547,28 @@ bool SoftBody3D::get_collision_layer_bit(int p_bit) const {
|
|||
return get_collision_layer() & (1 << p_bit);
|
||||
}
|
||||
|
||||
void SoftBody3D::set_disable_mode(DisableMode p_mode) {
|
||||
if (disable_mode == p_mode) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool inside_tree = is_inside_tree();
|
||||
|
||||
if (inside_tree && (disable_mode == DISABLE_MODE_REMOVE)) {
|
||||
prepare_physics_server();
|
||||
}
|
||||
|
||||
disable_mode = p_mode;
|
||||
|
||||
if (inside_tree && (disable_mode == DISABLE_MODE_REMOVE)) {
|
||||
prepare_physics_server();
|
||||
}
|
||||
}
|
||||
|
||||
SoftBody3D::DisableMode SoftBody3D::get_disable_mode() const {
|
||||
return disable_mode;
|
||||
}
|
||||
|
||||
void SoftBody3D::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) {
|
||||
parent_collision_ignore = p_parent_collision_ignore;
|
||||
}
|
||||
|
|
|
@ -67,6 +67,11 @@ class SoftBody3D : public MeshInstance3D {
|
|||
GDCLASS(SoftBody3D, MeshInstance3D);
|
||||
|
||||
public:
|
||||
enum DisableMode {
|
||||
DISABLE_MODE_REMOVE,
|
||||
DISABLE_MODE_KEEP_ACTIVE,
|
||||
};
|
||||
|
||||
struct PinnedPoint {
|
||||
int point_index = -1;
|
||||
NodePath spatial_attachment_path;
|
||||
|
@ -83,6 +88,8 @@ private:
|
|||
|
||||
RID physics_rid;
|
||||
|
||||
DisableMode disable_mode = DISABLE_MODE_REMOVE;
|
||||
|
||||
bool mesh_owner = false;
|
||||
uint32_t collision_mask = 1;
|
||||
uint32_t collision_layer = 1;
|
||||
|
@ -137,6 +144,9 @@ public:
|
|||
void set_collision_layer_bit(int p_bit, bool p_value);
|
||||
bool get_collision_layer_bit(int p_bit) const;
|
||||
|
||||
void set_disable_mode(DisableMode p_mode);
|
||||
DisableMode get_disable_mode() const;
|
||||
|
||||
void set_parent_collision_ignore(const NodePath &p_parent_collision_ignore);
|
||||
const NodePath &get_parent_collision_ignore() const;
|
||||
|
||||
|
@ -192,4 +202,6 @@ private:
|
|||
int _has_pinned_point(int p_point_index) const;
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(SoftBody3D::DisableMode);
|
||||
|
||||
#endif // SOFT_PHYSICS_BODY_H
|
||||
|
|
|
@ -79,7 +79,8 @@ public:
|
|||
};
|
||||
|
||||
void VehicleWheel3D::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent());
|
||||
if (!cb) {
|
||||
return;
|
||||
|
@ -91,14 +92,16 @@ void VehicleWheel3D::_notification(int p_what) {
|
|||
m_chassisConnectionPointCS = get_transform().origin;
|
||||
m_wheelDirectionCS = -get_transform().basis.get_axis(Vector3::AXIS_Y).normalized();
|
||||
m_wheelAxleCS = get_transform().basis.get_axis(Vector3::AXIS_X).normalized();
|
||||
}
|
||||
if (p_what == NOTIFICATION_EXIT_TREE) {
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
VehicleBody3D *cb = Object::cast_to<VehicleBody3D>(get_parent());
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
cb->wheels.erase(this);
|
||||
body = nullptr;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -402,6 +402,7 @@ void Node::set_process_mode(ProcessMode p_mode) {
|
|||
}
|
||||
|
||||
bool prev_can_process = can_process();
|
||||
bool prev_enabled = _is_enabled();
|
||||
|
||||
data.process_mode = p_mode;
|
||||
|
||||
|
@ -416,6 +417,7 @@ void Node::set_process_mode(ProcessMode p_mode) {
|
|||
}
|
||||
|
||||
bool next_can_process = can_process();
|
||||
bool next_enabled = _is_enabled();
|
||||
|
||||
int pause_notification = 0;
|
||||
|
||||
|
@ -425,7 +427,16 @@ void Node::set_process_mode(ProcessMode p_mode) {
|
|||
pause_notification = NOTIFICATION_UNPAUSED;
|
||||
}
|
||||
|
||||
_propagate_process_owner(data.process_owner, pause_notification);
|
||||
int enabled_notification = 0;
|
||||
|
||||
if (prev_enabled && !next_enabled) {
|
||||
enabled_notification = NOTIFICATION_DISABLED;
|
||||
} else if (!prev_enabled && next_enabled) {
|
||||
enabled_notification = NOTIFICATION_ENABLED;
|
||||
}
|
||||
|
||||
_propagate_process_owner(data.process_owner, pause_notification, enabled_notification);
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
// This is required for the editor to update the visibility of disabled nodes
|
||||
// It's very expensive during runtime to change, so editor-only
|
||||
|
@ -454,17 +465,21 @@ Node::ProcessMode Node::get_process_mode() const {
|
|||
return data.process_mode;
|
||||
}
|
||||
|
||||
void Node::_propagate_process_owner(Node *p_owner, int p_notification) {
|
||||
void Node::_propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification) {
|
||||
data.process_owner = p_owner;
|
||||
|
||||
if (p_notification != 0) {
|
||||
notification(p_notification);
|
||||
if (p_pause_notification != 0) {
|
||||
notification(p_pause_notification);
|
||||
}
|
||||
|
||||
if (p_enabled_notification != 0) {
|
||||
notification(p_enabled_notification);
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.children.size(); i++) {
|
||||
Node *c = data.children[i];
|
||||
if (c->data.process_mode == PROCESS_MODE_INHERIT) {
|
||||
c->_propagate_process_owner(p_owner, p_notification);
|
||||
c->_propagate_process_owner(p_owner, p_pause_notification, p_enabled_notification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -668,6 +683,27 @@ bool Node::_can_process(bool p_paused) const {
|
|||
}
|
||||
}
|
||||
|
||||
bool Node::_is_enabled() const {
|
||||
ProcessMode process_mode;
|
||||
|
||||
if (data.process_mode == PROCESS_MODE_INHERIT) {
|
||||
if (!data.process_owner) {
|
||||
process_mode = PROCESS_MODE_PAUSABLE;
|
||||
} else {
|
||||
process_mode = data.process_owner->data.process_mode;
|
||||
}
|
||||
} else {
|
||||
process_mode = data.process_mode;
|
||||
}
|
||||
|
||||
return (process_mode != PROCESS_MODE_DISABLED);
|
||||
}
|
||||
|
||||
bool Node::is_enabled() const {
|
||||
ERR_FAIL_COND_V(!is_inside_tree(), false);
|
||||
return _is_enabled();
|
||||
}
|
||||
|
||||
float Node::get_physics_process_delta_time() const {
|
||||
if (data.tree) {
|
||||
return data.tree->get_physics_process_time();
|
||||
|
@ -2619,6 +2655,8 @@ void Node::_bind_methods() {
|
|||
BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS);
|
||||
BIND_CONSTANT(NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
|
||||
BIND_CONSTANT(NOTIFICATION_POST_ENTER_TREE);
|
||||
BIND_CONSTANT(NOTIFICATION_DISABLED);
|
||||
BIND_CONSTANT(NOTIFICATION_ENABLED);
|
||||
|
||||
BIND_CONSTANT(NOTIFICATION_EDITOR_PRE_SAVE);
|
||||
BIND_CONSTANT(NOTIFICATION_EDITOR_POST_SAVE);
|
||||
|
|
|
@ -163,7 +163,7 @@ private:
|
|||
void _propagate_after_exit_tree();
|
||||
void _propagate_validate_owner();
|
||||
void _print_stray_nodes();
|
||||
void _propagate_process_owner(Node *p_owner, int p_notification);
|
||||
void _propagate_process_owner(Node *p_owner, int p_pause_notification, int p_enabled_notification);
|
||||
Array _get_node_and_resource(const NodePath &p_path);
|
||||
|
||||
void _duplicate_signals(const Node *p_original, Node *p_copy) const;
|
||||
|
@ -181,6 +181,7 @@ private:
|
|||
void _propagate_pause_notification(bool p_enable);
|
||||
|
||||
_FORCE_INLINE_ bool _can_process(bool p_paused) const;
|
||||
_FORCE_INLINE_ bool _is_enabled() const;
|
||||
|
||||
protected:
|
||||
void _block() { data.blocked++; }
|
||||
|
@ -224,6 +225,8 @@ public:
|
|||
NOTIFICATION_INTERNAL_PROCESS = 25,
|
||||
NOTIFICATION_INTERNAL_PHYSICS_PROCESS = 26,
|
||||
NOTIFICATION_POST_ENTER_TREE = 27,
|
||||
NOTIFICATION_DISABLED = 28,
|
||||
NOTIFICATION_ENABLED = 29,
|
||||
//keep these linked to node
|
||||
|
||||
NOTIFICATION_WM_MOUSE_ENTER = 1002,
|
||||
|
@ -380,6 +383,7 @@ public:
|
|||
ProcessMode get_process_mode() const;
|
||||
bool can_process() const;
|
||||
bool can_process_notification(int p_what) const;
|
||||
bool is_enabled() const;
|
||||
|
||||
void request_ready();
|
||||
|
||||
|
|
Loading…
Reference in a new issue