Browse Source

wait_pending()

David Rose 17 years ago
parent
commit
917568869f

+ 18 - 0
panda/src/chan/animControl.cxx

@@ -35,6 +35,8 @@ AnimControl::
 AnimControl(const string &name, PartBundle *part, 
 AnimControl(const string &name, PartBundle *part, 
             double frame_rate, int num_frames) :
             double frame_rate, int num_frames) :
   Namable(name),
   Namable(name),
+  _pending_lock(name),
+  _pending_cvar(_pending_lock),
   _bound_joints(BitArray::all_on())
   _bound_joints(BitArray::all_on())
 {
 {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
@@ -73,6 +75,7 @@ setup_anim(PartBundle *part, AnimBundle *anim, int channel_index,
   // Now the AnimControl is fully set up.
   // Now the AnimControl is fully set up.
   _marked_frame = -1;
   _marked_frame = -1;
   _pending = false;
   _pending = false;
+  _pending_cvar.signal_all();
   if (!_pending_done_event.empty()) {
   if (!_pending_done_event.empty()) {
     throw_event(_pending_done_event);
     throw_event(_pending_done_event);
   }
   }
@@ -90,6 +93,7 @@ fail_anim(PartBundle *part) {
   MutexHolder holder(_pending_lock);
   MutexHolder holder(_pending_lock);
   nassertv(_pending && part == _part);
   nassertv(_pending && part == _part);
   _pending = false;
   _pending = false;
+  _pending_cvar.signal_all();
   if (!_pending_done_event.empty()) {
   if (!_pending_done_event.empty()) {
     throw_event(_pending_done_event);
     throw_event(_pending_done_event);
   }
   }
@@ -105,6 +109,20 @@ AnimControl::
   get_part()->set_control_effect(this, 0.0f);
   get_part()->set_control_effect(this, 0.0f);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimControl::wait_pending
+//       Access: Published
+//  Description: Blocks the current thread until the AnimControl has
+//               finished loading and is fully bound.
+////////////////////////////////////////////////////////////////////
+bool AnimControl::
+wait_pending() {
+  MutexHolder holder(_pending_lock);
+  while (_pending) {
+    _pending_cvar.wait();
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimControl::set_pending_done_event
 //     Function: AnimControl::set_pending_done_event
 //       Access: Published
 //       Access: Published

+ 3 - 0
panda/src/chan/animControl.h

@@ -25,6 +25,7 @@
 #include "typedReferenceCount.h"
 #include "typedReferenceCount.h"
 #include "namable.h"
 #include "namable.h"
 #include "pmutex.h"
 #include "pmutex.h"
+#include "conditionVarFull.h"
 
 
 class PartBundle;
 class PartBundle;
 class AnimChannelBase;
 class AnimChannelBase;
@@ -49,6 +50,7 @@ PUBLISHED:
   virtual ~AnimControl();
   virtual ~AnimControl();
 
 
   INLINE bool is_pending() const;
   INLINE bool is_pending() const;
+  bool wait_pending();
   INLINE bool has_anim() const;
   INLINE bool has_anim() const;
   void set_pending_done_event(const string &done_event);
   void set_pending_done_event(const string &done_event);
   string get_pending_done_event() const;
   string get_pending_done_event() const;
@@ -81,6 +83,7 @@ private:
   bool _pending;
   bool _pending;
   string _pending_done_event;
   string _pending_done_event;
   Mutex _pending_lock;  // protects the above two.
   Mutex _pending_lock;  // protects the above two.
+  ConditionVarFull _pending_cvar; // signals when _pending goes true.
 
 
   PT(PartGroup) _part;
   PT(PartGroup) _part;
   PT(AnimBundle) _anim;
   PT(AnimBundle) _anim;

+ 25 - 1
panda/src/chan/partBundle.cxx

@@ -300,7 +300,9 @@ bind_anim(AnimBundle *anim, int hierarchy_match_flags,
 //               eventually becomes available.
 //               eventually becomes available.
 //
 //
 //               You can test AnimControl::is_pending() to see if the
 //               You can test AnimControl::is_pending() to see if the
-//               animation has been loaded yet.  You can also set an
+//               animation has been loaded yet, or wait for it to
+//               finish with AnimControl::wait_pending() or even
+//               PartBundle::wait_pending().  You can also set an
 //               event to be triggered when the animation finishes
 //               event to be triggered when the animation finishes
 //               loading with AnimControl::set_pending_done_event().
 //               loading with AnimControl::set_pending_done_event().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -360,6 +362,28 @@ load_bind_anim(Loader *loader, const Filename &filename,
   return control;
   return control;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PartBundle::wait_pending
+//       Access: Published
+//  Description: Blocks the current thread until all currently-pending
+//               AnimControls, with a nonzero control effect, have
+//               been loaded and are properly bound.
+////////////////////////////////////////////////////////////////////
+bool PartBundle::
+wait_pending() {
+  CDReader cdata(_cycler);
+  ChannelBlend::const_iterator cbi;
+  for (cbi = cdata->_blend.begin(); 
+       cbi != cdata->_blend.end(); 
+       ++cbi) {
+    AnimControl *control = (*cbi).first;
+    float effect = (*cbi).second;
+    if (effect != 0.0f) {
+      control->wait_pending();
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PartBundle::freeze_joint
 //     Function: PartBundle::freeze_joint
 //       Access: Published
 //       Access: Published

+ 1 - 0
panda/src/chan/partBundle.h

@@ -133,6 +133,7 @@ PUBLISHED:
                                  int hierarchy_match_flags,
                                  int hierarchy_match_flags,
                                  const PartSubset &subset,
                                  const PartSubset &subset,
                                  bool allow_async);
                                  bool allow_async);
+  bool wait_pending();
 
 
   bool freeze_joint(const string &joint_name, const TransformState *transform);
   bool freeze_joint(const string &joint_name, const TransformState *transform);
   bool control_joint(const string &joint_name, PandaNode *node);
   bool control_joint(const string &joint_name, PandaNode *node);