char: fix crash during Character destructor (regression)

This was a regression in 0bb81a43c9 which was not keeping an edge case in mind if a weak pointer is locked during object destruction.  This issue was fixed by 525a05ea2b1d00a1db901f883f1755943aeff33c, but that is not enough since it causes CharacterJointEffect::get_character() to return null now, so we need a separate method to check if a CharacterJointEffect belongs to a given character.  This is more efficient, too.

Fixes #330
This commit is contained in:
rdb 2018-05-27 15:37:45 +02:00
parent f2d429b817
commit 3d49986ce2
3 changed files with 18 additions and 6 deletions

View File

@ -214,7 +214,7 @@ bool CharacterJoint::
remove_net_transform(PandaNode *node) {
CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
if (effect != (RenderEffect *)NULL &&
DCAST(CharacterJointEffect, effect)->get_character() == _character) {
DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
node->clear_effect(CharacterJointEffect::get_class_type());
}
@ -244,7 +244,7 @@ clear_net_transforms() {
CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
if (effect != (RenderEffect *)NULL &&
DCAST(CharacterJointEffect, effect)->get_character() == _character) {
DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
node->clear_effect(CharacterJointEffect::get_class_type());
}
}
@ -306,7 +306,7 @@ bool CharacterJoint::
remove_local_transform(PandaNode *node) {
CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
if (effect != (RenderEffect *)NULL &&
DCAST(CharacterJointEffect, effect)->get_character() == _character) {
DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
node->clear_effect(CharacterJointEffect::get_class_type());
}
@ -336,7 +336,7 @@ clear_local_transforms() {
CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
if (effect != (RenderEffect *)NULL &&
DCAST(CharacterJointEffect, effect)->get_character() == _character) {
DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
node->clear_effect(CharacterJointEffect::get_class_type());
}
}
@ -427,7 +427,7 @@ set_character(Character *character) {
CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
if (effect != (RenderEffect *)NULL &&
DCAST(CharacterJointEffect, effect)->get_character() == _character) {
DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
node->clear_effect(CharacterJointEffect::get_class_type());
}
}
@ -438,7 +438,7 @@ set_character(Character *character) {
CPT(RenderEffect) effect = node->get_effect(CharacterJointEffect::get_class_type());
if (effect != (RenderEffect *)NULL &&
DCAST(CharacterJointEffect, effect)->get_character() == _character) {
DCAST(CharacterJointEffect, effect)->matches_character(_character)) {
node->clear_effect(CharacterJointEffect::get_class_type());
}
}

View File

@ -27,3 +27,13 @@ INLINE PT(Character) CharacterJointEffect::
get_character() const {
return _character.lock();
}
/**
* Returns true if this CharacterJointEffect contains the given Character.
* This exists because it is faster to check than get_character() and can even
* be called while the Character is destructing.
*/
INLINE bool CharacterJointEffect::
matches_character(Character *character) const {
return _character == character;
}

View File

@ -41,6 +41,8 @@ PUBLISHED:
INLINE PT(Character) get_character() const;
public:
INLINE bool matches_character(Character *character) const;
virtual bool safe_to_transform() const;
virtual bool safe_to_combine() const;
virtual void output(ostream &out) const;