00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pandaFramework.h"
00020 #include "clockObject.h"
00021 #include "pStatClient.h"
00022 #include "eventQueue.h"
00023 #include "dataGraphTraverser.h"
00024 #include "collisionNode.h"
00025 #include "config_framework.h"
00026 #include "graphicsPipeSelection.h"
00027
00028
00029
00030
00031
00032
00033 PandaFramework::
00034 PandaFramework() :
00035 _event_handler(EventQueue::get_global_event_queue())
00036 {
00037 _is_open = false;
00038 _made_default_pipe = false;
00039 _data_root = NodePath("data");
00040 _window_title = "Panda";
00041 _start_time = 0.0;
00042 _frame_count = 0;
00043 _wireframe_enabled = false;
00044 _texture_enabled = true;
00045 _two_sided_enabled = false;
00046 _lighting_enabled = false;
00047 _background_type = WindowFramework::BT_gray;
00048 _default_keys_enabled = false;
00049 _exit_flag = false;
00050 }
00051
00052
00053
00054
00055
00056
00057 PandaFramework::
00058 ~PandaFramework() {
00059 if (_is_open) {
00060 close_framework();
00061 }
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 void PandaFramework::
00074 open_framework(int &argc, char **&argv) {
00075 if (_is_open) {
00076 return;
00077 }
00078
00079 _is_open = true;
00080
00081 reset_frame_rate();
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091 void PandaFramework::
00092 close_framework() {
00093 if (!_is_open) {
00094 return;
00095 }
00096
00097 close_all_windows();
00098
00099 _engine.remove_all_windows();
00100 _event_handler.remove_all_hooks();
00101
00102 _is_open = false;
00103 _made_default_pipe = false;
00104 _default_pipe.clear();
00105
00106 _start_time = 0.0;
00107 _frame_count = 0;
00108 _wireframe_enabled = false;
00109 _two_sided_enabled = false;
00110 _lighting_enabled = false;
00111 _default_keys_enabled = false;
00112 _exit_flag = false;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 GraphicsPipe *PandaFramework::
00131 get_default_pipe() {
00132 nassertr(_is_open, NULL);
00133 if (!_made_default_pipe) {
00134 make_default_pipe();
00135 _made_default_pipe = true;
00136 }
00137 return _default_pipe;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147 void PandaFramework::
00148 get_default_window_props(WindowProperties &props) {
00149 props.set_open(true);
00150 props.set_size(win_width, win_height);
00151 props.set_fullscreen(fullscreen);
00152 props.set_undecorated(undecorated);
00153 props.set_cursor_hidden(cursor_hidden);
00154 props.set_title(_window_title);
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164 WindowFramework *PandaFramework::
00165 open_window(GraphicsPipe *pipe) {
00166 nassertr(_is_open, NULL);
00167
00168 WindowProperties props;
00169 get_default_window_props(props);
00170
00171 return open_window(props, pipe);
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 WindowFramework *PandaFramework::
00185 open_window(const WindowProperties &props, GraphicsPipe *pipe) {
00186 if (pipe == (GraphicsPipe *)NULL) {
00187 pipe = get_default_pipe();
00188 if (pipe == (GraphicsPipe *)NULL) {
00189
00190 return NULL;
00191 }
00192 }
00193
00194 nassertr(_is_open, NULL);
00195 PT(WindowFramework) wf = make_window_framework();
00196 wf->set_wireframe(get_wireframe());
00197 wf->set_texture(get_texture());
00198 wf->set_two_sided(get_two_sided());
00199 wf->set_lighting(get_lighting());
00200 wf->set_background_type(get_background_type());
00201
00202 GraphicsWindow *win = wf->open_window(props, &_engine, pipe);
00203 if (win == (GraphicsWindow *)NULL) {
00204
00205 delete wf;
00206 return NULL;
00207 }
00208
00209 _windows.push_back(wf);
00210 return wf;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220 int PandaFramework::
00221 find_window(const GraphicsWindow *win) const {
00222 int n;
00223 for (n = 0; n < (int)_windows.size(); n++) {
00224 if (_windows[n]->get_graphics_window() == win) {
00225 return n;
00226 }
00227 }
00228
00229 return -1;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239 int PandaFramework::
00240 find_window(const WindowFramework *wf) const {
00241 int n;
00242 for (n = 0; n < (int)_windows.size(); n++) {
00243 if (_windows[n] == wf) {
00244 return n;
00245 }
00246 }
00247
00248 return -1;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257 void PandaFramework::
00258 close_window(int n) {
00259 nassertv(n >= 0 && n < (int)_windows.size());
00260 WindowFramework *wf = _windows[n];
00261
00262 GraphicsWindow *win = wf->get_graphics_window();
00263 if (win != (GraphicsWindow *)NULL) {
00264 _engine.remove_window(win);
00265 }
00266
00267 wf->close_window();
00268 _windows.erase(_windows.begin() + n);
00269 }
00270
00271
00272
00273
00274
00275
00276
00277 void PandaFramework::
00278 close_all_windows() {
00279 Windows::iterator wi;
00280 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00281 WindowFramework *wf = (*wi);
00282
00283 GraphicsWindow *win = wf->get_graphics_window();
00284 if (win != (GraphicsWindow *)NULL) {
00285 _engine.remove_window(win);
00286 }
00287
00288 wf->close_window();
00289 }
00290
00291 _windows.clear();
00292 }
00293
00294
00295
00296
00297
00298
00299
00300 bool PandaFramework::
00301 all_windows_closed() const {
00302 Windows::const_iterator wi;
00303 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00304 WindowFramework *wf = (*wi);
00305 if (wf->get_graphics_window()->get_properties().get_open()) {
00306 return false;
00307 }
00308 }
00309
00310 return true;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 const NodePath &PandaFramework::
00322 get_models() {
00323 if (_models.is_empty()) {
00324 _models = NodePath("models");
00325 }
00326 return _models;
00327 }
00328
00329
00330
00331
00332
00333
00334
00335 void PandaFramework::
00336 report_frame_rate(ostream &out) const {
00337 double now = ClockObject::get_global_clock()->get_frame_time();
00338 double delta = now - _start_time;
00339
00340 int frame_count = ClockObject::get_global_clock()->get_frame_count();
00341 int num_frames = frame_count - _frame_count;
00342 if (num_frames > 0) {
00343 out << num_frames << " frames in " << delta << " seconds.\n";
00344 double fps = ((double)num_frames) / delta;
00345 out << fps << " fps average (" << 1000.0 / fps << "ms)\n";
00346 }
00347 }
00348
00349
00350
00351
00352
00353
00354 void PandaFramework::
00355 reset_frame_rate() {
00356 _start_time = ClockObject::get_global_clock()->get_frame_time();
00357 _frame_count = ClockObject::get_global_clock()->get_frame_count();
00358 }
00359
00360
00361
00362
00363
00364
00365 void PandaFramework::
00366 set_wireframe(bool enable) {
00367 Windows::iterator wi;
00368 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00369 WindowFramework *wf = (*wi);
00370 wf->set_wireframe(enable);
00371 }
00372
00373 _wireframe_enabled = enable;
00374 }
00375
00376
00377
00378
00379
00380
00381 void PandaFramework::
00382 set_texture(bool enable) {
00383 Windows::iterator wi;
00384 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00385 WindowFramework *wf = (*wi);
00386 wf->set_texture(enable);
00387 }
00388
00389 _texture_enabled = enable;
00390 }
00391
00392
00393
00394
00395
00396
00397 void PandaFramework::
00398 set_two_sided(bool enable) {
00399 Windows::iterator wi;
00400 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00401 WindowFramework *wf = (*wi);
00402 wf->set_two_sided(enable);
00403 }
00404
00405 _two_sided_enabled = enable;
00406 }
00407
00408
00409
00410
00411
00412
00413 void PandaFramework::
00414 set_lighting(bool enable) {
00415 Windows::iterator wi;
00416 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00417 WindowFramework *wf = (*wi);
00418 wf->set_lighting(enable);
00419 }
00420
00421 _lighting_enabled = enable;
00422 }
00423
00424
00425
00426
00427
00428
00429 void PandaFramework::
00430 set_background_type(WindowFramework::BackgroundType type) {
00431 Windows::iterator wi;
00432 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00433 WindowFramework *wf = (*wi);
00434 wf->set_background_type(type);
00435 }
00436
00437 _background_type = type;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447 int PandaFramework::
00448 hide_collision_solids(NodePath node) {
00449 int num_changed = 0;
00450
00451 if (node.node()->is_of_type(CollisionNode::get_class_type())) {
00452 if (!node.is_hidden()) {
00453 node.hide();
00454 num_changed++;
00455 }
00456 }
00457
00458 int num_children = node.get_num_children();
00459 for (int i = 0; i < num_children; i++) {
00460 num_changed += hide_collision_solids(node.get_child(i));
00461 }
00462
00463 return num_changed;
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473 int PandaFramework::
00474 show_collision_solids(NodePath node) {
00475 int num_changed = 0;
00476
00477 if (node.node()->is_of_type(CollisionNode::get_class_type())) {
00478 if (node.get_hidden_ancestor() == node) {
00479 node.show();
00480 num_changed++;
00481 }
00482 }
00483
00484 int num_children = node.get_num_children();
00485 for (int i = 0; i < num_children; i++) {
00486 num_changed += show_collision_solids(node.get_child(i));
00487 }
00488
00489 return num_changed;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498
00499 void PandaFramework::
00500 set_highlight(const NodePath &node) {
00501 clear_highlight();
00502 _highlight = node;
00503 if (!_highlight.is_empty()) {
00504 framework_cat.info(false) << _highlight << "\n";
00505 _highlight.show_bounds();
00506 }
00507 }
00508
00509
00510
00511
00512
00513
00514 void PandaFramework::
00515 clear_highlight() {
00516 if (!_highlight.is_empty()) {
00517 _highlight.hide_bounds();
00518 _highlight = NodePath();
00519 }
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529 void PandaFramework::
00530 enable_default_keys() {
00531 if (!_default_keys_enabled) {
00532 do_enable_default_keys();
00533 _default_keys_enabled = true;
00534 }
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 bool PandaFramework::
00546 do_frame() {
00547 nassertr(_is_open, false);
00548 DataGraphTraverser dg_trav;
00549 dg_trav.traverse(_data_root.node());
00550 _event_handler.process_events();
00551 _engine.render_frame();
00552
00553 return !_exit_flag;
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563 void PandaFramework::
00564 main_loop() {
00565 while (do_frame()) {
00566 }
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576 PT(WindowFramework) PandaFramework::
00577 make_window_framework() {
00578 return new WindowFramework(this);
00579 }
00580
00581
00582
00583
00584
00585
00586
00587 void PandaFramework::
00588 make_default_pipe() {
00589
00590
00591
00592 GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
00593 selection->print_pipe_types();
00594 _default_pipe = selection->make_default_pipe();
00595
00596 if (_default_pipe == (GraphicsPipe*)NULL) {
00597 nout << "No graphics pipe is available! Check your Configrc!\n";
00598 }
00599 }
00600
00601
00602
00603
00604
00605
00606 void PandaFramework::
00607 do_enable_default_keys() {
00608 _event_handler.add_hook("escape", event_esc, this);
00609 _event_handler.add_hook("q", event_esc, this);
00610 _event_handler.add_hook("f", event_f, this);
00611 _event_handler.add_hook("w", event_w, this);
00612 _event_handler.add_hook("t", event_t, this);
00613 _event_handler.add_hook("b", event_b, this);
00614 _event_handler.add_hook("i", event_i, this);
00615 _event_handler.add_hook("l", event_l, this);
00616 _event_handler.add_hook("c", event_c, this);
00617 _event_handler.add_hook("shift-c", event_C, this);
00618 _event_handler.add_hook("shift-b", event_B, this);
00619 _event_handler.add_hook("shift-l", event_L, this);
00620 _event_handler.add_hook("h", event_h, this);
00621 _event_handler.add_hook("arrow_up", event_arrow_up, this);
00622 _event_handler.add_hook("arrow_down", event_arrow_down, this);
00623 _event_handler.add_hook("arrow_left", event_arrow_left, this);
00624 _event_handler.add_hook("arrow_right", event_arrow_right, this);
00625 _event_handler.add_hook("shift-s", event_S, this);
00626 _event_handler.add_hook(",", event_comma, this);
00627 _event_handler.add_hook("window-event", event_window_event, this);
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637 void PandaFramework::
00638 event_esc(CPT_Event event, void *data) {
00639 if (event->get_num_parameters() == 1) {
00640 EventParameter param = event->get_parameter(0);
00641 WindowFramework *wf;
00642 DCAST_INTO_V(wf, param.get_ptr());
00643
00644 PandaFramework *self = (PandaFramework *)data;
00645 self->close_window(wf);
00646
00647
00648 if (self->_windows.empty()) {
00649 self->_exit_flag = true;
00650 }
00651 }
00652 }
00653
00654
00655
00656
00657
00658
00659
00660 void PandaFramework::
00661 event_f(CPT_Event, void *data) {
00662 PandaFramework *self = (PandaFramework *)data;
00663 self->report_frame_rate(nout);
00664 self->reset_frame_rate();
00665 }
00666
00667
00668
00669
00670
00671
00672 void PandaFramework::
00673 event_w(CPT_Event event, void *) {
00674 if (event->get_num_parameters() == 1) {
00675 EventParameter param = event->get_parameter(0);
00676 WindowFramework *wf;
00677 DCAST_INTO_V(wf, param.get_ptr());
00678
00679 wf->set_wireframe(!wf->get_wireframe());
00680 }
00681 }
00682
00683
00684
00685
00686
00687
00688 void PandaFramework::
00689 event_t(CPT_Event event, void *) {
00690 if (event->get_num_parameters() == 1) {
00691 EventParameter param = event->get_parameter(0);
00692 WindowFramework *wf;
00693 DCAST_INTO_V(wf, param.get_ptr());
00694
00695 wf->set_texture(!wf->get_texture());
00696 }
00697 }
00698
00699
00700
00701
00702
00703
00704
00705 void PandaFramework::
00706 event_b(CPT_Event event, void *) {
00707 if (event->get_num_parameters() == 1) {
00708 EventParameter param = event->get_parameter(0);
00709 WindowFramework *wf;
00710 DCAST_INTO_V(wf, param.get_ptr());
00711
00712 wf->set_two_sided(!wf->get_two_sided());
00713 }
00714 }
00715
00716
00717
00718
00719
00720
00721 void PandaFramework::
00722 event_i(CPT_Event event, void *) {
00723 if (event->get_num_parameters() == 1) {
00724 EventParameter param = event->get_parameter(0);
00725 WindowFramework *wf;
00726 DCAST_INTO_V(wf, param.get_ptr());
00727
00728 wf->set_one_sided_reverse(!wf->get_one_sided_reverse());
00729 }
00730 }
00731
00732
00733
00734
00735
00736
00737 void PandaFramework::
00738 event_l(CPT_Event event, void *) {
00739 if (event->get_num_parameters() == 1) {
00740 EventParameter param = event->get_parameter(0);
00741 WindowFramework *wf;
00742 DCAST_INTO_V(wf, param.get_ptr());
00743
00744 wf->set_lighting(!wf->get_lighting());
00745 }
00746 }
00747
00748
00749
00750
00751
00752
00753
00754 void PandaFramework::
00755 event_c(CPT_Event event, void *data) {
00756 if (event->get_num_parameters() == 1) {
00757 EventParameter param = event->get_parameter(0);
00758 WindowFramework *wf;
00759 DCAST_INTO_V(wf, param.get_ptr());
00760
00761 PandaFramework *self = (PandaFramework *)data;
00762
00763 NodePath node = self->get_highlight();
00764 if (node.is_empty()) {
00765 node = self->get_models();
00766 }
00767 wf->center_trackball(node);
00768 }
00769 }
00770
00771
00772
00773
00774
00775
00776
00777 void PandaFramework::
00778 event_C(CPT_Event, void *data) {
00779 PandaFramework *self = (PandaFramework *)data;
00780
00781 NodePath node = self->get_highlight();
00782 if (node.is_empty()) {
00783 node = self->get_models();
00784 }
00785
00786 if (self->hide_collision_solids(node) == 0) {
00787 self->show_collision_solids(node);
00788 }
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798 void PandaFramework::
00799 event_B(CPT_Event, void *data) {
00800 PandaFramework *self = (PandaFramework *)data;
00801
00802 NodePath node = self->get_highlight();
00803 if (node.is_empty()) {
00804 node = self->get_models();
00805 }
00806
00807 node.get_bounds()->write(nout);
00808 }
00809
00810
00811
00812
00813
00814
00815
00816 void PandaFramework::
00817 event_L(CPT_Event, void *data) {
00818 PandaFramework *self = (PandaFramework *)data;
00819
00820 NodePath node = self->get_highlight();
00821 if (node.is_empty()) {
00822 node = self->get_models();
00823 }
00824
00825 node.ls();
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835 void PandaFramework::
00836 event_h(CPT_Event, void *data) {
00837 PandaFramework *self = (PandaFramework *)data;
00838
00839 if (self->has_highlight()) {
00840 self->clear_highlight();
00841 } else {
00842 self->set_highlight(self->get_models());
00843 }
00844 }
00845
00846
00847
00848
00849
00850
00851
00852 void PandaFramework::
00853 event_arrow_up(CPT_Event, void *data) {
00854 PandaFramework *self = (PandaFramework *)data;
00855
00856 if (self->has_highlight()) {
00857 NodePath node = self->get_highlight();
00858 if (node.has_parent() && node != self->get_models()) {
00859 self->set_highlight(node.get_parent());
00860 }
00861 }
00862 }
00863
00864
00865
00866
00867
00868
00869
00870 void PandaFramework::
00871 event_arrow_down(CPT_Event, void *data) {
00872 PandaFramework *self = (PandaFramework *)data;
00873
00874 if (self->has_highlight()) {
00875 NodePath node = self->get_highlight();
00876 if (node.get_num_children() > 0) {
00877 self->set_highlight(node.get_child(0));
00878 }
00879 }
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889 void PandaFramework::
00890 event_arrow_left(CPT_Event, void *data) {
00891 PandaFramework *self = (PandaFramework *)data;
00892
00893 if (self->has_highlight()) {
00894 NodePath node = self->get_highlight();
00895 NodePath parent = node.get_parent();
00896 if (node.has_parent() && node != self->get_models()) {
00897 int index = parent.node()->find_child(node.node());
00898 nassertv(index >= 0);
00899 int sibling = index - 1;
00900 if (sibling >= 0) {
00901 self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
00902 }
00903 }
00904 }
00905 }
00906
00907
00908
00909
00910
00911
00912
00913
00914 void PandaFramework::
00915 event_arrow_right(CPT_Event, void *data) {
00916 PandaFramework *self = (PandaFramework *)data;
00917
00918 if (self->has_highlight()) {
00919 NodePath node = self->get_highlight();
00920 NodePath parent = node.get_parent();
00921 if (node.has_parent() && node != self->get_models()) {
00922 int index = parent.node()->find_child(node.node());
00923 nassertv(index >= 0);
00924 int num_children = parent.node()->get_num_children();
00925 int sibling = index + 1;
00926 if (sibling < num_children) {
00927 self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
00928 }
00929 }
00930 }
00931 }
00932
00933
00934
00935
00936
00937
00938 void PandaFramework::
00939 event_S(CPT_Event, void *data) {
00940 #ifdef DO_PSTATS
00941 nout << "Connecting to stats host" << endl;
00942 PStatClient::connect();
00943 #else
00944 nout << "Stats host not supported." << endl;
00945 #endif
00946 }
00947
00948
00949
00950
00951
00952
00953 void PandaFramework::
00954 event_comma(CPT_Event event, void *) {
00955 if (event->get_num_parameters() == 1) {
00956 EventParameter param = event->get_parameter(0);
00957 WindowFramework *wf;
00958 DCAST_INTO_V(wf, param.get_ptr());
00959
00960 switch (wf->get_background_type()) {
00961 case WindowFramework::BT_other:
00962 break;
00963
00964 case WindowFramework::BT_none:
00965 wf->set_background_type(WindowFramework::BT_default);
00966 break;
00967
00968 default:
00969 wf->set_background_type((WindowFramework::BackgroundType)(wf->get_background_type() + 1));
00970 }
00971 }
00972 }
00973
00974
00975
00976
00977
00978
00979
00980 void PandaFramework::
00981 event_window_event(CPT_Event event, void *data) {
00982 PandaFramework *self = (PandaFramework *)data;
00983 if (event->get_num_parameters() == 1) {
00984
00985
00986
00987 EventParameter param = event->get_parameter(0);
00988 const GraphicsWindow *win;
00989 DCAST_INTO_V(win, param.get_ptr());
00990
00991
00992 int window_index = self->find_window(win);
00993 if (window_index == -1) {
00994 framework_cat.debug()
00995 << "Ignoring message from unknown window.\n";
00996 } else {
00997 if (!win->get_properties().get_open()) {
00998
00999 if (self->all_windows_closed() && !self->_exit_flag) {
01000 framework_cat.info()
01001 << "Last window was closed by user.\n";
01002 self->_exit_flag = true;
01003 }
01004 }
01005 }
01006 }
01007 }