define start()/finish(), put more assertion checks in for state

This commit is contained in:
David Rose 2002-09-04 22:04:36 +00:00
parent 0bb406b5b4
commit c1b2fc4652
12 changed files with 192 additions and 27 deletions

View File

@ -4,11 +4,9 @@
of the CInterval class
"""
def play(self, t0 = 0.0, duration = None, scale = 1.0):
""" play(t0, duration)
"""
def start(self, t0 = 0.0, duration = None, scale = 1.0):
if self.isPlaying():
self.stop()
self.finish()
if duration: # None or 0 implies full length
self.setupPlay(t0, t0 + duration, scale)
else:
@ -17,7 +15,7 @@
self.resume()
def loop(self, t0 = 0.0, duration = None, scale = 1.0):
self.play(t0, duration, scale)
self.start(t0, duration, scale)
self.__loop = 1
return
@ -31,8 +29,8 @@
# Spawn task
taskMgr.add(self.__playTask, self.getName() + '-play')
def stop(self):
# Nowadays, stop() will implicitly set the interval to its
def finish(self):
# Nowadays, finish() will implicitly set the interval to its
# terminal state, like setFinalT() used to. Use pause()
# instead if you just want to leave the interval in its
# current state, whatever that may be.
@ -42,8 +40,14 @@
for func in self.setTHooks:
func(self.getT())
def play(self, *args, **kw):
self.start(*args, **kw)
def stop(self):
self.finish()
def setFinalT(self):
self.stop()
self.finish()
def setT(self, t, event = ETStep):
# Overridden from the C++ layer. We rename the C++ function
@ -115,7 +119,7 @@
command = lambda s=self: s.pause())
play = Button(
bf, text = 'Play',
command = lambda s=self, es=es: s.play(es.get()))
command = lambda s=self, es=es: s.start(es.get()))
jumpToEnd = Button(bf, text = '>>', command = toEnd)
jumpToStart.pack(side = LEFT, expand = 1, fill = X)
play.pack(side = LEFT, expand = 1, fill = X)

View File

@ -75,22 +75,22 @@ class Interval(DirectObject):
# Used by control panel to update scale
pass
def play(self, t0=0.0, duration=0.0, scale=1.0):
""" play(t0, duration)
"""
def start(self, t0=0.0, duration=0.0, scale=1.0):
# Starts playing the interval from the beginning, or at the
# indicated time if specified.
# Make sure the start time is sensible.
if t0 > self.duration:
t0 = self.duration
# Kill ongoing play task
if self.isPlaying():
self.stop()
self.finish()
# Start new one
self.offset = t0
self.startT = globalClock.getFrameTime()
assert(scale > 0.0)
self.scale = scale
self.vernier = 0.0
self.firstTime = 1
if (duration == 0.0):
# If no play duration specified, use duration of Interval
@ -105,7 +105,7 @@ class Interval(DirectObject):
def loop(self, t0=0.0, duration=0.0, scale=1.0):
self.accept(self.name + '-loop', self.play,
extraArgs=[t0, duration, scale])
self.play(t0, duration, scale)
self.start(t0, duration, scale)
return
def pause(self):
@ -121,16 +121,22 @@ class Interval(DirectObject):
# Spawn task
taskMgr.add(self.__playTask, self.getName() + '-play')
def stop(self):
# Nowadays, stop() will implicitly set the interval to its
def finish(self):
# Nowadays, finish() will implicitly set the interval to its
# terminal state, like setFinalT() used to. Use pause()
# instead if you just want to leave the interval in its
# current state, whatever that may be.
self.pause()
self.setT(self.getDuration(), IVAL_DONE)
def play(self, *args, **kw):
self.start(*args, **kw)
def stop(self):
self.finish()
def setFinalT(self):
self.stop()
self.finish()
def isPlaying(self):
return taskMgr.hasTaskNamed(self.name + '-play')
@ -139,7 +145,7 @@ class Interval(DirectObject):
""" __playTask(task)
"""
t = globalClock.getFrameTime()
te = self.offset + ((t - self.startT) * self.scale + self.vernier)
te = self.offset + ((t - self.startT) * self.scale)
if (te < self.endTime):
if (self.firstTime):
# If first call, init intervals
@ -215,7 +221,7 @@ class Interval(DirectObject):
command = lambda s=self: s.pause())
play = Button(
bf, text = 'Play',
command = lambda s=self, es=es: s.play(es.get()))
command = lambda s=self, es=es: s.start(es.get()))
jumpToEnd = Button(bf, text = '>>', command = toEnd)
jumpToStart.pack(side = LEFT, expand = 1, fill = X)
play.pack(side = LEFT, expand = 1, fill = X)

View File

@ -319,11 +319,11 @@ class MetaInterval(CMetaInterval):
CMetaInterval.interrupt(self)
self.__doPythonCallbacks()
def stop(self):
def finish(self):
# This function overrides from the parent level to check for Python
# callbacks afterwards.
self.__updateIvals()
CMetaInterval.stop(self)
CMetaInterval.finish(self)
self.__doPythonCallbacks()
def setFinalT(self):
@ -360,12 +360,12 @@ class MetaInterval(CMetaInterval):
self.__updateIvals()
return CMetaInterval.getDuration(self)
def play(self, *args, **kw):
def start(self, *args, **kw):
# This function overrides from the parent level to force it to
# update the interval list first, if necessary.
self.__updateIvals()
return CMetaInterval.play(self, *args, **kw)
return CMetaInterval.start(self, *args, **kw)
def loop(self, *args, **kw):
# This function overrides from the parent level to force it to

View File

@ -54,6 +54,18 @@ get_open_ended() const {
return _open_ended;
}
////////////////////////////////////////////////////////////////////
// Function: CInterval::get_state
// Access: Published
// Description: Indicates the state the interval believes it is in:
// whether it has been started, is currently in the
// middle, or has been finalized.
////////////////////////////////////////////////////////////////////
INLINE CInterval::State CInterval::
get_state() const {
return _state;
}
////////////////////////////////////////////////////////////////////
// Function: CInterval::set_t
// Access: Published
@ -123,6 +135,38 @@ recompute() const {
}
}
////////////////////////////////////////////////////////////////////
// Function: CInterval::check_stopped
// Access: Protected
// Description: Issues a warning if our internal state is not in
// one of the stopped states.
////////////////////////////////////////////////////////////////////
INLINE void CInterval::
check_stopped(const char *method_name) const {
if (_state != S_initial && _state != S_final) {
interval_cat.warning()
<< get_name() << "." << method_name << "() called in state "
<< _state << ".\n";
nassertv(!verify_intervals);
}
}
////////////////////////////////////////////////////////////////////
// Function: CInterval::check_started
// Access: Protected
// Description: Issues a warning if our internal state is not in
// one of the started states.
////////////////////////////////////////////////////////////////////
INLINE void CInterval::
check_started(const char *method_name) const {
if (_state != S_started && _state != S_paused) {
interval_cat.warning()
<< get_name() << "." << method_name << "() called in state "
<< _state << ".\n";
nassertv(!verify_intervals);
}
}
INLINE ostream &
operator << (ostream &out, const CInterval &ival) {
ival.output(out);

View File

@ -30,6 +30,7 @@ TypeHandle CInterval::_type_handle;
////////////////////////////////////////////////////////////////////
CInterval::
CInterval(const string &name, double duration, bool open_ended) :
_state(S_initial),
_curr_t(0.0),
_name(name),
_duration(duration),
@ -225,7 +226,9 @@ step_play() {
////////////////////////////////////////////////////////////////////
void CInterval::
initialize(double t) {
check_stopped("initialize");
recompute();
_state = S_started;
step(t);
}
@ -239,8 +242,11 @@ initialize(double t) {
////////////////////////////////////////////////////////////////////
void CInterval::
instant() {
check_stopped("instant");
recompute();
_state = S_started;
step(get_duration());
_state = S_final;
}
////////////////////////////////////////////////////////////////////
@ -252,6 +258,8 @@ instant() {
////////////////////////////////////////////////////////////////////
void CInterval::
step(double t) {
check_started("step");
_state = S_started;
_curr_t = t;
}
@ -265,7 +273,13 @@ step(double t) {
////////////////////////////////////////////////////////////////////
void CInterval::
finalize() {
step(get_duration());
double duration = get_duration();
if (_state == S_initial) {
initialize(duration);
}
step(duration);
_state = S_final;
}
////////////////////////////////////////////////////////////////////
@ -278,7 +292,9 @@ finalize() {
////////////////////////////////////////////////////////////////////
void CInterval::
reverse_initialize(double t) {
check_stopped("reverse_initialize");
recompute();
_state = S_started;
step(t);
}
@ -293,8 +309,11 @@ reverse_initialize(double t) {
////////////////////////////////////////////////////////////////////
void CInterval::
reverse_instant() {
check_stopped("reverse_instant");
recompute();
_state = S_started;
step(0.0);
_state = S_initial;
}
////////////////////////////////////////////////////////////////////
@ -306,7 +325,12 @@ reverse_instant() {
////////////////////////////////////////////////////////////////////
void CInterval::
reverse_finalize() {
if (_state == S_initial) {
initialize(0.0);
}
step(0.0);
_state = S_initial;
}
////////////////////////////////////////////////////////////////////
@ -325,6 +349,9 @@ reverse_finalize() {
////////////////////////////////////////////////////////////////////
void CInterval::
interrupt() {
if (_state == S_started) {
_state = S_paused;
}
}
////////////////////////////////////////////////////////////////////
@ -379,3 +406,23 @@ void CInterval::
do_recompute() {
_dirty = false;
}
ostream &
operator << (ostream &out, CInterval::State state) {
switch (state) {
case CInterval::S_initial:
return out << "initial";
case CInterval::S_started:
return out << "started";
case CInterval::S_paused:
return out << "paused";
case CInterval::S_final:
return out << "final";
}
return out << "**invalid state(" << (int)state << ")**";
}

View File

@ -22,6 +22,7 @@
#include "directbase.h"
#include "typedReferenceCount.h"
#include "pvector.h"
#include "config_interval.h"
////////////////////////////////////////////////////////////////////
// Class : CInterval
@ -56,6 +57,15 @@ PUBLISHED:
ET_interrupt
};
enum State {
S_initial,
S_started,
S_paused,
S_final
};
INLINE State get_state() const;
INLINE void set_t(double t, EventType event = ET_step);
INLINE double get_t() const;
@ -63,6 +73,9 @@ PUBLISHED:
int step_play();
// These functions control the actual playback of the interval.
// Don't call them directly; they're intended to be called from a
// supervising object, e.g. the Python start() .. finish()
// interface.
virtual void initialize(double t);
virtual void instant();
virtual void step(double t);
@ -81,7 +94,10 @@ public:
protected:
INLINE void recompute() const;
virtual void do_recompute();
INLINE void check_stopped(const char *method_name) const;
INLINE void check_started(const char *method_name) const;
State _state;
double _curr_t;
string _name;
double _duration;
@ -128,6 +144,7 @@ private:
};
INLINE ostream &operator << (ostream &out, const CInterval &ival);
ostream &operator << (ostream &out, CInterval::State state);
#include "cInterval.I"

View File

@ -31,6 +31,8 @@ TypeHandle CLerpAnimEffectInterval::_type_handle;
////////////////////////////////////////////////////////////////////
void CLerpAnimEffectInterval::
step(double t) {
check_started("step");
_state = S_started;
double d = compute_delta(t);
Controls::iterator ci;

View File

@ -64,8 +64,10 @@ CLerpNodePathInterval(const string &name, double duration,
////////////////////////////////////////////////////////////////////
void CLerpNodePathInterval::
initialize(double t) {
check_stopped("initialize");
recompute();
_prev_d = 0.0;
_state = S_started;
step(t);
}
@ -79,9 +81,12 @@ initialize(double t) {
////////////////////////////////////////////////////////////////////
void CLerpNodePathInterval::
instant() {
check_stopped("instant");
recompute();
_prev_d = 0.0;
_state = S_started;
step(get_duration());
_state = S_final;
}
////////////////////////////////////////////////////////////////////
@ -93,6 +98,8 @@ instant() {
////////////////////////////////////////////////////////////////////
void CLerpNodePathInterval::
step(double t) {
check_started("step");
_state = S_started;
double d = compute_delta(t);
if ((_flags & (F_end_pos | F_end_hpr | F_end_scale)) != 0) {
@ -278,7 +285,9 @@ step(double t) {
////////////////////////////////////////////////////////////////////
void CLerpNodePathInterval::
reverse_initialize(double t) {
check_stopped("reverse_initialize");
recompute();
_state = S_started;
_prev_d = 1.0;
step(t);
}
@ -294,9 +303,12 @@ reverse_initialize(double t) {
////////////////////////////////////////////////////////////////////
void CLerpNodePathInterval::
reverse_instant() {
check_stopped("reverse_initialize");
recompute();
_state = S_started;
_prev_d = 1.0;
step(0.0);
_state = S_initial;
}
////////////////////////////////////////////////////////////////////

View File

@ -330,6 +330,7 @@ get_interval_end_time(const string &name) const {
////////////////////////////////////////////////////////////////////
void CMetaInterval::
initialize(double t) {
check_stopped("initialize");
// It may be tempting to flush the event_queue here, but don't do
// it. Those are events that must still be serviced from some
// previous interval operation. Throwing them away would be a
@ -354,6 +355,7 @@ initialize(double t) {
finish_events_forward(now, new_active);
_curr_t = t;
_state = S_started;
}
////////////////////////////////////////////////////////////////////
@ -366,6 +368,7 @@ initialize(double t) {
////////////////////////////////////////////////////////////////////
void CMetaInterval::
instant() {
check_stopped("instant");
recompute();
_active.clear();
@ -381,6 +384,7 @@ instant() {
_next_event_index = _events.size();
_curr_t = get_duration();
_state = S_final;
}
////////////////////////////////////////////////////////////////////
@ -392,6 +396,7 @@ instant() {
////////////////////////////////////////////////////////////////////
void CMetaInterval::
step(double t) {
check_started("step");
int now = double_to_int_time(t);
// Now look for events between the last time we ran and the current
@ -426,6 +431,7 @@ step(double t) {
}
_curr_t = t;
_state = S_started;
}
////////////////////////////////////////////////////////////////////
@ -437,6 +443,11 @@ step(double t) {
////////////////////////////////////////////////////////////////////
void CMetaInterval::
finalize() {
double duration = get_duration();
if (_state == S_initial) {
initialize(duration);
}
// Do all remaining events.
ActiveEvents new_active;
while (_next_event_index < _events.size()) {
@ -446,8 +457,9 @@ finalize() {
_next_event_index++;
}
_curr_t = get_duration();
finish_events_forward(double_to_int_time(_curr_t), new_active);
finish_events_forward(double_to_int_time(duration), new_active);
_curr_t = duration;
_state = S_final;
}
////////////////////////////////////////////////////////////////////
@ -460,6 +472,7 @@ finalize() {
////////////////////////////////////////////////////////////////////
void CMetaInterval::
reverse_initialize(double t) {
check_stopped("reverse_initialize");
// It may be tempting to flush the event_queue here, but don't do
// it. Those are events that must still be serviced from some
// previous interval operation. Throwing them away would be a
@ -484,6 +497,7 @@ reverse_initialize(double t) {
finish_events_reverse(now, new_active);
_curr_t = t;
_state = S_started;
}
////////////////////////////////////////////////////////////////////
@ -497,6 +511,7 @@ reverse_initialize(double t) {
////////////////////////////////////////////////////////////////////
void CMetaInterval::
reverse_instant() {
check_stopped("reverse_instant");
recompute();
_active.clear();
@ -512,6 +527,7 @@ reverse_instant() {
_next_event_index = 0;
_curr_t = 0.0;
_state = S_initial;
}
////////////////////////////////////////////////////////////////////
@ -523,6 +539,10 @@ reverse_instant() {
////////////////////////////////////////////////////////////////////
void CMetaInterval::
reverse_finalize() {
if (_state == S_initial) {
initialize(0.0);
}
// Do all remaining events at the beginning.
ActiveEvents new_active;
@ -534,6 +554,7 @@ reverse_finalize() {
finish_events_reverse(0, new_active);
_curr_t = 0.0;
_state = S_initial;
}
////////////////////////////////////////////////////////////////////
@ -557,6 +578,9 @@ interrupt() {
PlaybackEvent *event = (*ai);
enqueue_event(event->_n, ET_interrupt, false);
}
if (_state == S_started) {
_state = S_paused;
}
}
////////////////////////////////////////////////////////////////////

View File

@ -38,6 +38,10 @@ ConfigureFn(config_interval) {
// CMetaInterval created.
const double interval_precision = config_interval.GetDouble("interval-precision", 1000.0);
// Set this true to generate an assertion failure if interval
// functions are called out-of-order.
const bool verify_intervals = config_interval.GetBool("verify-intervals", false);
////////////////////////////////////////////////////////////////////
// Function: init_libinterval
// Description: Initializes the library. This must be called at

View File

@ -26,6 +26,7 @@
NotifyCategoryDecl(interval, EXPCL_DIRECT, EXPTP_DIRECT);
extern const double interval_precision;
extern const bool verify_intervals;
extern EXPCL_DIRECT void init_libinterval();

View File

@ -50,7 +50,9 @@ ShowInterval(const NodePath &node, const string &name) :
////////////////////////////////////////////////////////////////////
void ShowInterval::
instant() {
check_stopped("instant");
_node.show();
_state = S_final;
}
////////////////////////////////////////////////////////////////////
@ -64,5 +66,7 @@ instant() {
////////////////////////////////////////////////////////////////////
void ShowInterval::
reverse_instant() {
check_stopped("instant");
_node.hide();
_state = S_initial;
}