don't auto-stop disjoint animations

This commit is contained in:
David Rose 2006-01-21 01:31:29 +00:00
parent 9164535479
commit ca8455d5ef
12 changed files with 89 additions and 33 deletions

View File

@ -44,3 +44,19 @@ INLINE int AnimControl::
get_channel_index() const {
return _channel_index;
}
////////////////////////////////////////////////////////////////////
// Function: AnimControl::get_bound_joints
// Access: Published
// Description: Returns the subset of joints controlled by this
// AnimControl. Most of the time, this will be
// BitArray::all_on(), for a normal full-body animation.
// For a subset animation, however, this will be just a
// subset of those bits, corresponding to the set of
// joints and sliders actually bound (as enumerated by
// bind_hierarchy() in depth-first LIFO order).
////////////////////////////////////////////////////////////////////
INLINE const BitArray &AnimControl::
get_bound_joints() const {
return _bound_joints;
}

View File

@ -29,7 +29,8 @@ TypeHandle AnimControl::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
AnimControl::
AnimControl(PartBundle *part, AnimBundle *anim, int channel_index) {
AnimControl(PartBundle *part, AnimBundle *anim, int channel_index,
const BitArray &bound_joints) {
#ifdef DO_MEMORY_USAGE
MemoryUsage::update_type(this, get_class_type());
#endif
@ -37,6 +38,7 @@ AnimControl(PartBundle *part, AnimBundle *anim, int channel_index) {
_part = part;
_anim = anim;
_channel_index = channel_index;
_bound_joints = bound_joints;
set_frame_rate(_anim->get_base_frame_rate());
set_num_frames(_anim->get_num_frames());

View File

@ -24,6 +24,7 @@
#include "animInterface.h"
#include "animBundle.h"
#include "partGroup.h"
#include "bitArray.h"
#include "referenceCount.h"
@ -40,7 +41,8 @@ class AnimChannelBase;
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA AnimControl : public ReferenceCount, public AnimInterface {
public:
AnimControl(PartBundle *part, AnimBundle *anim, int channel_index);
AnimControl(PartBundle *part, AnimBundle *anim, int channel_index,
const BitArray &bound_joints);
PUBLISHED:
virtual ~AnimControl();
@ -48,6 +50,7 @@ PUBLISHED:
PartBundle *get_part() const;
INLINE AnimBundle *get_anim() const;
INLINE int get_channel_index() const;
INLINE const BitArray &get_bound_joints() const;
virtual void output(ostream &out) const;
@ -73,6 +76,11 @@ private:
// This is the frame number as of the last call to mark_channels().
int _marked_frame;
// This is the bitmask of joints and/or sliders from the animation
// that we have actually bound into this AnimControl. See
// get_bound_joints().
BitArray _bound_joints;
public:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -16,10 +16,10 @@
//
////////////////////////////////////////////////////////////////////
#include "movingPartBase.h"
#include "animControl.h"
#include "animChannelBase.h"
#include "bitArray.h"
#include "indent.h"
@ -207,7 +207,8 @@ pick_channel_index(plist<int> &holes, int &next) const {
// hierarchy, at the given channel index number.
////////////////////////////////////////////////////////////////////
void MovingPartBase::
bind_hierarchy(AnimGroup *anim, int channel_index, bool is_included,
bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index,
bool is_included, BitArray &bound_joints,
const PartSubset &subset) {
if (chan_cat.is_debug()) {
chan_cat.debug()
@ -229,7 +230,16 @@ bind_hierarchy(AnimGroup *anim, int channel_index, bool is_included,
} else {
_channels[channel_index] = DCAST(AnimChannelBase, anim);
}
}
PartGroup::bind_hierarchy(anim, channel_index, is_included, subset);
// Record that we have bound this joint in the bound_joints
// BitArray.
bound_joints.set_bit(joint_index);
} else {
// Record that we have *not* bound this particular joint.
bound_joints.clear_bit(joint_index);
}
++joint_index;
PartGroup::bind_hierarchy(anim, channel_index, joint_index,
is_included, bound_joints, subset);
}

View File

@ -68,7 +68,9 @@ protected:
virtual void pick_channel_index(plist<int> &holes, int &next) const;
virtual void bind_hierarchy(AnimGroup *anim, int channel_index,
bool is_included, const PartSubset &subset);
int &joint_index, bool is_included,
BitArray &bound_joints,
const PartSubset &subset);
typedef pvector< PT(AnimChannelBase) > Channels;
Channels _channels;

View File

@ -89,9 +89,6 @@ get_blend_value(const PartBundle *root) {
switch (root->get_blend_type()) {
case PartBundle::BT_single:
// This one shouldn't be possible.
nassertv(false);
case PartBundle::BT_linear:
{
// An ordinary, linear blend.

View File

@ -21,6 +21,7 @@
#include "animBundle.h"
#include "animControl.h"
#include "config_chan.h"
#include "bitArray.h"
#include "indent.h"
#include "datagram.h"
@ -107,7 +108,7 @@ set_blend_type(BlendType bt) {
// most-recently-added one.
nassertv(_last_control_set != NULL);
clear_and_stop_except(_last_control_set);
clear_and_stop_intersecting(_last_control_set);
}
_anim_changed = true;
@ -173,7 +174,7 @@ set_control_effect(AnimControl *control, float effect) {
// If we currently have BT_single, we only allow one AnimControl
// at a time. Stop all of the other AnimControls.
if (get_blend_type() == BT_single) {
clear_and_stop_except(control);
clear_and_stop_intersecting(control);
}
if (get_control_effect(control) != effect) {
@ -285,8 +286,14 @@ bind_anim(AnimBundle *anim, int hierarchy_match_flags,
channel_index = holes.front();
}
bind_hierarchy(anim, channel_index, subset.is_empty(), subset);
return new AnimControl(this, anim, channel_index);
int joint_index = 0;
BitArray bound_joints;
if (subset.is_include_empty()) {
bound_joints = BitArray::all_on();
}
bind_hierarchy(anim, channel_index, joint_index, subset.is_include_empty(),
bound_joints, subset);
return new AnimControl(this, anim, channel_index, bound_joints);
}
////////////////////////////////////////////////////////////////////
@ -416,16 +423,17 @@ register_with_read_factory()
}
////////////////////////////////////////////////////////////////////
// Function: PartBundle::clear_and_stop_except
// Function: PartBundle::clear_and_stop_intersecting
// Access: Protected
// Description: Removes and stops all the currently activated
// AnimControls, except for the indicated one. This is
// a special internal function that's only called when
// _blend_type is BT_single, to automatically stop all
// the other currently-executing animations.
// AnimControls that animate some joints also animated
// by the indicated AnimControl. This is a special
// internal function that's only called when _blend_type
// is BT_single, to automatically stop all the other
// currently-executing animations.
////////////////////////////////////////////////////////////////////
void PartBundle::
clear_and_stop_except(AnimControl *control) {
clear_and_stop_intersecting(AnimControl *control) {
double new_net_blend = 0.0f;
ChannelBlend new_blend;
bool any_changed = false;
@ -433,8 +441,10 @@ clear_and_stop_except(AnimControl *control) {
ChannelBlend::iterator cbi;
for (cbi = _blend.begin(); cbi != _blend.end(); ++cbi) {
AnimControl *ac = (*cbi).first;
if (ac == control) {
// Save this control, but only this one.
if (ac == control ||
!ac->get_bound_joints().has_bits_in_common(control->get_bound_joints())) {
// Save this control--it's either the target control, or it has
// no joints in common with the target control.
new_blend.insert(new_blend.end(), (*cbi));
new_net_blend += (*cbi).second;
} else {

View File

@ -135,7 +135,7 @@ public:
protected:
void recompute_net_blend();
void clear_and_stop_except(AnimControl *control);
void clear_and_stop_intersecting(AnimControl *control);
BlendType _blend_type;
PartBundleNode *_node;

View File

@ -432,7 +432,8 @@ pick_channel_index(plist<int> &holes, int &next) const {
// hierarchy, at the given channel index number.
////////////////////////////////////////////////////////////////////
void PartGroup::
bind_hierarchy(AnimGroup *anim, int channel_index, bool is_included,
bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index,
bool is_included, BitArray &bound_joints,
const PartSubset &subset) {
if (subset.matches_include(get_name())) {
is_included = true;
@ -451,12 +452,18 @@ bind_hierarchy(AnimGroup *anim, int channel_index, bool is_included,
if (pc->get_name() < ac->get_name()) {
// Here's a part, not in the anim. Bind it to the special NULL
// anim.
pc->bind_hierarchy(NULL, channel_index, is_included, subset);
pc->bind_hierarchy(NULL, channel_index, joint_index, is_included,
bound_joints, subset);
i++;
} else if (ac->get_name() < pc->get_name()) {
// Here's an anim, not in the part. Ignore it.
j++;
} else {
pc->bind_hierarchy(ac, channel_index, is_included, subset);
// Here's a matched part and anim pair.
pc->bind_hierarchy(ac, channel_index, joint_index, is_included,
bound_joints, subset);
i++;
j++;
}
@ -465,7 +472,8 @@ bind_hierarchy(AnimGroup *anim, int channel_index, bool is_included,
// Now pick up any more parts, not in the anim.
while (i < part_num_children) {
PartGroup *pc = get_child(i);
pc->bind_hierarchy(NULL, channel_index, is_included, subset);
pc->bind_hierarchy(NULL, channel_index, joint_index, is_included,
bound_joints, subset);
i++;
}
}

View File

@ -34,6 +34,7 @@ class PartBundle;
class PartSubset;
class BamReader;
class FactoryParams;
class BitArray;
////////////////////////////////////////////////////////////////////
// Class : PartGroup
@ -93,7 +94,9 @@ protected:
virtual void pick_channel_index(plist<int> &holes, int &next) const;
virtual void bind_hierarchy(AnimGroup *anim, int channel_index,
bool is_included, const PartSubset &subset);
int &joint_index, bool is_included,
BitArray &bound_joints,
const PartSubset &subset);
typedef pvector< PT(PartGroup) > Children;
Children _children;

View File

@ -129,15 +129,15 @@ output(ostream &out) const {
}
////////////////////////////////////////////////////////////////////
// Function: PartSubset::is_empty
// Function: PartSubset::is_include_empty
// Access: Published
// Description: Returns true if the PartSubset is completely empty,
// Description: Returns true if the include list is completely empty,
// false otherwise. If it is empty, it is the same
// thing as including all joints.
////////////////////////////////////////////////////////////////////
bool PartSubset::
is_empty() const {
return _include_joints.empty() && _exclude_joints.empty();
is_include_empty() const {
return _include_joints.empty();
}
////////////////////////////////////////////////////////////////////

View File

@ -42,7 +42,7 @@ PUBLISHED:
void output(ostream &out) const;
bool is_empty() const;
bool is_include_empty() const;
bool matches_include(const string &joint_name) const;
bool matches_exclude(const string &joint_name) const;