Merge pull request #77465 from lyuma/ik_skeleton_reference_bug

SkeletonIK3D: Avoid holding hard pointers to Skeleton3D
This commit is contained in:
Rémi Verschelde 2023-06-20 00:02:47 +02:00
commit 243c8e0b40
No known key found for this signature in database
GPG key ID: C3336907360768E1
2 changed files with 17 additions and 9 deletions

View file

@ -330,6 +330,7 @@ void FabrikInverseKinematic::_update_chain(const Skeleton3D *p_sk, ChainItem *p_
void SkeletonIK3D::_validate_property(PropertyInfo &p_property) const { void SkeletonIK3D::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "root_bone" || p_property.name == "tip_bone") { if (p_property.name == "root_bone" || p_property.name == "tip_bone") {
Skeleton3D *skeleton = get_parent_skeleton();
if (skeleton) { if (skeleton) {
String names("--,"); String names("--,");
for (int i = 0; i < skeleton->get_bone_count(); i++) { for (int i = 0; i < skeleton->get_bone_count(); i++) {
@ -400,13 +401,13 @@ void SkeletonIK3D::_bind_methods() {
void SkeletonIK3D::_notification(int p_what) { void SkeletonIK3D::_notification(int p_what) {
switch (p_what) { switch (p_what) {
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
skeleton = Object::cast_to<Skeleton3D>(get_parent()); skeleton_ref = Object::cast_to<Skeleton3D>(get_parent());
set_process_priority(1); set_process_priority(1);
reload_chain(); reload_chain();
} break; } break;
case NOTIFICATION_INTERNAL_PROCESS: { case NOTIFICATION_INTERNAL_PROCESS: {
if (target_node_override) { if (target_node_override_ref) {
reload_goal(); reload_goal();
} }
_solve_chain(); _solve_chain();
@ -463,7 +464,7 @@ const Transform3D &SkeletonIK3D::get_target_transform() const {
void SkeletonIK3D::set_target_node(const NodePath &p_node) { void SkeletonIK3D::set_target_node(const NodePath &p_node) {
target_node_path_override = p_node; target_node_path_override = p_node;
target_node_override = nullptr; target_node_override_ref = Variant();
reload_goal(); reload_goal();
} }
@ -503,6 +504,10 @@ void SkeletonIK3D::set_max_iterations(int p_iterations) {
max_iterations = p_iterations; max_iterations = p_iterations;
} }
Skeleton3D *SkeletonIK3D::get_parent_skeleton() const {
return cast_to<Skeleton3D>(skeleton_ref.get_validated_object());
}
bool SkeletonIK3D::is_running() { bool SkeletonIK3D::is_running() {
return is_processing_internal(); return is_processing_internal();
} }
@ -511,7 +516,7 @@ void SkeletonIK3D::start(bool p_one_time) {
if (p_one_time) { if (p_one_time) {
set_process_internal(false); set_process_internal(false);
if (target_node_override) { if (target_node_override_ref) {
reload_goal(); reload_goal();
} }
@ -523,16 +528,18 @@ void SkeletonIK3D::start(bool p_one_time) {
void SkeletonIK3D::stop() { void SkeletonIK3D::stop() {
set_process_internal(false); set_process_internal(false);
Skeleton3D *skeleton = get_parent_skeleton();
if (skeleton) { if (skeleton) {
skeleton->clear_bones_global_pose_override(); skeleton->clear_bones_global_pose_override();
} }
} }
Transform3D SkeletonIK3D::_get_target_transform() { Transform3D SkeletonIK3D::_get_target_transform() {
if (!target_node_override && !target_node_path_override.is_empty()) { if (!target_node_override_ref && !target_node_path_override.is_empty()) {
target_node_override = Object::cast_to<Node3D>(get_node(target_node_path_override)); target_node_override_ref = Object::cast_to<Node3D>(get_node(target_node_path_override));
} }
Node3D *target_node_override = cast_to<Node3D>(target_node_override_ref.get_validated_object());
if (target_node_override && target_node_override->is_inside_tree()) { if (target_node_override && target_node_override->is_inside_tree()) {
return target_node_override->get_global_transform(); return target_node_override->get_global_transform();
} else { } else {
@ -544,6 +551,7 @@ void SkeletonIK3D::reload_chain() {
FabrikInverseKinematic::free_task(task); FabrikInverseKinematic::free_task(task);
task = nullptr; task = nullptr;
Skeleton3D *skeleton = get_parent_skeleton();
if (!skeleton) { if (!skeleton) {
return; return;
} }

View file

@ -132,8 +132,8 @@ class SkeletonIK3D : public Node {
real_t min_distance = 0.01; real_t min_distance = 0.01;
int max_iterations = 10; int max_iterations = 10;
Skeleton3D *skeleton = nullptr; Variant skeleton_ref = Variant();
Node3D *target_node_override = nullptr; Variant target_node_override_ref = Variant();
FabrikInverseKinematic::Task *task = nullptr; FabrikInverseKinematic::Task *task = nullptr;
protected: protected:
@ -176,7 +176,7 @@ public:
void set_max_iterations(int p_iterations); void set_max_iterations(int p_iterations);
int get_max_iterations() const { return max_iterations; } int get_max_iterations() const { return max_iterations; }
Skeleton3D *get_parent_skeleton() const { return skeleton; } Skeleton3D *get_parent_skeleton() const;
bool is_running(); bool is_running();