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