1
0
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:
Silc Lizard (Tokage) Renew
2025-03-06 02:45:24 +09:00
parent 6392241742
commit 96200abb97
20 changed files with 88 additions and 41 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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();

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);

View File

@@ -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());
}
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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 {