You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Add p_delta argument to _process_modification() and expose advance()
This commit is contained in:
@@ -20,6 +20,14 @@
|
||||
[b]Note:[/b] Bone names should be unique, non empty, and cannot include the [code]:[/code] and [code]/[/code] characters.
|
||||
</description>
|
||||
</method>
|
||||
<method name="advance">
|
||||
<return type="void" />
|
||||
<param index="0" name="delta" type="float" />
|
||||
<description>
|
||||
Manually advance the child [SkeletonModifier3D]s by the specified time (in seconds).
|
||||
[b]Note:[/b] The [param delta] is temporarily accumulated in the [Skeleton3D], and the deferred process uses the accumulated value to process the modification.
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear_bones">
|
||||
<return type="void" />
|
||||
<description>
|
||||
@@ -420,5 +428,8 @@
|
||||
<constant name="MODIFIER_CALLBACK_MODE_PROCESS_IDLE" value="1" enum="ModifierCallbackModeProcess">
|
||||
Set a flag to process modification during process frames (see [constant Node.NOTIFICATION_INTERNAL_PROCESS]).
|
||||
</constant>
|
||||
<constant name="MODIFIER_CALLBACK_MODE_PROCESS_MANUAL" value="2" enum="ModifierCallbackModeProcess">
|
||||
Do not process modification. Use [method advance] to process the modification manually.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
||||
@@ -12,13 +12,22 @@
|
||||
<link title="Design of the Skeleton Modifier 3D">https://godotengine.org/article/design-of-the-skeleton-modifier-3d/</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="_process_modification" qualifiers="virtual">
|
||||
<method name="_process_modification" qualifiers="virtual" deprecated="Use [method _process_modification_with_delta] instead.">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Override this virtual method to implement a custom skeleton modifier. You should do things like get the [Skeleton3D]'s current pose and apply the pose here.
|
||||
[method _process_modification] must not apply [member influence] to bone poses because the [Skeleton3D] automatically applies influence to all bone poses set by the modifier.
|
||||
</description>
|
||||
</method>
|
||||
<method name="_process_modification_with_delta" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<param index="0" name="delta" type="float" />
|
||||
<description>
|
||||
Override this virtual method to implement a custom skeleton modifier. You should do things like get the [Skeleton3D]'s current pose and apply the pose here.
|
||||
[method _process_modification_with_delta] must not apply [member influence] to bone poses because the [Skeleton3D] automatically applies influence to all bone poses set by the modifier.
|
||||
[param delta] is passed from parent [Skeleton3D]. See also [method Skeleton3D.advance].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_skeleton" qualifiers="const">
|
||||
<return type="Skeleton3D" />
|
||||
<description>
|
||||
|
||||
@@ -487,7 +487,7 @@ void LookAtModifier3D::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(ORIGIN_FROM_EXTERNAL_NODE);
|
||||
}
|
||||
|
||||
void LookAtModifier3D::_process_modification() {
|
||||
void LookAtModifier3D::_process_modification(double p_delta) {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
@@ -570,13 +570,7 @@ void LookAtModifier3D::_process_modification() {
|
||||
|
||||
// Do time-based interpolation.
|
||||
if (remaining > 0) {
|
||||
double delta = 0.0;
|
||||
if (skeleton->get_modifier_callback_mode_process() == Skeleton3D::MODIFIER_CALLBACK_MODE_PROCESS_IDLE) {
|
||||
delta = get_process_delta_time();
|
||||
} else {
|
||||
delta = get_physics_process_delta_time();
|
||||
}
|
||||
remaining = MAX(0, remaining - time_step * delta);
|
||||
remaining = MAX(0, remaining - time_step * p_delta);
|
||||
if (is_flippable) {
|
||||
// Interpolate through the rest same as AnimationTree blending for preventing to penetrate the bone into the body.
|
||||
Quaternion rest = skeleton->get_bone_rest(bone).basis.get_rotation_quaternion();
|
||||
|
||||
@@ -107,7 +107,7 @@ protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
virtual void _process_modification() override;
|
||||
virtual void _process_modification(double p_delta) override;
|
||||
|
||||
public:
|
||||
void set_bone_name(const String &p_bone_name);
|
||||
|
||||
@@ -364,7 +364,7 @@ void PhysicalBoneSimulator3D::set_bone_global_pose(int p_bone, const Transform3D
|
||||
bones.write[p_bone].global_pose = p_pose;
|
||||
}
|
||||
|
||||
void PhysicalBoneSimulator3D::_process_modification() {
|
||||
void PhysicalBoneSimulator3D::_process_modification(double p_delta) {
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (!skeleton) {
|
||||
return;
|
||||
|
||||
@@ -72,7 +72,7 @@ protected:
|
||||
void _pose_updated();
|
||||
void _bone_pose_updated(Skeleton3D *skeleton, int p_bone_id);
|
||||
|
||||
virtual void _process_modification() override;
|
||||
virtual void _process_modification(double p_delta) override;
|
||||
|
||||
virtual void _skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new) override;
|
||||
|
||||
|
||||
@@ -370,7 +370,7 @@ void RetargetModifier3D::_retarget_pose() {
|
||||
}
|
||||
}
|
||||
|
||||
void RetargetModifier3D::_process_modification() {
|
||||
void RetargetModifier3D::_process_modification(double p_delta) {
|
||||
if (use_global_pose) {
|
||||
_retarget_global_pose();
|
||||
} else {
|
||||
|
||||
@@ -96,7 +96,7 @@ protected:
|
||||
virtual void remove_child_notify(Node *p_child) override;
|
||||
|
||||
virtual void _set_active(bool p_active) override;
|
||||
virtual void _process_modification() override;
|
||||
virtual void _process_modification(double p_delta) override;
|
||||
|
||||
public:
|
||||
virtual PackedStringArray get_configuration_warnings() const override;
|
||||
|
||||
@@ -357,7 +357,9 @@ void Skeleton3D::_notification(int p_what) {
|
||||
// Store dirty flags for global bone poses.
|
||||
bone_global_pose_dirty_backup = bone_global_pose_dirty;
|
||||
|
||||
_process_modifiers();
|
||||
if (update_flags & UPDATE_FLAG_MODIFIER) {
|
||||
_process_modifiers();
|
||||
}
|
||||
}
|
||||
|
||||
// Abort if pose is not changed.
|
||||
@@ -438,13 +440,20 @@ void Skeleton3D::_notification(int p_what) {
|
||||
updating = false;
|
||||
update_flags = UPDATE_FLAG_NONE;
|
||||
} break;
|
||||
case NOTIFICATION_INTERNAL_PROCESS:
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
_find_modifiers();
|
||||
if (!modifiers.is_empty()) {
|
||||
_update_deferred(UPDATE_FLAG_MODIFIER);
|
||||
}
|
||||
case NOTIFICATION_INTERNAL_PROCESS: {
|
||||
advance(get_process_delta_time());
|
||||
} break;
|
||||
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
|
||||
advance(get_physics_process_delta_time());
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton3D::advance(double p_delta) {
|
||||
_find_modifiers();
|
||||
if (!modifiers.is_empty()) {
|
||||
update_delta += p_delta; // Accumulate delta for manual advance as it needs to process in deferred update.
|
||||
_update_deferred(UPDATE_FLAG_MODIFIER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,6 +476,9 @@ void Skeleton3D::_process_changed() {
|
||||
} else if (modifier_callback_mode_process == MODIFIER_CALLBACK_MODE_PROCESS_PHYSICS) {
|
||||
set_process_internal(false);
|
||||
set_physics_process_internal(true);
|
||||
} else {
|
||||
set_process_internal(false);
|
||||
set_physics_process_internal(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1194,7 +1206,7 @@ void Skeleton3D::_process_modifiers() {
|
||||
for (int i = 0; i < get_bone_count(); i++) {
|
||||
old_poses.push_back(get_bone_pose(i));
|
||||
}
|
||||
mod->process_modification();
|
||||
mod->process_modification(update_delta);
|
||||
LocalVector<Transform3D> new_poses;
|
||||
for (int i = 0; i < get_bone_count(); i++) {
|
||||
new_poses.push_back(get_bone_pose(i));
|
||||
@@ -1206,10 +1218,11 @@ void Skeleton3D::_process_modifiers() {
|
||||
set_bone_pose(i, old_poses[i].interpolate_with(new_poses[i], influence));
|
||||
}
|
||||
} else {
|
||||
mod->process_modification();
|
||||
mod->process_modification(update_delta);
|
||||
}
|
||||
force_update_all_dirty_bones();
|
||||
}
|
||||
update_delta = 0; // Reset accumulated delta.
|
||||
}
|
||||
|
||||
void Skeleton3D::add_child_notify(Node *p_child) {
|
||||
@@ -1297,11 +1310,13 @@ void Skeleton3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_modifier_callback_mode_process", "mode"), &Skeleton3D::set_modifier_callback_mode_process);
|
||||
ClassDB::bind_method(D_METHOD("get_modifier_callback_mode_process"), &Skeleton3D::get_modifier_callback_mode_process);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("advance", "delta"), &Skeleton3D::advance);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "motion_scale", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater"), "set_motion_scale", "get_motion_scale");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_rest_only"), "set_show_rest_only", "is_show_rest_only");
|
||||
|
||||
ADD_GROUP("Modifier", "modifier_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "modifier_callback_mode_process", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_modifier_callback_mode_process", "get_modifier_callback_mode_process");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "modifier_callback_mode_process", PROPERTY_HINT_ENUM, "Physics,Idle,Manual"), "set_modifier_callback_mode_process", "get_modifier_callback_mode_process");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("rest_updated"));
|
||||
ADD_SIGNAL(MethodInfo("pose_updated"));
|
||||
@@ -1313,6 +1328,7 @@ void Skeleton3D::_bind_methods() {
|
||||
BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON);
|
||||
BIND_ENUM_CONSTANT(MODIFIER_CALLBACK_MODE_PROCESS_PHYSICS);
|
||||
BIND_ENUM_CONSTANT(MODIFIER_CALLBACK_MODE_PROCESS_IDLE);
|
||||
BIND_ENUM_CONSTANT(MODIFIER_CALLBACK_MODE_PROCESS_MANUAL);
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
ClassDB::bind_method(D_METHOD("clear_bones_global_pose_override"), &Skeleton3D::clear_bones_global_pose_override);
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
enum ModifierCallbackModeProcess {
|
||||
MODIFIER_CALLBACK_MODE_PROCESS_PHYSICS,
|
||||
MODIFIER_CALLBACK_MODE_PROCESS_IDLE,
|
||||
MODIFIER_CALLBACK_MODE_PROCESS_MANUAL,
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -93,6 +94,7 @@ private:
|
||||
void _update_deferred(UpdateFlag p_update_flag = UPDATE_FLAG_POSE);
|
||||
uint8_t update_flags = UPDATE_FLAG_NONE;
|
||||
bool updating = false; // Is updating now?
|
||||
double update_delta = 0.0;
|
||||
|
||||
struct Bone {
|
||||
String name;
|
||||
@@ -294,6 +296,8 @@ public:
|
||||
void set_modifier_callback_mode_process(ModifierCallbackModeProcess p_mode);
|
||||
ModifierCallbackModeProcess get_modifier_callback_mode_process() const;
|
||||
|
||||
void advance(double p_delta);
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
Transform3D get_bone_global_pose_no_override(int p_bone) const;
|
||||
void clear_bones_global_pose_override();
|
||||
|
||||
@@ -366,7 +366,7 @@ void SkeletonIK3D::_bind_methods() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void SkeletonIK3D::_process_modification() {
|
||||
void SkeletonIK3D::_process_modification(double p_delta) {
|
||||
if (!internal_active) {
|
||||
return;
|
||||
}
|
||||
@@ -485,7 +485,7 @@ bool SkeletonIK3D::is_running() {
|
||||
void SkeletonIK3D::start(bool p_one_time) {
|
||||
if (p_one_time) {
|
||||
internal_active = true;
|
||||
SkeletonModifier3D::process_modification();
|
||||
SkeletonModifier3D::process_modification(0);
|
||||
internal_active = false;
|
||||
} else {
|
||||
internal_active = true;
|
||||
|
||||
@@ -144,7 +144,7 @@ protected:
|
||||
static void _bind_methods();
|
||||
virtual void _notification(int p_what);
|
||||
|
||||
virtual void _process_modification() override;
|
||||
virtual void _process_modification(double p_delta) override;
|
||||
|
||||
public:
|
||||
SkeletonIK3D();
|
||||
|
||||
@@ -113,16 +113,23 @@ real_t SkeletonModifier3D::get_influence() const {
|
||||
return influence;
|
||||
}
|
||||
|
||||
void SkeletonModifier3D::process_modification() {
|
||||
void SkeletonModifier3D::process_modification(double p_delta) {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
_process_modification();
|
||||
_process_modification(p_delta);
|
||||
emit_signal(SNAME("modification_processed"));
|
||||
}
|
||||
|
||||
void SkeletonModifier3D::_process_modification() {
|
||||
GDVIRTUAL_CALL(_process_modification);
|
||||
void SkeletonModifier3D::_process_modification(double p_delta) {
|
||||
if (GDVIRTUAL_CALL(_process_modification_with_delta, p_delta)) {
|
||||
return;
|
||||
}
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
if (GDVIRTUAL_CALL(_process_modification)) {
|
||||
return;
|
||||
}
|
||||
#endif // DISABLE_DEPRECATED
|
||||
}
|
||||
|
||||
void SkeletonModifier3D::_notification(int p_what) {
|
||||
@@ -151,7 +158,10 @@ void SkeletonModifier3D::_bind_methods() {
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "influence", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_influence", "get_influence");
|
||||
|
||||
ADD_SIGNAL(MethodInfo("modification_processed"));
|
||||
GDVIRTUAL_BIND(_process_modification_with_delta, "delta");
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
GDVIRTUAL_BIND(_process_modification);
|
||||
#endif
|
||||
|
||||
BIND_ENUM_CONSTANT(BONE_AXIS_PLUS_X);
|
||||
BIND_ENUM_CONSTANT(BONE_AXIS_MINUS_X);
|
||||
|
||||
@@ -68,8 +68,12 @@ protected:
|
||||
|
||||
virtual void _set_active(bool p_active);
|
||||
|
||||
virtual void _process_modification();
|
||||
virtual void _process_modification(double p_delta);
|
||||
// TODO: In Godot 5, should obsolete old GDVIRTUAL0(_process_modification); and replace it with _process_modification_with_delta as GDVIRTUAL1(_process_modification, double).
|
||||
GDVIRTUAL1(_process_modification_with_delta, double);
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
GDVIRTUAL0(_process_modification);
|
||||
#endif
|
||||
|
||||
public:
|
||||
virtual PackedStringArray get_configuration_warnings() const override;
|
||||
@@ -83,7 +87,7 @@ public:
|
||||
|
||||
Skeleton3D *get_skeleton() const;
|
||||
|
||||
void process_modification();
|
||||
void process_modification(double p_delta);
|
||||
|
||||
// Utility APIs.
|
||||
static Vector3 get_vector_from_bone_axis(BoneAxis p_axis);
|
||||
|
||||
@@ -1496,7 +1496,7 @@ void SpringBoneSimulator3D::_set_active(bool p_active) {
|
||||
}
|
||||
}
|
||||
|
||||
void SpringBoneSimulator3D::_process_modification() {
|
||||
void SpringBoneSimulator3D::_process_modification(double p_delta) {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
@@ -1514,10 +1514,9 @@ void SpringBoneSimulator3D::_process_modification() {
|
||||
}
|
||||
#endif //TOOLS_ENABLED
|
||||
|
||||
double delta = skeleton->get_modifier_callback_mode_process() == Skeleton3D::MODIFIER_CALLBACK_MODE_PROCESS_IDLE ? skeleton->get_process_delta_time() : skeleton->get_physics_process_delta_time();
|
||||
for (int i = 0; i < settings.size(); i++) {
|
||||
_init_joints(skeleton, settings[i]);
|
||||
_process_joints(delta, skeleton, settings[i]->joints, get_valid_collision_instance_ids(i), settings[i]->cached_center, settings[i]->cached_inverted_center, settings[i]->cached_inverted_center.basis.get_rotation_quaternion());
|
||||
_process_joints(p_delta, skeleton, settings[i]->joints, get_valid_collision_instance_ids(i), settings[i]->cached_center, settings[i]->cached_inverted_center, settings[i]->cached_inverted_center.basis.get_rotation_quaternion());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ protected:
|
||||
static void _bind_methods();
|
||||
|
||||
virtual void _set_active(bool p_active) override;
|
||||
virtual void _process_modification() override;
|
||||
virtual void _process_modification(double p_delta) override;
|
||||
void _init_joints(Skeleton3D *p_skeleton, SpringBone3DSetting *p_setting);
|
||||
void _process_joints(double p_delta, Skeleton3D *p_skeleton, Vector<SpringBone3DJointSetting *> &p_joints, const LocalVector<ObjectID> &p_collisions, const Transform3D &p_center_transform, const Transform3D &p_inverted_center_transform, const Quaternion &p_inverted_center_rotation);
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ void XRBodyModifier3D::_get_joint_data() {
|
||||
}
|
||||
}
|
||||
|
||||
void XRBodyModifier3D::_process_modification() {
|
||||
void XRBodyModifier3D::_process_modification(double p_delta) {
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (!skeleton) {
|
||||
return;
|
||||
|
||||
@@ -71,7 +71,7 @@ protected:
|
||||
static void _bind_methods();
|
||||
|
||||
virtual void _skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new) override;
|
||||
virtual void _process_modification() override;
|
||||
virtual void _process_modification(double p_delta) override;
|
||||
|
||||
private:
|
||||
struct JointData {
|
||||
|
||||
@@ -183,7 +183,7 @@ void XRHandModifier3D::_get_joint_data() {
|
||||
}
|
||||
}
|
||||
|
||||
void XRHandModifier3D::_process_modification() {
|
||||
void XRHandModifier3D::_process_modification(double p_delta) {
|
||||
Skeleton3D *skeleton = get_skeleton();
|
||||
if (!skeleton) {
|
||||
return;
|
||||
|
||||
@@ -62,7 +62,7 @@ protected:
|
||||
static void _bind_methods();
|
||||
|
||||
virtual void _skeleton_changed(Skeleton3D *p_old, Skeleton3D *p_new) override;
|
||||
virtual void _process_modification() override;
|
||||
virtual void _process_modification(double p_delta) override;
|
||||
|
||||
private:
|
||||
struct JointData {
|
||||
|
||||
Reference in New Issue
Block a user