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