32 CMetaInterval(
const string &name) :
35 _precision = interval_precision;
36 _current_nesting_level = 0;
37 _next_event_index = 0;
38 _processing_events =
false;
56 bool lost_events =
false;
57 if (!_event_queue.empty()) {
58 interval_cat.warning()
59 <<
"Losing outstanding events for " << *
this <<
"\n";
69 for (di = _defs.begin(); di != _defs.end(); ++di) {
70 IntervalDef &def = (*di);
71 if (def._c_interval !=
nullptr) {
72 CInterval::Parents::iterator pi =
73 find(def._c_interval->_parents.begin(),
74 def._c_interval->_parents.end(),
76 nassertv(pi != def._c_interval->_parents.end());
77 def._c_interval->_parents.erase(pi);
82 _current_nesting_level = 0;
83 _next_event_index = 0;
86 if (verify_intervals) {
87 nassertv(!lost_events);
101 push_level(
const string &name,
double rel_time, RelativeStart rel_to) {
102 nassertr(_event_queue.empty() && !_processing_events, -1);
104 _defs.push_back(IntervalDef());
105 IntervalDef &def = _defs.back();
106 def._type = DT_push_level;
107 def._ext_name = name;
108 def._rel_time = rel_time;
109 def._rel_to = rel_to;
110 _current_nesting_level++;
113 return (
int)_defs.size() - 1;
125 double rel_time, RelativeStart rel_to) {
126 nassertr(_event_queue.empty() && !_processing_events, -1);
127 nassertr(c_interval !=
nullptr, -1);
129 c_interval->_parents.push_back(
this);
130 c_interval->_ival_pcollector =
PStatCollector(_ival_pcollector, c_interval->_pname);
131 _defs.push_back(IntervalDef());
132 IntervalDef &def = _defs.back();
133 def._type = DT_c_interval;
134 def._c_interval = c_interval;
135 def._rel_time = rel_time;
136 def._rel_to = rel_to;
139 return (
int)_defs.size() - 1;
161 double rel_time, RelativeStart rel_to) {
162 nassertr(_event_queue.empty() && !_processing_events, -1);
164 _defs.push_back(IntervalDef());
165 IntervalDef &def = _defs.back();
166 def._type = DT_ext_index;
167 def._ext_index = ext_index;
168 def._ext_name = name;
169 def._ext_duration = duration;
170 def._ext_open_ended = open_ended;
171 def._rel_time = rel_time;
172 def._rel_to = rel_to;
175 return (
int)_defs.size() - 1;
188 nassertr(_event_queue.empty() && !_processing_events, -1);
189 nassertr(_current_nesting_level > 0, -1);
191 _defs.push_back(IntervalDef());
192 IntervalDef &def = _defs.back();
193 def._type = DT_pop_level;
194 def._ext_duration = duration;
195 _current_nesting_level--;
198 return (
int)_defs.size() - 1;
212 CMetaInterval::RelativeStart rel_to) {
213 nassertr(_event_queue.empty() && !_processing_events,
false);
215 for (di = _defs.begin(); di != _defs.end(); ++di) {
216 IntervalDef &def = (*di);
221 match = (def._c_interval->get_name() == name);
225 match = (def._ext_name == name);
233 def._rel_time = rel_time;
234 def._rel_to = rel_to;
251 Defs::const_iterator di;
252 for (di = _defs.begin(); di != _defs.end(); ++di) {
253 const IntervalDef &def = (*di);
258 match = (def._c_interval->get_name() == name);
262 match = (def._ext_name == name);
270 return int_to_double_time(def._actual_begin_time);
285 Defs::const_iterator di;
286 for (di = _defs.begin(); di != _defs.end(); ++di) {
287 const IntervalDef &def = (*di);
290 double duration = 0.0;
293 duration = def._c_interval->get_duration();
294 match = (def._c_interval->get_name() == name);
298 duration = def._ext_duration;
299 match = (def._ext_name == name);
307 return int_to_double_time(def._actual_begin_time) + duration;
321 if (_processing_events) {
322 enqueue_self_event(ET_initialize, t);
326 check_stopped(get_class_type(),
"priv_initialize");
332 _next_event_index = 0;
335 int now = double_to_int_time(t);
348 _processing_events =
true;
350 while (_next_event_index < _events.size() &&
351 _events[_next_event_index]->_time <= now) {
352 PlaybackEvent *
event = _events[_next_event_index];
356 do_event_forward(event, new_active,
true);
358 finish_events_forward(now, new_active);
359 _processing_events =
false;
372 if (_processing_events) {
373 enqueue_self_event(ET_instant);
377 check_stopped(get_class_type(),
"priv_instant");
383 _processing_events =
true;
384 PlaybackEvents::iterator ei;
385 for (ei = _events.begin(); ei != _events.end(); ++ei) {
386 PlaybackEvent *
event = (*ei);
387 if (event->_type != PET_begin) {
388 enqueue_event(event->_n, ET_instant,
true, 0);
391 _processing_events =
false;
393 _next_event_index = _events.size();
397 if (_event_queue.empty()) {
400 enqueue_done_event();
411 if (_processing_events) {
412 enqueue_self_event(ET_step, t);
416 check_started(get_class_type(),
"priv_step");
417 int now = double_to_int_time(t);
431 _processing_events =
true;
432 if (_next_event_index < _events.size() &&
433 _events[_next_event_index]->_time <= now) {
436 while (_next_event_index < _events.size() &&
437 _events[_next_event_index]->_time <= now) {
438 PlaybackEvent *
event = _events[_next_event_index];
442 do_event_forward(event, new_active,
false);
445 finish_events_forward(now, new_active);
450 while (_next_event_index > 0 &&
451 _events[_next_event_index - 1]->_time > now) {
453 PlaybackEvent *
event = _events[_next_event_index];
455 do_event_reverse(event, new_active,
false);
458 finish_events_reverse(now, new_active);
460 _processing_events =
false;
473 if (_processing_events) {
474 enqueue_self_event(ET_finalize);
479 if (_state == S_initial) {
484 _processing_events =
true;
486 while (_next_event_index < _events.size()) {
487 PlaybackEvent *
event = _events[_next_event_index];
491 do_event_forward(event, new_active,
true);
493 finish_events_forward(double_to_int_time(duration), new_active);
494 _processing_events =
false;
499 if (_event_queue.empty()) {
502 enqueue_done_event();
513 if (_processing_events) {
514 enqueue_self_event(ET_reverse_initialize, t);
518 check_stopped(get_class_type(),
"priv_reverse_initialize");
524 _next_event_index = _events.size();
527 int now = double_to_int_time(t);
540 _processing_events =
true;
542 while (_next_event_index > 0 &&
543 _events[_next_event_index - 1]->_time > now) {
545 PlaybackEvent *
event = _events[_next_event_index];
548 do_event_reverse(event, new_active,
true);
550 finish_events_reverse(now, new_active);
551 _processing_events =
false;
565 if (_processing_events) {
566 enqueue_self_event(ET_reverse_instant);
570 check_stopped(get_class_type(),
"priv_reverse_instant");
576 _processing_events =
true;
577 PlaybackEvents::reverse_iterator ei;
578 for (ei = _events.rbegin(); ei != _events.rend(); ++ei) {
579 PlaybackEvent *
event = (*ei);
580 if (event->_type != PET_begin) {
581 enqueue_event(event->_n, ET_reverse_instant,
true, 0);
584 _processing_events =
false;
586 _next_event_index = 0;
597 if (_processing_events) {
598 enqueue_self_event(ET_reverse_finalize);
602 if (_state == S_initial) {
607 _processing_events =
true;
610 while (_next_event_index > 0) {
612 PlaybackEvent *
event = _events[_next_event_index];
614 do_event_reverse(event, new_active,
true);
616 finish_events_reverse(0, new_active);
617 _processing_events =
false;
635 if (_processing_events) {
636 enqueue_self_event(ET_interrupt);
640 _processing_events =
true;
641 ActiveEvents::iterator ai;
642 for (ai = _active.begin(); ai != _active.end(); ++ai) {
643 PlaybackEvent *
event = (*ai);
644 enqueue_event(event->_n, ET_interrupt,
false);
646 _processing_events =
false;
648 if (_state == S_started) {
662 nassertv(!_event_queue.empty());
663 const EventQueueEntry &entry = _event_queue.front();
664 const IntervalDef &def = _defs[entry._n];
665 nassertv(def._type == DT_ext_index);
667 _event_queue.pop_front();
674 write(std::ostream &out,
int indent_level)
const {
678 int num_decimals = (int)ceil(log10(_precision));
679 int total_digits = num_decimals + 4;
680 static const int max_digits = 32;
681 nassertv(total_digits <= max_digits);
683 sprintf(format_str,
"%%%d.%df", total_digits, num_decimals);
687 int extra_indent_level = 1;
688 Defs::const_iterator di;
689 for (di = _defs.begin(); di != _defs.end(); ++di) {
690 const IntervalDef &def = (*di);
691 char time_str[max_digits + 1];
692 sprintf(time_str, format_str, int_to_double_time(def._actual_begin_time));
693 indent(out, indent_level) << time_str;
695 write_event_desc(out, def, extra_indent_level);
707 int num_decimals = (int)ceil(log10(_precision));
708 int total_digits = num_decimals + 4;
709 static const int max_digits = 32;
710 nassertv(total_digits <= max_digits);
712 sprintf(format_str,
"%%%d.%df", total_digits, num_decimals);
714 int extra_indent_level = 0;
715 PlaybackEvents::const_iterator ei;
716 for (ei = _events.begin(); ei != _events.end(); ++ei) {
717 const PlaybackEvent *
event = (*ei);
719 char time_str[max_digits + 1];
720 sprintf(time_str, format_str, int_to_double_time(event->_time));
723 switch (event->_type) {
736 nassertv(n >= 0 && n < (
int)_defs.size());
737 const IntervalDef &def = _defs[n];
739 write_event_desc(out, def, extra_indent_level);
752 int n = recompute_level(0, 0, _end_time);
754 if (n != (
int)_defs.size()) {
755 interval_cat.warning()
756 <<
"CMetaInterval pushes don't match pops.\n";
762 _duration = int_to_double_time(_end_time);
770 PlaybackEvents::iterator ei;
771 for (ei = _events.begin(); ei != _events.end(); ++ei) {
772 PlaybackEvent *
event = (*ei);
788 do_event_forward(CMetaInterval::PlaybackEvent *event,
790 switch (event->_type) {
792 nassertv(event->_begin_event == event);
793 new_active.push_back(event);
800 ActiveEvents::iterator ai;
801 ai = find(new_active.begin(), new_active.end(), event->_begin_event);
802 if (ai != new_active.end()) {
803 new_active.erase(ai);
806 enqueue_event(event->_n, ET_instant, is_initial);
809 ai = find(_active.begin(), _active.end(), event->_begin_event);
810 if (ai != _active.end()) {
812 enqueue_event(event->_n, ET_finalize, is_initial);
818 <<
"Event " <<
event->_begin_event->_n <<
" not on active list.\n";
826 nassertv(event->_begin_event == event);
827 enqueue_event(event->_n, ET_instant, is_initial);
841 ActiveEvents::iterator ai;
842 for (ai = _active.begin(); ai != _active.end(); ++ai) {
843 PlaybackEvent *
event = (*ai);
844 enqueue_event(event->_n, ET_step,
false, now - event->_time);
848 for (ai = new_active.begin(); ai != new_active.end(); ++ai) {
849 PlaybackEvent *
event = (*ai);
850 enqueue_event(event->_n, ET_initialize,
false, now - event->_time);
851 _active.push_back(event);
865 do_event_reverse(CMetaInterval::PlaybackEvent *event,
868 switch (event->_type) {
871 nassertv(event->_begin_event == event);
874 ActiveEvents::iterator ai;
875 ai = find(new_active.begin(), new_active.end(), event);
876 if (ai != new_active.end()) {
877 new_active.erase(ai);
879 enqueue_event(event->_n, ET_reverse_instant, is_initial);
882 ai = find(_active.begin(), _active.end(), event);
883 if (ai != _active.end()) {
885 enqueue_event(event->_n, ET_reverse_finalize, is_initial);
891 <<
"Event " <<
event->_n <<
" not on active list.\n";
899 new_active.push_front(event->_begin_event);
903 nassertv(event->_begin_event == event);
904 enqueue_event(event->_n, ET_reverse_instant, is_initial);
918 ActiveEvents::iterator ai;
919 for (ai = _active.begin(); ai != _active.end(); ++ai) {
920 PlaybackEvent *
event = (*ai);
921 enqueue_event(event->_n, ET_step,
false, now - event->_time);
925 for (ai = new_active.begin(); ai != new_active.end(); ++ai) {
926 PlaybackEvent *
event = (*ai);
927 enqueue_event(event->_n, ET_reverse_initialize,
false, now - event->_time);
928 _active.push_front(event);
945 enqueue_event(
int n, CInterval::EventType event_type,
bool is_initial,
int time) {
946 nassertv(n >= 0 && n < (
int)_defs.size());
947 const IntervalDef &def = _defs[n];
951 (event_type == ET_instant || event_type == ET_reverse_instant) &&
952 !def._c_interval->get_open_ended()) {
957 if (_event_queue.empty()) {
961 def._c_interval->priv_do_event(int_to_double_time(time), event_type);
969 (event_type == ET_instant || event_type == ET_reverse_instant) &&
970 !def._ext_open_ended) {
982 _event_queue.push_back(EventQueueEntry(n, event_type, time));
994 enqueue_self_event(CInterval::EventType event_type,
double t) {
996 <<
"Recursive reentry detected into " << *
this <<
"\n";
997 int time = double_to_int_time(t);
998 _event_queue.push_back(EventQueueEntry(-1, event_type, time));
1005 void CMetaInterval::
1006 enqueue_done_event() {
1007 _event_queue.push_back(EventQueueEntry(-2, ET_finalize, 0));
1017 bool CMetaInterval::
1018 service_event_queue() {
1019 while (!_event_queue.empty()) {
1020 nassertr(!_processing_events,
true);
1021 const EventQueueEntry &entry = _event_queue.front();
1022 if (entry._n == -1) {
1024 priv_do_event(int_to_double_time(entry._time), entry._event_type);
1026 }
else if (entry._n == -2) {
1032 nassertr(entry._n >= 0 && entry._n < (
int)_defs.size(),
false);
1033 const IntervalDef &def = _defs[entry._n];
1034 switch (def._type) {
1037 def._c_interval->priv_do_event(int_to_double_time(entry._time), entry._event_type);
1045 nassertr(
false,
false);
1049 _event_queue.pop_front();
1053 nassertr(!_processing_events,
false);
1069 recompute_level(
int n,
int level_begin,
int &level_end) {
1070 level_end = level_begin;
1071 int previous_begin = level_begin;
1072 int previous_end = level_begin;
1074 while (n < (
int)_defs.size() && _defs[n]._type != DT_pop_level) {
1075 IntervalDef &def = _defs[n];
1076 int begin_time = previous_begin;
1077 int end_time = previous_end;
1078 switch (def._type) {
1080 begin_time = get_begin_time(def, level_begin, previous_begin, previous_end);
1081 def._actual_begin_time = begin_time;
1082 end_time = begin_time + double_to_int_time(def._c_interval->get_duration());
1084 if (def._c_interval->is_exact_type(WaitInterval::get_class_type())) {
1089 if (begin_time == end_time) {
1090 _events.push_back(
new PlaybackEvent(begin_time, n, PET_instant));
1092 PlaybackEvent *begin =
new PlaybackEvent(begin_time, n, PET_begin);
1093 PlaybackEvent *end =
new PlaybackEvent(end_time, n, PET_end);
1094 end->_begin_event = begin;
1095 _events.push_back(begin);
1096 _events.push_back(end);
1102 begin_time = get_begin_time(def, level_begin, previous_begin, previous_end);
1103 def._actual_begin_time = begin_time;
1104 end_time = begin_time + double_to_int_time(def._ext_duration);
1105 if (begin_time == end_time) {
1106 _events.push_back(
new PlaybackEvent(begin_time, n, PET_instant));
1108 PlaybackEvent *begin =
new PlaybackEvent(begin_time, n, PET_begin);
1109 PlaybackEvent *end =
new PlaybackEvent(end_time, n, PET_end);
1110 end->_begin_event = begin;
1111 _events.push_back(begin);
1112 _events.push_back(end);
1117 begin_time = get_begin_time(def, level_begin, previous_begin, previous_end);
1118 def._actual_begin_time = begin_time;
1119 n = recompute_level(n + 1, begin_time, end_time);
1123 nassertr(
false, _defs.size());
1127 previous_begin = begin_time;
1128 previous_end = end_time;
1129 level_end = std::max(level_end, end_time);
1133 if (n < (
int)_defs.size()) {
1134 IntervalDef &def = _defs[n];
1136 if (def._ext_duration >= 0.0) {
1137 level_end = level_begin + double_to_int_time(def._ext_duration);
1142 def._actual_begin_time = level_end;
1153 get_begin_time(
const CMetaInterval::IntervalDef &def,
int level_begin,
1154 int previous_begin,
int previous_end) {
1155 switch (def._rel_to) {
1156 case RS_previous_end:
1157 return previous_end + double_to_int_time(def._rel_time);
1159 case RS_previous_begin:
1160 return previous_begin + double_to_int_time(def._rel_time);
1162 case RS_level_begin:
1163 return level_begin + double_to_int_time(def._rel_time);
1166 nassertr(
false, previous_end);
1167 return previous_end;
1173 void CMetaInterval::
1174 write_event_desc(std::ostream &out,
const CMetaInterval::IntervalDef &def,
1175 int &extra_indent_level)
const {
1176 switch (def._type) {
1178 indent(out, extra_indent_level)
1179 << *def._c_interval;
1180 if (!def._c_interval->get_open_ended()) {
1187 indent(out, extra_indent_level)
1188 <<
"*" << def._ext_name;
1189 if (def._ext_duration != 0.0) {
1190 out <<
" dur " << def._ext_duration;
1192 if (!def._ext_open_ended) {
1199 indent(out, extra_indent_level)
1200 << def._ext_name <<
" {\n";
1201 extra_indent_level += 2;
1205 extra_indent_level -= 2;
1206 indent(out, extra_indent_level)