don't auto-stop disjoint animations
This commit is contained in:
parent
9164535479
commit
ca8455d5ef
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue