00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "cMetaInterval.h"
00016 #include "waitInterval.h"
00017 #include "config_interval.h"
00018 #include "indirectLess.h"
00019 #include "indent.h"
00020
00021 #include <algorithm>
00022 #include <math.h>
00023 #include <stdio.h>
00024
00025 TypeHandle CMetaInterval::_type_handle;
00026
00027
00028
00029
00030
00031
00032 CMetaInterval::
00033 CMetaInterval(const string &name) :
00034 CInterval(name, 0.0, true)
00035 {
00036 _precision = interval_precision;
00037 _current_nesting_level = 0;
00038 _next_event_index = 0;
00039 _processing_events = false;
00040 }
00041
00042
00043
00044
00045
00046
00047 CMetaInterval::
00048 ~CMetaInterval() {
00049 clear_intervals();
00050 }
00051
00052
00053
00054
00055
00056
00057
00058 void CMetaInterval::
00059 clear_intervals() {
00060
00061
00062 bool lost_events = false;
00063 if (!_event_queue.empty()) {
00064 interval_cat.warning()
00065 << "Losing outstanding events for " << *this << "\n";
00066 _event_queue.clear();
00067 lost_events = true;
00068 }
00069
00070 clear_events();
00071
00072
00073
00074 Defs::iterator di;
00075 for (di = _defs.begin(); di != _defs.end(); ++di) {
00076 IntervalDef &def = (*di);
00077 if (def._c_interval != (CInterval *)NULL) {
00078 CInterval::Parents::iterator pi =
00079 find(def._c_interval->_parents.begin(),
00080 def._c_interval->_parents.end(),
00081 this);
00082 nassertv(pi != def._c_interval->_parents.end());
00083 def._c_interval->_parents.erase(pi);
00084 }
00085 }
00086 _defs.clear();
00087
00088 _current_nesting_level = 0;
00089 _next_event_index = 0;
00090
00091 #ifndef NDEBUG
00092 if (verify_intervals) {
00093 nassertv(!lost_events);
00094 }
00095 #endif
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 int CMetaInterval::
00111 push_level(const string &name, double rel_time, RelativeStart rel_to) {
00112 nassertr(_event_queue.empty() && !_processing_events, -1);
00113
00114 _defs.push_back(IntervalDef());
00115 IntervalDef &def = _defs.back();
00116 def._type = DT_push_level;
00117 def._ext_name = name;
00118 def._rel_time = rel_time;
00119 def._rel_to = rel_to;
00120 _current_nesting_level++;
00121 mark_dirty();
00122
00123 return (int)_defs.size() - 1;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 int CMetaInterval::
00137 add_c_interval(CInterval *c_interval,
00138 double rel_time, RelativeStart rel_to) {
00139 nassertr(_event_queue.empty() && !_processing_events, -1);
00140 nassertr(c_interval != (CInterval *)NULL, -1);
00141
00142 c_interval->_parents.push_back(this);
00143 c_interval->_ival_pcollector = PStatCollector(_ival_pcollector, c_interval->_pname);
00144 _defs.push_back(IntervalDef());
00145 IntervalDef &def = _defs.back();
00146 def._type = DT_c_interval;
00147 def._c_interval = c_interval;
00148 def._rel_time = rel_time;
00149 def._rel_to = rel_to;
00150 mark_dirty();
00151
00152 return (int)_defs.size() - 1;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 int CMetaInterval::
00178 add_ext_index(int ext_index, const string &name, double duration,
00179 bool open_ended,
00180 double rel_time, RelativeStart rel_to) {
00181 nassertr(_event_queue.empty() && !_processing_events, -1);
00182
00183 _defs.push_back(IntervalDef());
00184 IntervalDef &def = _defs.back();
00185 def._type = DT_ext_index;
00186 def._ext_index = ext_index;
00187 def._ext_name = name;
00188 def._ext_duration = duration;
00189 def._ext_open_ended = open_ended;
00190 def._rel_time = rel_time;
00191 def._rel_to = rel_to;
00192 mark_dirty();
00193
00194 return (int)_defs.size() - 1;
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 int CMetaInterval::
00210 pop_level(double duration) {
00211 nassertr(_event_queue.empty() && !_processing_events, -1);
00212 nassertr(_current_nesting_level > 0, -1);
00213
00214 _defs.push_back(IntervalDef());
00215 IntervalDef &def = _defs.back();
00216 def._type = DT_pop_level;
00217 def._ext_duration = duration;
00218 _current_nesting_level--;
00219 mark_dirty();
00220
00221 return (int)_defs.size() - 1;
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 bool CMetaInterval::
00240 set_interval_start_time(const string &name, double rel_time,
00241 CMetaInterval::RelativeStart rel_to) {
00242 nassertr(_event_queue.empty() && !_processing_events, false);
00243 Defs::iterator di;
00244 for (di = _defs.begin(); di != _defs.end(); ++di) {
00245 IntervalDef &def = (*di);
00246
00247 bool match = false;
00248 switch (def._type) {
00249 case DT_c_interval:
00250 match = (def._c_interval->get_name() == name);
00251 break;
00252
00253 case DT_ext_index:
00254 match = (def._ext_name == name);
00255 break;
00256
00257 default:
00258 break;
00259 }
00260 if (match) {
00261
00262 def._rel_time = rel_time;
00263 def._rel_to = rel_to;
00264 mark_dirty();
00265 return true;
00266 }
00267 }
00268
00269 return false;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 double CMetaInterval::
00281 get_interval_start_time(const string &name) const {
00282 recompute();
00283 Defs::const_iterator di;
00284 for (di = _defs.begin(); di != _defs.end(); ++di) {
00285 const IntervalDef &def = (*di);
00286
00287 bool match = false;
00288 switch (def._type) {
00289 case DT_c_interval:
00290 match = (def._c_interval->get_name() == name);
00291 break;
00292
00293 case DT_ext_index:
00294 match = (def._ext_name == name);
00295 break;
00296
00297 default:
00298 break;
00299 }
00300 if (match) {
00301
00302 return int_to_double_time(def._actual_begin_time);
00303 }
00304 }
00305
00306 return -1.0;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 double CMetaInterval::
00318 get_interval_end_time(const string &name) const {
00319 recompute();
00320 Defs::const_iterator di;
00321 for (di = _defs.begin(); di != _defs.end(); ++di) {
00322 const IntervalDef &def = (*di);
00323
00324 bool match = false;
00325 double duration = 0.0;
00326 switch (def._type) {
00327 case DT_c_interval:
00328 duration = def._c_interval->get_duration();
00329 match = (def._c_interval->get_name() == name);
00330 break;
00331
00332 case DT_ext_index:
00333 duration = def._ext_duration;
00334 match = (def._ext_name == name);
00335 break;
00336
00337 default:
00338 break;
00339 }
00340 if (match) {
00341
00342 return int_to_double_time(def._actual_begin_time) + duration;
00343 }
00344 }
00345
00346 return -1.0;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 void CMetaInterval::
00358 priv_initialize(double t) {
00359 if (_processing_events) {
00360 enqueue_self_event(ET_initialize, t);
00361 return;
00362 }
00363
00364 check_stopped(get_class_type(), "priv_initialize");
00365
00366
00367
00368
00369
00370 recompute();
00371 _next_event_index = 0;
00372 _active.clear();
00373
00374 int now = double_to_int_time(t);
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 _processing_events = true;
00388 ActiveEvents new_active;
00389 while (_next_event_index < _events.size() &&
00390 _events[_next_event_index]->_time <= now) {
00391 PlaybackEvent *event = _events[_next_event_index];
00392 _next_event_index++;
00393
00394
00395 do_event_forward(event, new_active, true);
00396 }
00397 finish_events_forward(now, new_active);
00398 _processing_events = false;
00399
00400 _curr_t = t;
00401 _state = S_started;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 void CMetaInterval::
00413 priv_instant() {
00414 if (_processing_events) {
00415 enqueue_self_event(ET_instant);
00416 return;
00417 }
00418
00419 check_stopped(get_class_type(), "priv_instant");
00420 recompute();
00421 _active.clear();
00422
00423
00424
00425 _processing_events = true;
00426 PlaybackEvents::iterator ei;
00427 for (ei = _events.begin(); ei != _events.end(); ++ei) {
00428 PlaybackEvent *event = (*ei);
00429 if (event->_type != PET_begin) {
00430 enqueue_event(event->_n, ET_instant, true, 0);
00431 }
00432 }
00433 _processing_events = false;
00434
00435 _next_event_index = _events.size();
00436 _curr_t = get_duration();
00437 _state = S_final;
00438
00439 if (_event_queue.empty()) {
00440 interval_done();
00441 } else {
00442 enqueue_done_event();
00443 }
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453 void CMetaInterval::
00454 priv_step(double t) {
00455 if (_processing_events) {
00456 enqueue_self_event(ET_step, t);
00457 return;
00458 }
00459
00460 check_started(get_class_type(), "priv_step");
00461 int now = double_to_int_time(t);
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 _processing_events = true;
00477 if (_next_event_index < _events.size() &&
00478 _events[_next_event_index]->_time <= now) {
00479
00480 ActiveEvents new_active;
00481 while (_next_event_index < _events.size() &&
00482 _events[_next_event_index]->_time <= now) {
00483 PlaybackEvent *event = _events[_next_event_index];
00484 _next_event_index++;
00485
00486
00487 do_event_forward(event, new_active, false);
00488 }
00489
00490 finish_events_forward(now, new_active);
00491
00492 } else {
00493
00494 ActiveEvents new_active;
00495 while (_next_event_index > 0 &&
00496 _events[_next_event_index - 1]->_time > now) {
00497 _next_event_index--;
00498 PlaybackEvent *event = _events[_next_event_index];
00499
00500 do_event_reverse(event, new_active, false);
00501 }
00502
00503 finish_events_reverse(now, new_active);
00504 }
00505 _processing_events = false;
00506
00507 _curr_t = t;
00508 _state = S_started;
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518 void CMetaInterval::
00519 priv_finalize() {
00520 if (_processing_events) {
00521 enqueue_self_event(ET_finalize);
00522 return;
00523 }
00524
00525 double duration = get_duration();
00526 if (_state == S_initial) {
00527 priv_initialize(duration);
00528 }
00529
00530
00531 _processing_events = true;
00532 ActiveEvents new_active;
00533 while (_next_event_index < _events.size()) {
00534 PlaybackEvent *event = _events[_next_event_index];
00535 _next_event_index++;
00536
00537
00538 do_event_forward(event, new_active, true);
00539 }
00540 finish_events_forward(double_to_int_time(duration), new_active);
00541 _processing_events = false;
00542
00543 _curr_t = duration;
00544 _state = S_final;
00545
00546 if (_event_queue.empty()) {
00547 interval_done();
00548 } else {
00549 enqueue_done_event();
00550 }
00551 }
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 void CMetaInterval::
00562 priv_reverse_initialize(double t) {
00563 if (_processing_events) {
00564 enqueue_self_event(ET_reverse_initialize, t);
00565 return;
00566 }
00567
00568 check_stopped(get_class_type(), "priv_reverse_initialize");
00569
00570
00571
00572
00573
00574 recompute();
00575 _next_event_index = _events.size();
00576 _active.clear();
00577
00578 int now = double_to_int_time(t);
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 _processing_events = true;
00592 ActiveEvents new_active;
00593 while (_next_event_index > 0 &&
00594 _events[_next_event_index - 1]->_time > now) {
00595 _next_event_index--;
00596 PlaybackEvent *event = _events[_next_event_index];
00597
00598
00599 do_event_reverse(event, new_active, true);
00600 }
00601 finish_events_reverse(now, new_active);
00602 _processing_events = false;
00603
00604 _curr_t = t;
00605 _state = S_started;
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 void CMetaInterval::
00618 priv_reverse_instant() {
00619 if (_processing_events) {
00620 enqueue_self_event(ET_reverse_instant);
00621 return;
00622 }
00623
00624 check_stopped(get_class_type(), "priv_reverse_instant");
00625 recompute();
00626 _active.clear();
00627
00628
00629
00630 _processing_events = true;
00631 PlaybackEvents::reverse_iterator ei;
00632 for (ei = _events.rbegin(); ei != _events.rend(); ++ei) {
00633 PlaybackEvent *event = (*ei);
00634 if (event->_type != PET_begin) {
00635 enqueue_event(event->_n, ET_reverse_instant, true, 0);
00636 }
00637 }
00638 _processing_events = false;
00639
00640 _next_event_index = 0;
00641 _curr_t = 0.0;
00642 _state = S_initial;
00643 }
00644
00645
00646
00647
00648
00649
00650
00651
00652 void CMetaInterval::
00653 priv_reverse_finalize() {
00654 if (_processing_events) {
00655 enqueue_self_event(ET_reverse_finalize);
00656 return;
00657 }
00658
00659 if (_state == S_initial) {
00660 priv_initialize(0.0);
00661 }
00662
00663
00664 _processing_events = true;
00665 ActiveEvents new_active;
00666
00667 while (_next_event_index > 0) {
00668 _next_event_index--;
00669 PlaybackEvent *event = _events[_next_event_index];
00670
00671 do_event_reverse(event, new_active, true);
00672 }
00673 finish_events_reverse(0, new_active);
00674 _processing_events = false;
00675
00676 _curr_t = 0.0;
00677 _state = S_initial;
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 void CMetaInterval::
00695 priv_interrupt() {
00696 if (_processing_events) {
00697 enqueue_self_event(ET_interrupt);
00698 return;
00699 }
00700
00701 _processing_events = true;
00702 ActiveEvents::iterator ai;
00703 for (ai = _active.begin(); ai != _active.end(); ++ai) {
00704 PlaybackEvent *event = (*ai);
00705 enqueue_event(event->_n, ET_interrupt, false);
00706 }
00707 _processing_events = false;
00708
00709 if (_state == S_started) {
00710 _state = S_paused;
00711 }
00712 }
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724 void CMetaInterval::
00725 pop_event() {
00726 #ifndef NDEBUG
00727 nassertv(!_event_queue.empty());
00728 const EventQueueEntry &entry = _event_queue.front();
00729 const IntervalDef &def = _defs[entry._n];
00730 nassertv(def._type == DT_ext_index);
00731 #endif
00732 _event_queue.pop_front();
00733 }
00734
00735
00736
00737
00738
00739
00740 void CMetaInterval::
00741 write(ostream &out, int indent_level) const {
00742 recompute();
00743
00744
00745 int num_decimals = (int)ceil(log10(_precision));
00746 int total_digits = num_decimals + 4;
00747 static const int max_digits = 32;
00748 nassertv(total_digits <= max_digits);
00749 char format_str[12];
00750 sprintf(format_str, "%%%d.%df", total_digits, num_decimals);
00751
00752 indent(out, indent_level) << get_name() << ":\n";
00753
00754 int extra_indent_level = 1;
00755 Defs::const_iterator di;
00756 for (di = _defs.begin(); di != _defs.end(); ++di) {
00757 const IntervalDef &def = (*di);
00758 char time_str[max_digits + 1];
00759 sprintf(time_str, format_str, int_to_double_time(def._actual_begin_time));
00760 indent(out, indent_level) << time_str;
00761
00762 write_event_desc(out, def, extra_indent_level);
00763 }
00764 }
00765
00766
00767
00768
00769
00770
00771
00772 void CMetaInterval::
00773 timeline(ostream &out) const {
00774 recompute();
00775
00776
00777 int num_decimals = (int)ceil(log10(_precision));
00778 int total_digits = num_decimals + 4;
00779 static const int max_digits = 32;
00780 nassertv(total_digits <= max_digits);
00781 char format_str[12];
00782 sprintf(format_str, "%%%d.%df", total_digits, num_decimals);
00783
00784 int extra_indent_level = 0;
00785 PlaybackEvents::const_iterator ei;
00786 for (ei = _events.begin(); ei != _events.end(); ++ei) {
00787 const PlaybackEvent *event = (*ei);
00788
00789 char time_str[max_digits + 1];
00790 sprintf(time_str, format_str, int_to_double_time(event->_time));
00791 out << time_str;
00792
00793 switch (event->_type) {
00794 case PET_begin:
00795 out << " begin ";
00796 break;
00797 case PET_end:
00798 out << " end ";
00799 break;
00800 case PET_instant:
00801 out << " instant ";
00802 break;
00803 }
00804
00805 int n = event->_n;
00806 nassertv(n >= 0 && n < (int)_defs.size());
00807 const IntervalDef &def = _defs[n];
00808
00809 write_event_desc(out, def, extra_indent_level);
00810 }
00811 }
00812
00813
00814
00815
00816
00817
00818
00819 void CMetaInterval::
00820 do_recompute() {
00821 _dirty = false;
00822 clear_events();
00823
00824 int n = recompute_level(0, 0, _end_time);
00825
00826 if (n != (int)_defs.size()) {
00827 interval_cat.warning()
00828 << "CMetaInterval pushes don't match pops.\n";
00829 }
00830
00831
00832
00833
00834 stable_sort(_events.begin(), _events.end(), IndirectLess<PlaybackEvent>());
00835 _duration = int_to_double_time(_end_time);
00836 }
00837
00838
00839
00840
00841
00842
00843 void CMetaInterval::
00844 clear_events() {
00845 PlaybackEvents::iterator ei;
00846 for (ei = _events.begin(); ei != _events.end(); ++ei) {
00847 PlaybackEvent *event = (*ei);
00848 delete event;
00849 }
00850 _events.clear();
00851 _active.clear();
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866 void CMetaInterval::
00867 do_event_forward(CMetaInterval::PlaybackEvent *event,
00868 CMetaInterval::ActiveEvents &new_active, bool is_initial) {
00869 switch (event->_type) {
00870 case PET_begin:
00871 nassertv(event->_begin_event == event);
00872 new_active.push_back(event);
00873 break;
00874
00875 case PET_end:
00876 {
00877
00878
00879 ActiveEvents::iterator ai;
00880 ai = find(new_active.begin(), new_active.end(), event->_begin_event);
00881 if (ai != new_active.end()) {
00882 new_active.erase(ai);
00883
00884
00885 enqueue_event(event->_n, ET_instant, is_initial);
00886
00887 } else {
00888 ai = find(_active.begin(), _active.end(), event->_begin_event);
00889 if (ai != _active.end()) {
00890 _active.erase(ai);
00891 enqueue_event(event->_n, ET_finalize, is_initial);
00892
00893 } else {
00894
00895
00896 interval_cat.error()
00897 << "Event " << event->_begin_event->_n << " not on active list.\n";
00898 nassertv(false);
00899 }
00900 }
00901 }
00902 break;
00903
00904 case PET_instant:
00905 nassertv(event->_begin_event == event);
00906 enqueue_event(event->_n, ET_instant, is_initial);
00907 break;
00908 }
00909 }
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920 void CMetaInterval::
00921 finish_events_forward(int now, CMetaInterval::ActiveEvents &new_active) {
00922
00923 ActiveEvents::iterator ai;
00924 for (ai = _active.begin(); ai != _active.end(); ++ai) {
00925 PlaybackEvent *event = (*ai);
00926 enqueue_event(event->_n, ET_step, false, now - event->_time);
00927 }
00928
00929
00930 for (ai = new_active.begin(); ai != new_active.end(); ++ai) {
00931 PlaybackEvent *event = (*ai);
00932 enqueue_event(event->_n, ET_initialize, false, now - event->_time);
00933 _active.push_back(event);
00934 }
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 void CMetaInterval::
00951 do_event_reverse(CMetaInterval::PlaybackEvent *event,
00952 CMetaInterval::ActiveEvents &new_active, bool is_initial) {
00953
00954 switch (event->_type) {
00955 case PET_begin:
00956 {
00957 nassertv(event->_begin_event == event);
00958
00959
00960 ActiveEvents::iterator ai;
00961 ai = find(new_active.begin(), new_active.end(), event);
00962 if (ai != new_active.end()) {
00963 new_active.erase(ai);
00964
00965
00966 enqueue_event(event->_n, ET_reverse_instant, is_initial);
00967
00968 } else {
00969 ai = find(_active.begin(), _active.end(), event);
00970 if (ai != _active.end()) {
00971 _active.erase(ai);
00972 enqueue_event(event->_n, ET_reverse_finalize, is_initial);
00973
00974 } else {
00975
00976
00977
00978 interval_cat.error()
00979 << "Event " << event->_n << " not on active list.\n";
00980 nassertv(false);
00981 }
00982 }
00983 }
00984 break;
00985
00986 case PET_end:
00987 new_active.push_front(event->_begin_event);
00988 break;
00989
00990 case PET_instant:
00991 nassertv(event->_begin_event == event);
00992 enqueue_event(event->_n, ET_reverse_instant, is_initial);
00993 break;
00994 }
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007 void CMetaInterval::
01008 finish_events_reverse(int now, CMetaInterval::ActiveEvents &new_active) {
01009
01010 ActiveEvents::iterator ai;
01011 for (ai = _active.begin(); ai != _active.end(); ++ai) {
01012 PlaybackEvent *event = (*ai);
01013 enqueue_event(event->_n, ET_step, false, now - event->_time);
01014 }
01015
01016
01017 for (ai = new_active.begin(); ai != new_active.end(); ++ai) {
01018 PlaybackEvent *event = (*ai);
01019 enqueue_event(event->_n, ET_reverse_initialize, false, now - event->_time);
01020 _active.push_front(event);
01021 }
01022 }
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040 void CMetaInterval::
01041 enqueue_event(int n, CInterval::EventType event_type, bool is_initial, int time) {
01042 nassertv(n >= 0 && n < (int)_defs.size());
01043 const IntervalDef &def = _defs[n];
01044 switch (def._type) {
01045 case DT_c_interval:
01046 if (is_initial &&
01047 (event_type == ET_instant || event_type == ET_reverse_instant) &&
01048 !def._c_interval->get_open_ended()) {
01049
01050
01051 return;
01052 } else {
01053 if (_event_queue.empty()) {
01054
01055
01056
01057
01058 def._c_interval->priv_do_event(int_to_double_time(time), event_type);
01059 return;
01060 }
01061 }
01062 break;
01063
01064 case DT_ext_index:
01065 if (is_initial &&
01066 (event_type == ET_instant || event_type == ET_reverse_instant) &&
01067 !def._ext_open_ended) {
01068
01069
01070 return;
01071 }
01072 break;
01073
01074 default:
01075 nassertv(false);
01076 return;
01077 }
01078
01079 _event_queue.push_back(EventQueueEntry(n, event_type, time));
01080 }
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093 void CMetaInterval::
01094 enqueue_self_event(CInterval::EventType event_type, double t) {
01095 interval_cat.info()
01096 << "Recursive reentry detected into " << *this << "\n";
01097 int time = double_to_int_time(t);
01098 _event_queue.push_back(EventQueueEntry(-1, event_type, time));
01099 }
01100
01101
01102
01103
01104
01105
01106
01107
01108 void CMetaInterval::
01109 enqueue_done_event() {
01110 _event_queue.push_back(EventQueueEntry(-2, ET_finalize, 0));
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124 bool CMetaInterval::
01125 service_event_queue() {
01126 while (!_event_queue.empty()) {
01127 nassertr(!_processing_events, true);
01128 const EventQueueEntry &entry = _event_queue.front();
01129 if (entry._n == -1) {
01130
01131 priv_do_event(int_to_double_time(entry._time), entry._event_type);
01132
01133 } else if (entry._n == -2) {
01134
01135
01136 interval_done();
01137
01138 } else {
01139 nassertr(entry._n >= 0 && entry._n < (int)_defs.size(), false);
01140 const IntervalDef &def = _defs[entry._n];
01141 switch (def._type) {
01142 case DT_c_interval:
01143
01144 def._c_interval->priv_do_event(int_to_double_time(entry._time), entry._event_type);
01145 break;
01146
01147 case DT_ext_index:
01148
01149 return true;
01150
01151 default:
01152 nassertr(false, false);
01153 return false;
01154 }
01155 }
01156 _event_queue.pop_front();
01157 }
01158
01159
01160 nassertr(!_processing_events, false);
01161 return false;
01162 }
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179 int CMetaInterval::
01180 recompute_level(int n, int level_begin, int &level_end) {
01181 level_end = level_begin;
01182 int previous_begin = level_begin;
01183 int previous_end = level_begin;
01184
01185 while (n < (int)_defs.size() && _defs[n]._type != DT_pop_level) {
01186 IntervalDef &def = _defs[n];
01187 int begin_time = previous_begin;
01188 int end_time = previous_end;
01189 switch (def._type) {
01190 case DT_c_interval:
01191 begin_time = get_begin_time(def, level_begin, previous_begin, previous_end);
01192 def._actual_begin_time = begin_time;
01193 end_time = begin_time + double_to_int_time(def._c_interval->get_duration());
01194
01195 if (def._c_interval->is_exact_type(WaitInterval::get_class_type())) {
01196
01197
01198
01199 } else {
01200 if (begin_time == end_time) {
01201 _events.push_back(new PlaybackEvent(begin_time, n, PET_instant));
01202 } else {
01203 PlaybackEvent *begin = new PlaybackEvent(begin_time, n, PET_begin);
01204 PlaybackEvent *end = new PlaybackEvent(end_time, n, PET_end);
01205 end->_begin_event = begin;
01206 _events.push_back(begin);
01207 _events.push_back(end);
01208 }
01209 }
01210 break;
01211
01212 case DT_ext_index:
01213 begin_time = get_begin_time(def, level_begin, previous_begin, previous_end);
01214 def._actual_begin_time = begin_time;
01215 end_time = begin_time + double_to_int_time(def._ext_duration);
01216 if (begin_time == end_time) {
01217 _events.push_back(new PlaybackEvent(begin_time, n, PET_instant));
01218 } else {
01219 PlaybackEvent *begin = new PlaybackEvent(begin_time, n, PET_begin);
01220 PlaybackEvent *end = new PlaybackEvent(end_time, n, PET_end);
01221 end->_begin_event = begin;
01222 _events.push_back(begin);
01223 _events.push_back(end);
01224 }
01225 break;
01226
01227 case DT_push_level:
01228 begin_time = get_begin_time(def, level_begin, previous_begin, previous_end);
01229 def._actual_begin_time = begin_time;
01230 n = recompute_level(n + 1, begin_time, end_time);
01231 break;
01232
01233 case DT_pop_level:
01234 nassertr(false, _defs.size());
01235 break;
01236 }
01237
01238 previous_begin = begin_time;
01239 previous_end = end_time;
01240 level_end = max(level_end, end_time);
01241 n++;
01242 }
01243
01244 if (n < (int)_defs.size()) {
01245 IntervalDef &def = _defs[n];
01246
01247 if (def._ext_duration >= 0.0) {
01248 level_end = level_begin + double_to_int_time(def._ext_duration);
01249 }
01250
01251
01252
01253 def._actual_begin_time = level_end;
01254 }
01255
01256 return n;
01257 }
01258
01259
01260
01261
01262
01263
01264
01265
01266 int CMetaInterval::
01267 get_begin_time(const CMetaInterval::IntervalDef &def, int level_begin,
01268 int previous_begin, int previous_end) {
01269 switch (def._rel_to) {
01270 case RS_previous_end:
01271 return previous_end + double_to_int_time(def._rel_time);
01272
01273 case RS_previous_begin:
01274 return previous_begin + double_to_int_time(def._rel_time);
01275
01276 case RS_level_begin:
01277 return level_begin + double_to_int_time(def._rel_time);
01278 }
01279
01280 nassertr(false, previous_end);
01281 return previous_end;
01282 }
01283
01284
01285
01286
01287
01288
01289
01290 void CMetaInterval::
01291 write_event_desc(ostream &out, const CMetaInterval::IntervalDef &def,
01292 int &extra_indent_level) const {
01293 switch (def._type) {
01294 case DT_c_interval:
01295 indent(out, extra_indent_level)
01296 << *def._c_interval;
01297 if (!def._c_interval->get_open_ended()) {
01298 out << " (!oe)";
01299 }
01300 out << "\n";
01301 break;
01302
01303 case DT_ext_index:
01304 indent(out, extra_indent_level)
01305 << "*" << def._ext_name;
01306 if (def._ext_duration != 0.0) {
01307 out << " dur " << def._ext_duration;
01308 }
01309 if (!def._ext_open_ended) {
01310 out << " (!oe)";
01311 }
01312 out<< "\n";
01313 break;
01314
01315 case DT_push_level:
01316 indent(out, extra_indent_level)
01317 << def._ext_name << " {\n";
01318 extra_indent_level += 2;
01319 break;
01320
01321 case DT_pop_level:
01322 extra_indent_level -= 2;
01323 indent(out, extra_indent_level)
01324 << "}\n";
01325 break;
01326 }
01327 }