diff --git a/panda/src/chan/animControl.cxx b/panda/src/chan/animControl.cxx index 44f014d289..b460ce5d9e 100644 --- a/panda/src/chan/animControl.cxx +++ b/panda/src/chan/animControl.cxx @@ -81,6 +81,18 @@ setup_anim(PartBundle *part, AnimBundle *anim, int channel_index, } } +//////////////////////////////////////////////////////////////////// +// Function: AnimControl::set_bound_joints +// Access: Public +// Description: Called to initialize the AnimControl with its array +// of bound_joints, before setup_anim() has completed. +//////////////////////////////////////////////////////////////////// +void AnimControl:: +set_bound_joints(const BitArray &bound_joints) { + MutexHolder holder(_pending_lock); + _bound_joints = bound_joints; +} + //////////////////////////////////////////////////////////////////// // Function: AnimControl::fail_anim // Access: Public @@ -118,8 +130,16 @@ AnimControl:: void AnimControl:: wait_pending() { MutexHolder holder(_pending_lock); - while (_pending) { - _pending_cvar.wait(); + if (_pending) { + // TODO: we should elevate the priority of the associated + // BindAnimRequest while we're waiting for it, so it will jump to + // the front of the queue. + chan_cat.info() + << "Blocking " << *Thread::get_current_thread() + << " until " << get_name() << " is bound\n"; + while (_pending) { + _pending_cvar.wait(); + } } } diff --git a/panda/src/chan/animControl.h b/panda/src/chan/animControl.h index 22c6343622..e4d7284a2c 100644 --- a/panda/src/chan/animControl.h +++ b/panda/src/chan/animControl.h @@ -44,6 +44,7 @@ public: double frame_rate, int num_frames); void setup_anim(PartBundle *part, AnimBundle *anim, int channel_index, const BitArray &bound_joints); + void set_bound_joints(const BitArray &bound_joints); void fail_anim(PartBundle *part); PUBLISHED: diff --git a/panda/src/chan/movingPartBase.cxx b/panda/src/chan/movingPartBase.cxx index 4525986764..978caf135a 100644 --- a/panda/src/chan/movingPartBase.cxx +++ b/panda/src/chan/movingPartBase.cxx @@ -289,3 +289,29 @@ bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index, PartGroup::bind_hierarchy(anim, channel_index, joint_index, is_included, bound_joints, subset); } + +//////////////////////////////////////////////////////////////////// +// Function: MovingPartBase::find_bound_joints +// Access: Protected, Virtual +// Description: Similar to bind_hierarchy, but does not actually +// perform any binding. All it does is compute the +// BitArray bount_joints according to the specified +// subset. This is useful in preparation for +// asynchronous binding--in this case, we may need to +// know bound_joints immediately, without having to wait +// for the animation itself to load and bind. +//////////////////////////////////////////////////////////////////// +void MovingPartBase:: +find_bound_joints(int &joint_index, bool is_included, BitArray &bound_joints, + const PartSubset &subset) { + if (subset.matches_include(get_name())) { + is_included = true; + } else if (subset.matches_exclude(get_name())) { + is_included = false; + } + + bound_joints.set_bit_to(joint_index, is_included); + ++joint_index; + + PartGroup::find_bound_joints(joint_index, is_included, bound_joints, subset); +} diff --git a/panda/src/chan/movingPartBase.h b/panda/src/chan/movingPartBase.h index 1173e0e9b4..12581a9c11 100644 --- a/panda/src/chan/movingPartBase.h +++ b/panda/src/chan/movingPartBase.h @@ -72,6 +72,9 @@ protected: int &joint_index, bool is_included, BitArray &bound_joints, const PartSubset &subset); + virtual void find_bound_joints(int &joint_index, bool is_included, + BitArray &bound_joints, + const PartSubset &subset); typedef pvector< PT(AnimChannelBase) > Channels; Channels _channels; diff --git a/panda/src/chan/partBundle.cxx b/panda/src/chan/partBundle.cxx index ad59adc384..95cf9060ef 100644 --- a/panda/src/chan/partBundle.cxx +++ b/panda/src/chan/partBundle.cxx @@ -354,6 +354,14 @@ load_bind_anim(Loader *loader, const Filename &filename, PT(AnimControl) control = new AnimControl(basename, this, frame_rate, num_frames); + if (!subset.is_include_empty()) { + // Figure out the actual subset of joints to be bound. + int joint_index = 0; + BitArray bound_joints; + find_bound_joints(joint_index, false, bound_joints, subset); + control->set_bound_joints(bound_joints); + } + PT(BindAnimRequest) request = new BindAnimRequest(filename, anim_options, control, hierarchy_match_flags, subset); diff --git a/panda/src/chan/partGroup.cxx b/panda/src/chan/partGroup.cxx index 08dc61d98b..f04d026ab9 100644 --- a/panda/src/chan/partGroup.cxx +++ b/panda/src/chan/partGroup.cxx @@ -552,6 +552,33 @@ bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index, } } +//////////////////////////////////////////////////////////////////// +// Function: PartGroup::find_bound_joints +// Access: Protected, Virtual +// Description: Similar to bind_hierarchy, but does not actually +// perform any binding. All it does is compute the +// BitArray bount_joints according to the specified +// subset. This is useful in preparation for +// asynchronous binding--in this case, we may need to +// know bound_joints immediately, without having to wait +// for the animation itself to load and bind. +//////////////////////////////////////////////////////////////////// +void PartGroup:: +find_bound_joints(int &joint_index, bool is_included, BitArray &bound_joints, + const PartSubset &subset) { + if (subset.matches_include(get_name())) { + is_included = true; + } else if (subset.matches_exclude(get_name())) { + is_included = false; + } + + int part_num_children = get_num_children(); + for (int i = 0; i < part_num_children; ++i) { + PartGroup *pc = get_child(i); + pc->find_bound_joints(joint_index, is_included, bound_joints, subset); + } +} + //////////////////////////////////////////////////////////////////// // Function: PartGroup::write_datagram // Access: Public diff --git a/panda/src/chan/partGroup.h b/panda/src/chan/partGroup.h index 2a17d6033f..a8d3f3458c 100644 --- a/panda/src/chan/partGroup.h +++ b/panda/src/chan/partGroup.h @@ -105,6 +105,9 @@ protected: int &joint_index, bool is_included, BitArray &bound_joints, const PartSubset &subset); + virtual void find_bound_joints(int &joint_index, bool is_included, + BitArray &bound_joints, + const PartSubset &subset); typedef pvector< PT(PartGroup) > Children; Children _children;