generalize interruptible to autoPause and autoFinish

This commit is contained in:
David Rose 2003-02-26 22:26:43 +00:00
parent 3d1374ba8a
commit a71af97bf4
8 changed files with 173 additions and 33 deletions

View File

@ -1,5 +1,6 @@
from PandaModules import * from PandaModules import *
from DirectNotifyGlobal import * from DirectNotifyGlobal import *
import EventManager
import Interval import Interval
import types import types
@ -24,6 +25,12 @@ class IntervalManager(CIntervalManager):
else: else:
CIntervalManager.__init__(self) CIntervalManager.__init__(self)
# Set up a custom event queue for handling C++ events from
# intervals.
self.eventQueue = EventQueue()
self.eventManager = EventManager.EventManager(self.eventQueue)
self.setEventQueue(self.eventQueue)
self.ivals = [] self.ivals = []
self.removedIvals = {} self.removedIvals = {}
@ -46,9 +53,26 @@ class IntervalManager(CIntervalManager):
return None return None
def step(self): def step(self):
# Call C++ step, then do all the required Python post-processing. # This method should be called once per frame to perform all
# of the per-frame processing on the active intervals.
# Call C++ step, then do the Python stuff.
CIntervalManager.step(self) CIntervalManager.step(self)
self.__doPythonCallbacks()
def interrupt(self):
# This method should be called during an emergency cleanup
# operation, to automatically pause or finish all active
# intervals tagged with autoPause or autoFinish set true.
# Call C++ interrupt, then do the Python stuff.
CIntervalManager.interrupt(self)
self.__doPythonCallbacks()
def __doPythonCallbacks(self):
# This method does all of the required Python post-processing
# after performing some C++-level action.
# It is important to call all of the python callbacks on the # It is important to call all of the python callbacks on the
# just-removed intervals before we call any of the callbacks # just-removed intervals before we call any of the callbacks
# on the still-running intervals. # on the still-running intervals.
@ -67,6 +91,13 @@ class IntervalManager(CIntervalManager):
self.ivals[index].privPostEvent() self.ivals[index].privPostEvent()
index = self.getNextEvent() index = self.getNextEvent()
# Finally, throw all the events on the custom event queue.
# These are the done events that may have been generated in
# C++. We use a custom event queue so we can service all of
# these immediately, rather than waiting for the global event
# queue to be serviced (which might not be till next frame).
self.eventManager.doEvents()
def __storeInterval(self, interval, index): def __storeInterval(self, interval, index):
while index >= len(self.ivals): while index >= len(self.ivals):

View File

@ -32,10 +32,22 @@ class MetaInterval(CMetaInterval):
name = kw['name'] name = kw['name']
del kw['name'] del kw['name']
interruptible = 0 # If the keyword "autoPause" or "autoFinish" is defined to
if kw.has_key('interruptible'): # non-zero, it means the interval may be automatically paused
interruptible = kw['interruptible'] # or finished when CIntervalManager::interrupt() is called.
del kw['interruptible'] # This is generally called only on a catastrophic situation
# (for instance, the connection to the server being lost) when
# we have to exit right away; these keywords indicate
# intervals that might not be cleaned up by their owners.
autoPause = 0
autoFinish = 0
if kw.has_key('autoPause'):
autoPause = kw['autoPause']
del kw['autoPause']
if kw.has_key('autoFinish'):
autoFinish = kw['autoFinish']
del kw['autoFinish']
# A duration keyword specifies the duration the interval will # A duration keyword specifies the duration the interval will
# appear to have for the purposes of computing the start time # appear to have for the purposes of computing the start time
@ -71,7 +83,8 @@ class MetaInterval(CMetaInterval):
CMetaInterval.__init__(self, name) CMetaInterval.__init__(self, name)
self.__manager = ivalMgr self.__manager = ivalMgr
self.setInterruptible(interruptible) self.setAutoPause(autoPause)
self.setAutoFinish(autoFinish)
self.pythonIvals = [] self.pythonIvals = []

View File

@ -117,30 +117,57 @@ get_t() const {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CInterval::set_interruptible // Function: CInterval::set_auto_pause
// Access: Published // Access: Published
// Description: Changes the state of the 'interruptible' flag. If // Description: Changes the state of the 'auto_pause' flag. If
// this is true, the interval may be arbitrarily // this is true, the interval may be arbitrarily
// interrupted when the system needs to reset due to // interrupted when the system needs to reset due to
// some external event by calling // some external event by calling
// CIntervalManager::pause_all_interruptible(). If this // CIntervalManager::interrupt(). If this
// is false (the default), the interval must always be // is false (the default), the interval must always be
// explicitly finished or paused. // explicitly finished or paused.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void CInterval:: INLINE void CInterval::
set_interruptible(bool interruptible) { set_auto_pause(bool auto_pause) {
_interruptible = interruptible; _auto_pause = auto_pause;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CInterval::get_interruptible // Function: CInterval::get_auto_pause
// Access: Published // Access: Published
// Description: Returns the state of the 'interruptible' flag. See // Description: Returns the state of the 'auto_pause' flag. See
// set_interruptible(). // set_auto_pause().
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool CInterval:: INLINE bool CInterval::
get_interruptible() const { get_auto_pause() const {
return _interruptible; return _auto_pause;
}
////////////////////////////////////////////////////////////////////
// Function: CInterval::set_auto_finish
// Access: Published
// Description: Changes the state of the 'auto_finish' flag. If
// this is true, the interval may be arbitrarily
// finished when the system needs to reset due to
// some external event by calling
// CIntervalManager::interrupt(). If this
// is false (the default), the interval must always be
// explicitly finished or paused.
////////////////////////////////////////////////////////////////////
INLINE void CInterval::
set_auto_finish(bool auto_finish) {
_auto_finish = auto_finish;
}
////////////////////////////////////////////////////////////////////
// Function: CInterval::get_auto_finish
// Access: Published
// Description: Returns the state of the 'auto_finish' flag. See
// set_auto_finish().
////////////////////////////////////////////////////////////////////
INLINE bool CInterval::
get_auto_finish() const {
return _auto_finish;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -20,7 +20,8 @@
#include "cIntervalManager.h" #include "cIntervalManager.h"
#include "indent.h" #include "indent.h"
#include "clockObject.h" #include "clockObject.h"
#include "throw_event.h" #include "event.h"
#include "eventQueue.h"
#include <math.h> #include <math.h>
TypeHandle CInterval::_type_handle; TypeHandle CInterval::_type_handle;
@ -39,7 +40,8 @@ CInterval(const string &name, double duration, bool open_ended) :
_open_ended(open_ended), _open_ended(open_ended),
_dirty(false) _dirty(false)
{ {
_interruptible = false; _auto_pause = false;
_auto_finish = false;
_wants_t_callback = false; _wants_t_callback = false;
_last_t_callback = -1.0; _last_t_callback = -1.0;
_manager = CIntervalManager::get_global_ptr(); _manager = CIntervalManager::get_global_ptr();
@ -610,7 +612,7 @@ mark_dirty() {
void CInterval:: void CInterval::
interval_done() { interval_done() {
if (!_done_event.empty()) { if (!_done_event.empty()) {
throw_event(_done_event); _manager->get_event_queue()->queue_event(new Event(_done_event));
} }
} }

View File

@ -75,8 +75,10 @@ PUBLISHED:
void set_t(double t); void set_t(double t);
INLINE double get_t() const; INLINE double get_t() const;
INLINE void set_interruptible(bool interruptible); INLINE void set_auto_pause(bool auto_pause);
INLINE bool get_interruptible() const; INLINE bool get_auto_pause() const;
INLINE void set_auto_finish(bool auto_finish);
INLINE bool get_auto_finish() const;
INLINE void set_wants_t_callback(bool wants_t_callback); INLINE void set_wants_t_callback(bool wants_t_callback);
INLINE bool get_wants_t_callback() const; INLINE bool get_wants_t_callback() const;
@ -136,7 +138,8 @@ protected:
string _done_event; string _done_event;
double _duration; double _duration;
bool _interruptible; bool _auto_pause;
bool _auto_finish;
bool _wants_t_callback; bool _wants_t_callback;
double _last_t_callback; double _last_t_callback;
CIntervalManager *_manager; CIntervalManager *_manager;

View File

@ -17,6 +17,35 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: CIntervalManager::set_event_queue
// Access: Published
// Description: Specifies a custom event queue to be used for
// throwing done events from intervals as they finish.
// If this is not specified, the global event queue is
// used.
//
// The caller maintains ownership of the EventQueue
// object; it is the caller's responsibility to ensure
// that the supplied EventQueue does not destruct during
// the lifetime of the CIntervalManager.
////////////////////////////////////////////////////////////////////
INLINE void CIntervalManager::
set_event_queue(EventQueue *event_queue) {
_event_queue = event_queue;
}
////////////////////////////////////////////////////////////////////
// Function: CIntervalManager::get_event_queue
// Access: Published
// Description: Returns the custom event queue to be used for
// throwing done events from intervals as they finish.
////////////////////////////////////////////////////////////////////
INLINE EventQueue *CIntervalManager::
get_event_queue() const {
return _event_queue;
}
INLINE ostream & INLINE ostream &
operator << (ostream &out, const CIntervalManager &ival_mgr) { operator << (ostream &out, const CIntervalManager &ival_mgr) {
ival_mgr.output(out); ival_mgr.output(out);

View File

@ -19,6 +19,7 @@
#include "cIntervalManager.h" #include "cIntervalManager.h"
#include "cMetaInterval.h" #include "cMetaInterval.h"
#include "dcast.h" #include "dcast.h"
#include "eventQueue.h"
CIntervalManager *CIntervalManager::_global_ptr; CIntervalManager *CIntervalManager::_global_ptr;
@ -31,6 +32,7 @@ CIntervalManager::
CIntervalManager() { CIntervalManager() {
_first_slot = 0; _first_slot = 0;
_next_event_index = 0; _next_event_index = 0;
_event_queue = EventQueue::get_global_event_queue();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -164,18 +166,18 @@ remove_c_interval(int index) {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CIntervalManager::pause_all_interruptible // Function: CIntervalManager::interrupt
// Access: Published // Access: Published
// Description: Pauses (removes from the active queue) all intervals // Description: Pauses or finishes (removes from the active queue)
// tagged as "interruptible". These are intervals that // all intervals tagged with auto_pause or auto_finish
// someone fired up but won't necessarily expect to // set to true. These are intervals that someone fired
// clean up; they can be interrupted at will when // up but won't necessarily expect to clean up; they can
// necessary. // be interrupted at will when necessary.
// //
// Returns the number of intervals affected. // Returns the number of intervals affected.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int CIntervalManager:: int CIntervalManager::
pause_all_interruptible() { interrupt() {
int num_paused = 0; int num_paused = 0;
NameIndex::iterator ni; NameIndex::iterator ni;
@ -184,11 +186,38 @@ pause_all_interruptible() {
int index = (*ni).second; int index = (*ni).second;
const IntervalDef &def = _intervals[index]; const IntervalDef &def = _intervals[index];
nassertr(def._interval != (CInterval *)NULL, num_paused); nassertr(def._interval != (CInterval *)NULL, num_paused);
if (def._interval->get_interruptible()) { if (def._interval->get_auto_pause() || def._interval->get_auto_finish()) {
// This interval may be interrupted. // This interval may be interrupted.
if (def._interval->get_state() == CInterval::S_started) { if (def._interval->get_auto_pause()) {
def._interval->priv_interrupt(); // It may be interrupted simply by pausing it.
if (interval_cat.is_debug()) {
interval_cat.debug()
<< "Auto-pausing " << def._interval->get_name() << "\n";
}
if (def._interval->get_state() == CInterval::S_started) {
def._interval->priv_interrupt();
}
} else {
// It should be interrupted by finishing it.
if (interval_cat.is_debug()) {
interval_cat.debug()
<< "Auto-finishing " << def._interval->get_name() << "\n";
}
switch (def._interval->get_state()) {
case CInterval::S_initial:
def._interval->priv_instant();
break;
case CInterval::S_final:
break;
default:
def._interval->priv_finalize();
}
} }
// Now carefully remove it from the active list.
NameIndex::iterator prev; NameIndex::iterator prev;
prev = ni; prev = ni;
++ni; ++ni;

View File

@ -26,6 +26,8 @@
#include "pmap.h" #include "pmap.h"
#include "vector_int.h" #include "vector_int.h"
class EventQueue;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : CIntervalManager // Class : CIntervalManager
// Description : This object holds a number of currently-playing // Description : This object holds a number of currently-playing
@ -46,13 +48,16 @@ PUBLISHED:
CIntervalManager(); CIntervalManager();
~CIntervalManager(); ~CIntervalManager();
INLINE void set_event_queue(EventQueue *event_queue);
INLINE EventQueue *get_event_queue() const;
int add_c_interval(CInterval *interval, bool external); int add_c_interval(CInterval *interval, bool external);
int find_c_interval(const string &name) const; int find_c_interval(const string &name) const;
CInterval *get_c_interval(int index) const; CInterval *get_c_interval(int index) const;
void remove_c_interval(int index); void remove_c_interval(int index);
int pause_all_interruptible(); int interrupt();
int get_num_intervals() const; int get_num_intervals() const;
void step(); void step();
@ -84,6 +89,7 @@ private:
NameIndex _name_index; NameIndex _name_index;
typedef vector_int Removed; typedef vector_int Removed;
Removed _removed; Removed _removed;
EventQueue *_event_queue;
int _first_slot; int _first_slot;
int _next_event_index; int _next_event_index;