15 #include "cInterval.h"
16 #include "cIntervalManager.h"
18 #include "clockObject.h"
20 #include "eventQueue.h"
21 #include "pStatTimer.h"
23 PStatCollector CInterval::_root_pcollector(
"App:Show code:ivalLoop");
27 get_pstats_name(
const string &name) {
29 size_t hyphen = pname.find(
'-');
30 if (hyphen != string::npos) {
31 pname = pname.substr(0, hyphen);
42 CInterval(
const string &name,
double duration,
bool open_ended) :
46 _pname(get_pstats_name(name)),
47 _duration(max(duration, 0.0)),
48 _open_ended(open_ended),
50 _ival_pcollector(_root_pcollector, _pname)
54 _wants_t_callback =
false;
55 _last_t_callback = -1.0;
60 _start_t_at_start =
true;
66 if (interval_cat.is_spam()) {
68 <<
"Constructing interval " << (
void *)
this <<
", duration = "
80 if (interval_cat.is_spam()) {
82 <<
"Destructing interval " << (
void *)
this <<
"\n";
151 start(
double start_t,
double end_t,
double play_rate) {
169 loop(
double start_t,
double end_t,
double play_rate) {
311 _play_rate = play_rate;
314 _play_rate = play_rate;
344 case ET_reverse_initialize:
348 case ET_reverse_instant:
352 case ET_reverse_finalize:
361 interval_cat.warning()
362 <<
"Invalid event type: " << (int)event <<
"\n";
375 check_stopped(get_class_type(),
"priv_initialize");
391 check_stopped(get_class_type(),
"priv_instant");
408 check_started(get_class_type(),
"priv_step");
423 check_started(get_class_type(),
"priv_finalize");
440 check_stopped(get_class_type(),
"priv_reverse_initialize");
457 check_stopped(get_class_type(),
"priv_reverse_instant");
473 check_started(get_class_type(),
"priv_reverse_finalize");
494 check_started(get_class_type(),
"priv_interrupt");
504 output(ostream &out)
const {
517 write(ostream &out,
int indent_level)
const {
518 indent(out, indent_level) << *
this <<
"\n";
538 setup_play(
double start_t,
double end_t,
double play_rate,
bool do_loop) {
539 nassertv(start_t < end_t || end_t < 0.0);
540 nassertv(play_rate != 0.0);
545 if (start_t <= 0.0) {
547 _start_t_at_start =
true;
548 }
else if (start_t > duration) {
550 _start_t_at_start =
false;
553 _start_t_at_start =
false;
555 if (end_t < 0.0 || end_t >= duration) {
557 _end_t_at_end =
true;
560 _end_t_at_end =
false;
564 _play_rate = play_rate;
579 if (_play_rate > 0.0) {
580 _clock_start = now - ((
get_t() - _start_t) / _play_rate);
582 }
else if (_play_rate < 0.0) {
583 _clock_start = now - ((
get_t() - _end_t) / _play_rate);
600 if (end_t < 0.0 || end_t >= duration) {
602 _end_t_at_end =
true;
605 _end_t_at_end =
false;
625 if (_play_rate >= 0.0) {
626 double t = (now - _clock_start) * _play_rate + _start_t;
664 if (_end_t == _start_t) {
671 double time_per_loop = (_end_t - _start_t) / _play_rate;
672 double num_loops = floor((now - _clock_start) / time_per_loop);
673 _loop_count += (int)num_loops;
674 _clock_start += num_loops * time_per_loop;
680 double t = (now - _clock_start) * _play_rate + _end_t;
692 if (_start_t_at_start) {
714 if (_end_t == _start_t) {
721 double time_per_loop = (_end_t - _start_t) / -_play_rate;
722 double num_loops = floor((now - _clock_start) / time_per_loop);
723 _loop_count += (int)num_loops;
724 _clock_start += num_loops * time_per_loop;
729 bool should_continue = (_loop_count == 0 || _do_loop);
731 if (!should_continue && _state == S_started) {
735 return should_continue;
749 Parents::iterator pi;
750 for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
764 if (!_done_event.empty()) {
782 operator << (ostream &out, CInterval::State state) {
784 case CInterval::S_initial:
785 return out <<
"initial";
787 case CInterval::S_started:
788 return out <<
"started";
790 case CInterval::S_paused:
791 return out <<
"paused";
793 case CInterval::S_final:
794 return out <<
"final";
797 return out <<
"**invalid state(" << (int)state <<
")**";
int find_c_interval(const string &name) const
Returns the index associated with the named interval, if there is such an interval, or -1 if there is not.
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
void set_t(double t)
Explicitly sets the time within the interval.
virtual void priv_step(double t)
Advances the time on the interval.
void setup_play(double start_time, double end_time, double play_rate, bool do_loop)
Called to prepare the interval for automatic timed playback, e.g.
virtual void priv_instant()
This is called in lieu of priv_initialize() .
double pause()
Stops the interval from playing but leaves it in its current state.
bool is_stopped() const
Returns true if the interval is in either its initial or final states (but not in a running or paused...
void resume_until(double end_t)
Restarts the interval from the current point after a previous call to pause() (or a previous play-to-...
void setup_resume()
Called to prepare the interval for restarting at the current point within the interval after an inter...
bool is_playing() const
Returns true if the interval is currently playing, false otherwise.
const string & get_name() const
Returns the interval's name.
void loop(double start_t=0.0, double end_t=-1.0, double play_rate=1.0)
Starts the interval playing by registering it with the current CIntervalManager.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
bool step_play()
Should be called once per frame to execute the automatic timed playback begun with setup_play()...
virtual void priv_finalize()
This is called to stop an interval, forcing it to whatever state it would be after it played all the ...
virtual void priv_interrupt()
This is called while the interval is playing to indicate that it is about to be interrupted; that is...
static CIntervalManager * get_global_ptr()
Returns the pointer to the one global CIntervalManager object.
State get_state() const
Indicates the state the interval believes it is in: whether it has been started, is currently in the ...
void finish()
Stops the interval from playing and sets it to its final state.
void set_play_rate(double play_rate)
Changes the play rate of the interval.
void remove_c_interval(int index)
Removes the indicated interval from the queue immediately.
A lightweight class that represents a single element that may be timed and/or counted via stats...
double get_duration() const
Returns the duration of the interval in seconds.
EventQueue * get_event_queue() const
Returns the custom event queue to be used for throwing done events from intervals as they finish...
double get_frame_time(Thread *current_thread=Thread::get_current_thread()) const
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
void start(double start_t=0.0, double end_t=-1.0, double play_rate=1.0)
Starts the interval playing by registering it with the current CIntervalManager.
virtual void priv_reverse_initialize(double t)
Similar to priv_initialize(), but this is called when the interval is being played backwards; it indi...
bool get_open_ended() const
Returns the state of the "open_ended" flag.
virtual void priv_initialize(double t)
This replaces the first call to priv_step(), and indicates that the interval has just begun...
void setup_resume_until(double end_t)
Called to prepare the interval for restarting from the current point after a previous call to pause()...
A named event, possibly with parameters.
double get_t() const
Returns the current time of the interval: the last value of t passed to priv_initialize(), priv_step(), or priv_finalize().
void resume()
Restarts the interval from its current point after a previous call to pause().
virtual void priv_reverse_instant()
This is called in lieu of priv_reverse_initialize()
void priv_do_event(double t, EventType event)
Calls the appropriate event function indicated by the EventType.
void mark_dirty()
Called by a derived class to indicate the interval has been changed internally and must be recomputed...
int add_c_interval(CInterval *interval, bool external)
Adds the interval to the manager, and returns a unique index for the interval.
TypeHandle is the identifier used to differentiate C++ class types.
double get_play_rate() const
Returns the play rate as set by the last call to start(), loop(), or set_play_rate().
virtual void priv_reverse_finalize()
Called generally following a priv_reverse_initialize(), this indicates the interval should set itself...
void clear_to_initial()
Pauses the interval, if it is playing, and resets its state to its initial state, abandoning any stat...