Browse Source

add done event

David Rose 23 years ago
parent
commit
fb3ca83e5f

+ 15 - 0
direct/src/interval/Interval.py

@@ -21,6 +21,7 @@ class Interval(DirectObject):
         self.duration = duration
         self.state = CInterval.SInitial
         self.currT = 0.0
+        self.doneEvent = None
         self.setTHooks = []
         self.__startT = 0
         self.__startTAtStart = 1
@@ -56,6 +57,12 @@ class Interval(DirectObject):
     def getT(self):
         return self.currT
 
+    def setDoneEvent(self, event):
+        self.doneEvent = event
+
+    def getDoneEvent(self):
+        return self.doneEvent
+
     def privDoEvent(self, t, event):
         if event == CInterval.ETStep:
             self.privStep(t)
@@ -87,6 +94,7 @@ class Interval(DirectObject):
         self.state = CInterval.SStarted
         self.privStep(self.getDuration())
         self.state = CInterval.SFinal
+        self.intervalDone()
 
     def privStep(self, t):
         # Subclasses may redefine this function
@@ -97,6 +105,7 @@ class Interval(DirectObject):
         # Subclasses may redefine this function
         self.privStep(self.getDuration())
         self.state = CInterval.SFinal
+        self.intervalDone()
 
     def privReverseInitialize(self, t):
         # Subclasses may redefine this function
@@ -118,6 +127,12 @@ class Interval(DirectObject):
         # Subclasses may redefine this function
         self.state = CInterval.SPaused
 
+    def intervalDone(self):
+        # Subclasses should call this when the interval transitions to
+        # its final state.
+        if self.doneEvent:
+            messenger.throw(self.doneEvent)
+
     def setupPlay(self, startT, endT, playRate):
         duration = self.getDuration()
         

+ 26 - 0
direct/src/interval/cInterval.I

