00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pandaFramework.h"
00016 #include "clockObject.h"
00017 #include "pStatClient.h"
00018 #include "eventQueue.h"
00019 #include "dataGraphTraverser.h"
00020 #include "depthOffsetAttrib.h"
00021 #include "collisionNode.h"
00022 #include "occluderNode.h"
00023 #include "config_framework.h"
00024 #include "graphicsPipeSelection.h"
00025 #include "nodePathCollection.h"
00026 #include "textNode.h"
00027 #include "mouseAndKeyboard.h"
00028 #include "mouseRecorder.h"
00029 #include "throw_event.h"
00030 #include "executionEnvironment.h"
00031 #include "sceneGraphAnalyzer.h"
00032 #include "transformState.h"
00033 #include "renderState.h"
00034
00035 LoaderOptions PandaFramework::_loader_options;
00036
00037
00038
00039
00040
00041
00042 PandaFramework::
00043 PandaFramework() :
00044 _event_handler(*EventHandler::get_global_event_handler()),
00045 _task_mgr(*AsyncTaskManager::get_global_ptr())
00046 {
00047 _is_open = false;
00048 _made_default_pipe = false;
00049 _window_title = string();
00050 _engine = (GraphicsEngine *)NULL;
00051 _start_time = 0.0;
00052 _frame_count = 0;
00053 _wireframe_enabled = false;
00054 _texture_enabled = true;
00055 _two_sided_enabled = false;
00056 _lighting_enabled = false;
00057 _perpixel_enabled = false;
00058 _background_type = WindowFramework::BT_default;
00059 _default_keys_enabled = false;
00060 _exit_flag = false;
00061 }
00062
00063
00064
00065
00066
00067
00068 PandaFramework::
00069 ~PandaFramework() {
00070 if (_is_open) {
00071 close_framework();
00072 }
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 void PandaFramework::
00085 open_framework(int &argc, char **&argv) {
00086 if (_is_open) {
00087 return;
00088 }
00089
00090 _is_open = true;
00091
00092 #ifdef LINK_ALL_STATIC
00093
00094
00095 #ifdef HAVE_GL
00096 extern EXPCL_PANDAGL void init_libpandagl();
00097 init_libpandagl();
00098 #elif HAVE_DX9
00099 extern EXPCL_PANDADX9 void init_libpandadx9();
00100 init_libpandadx9();
00101 #elif HAVE_DX8
00102 extern EXPCL_PANDADX8 void init_libpandadx8();
00103 init_libpandadx8();
00104 #elif HAVE_TINYDISPLAY
00105 extern EXPCL_TINYDISPLAY void init_libtinydisplay();
00106 init_libtinydisplay();
00107 #endif
00108
00109
00110 extern EXPCL_PANDA_CHAR void init_libchar();
00111 init_libchar();
00112
00113
00114 #ifdef HAVE_EGG
00115 extern EXPCL_PANDAEGG void init_libpandaegg();
00116 init_libpandaegg();
00117 #endif
00118
00119 #endif
00120
00121
00122
00123 extern EXPCL_PANDA_PNMIMAGETYPES void init_libpnmimagetypes();
00124 init_libpnmimagetypes();
00125
00126 reset_frame_rate();
00127
00128 {
00129 PT(GenericAsyncTask) task = new GenericAsyncTask("event", task_event, this);
00130 _task_mgr.add(task);
00131 }
00132
00133 _data_root = NodePath("data");
00134 {
00135 PT(GenericAsyncTask) task = new GenericAsyncTask("data_loop", task_data_loop, this);
00136 task->set_sort(-50);
00137 _task_mgr.add(task);
00138 }
00139
00140 if (garbage_collect_states) {
00141 PT(GenericAsyncTask) task = new GenericAsyncTask("garbageCollectStates", task_garbage_collect, this);
00142 task->set_sort(46);
00143 _task_mgr.add(task);
00144 }
00145
00146 _highlight_wireframe = NodePath("wireframe");
00147 _highlight_wireframe.set_render_mode_wireframe(1);
00148 _highlight_wireframe.set_texture_off(1);
00149 _highlight_wireframe.set_color(1.0f, 0.0f, 0.0f, 1.0f, 1);
00150 _highlight_wireframe.set_attrib(DepthOffsetAttrib::make());
00151
00152 if (!playback_session.empty()) {
00153
00154
00155 _recorder = new RecorderController;
00156 _recorder->begin_playback(Filename::from_os_specific(playback_session));
00157
00158 PT(GenericAsyncTask) task = new GenericAsyncTask("play_frame", task_play_frame, this);
00159 task->set_sort(55);
00160 _task_mgr.add(task);
00161
00162 } else if (!record_session.empty()) {
00163
00164
00165 _recorder = new RecorderController;
00166 _recorder->begin_record(Filename::from_os_specific(record_session));
00167
00168 PT(GenericAsyncTask) task = new GenericAsyncTask("record_frame", task_record_frame, this);
00169 task->set_sort(45);
00170 _task_mgr.add(task);
00171 }
00172
00173 _event_handler.add_hook("window-event", event_window_event, this);
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183 void PandaFramework::
00184 close_framework() {
00185 if (!_is_open) {
00186 return;
00187 }
00188
00189 close_all_windows();
00190
00191 if (_engine != (GraphicsEngine *)NULL) {
00192 _engine->remove_all_windows();
00193 _engine = NULL;
00194 }
00195
00196 _event_handler.remove_all_hooks();
00197
00198 _is_open = false;
00199 _made_default_pipe = false;
00200 _default_pipe.clear();
00201
00202 _start_time = 0.0;
00203 _frame_count = 0;
00204 _wireframe_enabled = false;
00205 _two_sided_enabled = false;
00206 _lighting_enabled = false;
00207 _default_keys_enabled = false;
00208 _exit_flag = false;
00209
00210 _recorder = NULL;
00211
00212 Thread::prepare_for_exit();
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 GraphicsPipe *PandaFramework::
00231 get_default_pipe() {
00232 nassertr(_is_open, NULL);
00233 if (!_made_default_pipe) {
00234 make_default_pipe();
00235 _made_default_pipe = true;
00236 }
00237 return _default_pipe;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 NodePath PandaFramework::
00253 get_mouse(GraphicsOutput *window) {
00254 Mouses::iterator mi = _mouses.find(window);
00255 if (mi != _mouses.end()) {
00256 return (*mi).second;
00257 }
00258
00259 NodePath mouse;
00260
00261 if (window->is_of_type(GraphicsWindow::get_class_type())) {
00262 NodePath data_root = get_data_root();
00263 GraphicsWindow *win = DCAST(GraphicsWindow, window);
00264 MouseAndKeyboard *mouse_node = new MouseAndKeyboard(win, 0, "mouse");
00265 mouse = data_root.attach_new_node(mouse_node);
00266
00267 RecorderController *recorder = get_recorder();
00268 if (recorder != (RecorderController *)NULL) {
00269
00270 MouseRecorder *mouse_recorder = new MouseRecorder("mouse");
00271 mouse = mouse.attach_new_node(mouse_recorder);
00272 recorder->add_recorder("mouse", mouse_recorder);
00273 }
00274 }
00275
00276 _mouses[window] = mouse;
00277
00278 return mouse;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287 void PandaFramework::
00288 remove_mouse(const GraphicsOutput *window) {
00289 Mouses::iterator mi = _mouses.find(window);
00290 if (mi != _mouses.end()) {
00291 (*mi).second.remove_node();
00292 _mouses.erase(mi);
00293 }
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 void PandaFramework::
00305 define_key(const string &event_name, const string &description,
00306 EventHandler::EventCallbackFunction *function,
00307 void *data) {
00308 if (_event_handler.has_hook(event_name)) {
00309
00310
00311
00312 KeyDefinitions::iterator di;
00313 di = _key_definitions.begin();
00314 while (di != _key_definitions.end() && (*di)._event_name != event_name) {
00315 ++di;
00316 }
00317 if (di != _key_definitions.end()) {
00318 _key_definitions.erase(di);
00319 }
00320 }
00321
00322
00323
00324 _event_handler.add_hook(event_name, function, data);
00325
00326 if (!description.empty()) {
00327 KeyDefinition keydef;
00328 keydef._event_name = event_name;
00329 keydef._description = description;
00330 _key_definitions.push_back(keydef);
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341 void PandaFramework::
00342 get_default_window_props(WindowProperties &props) {
00343
00344
00345
00346
00347 props.add_properties(WindowProperties::get_default());
00348 if (!_window_title.empty()) {
00349 props.set_title(_window_title);
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 WindowFramework *PandaFramework::
00364 open_window() {
00365 GraphicsPipe *pipe = get_default_pipe();
00366 if (pipe == (GraphicsPipe *)NULL) {
00367
00368 return NULL;
00369 }
00370
00371 WindowFramework *wf = open_window(pipe, NULL);
00372 if (wf == (WindowFramework *)NULL) {
00373
00374 GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
00375 selection->load_aux_modules();
00376
00377 int num_pipe_types = selection->get_num_pipe_types();
00378 for (int i = 0; i < num_pipe_types; i++) {
00379 TypeHandle pipe_type = selection->get_pipe_type(i);
00380 if (pipe_type != _default_pipe->get_type()) {
00381 PT(GraphicsPipe) new_pipe = selection->make_pipe(pipe_type);
00382 if (new_pipe != (GraphicsPipe *)NULL) {
00383 wf = open_window(new_pipe, NULL);
00384 if (wf != (WindowFramework *)NULL) {
00385
00386 _default_pipe = new_pipe;
00387 return wf;
00388 }
00389 }
00390 }
00391 }
00392
00393
00394
00395 }
00396
00397 return wf;
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407 WindowFramework *PandaFramework::
00408 open_window(GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
00409 nassertr(_is_open, NULL);
00410
00411 WindowProperties props;
00412 get_default_window_props(props);
00413
00414 int flags = GraphicsPipe::BF_require_window;
00415 if (window_type == "offscreen") {
00416 flags = GraphicsPipe::BF_refuse_window;
00417 }
00418
00419 return open_window(props, flags, pipe, gsg);
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 WindowFramework *PandaFramework::
00433 open_window(const WindowProperties &props, int flags,
00434 GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
00435 if (pipe == (GraphicsPipe *)NULL) {
00436 pipe = get_default_pipe();
00437 if (pipe == (GraphicsPipe *)NULL) {
00438
00439 return NULL;
00440 }
00441 }
00442
00443 nassertr(_is_open, NULL);
00444 PT(WindowFramework) wf = make_window_framework();
00445 wf->set_wireframe(get_wireframe());
00446 wf->set_texture(get_texture());
00447 wf->set_two_sided(get_two_sided());
00448 wf->set_lighting(get_lighting());
00449 wf->set_perpixel(get_perpixel());
00450 wf->set_background_type(get_background_type());
00451
00452 GraphicsOutput *win = wf->open_window(props, flags, get_graphics_engine(),
00453 pipe, gsg);
00454 _engine->open_windows();
00455 if (win != (GraphicsOutput *)NULL && !win->is_valid()) {
00456
00457 _engine->remove_window(win);
00458 wf->close_window();
00459 win = NULL;
00460 }
00461
00462 if (win == (GraphicsOutput *)NULL) {
00463
00464 framework_cat.error()
00465 << "Unable to create window.\n";
00466 return NULL;
00467 }
00468
00469 _windows.push_back(wf);
00470 return wf;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480 int PandaFramework::
00481 find_window(const GraphicsOutput *win) const {
00482 int n;
00483 for (n = 0; n < (int)_windows.size(); n++) {
00484 if (_windows[n]->get_graphics_output() == win) {
00485 return n;
00486 }
00487 }
00488
00489 return -1;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498
00499 int PandaFramework::
00500 find_window(const WindowFramework *wf) const {
00501 int n;
00502 for (n = 0; n < (int)_windows.size(); n++) {
00503 if (_windows[n] == wf) {
00504 return n;
00505 }
00506 }
00507
00508 return -1;
00509 }
00510
00511
00512
00513
00514
00515
00516
00517 void PandaFramework::
00518 close_window(int n) {
00519 nassertv(n >= 0 && n < (int)_windows.size());
00520 WindowFramework *wf = _windows[n];
00521
00522 GraphicsOutput *win = wf->get_graphics_output();
00523 if (win != (GraphicsOutput *)NULL) {
00524 _engine->remove_window(win);
00525 }
00526
00527 wf->close_window();
00528 _windows.erase(_windows.begin() + n);
00529 }
00530
00531
00532
00533
00534
00535
00536
00537 void PandaFramework::
00538 close_all_windows() {
00539 Windows::iterator wi;
00540 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00541 WindowFramework *wf = (*wi);
00542
00543 GraphicsOutput *win = wf->get_graphics_output();
00544 if (win != (GraphicsOutput *)NULL) {
00545 _engine->remove_window(win);
00546 }
00547
00548 wf->close_window();
00549 }
00550
00551 Mouses::iterator mi;
00552 for (mi = _mouses.begin(); mi != _mouses.end(); ++mi) {
00553 (*mi).second.remove_node();
00554 }
00555
00556 _windows.clear();
00557 _mouses.clear();
00558 }
00559
00560
00561
00562
00563
00564
00565
00566 bool PandaFramework::
00567 all_windows_closed() const {
00568 Windows::const_iterator wi;
00569 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00570 WindowFramework *wf = (*wi);
00571 if (wf->get_graphics_output()->is_valid()) {
00572 return false;
00573 }
00574 }
00575
00576 return true;
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 NodePath &PandaFramework::
00588 get_models() {
00589 if (_models.is_empty()) {
00590 _models = NodePath("models");
00591 }
00592 return _models;
00593 }
00594
00595
00596
00597
00598
00599
00600
00601 void PandaFramework::
00602 report_frame_rate(ostream &out) const {
00603 double now = ClockObject::get_global_clock()->get_frame_time();
00604 double delta = now - _start_time;
00605
00606 int frame_count = ClockObject::get_global_clock()->get_frame_count();
00607 int num_frames = frame_count - _frame_count;
00608 if (num_frames > 0) {
00609 out << num_frames << " frames in " << delta << " seconds.\n";
00610 double fps = ((double)num_frames) / delta;
00611 out << fps << " fps average (" << 1000.0 / fps << "ms)\n";
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620 void PandaFramework::
00621 reset_frame_rate() {
00622 _start_time = ClockObject::get_global_clock()->get_frame_time();
00623 _frame_count = ClockObject::get_global_clock()->get_frame_count();
00624 }
00625
00626
00627
00628
00629
00630
00631 void PandaFramework::
00632 set_wireframe(bool enable) {
00633 Windows::iterator wi;
00634 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00635 WindowFramework *wf = (*wi);
00636 wf->set_wireframe(enable);
00637 }
00638
00639 _wireframe_enabled = enable;
00640 }
00641
00642
00643
00644
00645
00646
00647 void PandaFramework::
00648 set_texture(bool enable) {
00649 Windows::iterator wi;
00650 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00651 WindowFramework *wf = (*wi);
00652 wf->set_texture(enable);
00653 }
00654
00655 _texture_enabled = enable;
00656 }
00657
00658
00659
00660
00661
00662
00663 void PandaFramework::
00664 set_two_sided(bool enable) {
00665 Windows::iterator wi;
00666 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00667 WindowFramework *wf = (*wi);
00668 wf->set_two_sided(enable);
00669 }
00670
00671 _two_sided_enabled = enable;
00672 }
00673
00674
00675
00676
00677
00678
00679 void PandaFramework::
00680 set_lighting(bool enable) {
00681 Windows::iterator wi;
00682 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00683 WindowFramework *wf = (*wi);
00684 wf->set_lighting(enable);
00685 }
00686
00687 _lighting_enabled = enable;
00688 }
00689
00690
00691
00692
00693
00694
00695 void PandaFramework::
00696 set_perpixel(bool enable) {
00697 Windows::iterator wi;
00698 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00699 WindowFramework *wf = (*wi);
00700 wf->set_perpixel(enable);
00701 }
00702
00703 _perpixel_enabled = enable;
00704 }
00705
00706
00707
00708
00709
00710
00711 void PandaFramework::
00712 set_background_type(WindowFramework::BackgroundType type) {
00713 Windows::iterator wi;
00714 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
00715 WindowFramework *wf = (*wi);
00716 wf->set_background_type(type);
00717 }
00718
00719 _background_type = type;
00720 }
00721
00722
00723
00724
00725
00726
00727
00728
00729 int PandaFramework::
00730 hide_collision_solids(NodePath node) {
00731 int num_changed = 0;
00732
00733 if (node.node()->is_of_type(CollisionNode::get_class_type()) ||
00734 node.node()->is_of_type(OccluderNode::get_class_type())) {
00735 if (!node.is_hidden()) {
00736 node.hide();
00737 num_changed++;
00738 }
00739 }
00740
00741 int num_children = node.get_num_children();
00742 for (int i = 0; i < num_children; i++) {
00743 num_changed += hide_collision_solids(node.get_child(i));
00744 }
00745
00746 return num_changed;
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00756 int PandaFramework::
00757 show_collision_solids(NodePath node) {
00758 int num_changed = 0;
00759
00760 if (node.node()->is_of_type(CollisionNode::get_class_type()) ||
00761 node.node()->is_of_type(OccluderNode::get_class_type())) {
00762 if (node.get_hidden_ancestor() == node) {
00763 node.show();
00764 num_changed++;
00765 }
00766 }
00767
00768 int num_children = node.get_num_children();
00769 for (int i = 0; i < num_children; i++) {
00770 num_changed += show_collision_solids(node.get_child(i));
00771 }
00772
00773 return num_changed;
00774 }
00775
00776
00777
00778
00779
00780
00781
00782
00783 void PandaFramework::
00784 set_highlight(const NodePath &node) {
00785 clear_highlight();
00786 _highlight = node;
00787 if (!_highlight.is_empty()) {
00788 framework_cat.info(false) << _highlight << "\n";
00789 _highlight.show_bounds();
00790
00791
00792
00793 if (_highlight.has_parent()) {
00794 _highlight_wireframe.reparent_to(_highlight.get_parent());
00795 _highlight.instance_to(_highlight_wireframe);
00796 }
00797 }
00798 }
00799
00800
00801
00802
00803
00804
00805 void PandaFramework::
00806 clear_highlight() {
00807 if (!_highlight.is_empty()) {
00808 _highlight.hide_bounds();
00809 _highlight = NodePath();
00810
00811
00812 _highlight_wireframe.detach_node();
00813 _highlight_wireframe.get_children().detach();
00814 }
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824 void PandaFramework::
00825 enable_default_keys() {
00826 if (!_default_keys_enabled) {
00827 do_enable_default_keys();
00828 _default_keys_enabled = true;
00829 }
00830 }
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840 bool PandaFramework::
00841 do_frame(Thread *current_thread) {
00842 nassertr(_is_open, false);
00843
00844 _task_mgr.poll();
00845
00846 return !_exit_flag;
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856 void PandaFramework::
00857 main_loop() {
00858 Thread *current_thread = Thread::get_current_thread();
00859 while (do_frame(current_thread)) {
00860 }
00861 }
00862
00863
00864
00865
00866
00867
00868
00869
00870 PT(WindowFramework) PandaFramework::
00871 make_window_framework() {
00872 return new WindowFramework(this);
00873 }
00874
00875
00876
00877
00878
00879
00880
00881 void PandaFramework::
00882 make_default_pipe() {
00883
00884
00885
00886 GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr();
00887 selection->print_pipe_types();
00888 _default_pipe = selection->make_default_pipe();
00889
00890 if (_default_pipe == (GraphicsPipe*)NULL) {
00891 nout << "No graphics pipe is available!\n"
00892 << "Your Config.prc file must name at least one valid panda display\n"
00893 << "library via load-display or aux-display.\n";
00894 }
00895 }
00896
00897
00898
00899
00900
00901
00902 void PandaFramework::
00903 do_enable_default_keys() {
00904 define_key("escape", "close window", event_esc, this);
00905 define_key("q", "close window", event_esc, this);
00906 define_key("f", "report frame rate", event_f, this);
00907 define_key("w", "toggle wireframe mode", event_w, this);
00908 define_key("t", "toggle texturing", event_t, this);
00909 define_key("b", "toggle backface (double-sided) rendering", event_b, this);
00910 define_key("i", "invert (reverse) single-sided faces", event_i, this);
00911 define_key("l", "toggle lighting", event_l, this);
00912 define_key("p", "toggle per-pixel lighting", event_p, this);
00913 define_key("c", "recenter view on object", event_c, this);
00914 define_key("a", "toggle animation controls", event_a, this);
00915 define_key("shift-c", "toggle collision surfaces", event_C, this);
00916 define_key("shift-b", "report bounding volume", event_B, this);
00917 define_key("shift-l", "list hierarchy", event_L, this);
00918 define_key("shift-a", "analyze hierarchy", event_A, this);
00919 define_key("h", "highlight node", event_h, this);
00920 define_key("arrow_up", "move highlight to parent", event_arrow_up, this);
00921 define_key("arrow_down", "move highlight to child", event_arrow_down, this);
00922 define_key("arrow_left", "move highlight to sibling", event_arrow_left, this);
00923 define_key("arrow_right", "move highlight to sibling", event_arrow_right, this);
00924 define_key("shift-s", "activate PStats", event_S, this);
00925 define_key("f9", "Take screenshot", event_f9, this);
00926 define_key(",", "change background color", event_comma, this);
00927 define_key("?", "", event_question, this);
00928 define_key("shift-/", "", event_question, this);
00929 }
00930
00931
00932
00933
00934
00935
00936
00937
00938 bool PandaFramework::
00939 clear_text() {
00940 bool any_text = false;
00941 if (!_screenshot_text.is_empty()) {
00942 _screenshot_text.remove_node();
00943 any_text = true;
00944 }
00945
00946 if (!_help_text.is_empty()) {
00947 _help_text.remove_node();
00948 any_text = true;
00949 }
00950
00951 return any_text;
00952 }
00953
00954
00955
00956
00957
00958
00959
00960
00961 void PandaFramework::
00962 event_esc(const Event *event, void *data) {
00963 if (event->get_num_parameters() == 1) {
00964 EventParameter param = event->get_parameter(0);
00965 WindowFramework *wf;
00966 DCAST_INTO_V(wf, param.get_ptr());
00967
00968 PT(GraphicsOutput) win = wf->get_graphics_output();
00969
00970 PandaFramework *self = (PandaFramework *)data;
00971 self->close_window(wf);
00972
00973
00974 int window_index = self->find_window(win);
00975 while (window_index != -1) {
00976 self->close_window(window_index);
00977 window_index = self->find_window(win);
00978 }
00979
00980
00981 self->remove_mouse(win);
00982
00983
00984 self->_engine->open_windows();
00985
00986
00987 if (self->all_windows_closed()) {
00988 self->_exit_flag = true;
00989 }
00990 }
00991 }
00992
00993
00994
00995
00996
00997
00998
00999 void PandaFramework::
01000 event_f(const Event *, void *data) {
01001 PandaFramework *self = (PandaFramework *)data;
01002 self->report_frame_rate(nout);
01003 self->reset_frame_rate();
01004 }
01005
01006
01007
01008
01009
01010
01011 void PandaFramework::
01012 event_w(const Event *event, void *) {
01013 if (event->get_num_parameters() == 1) {
01014 EventParameter param = event->get_parameter(0);
01015 WindowFramework *wf;
01016 DCAST_INTO_V(wf, param.get_ptr());
01017
01018 wf->set_wireframe(!wf->get_wireframe());
01019 }
01020 }
01021
01022
01023
01024
01025
01026
01027 void PandaFramework::
01028 event_t(const Event *event, void *) {
01029 if (event->get_num_parameters() == 1) {
01030 EventParameter param = event->get_parameter(0);
01031 WindowFramework *wf;
01032 DCAST_INTO_V(wf, param.get_ptr());
01033
01034 wf->set_texture(!wf->get_texture());
01035 }
01036 }
01037
01038
01039
01040
01041
01042
01043
01044 void PandaFramework::
01045 event_b(const Event *event, void *) {
01046 if (event->get_num_parameters() == 1) {
01047 EventParameter param = event->get_parameter(0);
01048 WindowFramework *wf;
01049 DCAST_INTO_V(wf, param.get_ptr());
01050
01051 wf->set_two_sided(!wf->get_two_sided());
01052 }
01053 }
01054
01055
01056
01057
01058
01059
01060 void PandaFramework::
01061 event_i(const Event *event, void *) {
01062 if (event->get_num_parameters() == 1) {
01063 EventParameter param = event->get_parameter(0);
01064 WindowFramework *wf;
01065 DCAST_INTO_V(wf, param.get_ptr());
01066
01067 wf->set_one_sided_reverse(!wf->get_one_sided_reverse());
01068 }
01069 }
01070
01071
01072
01073
01074
01075
01076 void PandaFramework::
01077 event_l(const Event *event, void *) {
01078 if (event->get_num_parameters() == 1) {
01079 EventParameter param = event->get_parameter(0);
01080 WindowFramework *wf;
01081 DCAST_INTO_V(wf, param.get_ptr());
01082
01083 wf->set_lighting(!wf->get_lighting());
01084 }
01085 }
01086
01087
01088
01089
01090
01091
01092 void PandaFramework::
01093 event_p(const Event *event, void *) {
01094 if (event->get_num_parameters() == 1) {
01095 EventParameter param = event->get_parameter(0);
01096 WindowFramework *wf;
01097 DCAST_INTO_V(wf, param.get_ptr());
01098
01099 wf->set_perpixel(!wf->get_perpixel());
01100 }
01101 }
01102
01103
01104
01105
01106
01107
01108
01109 void PandaFramework::
01110 event_c(const Event *event, void *data) {
01111 if (event->get_num_parameters() == 1) {
01112 EventParameter param = event->get_parameter(0);
01113 WindowFramework *wf;
01114 DCAST_INTO_V(wf, param.get_ptr());
01115
01116 PandaFramework *self = (PandaFramework *)data;
01117
01118 NodePath node = self->get_highlight();
01119 if (node.is_empty()) {
01120 node = self->get_models();
01121 }
01122 wf->center_trackball(node);
01123 }
01124 }
01125
01126
01127
01128
01129
01130
01131
01132 void PandaFramework::
01133 event_a(const Event *event, void *data) {
01134 if (event->get_num_parameters() == 1) {
01135 EventParameter param = event->get_parameter(0);
01136 WindowFramework *wf;
01137 DCAST_INTO_V(wf, param.get_ptr());
01138
01139 wf->next_anim_control();
01140 }
01141 }
01142
01143
01144
01145
01146
01147
01148
01149 void PandaFramework::
01150 event_C(const Event *, void *data) {
01151 PandaFramework *self = (PandaFramework *)data;
01152
01153 NodePath node = self->get_highlight();
01154 if (node.is_empty()) {
01155 node = self->get_models();
01156 }
01157
01158 if (self->hide_collision_solids(node) == 0) {
01159 self->show_collision_solids(node);
01160 }
01161 }
01162
01163
01164
01165
01166
01167
01168
01169
01170 void PandaFramework::
01171 event_B(const Event *, void *data) {
01172 PandaFramework *self = (PandaFramework *)data;
01173
01174 NodePath node = self->get_highlight();
01175 if (node.is_empty()) {
01176 node = self->get_models();
01177 }
01178
01179 node.get_bounds()->write(nout);
01180 }
01181
01182
01183
01184
01185
01186
01187
01188 void PandaFramework::
01189 event_L(const Event *, void *data) {
01190 PandaFramework *self = (PandaFramework *)data;
01191
01192 NodePath node = self->get_highlight();
01193 if (node.is_empty()) {
01194 node = self->get_models();
01195 }
01196
01197 node.ls();
01198 }
01199
01200
01201
01202
01203
01204
01205
01206 void PandaFramework::
01207 event_A(const Event *, void *data) {
01208 PandaFramework *self = (PandaFramework *)data;
01209
01210 NodePath node = self->get_highlight();
01211 if (node.is_empty()) {
01212 node = self->get_models();
01213 }
01214
01215 SceneGraphAnalyzer sga;
01216 sga.add_node(node.node());
01217 sga.write(nout);
01218 }
01219
01220
01221
01222
01223
01224
01225
01226
01227 void PandaFramework::
01228 event_h(const Event *, void *data) {
01229 PandaFramework *self = (PandaFramework *)data;
01230
01231 if (self->has_highlight()) {
01232 self->clear_highlight();
01233 } else {
01234 self->set_highlight(self->get_models());
01235 }
01236 }
01237
01238
01239
01240
01241
01242
01243
01244 void PandaFramework::
01245 event_arrow_up(const Event *, void *data) {
01246 PandaFramework *self = (PandaFramework *)data;
01247
01248 if (self->has_highlight()) {
01249 NodePath node = self->get_highlight();
01250 if (node.has_parent() && node != self->get_models()) {
01251 self->set_highlight(node.get_parent());
01252 }
01253 }
01254 }
01255
01256
01257
01258
01259
01260
01261
01262 void PandaFramework::
01263 event_arrow_down(const Event *, void *data) {
01264 PandaFramework *self = (PandaFramework *)data;
01265
01266 if (self->has_highlight()) {
01267 NodePath node = self->get_highlight();
01268 if (node.get_num_children() > 0) {
01269 self->set_highlight(node.get_child(0));
01270 }
01271 }
01272 }
01273
01274
01275
01276
01277
01278
01279
01280
01281 void PandaFramework::
01282 event_arrow_left(const Event *, void *data) {
01283 PandaFramework *self = (PandaFramework *)data;
01284
01285 if (self->has_highlight()) {
01286 NodePath node = self->get_highlight();
01287 NodePath parent = node.get_parent();
01288 if (node.has_parent() && node != self->get_models()) {
01289 int index = parent.node()->find_child(node.node());
01290 nassertv(index >= 0);
01291 int sibling = index - 1;
01292
01293 if (sibling >= 0 &&
01294 parent.node()->get_child(sibling) == self->_highlight_wireframe.node()) {
01295
01296 sibling--;
01297 }
01298
01299 if (sibling >= 0) {
01300 self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
01301 }
01302 }
01303 }
01304 }
01305
01306
01307
01308
01309
01310
01311
01312
01313 void PandaFramework::
01314 event_arrow_right(const Event *, void *data) {
01315 PandaFramework *self = (PandaFramework *)data;
01316
01317 if (self->has_highlight()) {
01318 NodePath node = self->get_highlight();
01319 NodePath parent = node.get_parent();
01320 if (node.has_parent() && node != self->get_models()) {
01321 int index = parent.node()->find_child(node.node());
01322 nassertv(index >= 0);
01323 int num_children = parent.node()->get_num_children();
01324 int sibling = index + 1;
01325
01326 if (sibling < num_children &&
01327 parent.node()->get_child(sibling) == self->_highlight_wireframe.node()) {
01328
01329 sibling++;
01330 }
01331
01332 if (sibling < num_children) {
01333 self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
01334 }
01335 }
01336 }
01337 }
01338
01339
01340
01341
01342
01343
01344 void PandaFramework::
01345 event_S(const Event *, void *) {
01346 #ifdef DO_PSTATS
01347 nout << "Connecting to stats host" << endl;
01348 PStatClient::connect();
01349 #else
01350 nout << "Stats host not supported." << endl;
01351 #endif
01352 }
01353
01354
01355
01356
01357
01358
01359 void PandaFramework::
01360 event_f9(const Event *event, void *data) {
01361 PandaFramework *self = (PandaFramework *)data;
01362
01363 if (event->get_num_parameters() == 1) {
01364 EventParameter param = event->get_parameter(0);
01365 WindowFramework *wf;
01366 DCAST_INTO_V(wf, param.get_ptr());
01367
01368 if (self->clear_text()) {
01369
01370 self->_engine->render_frame();
01371 }
01372
01373 Filename filename = wf->get_graphics_output()->save_screenshot_default();
01374 string text;
01375 if (filename.empty()) {
01376 text = "Screenshot failed";
01377 } else {
01378 text = filename;
01379 }
01380
01381
01382 string output_text = (string)ExecutionEnvironment::get_cwd() + "/" + (string)text;
01383
01384 TextNode *text_node = new TextNode("screenshot");
01385 self->_screenshot_text = NodePath(text_node);
01386 text_node->set_align(TextNode::A_center);
01387 text_node->set_shadow_color(0.0f, 0.0f, 0.0f, 1.0f);
01388 text_node->set_shadow(0.04, 0.04);
01389 text_node->set_text(output_text);
01390 self->_screenshot_text.set_scale(0.06);
01391 self->_screenshot_text.set_pos(0.0, 0.0, -0.7);
01392 self->_screenshot_text.reparent_to(wf->get_aspect_2d());
01393 cout << "Screenshot saved: " + output_text + "\n";
01394
01395
01396 self->_task_mgr.remove(self->_task_mgr.find_tasks("clear_text"));
01397 PT(GenericAsyncTask) task = new GenericAsyncTask("clear_text", task_clear_text, self);
01398 task->set_delay(3.0);
01399 self->_task_mgr.add(task);
01400 }
01401 }
01402
01403
01404
01405
01406
01407
01408 void PandaFramework::
01409 event_comma(const Event *event, void *) {
01410 if (event->get_num_parameters() == 1) {
01411 EventParameter param = event->get_parameter(0);
01412 WindowFramework *wf;
01413 DCAST_INTO_V(wf, param.get_ptr());
01414
01415 switch (wf->get_background_type()) {
01416 case WindowFramework::BT_other:
01417 case WindowFramework::BT_none:
01418 break;
01419
01420 case WindowFramework::BT_white:
01421 wf->set_background_type(WindowFramework::BT_default);
01422 break;
01423
01424 default:
01425 wf->set_background_type((WindowFramework::BackgroundType)(wf->get_background_type() + 1));
01426 }
01427 }
01428 }
01429
01430
01431
01432
01433
01434
01435 void PandaFramework::
01436 event_question(const Event *event, void *data) {
01437 PandaFramework *self = (PandaFramework *)data;
01438 if (event->get_num_parameters() == 1) {
01439 EventParameter param = event->get_parameter(0);
01440 WindowFramework *wf;
01441 DCAST_INTO_V(wf, param.get_ptr());
01442
01443 self->_screenshot_text.remove_node();
01444
01445 if (!self->_help_text.is_empty()) {
01446 self->_help_text.remove_node();
01447
01448
01449 } else {
01450
01451 ostringstream help;
01452 KeyDefinitions::const_iterator ki;
01453 for (ki = self->_key_definitions.begin();
01454 ki != self->_key_definitions.end();
01455 ++ki) {
01456 const KeyDefinition &keydef = (*ki);
01457 help << keydef._event_name << "\t" << keydef._description << "\n";
01458 }
01459
01460 string help_text = help.str();
01461
01462 TextNode *text_node = new TextNode("help");
01463 self->_help_text = NodePath(text_node);
01464 text_node->set_align(TextNode::A_left);
01465 text_node->set_shadow_color(0.0f, 0.0f, 0.0f, 1.0f);
01466 text_node->set_shadow(0.04, 0.04);
01467 text_node->set_text(help_text);
01468
01469 LVecBase4 frame = text_node->get_frame_actual();
01470
01471 PN_stdfloat height = frame[3] - frame[2];
01472 PN_stdfloat scale = min(0.06, 1.8 / height);
01473 self->_help_text.set_scale(scale);
01474
01475 PN_stdfloat pos_scale = scale / -2.0;
01476 self->_help_text.set_pos((frame[0] + frame[1]) * pos_scale,
01477 0.0,
01478 (frame[2] + frame[3]) * pos_scale);
01479
01480 self->_help_text.reparent_to(wf->get_aspect_2d());
01481 }
01482 }
01483 }
01484
01485
01486
01487
01488
01489
01490
01491 void PandaFramework::
01492 event_window_event(const Event *event, void *data) {
01493 PandaFramework *self = (PandaFramework *)data;
01494 if (event->get_num_parameters() == 1) {
01495
01496
01497
01498 EventParameter param = event->get_parameter(0);
01499 const GraphicsOutput *win;
01500 DCAST_INTO_V(win, param.get_ptr());
01501
01502
01503 int window_index = self->find_window(win);
01504 if (window_index == -1) {
01505 framework_cat.debug()
01506 << "Ignoring message from unknown window.\n";
01507
01508 } else {
01509 if (!win->is_valid()) {
01510
01511 int window_index = self->find_window(win);
01512 while (window_index != -1) {
01513 self->close_window(window_index);
01514 window_index = self->find_window(win);
01515 }
01516
01517
01518 self->remove_mouse(win);
01519
01520
01521 if (self->all_windows_closed() && !self->_exit_flag) {
01522 framework_cat.info()
01523 << "Last window was closed by user.\n";
01524 self->_exit_flag = true;
01525 }
01526 } else {
01527
01528 for (int n = 0; n < (int)self->_windows.size(); n++) {
01529 if (self->_windows[n]->get_graphics_output() == win) {
01530 self->_windows[n]->adjust_dimensions();
01531 }
01532 }
01533 }
01534 }
01535 }
01536 }
01537
01538
01539
01540
01541
01542
01543
01544 AsyncTask::DoneStatus PandaFramework::
01545 task_data_loop(GenericAsyncTask *task, void *data) {
01546 PandaFramework *self = (PandaFramework *)data;
01547
01548 DataGraphTraverser dg_trav;
01549 dg_trav.traverse(self->_data_root.node());
01550
01551 return AsyncTask::DS_cont;
01552 }
01553
01554
01555
01556
01557
01558
01559 AsyncTask::DoneStatus PandaFramework::
01560 task_event(GenericAsyncTask *task, void *data) {
01561 PandaFramework *self = (PandaFramework *)data;
01562
01563 throw_event("NewFrame");
01564 self->_event_handler.process_events();
01565
01566 return AsyncTask::DS_cont;
01567 }
01568
01569
01570
01571
01572
01573
01574 AsyncTask::DoneStatus PandaFramework::
01575 task_igloop(GenericAsyncTask *task, void *data) {
01576 PandaFramework *self = (PandaFramework *)data;
01577
01578 if (self->_engine != (GraphicsEngine *)NULL) {
01579 self->_engine->render_frame();
01580 }
01581
01582 return AsyncTask::DS_cont;
01583 }
01584
01585
01586
01587
01588
01589
01590
01591 AsyncTask::DoneStatus PandaFramework::
01592 task_record_frame(GenericAsyncTask *task, void *data) {
01593 PandaFramework *self = (PandaFramework *)data;
01594
01595 if (self->_recorder != (RecorderController *)NULL) {
01596 self->_recorder->record_frame();
01597 }
01598
01599 return AsyncTask::DS_cont;
01600 }
01601
01602
01603
01604
01605
01606
01607
01608 AsyncTask::DoneStatus PandaFramework::
01609 task_play_frame(GenericAsyncTask *task, void *data) {
01610 PandaFramework *self = (PandaFramework *)data;
01611
01612 if (self->_recorder != (RecorderController *)NULL) {
01613 self->_recorder->play_frame();
01614 }
01615
01616 return AsyncTask::DS_cont;
01617 }
01618
01619
01620
01621
01622
01623
01624 AsyncTask::DoneStatus PandaFramework::
01625 task_clear_text(GenericAsyncTask *task, void *data) {
01626 PandaFramework *self = (PandaFramework *)data;
01627
01628 self->clear_text();
01629 return AsyncTask::DS_cont;
01630 }
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640 AsyncTask::DoneStatus PandaFramework::
01641 task_garbage_collect(GenericAsyncTask *task, void *data) {
01642 TransformState::garbage_collect();
01643 RenderState::garbage_collect();
01644 return AsyncTask::DS_cont;
01645 }