@@ -90,6 +90,32 @@ get_t() const {
   return _curr_t;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CInterval::set_done_event
+//       Access: Published
+//  Description: Sets the event that is generated whenever the
+//               interval reaches its final state, whether it is
+//               explicitly finished or whether it gets there on its
+//               own.
+////////////////////////////////////////////////////////////////////
+INLINE void CInterval::
+set_done_event(const string &event) {
+  _done_event = event;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CInterval::get_done_event
+//       Access: Published
+//  Description: Returns the event that is generated whenever the
+//               interval reaches its final state, whether it is
+//               explicitly finished or whether it gets there on its
+//               own.
+////////////////////////////////////////////////////////////////////
+INLINE const string &CInterval::
+get_done_event() const {
+  return _done_event;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CInterval::recompute
 //       Access: Protected

+ 16 - 0
direct/src/interval/cInterval.cxx

@@ -19,6 +19,7 @@
 #include "cInterval.h"
 #include "indent.h"
 #include "clockObject.h"
+#include "throw_event.h"
 #include <math.h>
 
 TypeHandle CInterval::_type_handle;
@@ -308,6 +309,7 @@ priv_instant() {
   _state = S_started;
   priv_step(get_duration());
   _state = S_final;
+  interval_done();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -338,6 +340,7 @@ priv_finalize() {
   double duration = get_duration();
   priv_step(duration);
   _state = S_final;
+  interval_done();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -449,6 +452,19 @@ mark_dirty() {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CInterval::interval_done
+//       Access: Protected
+//  Description: Called internally whenever the interval reaches its
+//               final state.
+////////////////////////////////////////////////////////////////////
+void CInterval::
+interval_done() {
+  if (!_done_event.empty()) {
+    throw_event(_done_event);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CInterval::do_recompute
 //       Access: Protected, Virtual

+ 7 - 1
direct/src/interval/cInterval.h

@@ -68,6 +68,9 @@ PUBLISHED:
   INLINE bool is_stopped() const;
   INLINE double get_t() const;
 
+  INLINE void set_done_event(const string &event);
+  INLINE const string &get_done_event() const;
+
   void setup_play(double start_time, double end_time, double play_rate);
   void setup_resume();
   int step_play();
@@ -78,7 +81,7 @@ PUBLISHED:
   // interface.
 
   // These cannot be declared private because they must be accessible
-  // Python, but the method names are prefixed with priv_ to remind
+  // to Python, but the method names are prefixed with priv_ to remind
   // you that you probably don't want to be using them directly.
   void priv_do_event(double t, EventType event);
   virtual void priv_initialize(double t);
@@ -97,6 +100,8 @@ public:
   void mark_dirty();
 
 protected:
+  void interval_done();
+
   INLINE void recompute() const;
   virtual void do_recompute();
   INLINE void check_stopped(const char *method_name) const;
@@ -105,6 +110,7 @@ protected:
   State _state;
   double _curr_t;
   string _name;
+  string _done_event;
   double _duration;
 
   // For setup_play() and step_play().

+ 0 - 21
direct/src/interval/cMetaInterval.I

@@ -155,27 +155,6 @@ get_event_type() const {
   return _event_queue.front()._event_type;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: CMetaInterval::pop_event
-//       Access: Published
-//  Description: Acknowledges that the external interval on the top of
-//               the queue has been extracted, and is about to be
-//               serviced by the scripting language.  This prepares
-//               the interval so the next call to is_event_ready()
-//               will return information about the next external
-//               interval on the queue, if any.
-////////////////////////////////////////////////////////////////////
-INLINE void CMetaInterval::
-pop_event() {
-#ifndef NDEBUG
-  nassertv(!_event_queue.empty());
-  const EventQueueEntry &entry = _event_queue.front();
-  const IntervalDef &def = _defs[entry._n];
-  nassertv(def._type == DT_ext_index);
-#endif
-  _event_queue.pop_front();
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: CMetaInterval::double_to_int_time
 //       Access: Private

+ 49 - 0
direct/src/interval/cMetaInterval.cxx

@@ -419,6 +419,10 @@ priv_instant() {
   _next_event_index = _events.size();
   _curr_t = get_duration();
   _state = S_final;
+
+  if (_event_queue.empty()) {
+    interval_done();
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -510,6 +514,10 @@ priv_finalize() {
 
   _curr_t = duration;
   _state = S_final;
+
+  if (_event_queue.empty()) {
+    interval_done();
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -663,6 +671,36 @@ priv_interrupt() {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CMetaInterval::pop_event
+//       Access: Published
+//  Description: Acknowledges that the external interval on the top of
+//               the queue has been extracted, and is about to be
+//               serviced by the scripting language.  This prepares
+//               the interval so the next call to is_event_ready()
+//               will return information about the next external
+//               interval on the queue, if any.
+////////////////////////////////////////////////////////////////////
+void CMetaInterval::
+pop_event() {
+#ifndef NDEBUG
+  nassertv(!_event_queue.empty());
+  const EventQueueEntry &entry = _event_queue.front();
+  const IntervalDef &def = _defs[entry._n];
+  nassertv(def._type == DT_ext_index);
+#endif
+  _event_queue.pop_front();
+
+  // Really, we should set a flag to call this at the next call to
+  // service_event_queue(), instead of calling it immediately, because
+  // the just-popped event probably hasn't been processed yet.  But we
+  // can get away with calling this here for now because Python
+  // doesn't process C++ events immediately.
+  if (_state == S_final) {
+    interval_done();
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CMetaInterval::write
 //       Access: Published, Virtual
@@ -1017,6 +1055,13 @@ enqueue_self_event(CInterval::EventType event_type, double t) {
 ////////////////////////////////////////////////////////////////////
 bool CMetaInterval::
 service_event_queue() {
+  if (_event_queue.empty()) {
+    // Return early if we're empty on entry, so we don't throw the
+    // done event more than once.
+    nassertr(!_processing_events, false);
+    return false;
+  }
+
   while (!_event_queue.empty()) {
     nassertr(!_processing_events, true);
     const EventQueueEntry &entry = _event_queue.front();
@@ -1045,6 +1090,10 @@ service_event_queue() {
     _event_queue.pop_front();
   }
 
+  if (_state == S_final) {
+    interval_done();
+  }
+
   // No more events on the queue.
   nassertr(!_processing_events, false);
 

+ 1 - 1
direct/src/interval/cMetaInterval.h

@@ -87,7 +87,7 @@ PUBLISHED:
   INLINE int get_event_index() const;
   INLINE double get_event_t() const;
   INLINE EventType get_event_type() const;
-  INLINE void pop_event();
+  void pop_event();
 
   virtual void write(ostream &out, int indent_level) const;