Panda3D
pandaFramework.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pandaFramework.cxx
10  * @author drose
11  * @date 2002-04-02
12  */
13 
14 #include "pandaFramework.h"
15 #include "clockObject.h"
16 #include "pStatClient.h"
17 #include "eventQueue.h"
18 #include "dataGraphTraverser.h"
19 #include "depthOffsetAttrib.h"
20 #include "collisionNode.h"
21 #include "occluderNode.h"
22 #include "config_framework.h"
23 #include "graphicsPipeSelection.h"
24 #include "nodePathCollection.h"
25 #include "textNode.h"
26 #include "mouseAndKeyboard.h"
27 #include "mouseRecorder.h"
28 #include "throw_event.h"
29 #include "executionEnvironment.h"
30 #include "sceneGraphAnalyzer.h"
31 #include "transformState.h"
32 #include "renderState.h"
33 
34 #ifdef LINK_ALL_STATIC
35 #ifdef HAVE_EGG
36 #include "pandaegg.h"
37 #endif
38 #endif
39 
40 using std::string;
41 
42 LoaderOptions PandaFramework::_loader_options;
43 
44 /**
45  *
46  */
47 PandaFramework::
48 PandaFramework() :
49  _event_handler(*EventHandler::get_global_event_handler()),
50  _task_mgr(*AsyncTaskManager::get_global_ptr())
51 {
52  _is_open = false;
53  _made_default_pipe = false;
54  _window_title = string();
55  _engine = nullptr;
56  _start_time = 0.0;
57  _frame_count = 0;
58  _wireframe_enabled = false;
59  _texture_enabled = true;
60  _two_sided_enabled = false;
61  _lighting_enabled = false;
62  _perpixel_enabled = false;
63  _background_type = WindowFramework::BT_default;
64  _default_keys_enabled = false;
65  _exit_flag = false;
66 }
67 
68 /**
69  *
70  */
71 PandaFramework::
72 ~PandaFramework() {
73  if (_is_open) {
75  }
76 }
77 
78 /**
79  * Should be called once at the beginning of the application to initialize
80  * Panda (and the framework) for use. The command-line arguments should be
81  * passed in so Panda can remove any arguments that it recognizes as special
82  * control parameters.
83  */
86  if (_is_open) {
87  return;
88  }
89 
90  _is_open = true;
91 
92 #ifdef LINK_ALL_STATIC
93  // If we're statically linking, we need to explicitly link with at least one
94  // of the available renderers.
95  #if defined(HAVE_GL)
96  extern void init_libpandagl();
98  #elif defined(HAVE_DX9)
99  extern EXPCL_PANDADX void init_libpandadx9();
101  #elif defined(HAVE_TINYDISPLAY)
102  extern EXPCL_TINYDISPLAY void init_libtinydisplay();
103  init_libtinydisplay();
104  #endif
105 
106  // Ensure the animation subsystem is available.
107  extern EXPCL_PANDA_CHAR void init_libchar();
108  init_libchar();
109 
110  // We also want the egg loader.
111  #ifdef HAVE_EGG
113  #endif
114 #endif
115 
116  // Let's explicitly make a call to the image type library to ensure it gets
117  // pulled in by the dynamic linker.
118  extern EXPCL_PANDA_PNMIMAGETYPES void init_libpnmimagetypes();
120 
122 
123  {
124  PT(GenericAsyncTask) task = new GenericAsyncTask("event", task_event, this);
125  _task_mgr.add(task);
126  }
127 
128  _data_root = NodePath("data");
129  {
130  PT(GenericAsyncTask) task = new GenericAsyncTask("data_loop", task_data_loop, this);
131  task->set_sort(-50);
132  _task_mgr.add(task);
133  }
134 
135  if (garbage_collect_states) {
136  PT(GenericAsyncTask) task = new GenericAsyncTask("garbageCollectStates", task_garbage_collect, this);
137  task->set_sort(46);
138  _task_mgr.add(task);
139  }
140 
141  if (!playback_session.empty()) {
142  // If the config file so indicates, create a recorder and start it
143  // playing.
144  _recorder = new RecorderController;
145  _recorder->begin_playback(Filename::from_os_specific(playback_session));
146 
147  PT(GenericAsyncTask) task = new GenericAsyncTask("play_frame", task_play_frame, this);
148  task->set_sort(55);
149  _task_mgr.add(task);
150 
151  } else if (!record_session.empty()) {
152  // If the config file so indicates, create a recorder and start it
153  // recording.
154  _recorder = new RecorderController;
155  _recorder->begin_record(Filename::from_os_specific(record_session));
156 
157  PT(GenericAsyncTask) task = new GenericAsyncTask("record_frame", task_record_frame, this);
158  task->set_sort(45);
159  _task_mgr.add(task);
160  }
161 
162  _event_handler.add_hook("window-event", event_window_event, this);
163 }
164 
165 /**
166  * @deprecated See the version of open_framework() without arguments.
167  */
168 void PandaFramework::
169 open_framework(int &argc, char **&argv) {
170  open_framework();
171 }
172 
173 /**
174  * Should be called at the end of an application to close Panda. This is
175  * optional, as the destructor will do the same thing.
176  */
177 void PandaFramework::
179  if (!_is_open) {
180  return;
181  }
182 
184  // Also close down any other windows that might have been opened.
185  if (_engine != nullptr) {
186  _engine->remove_all_windows();
187  _engine = nullptr;
188  }
189 
190  _event_handler.remove_all_hooks();
191 
192  _is_open = false;
193  _made_default_pipe = false;
194  _default_pipe.clear();
195 
196  _start_time = 0.0;
197  _frame_count = 0;
198  _wireframe_enabled = false;
199  _two_sided_enabled = false;
200  _lighting_enabled = false;
201  _default_keys_enabled = false;
202  _exit_flag = false;
203 
204  _recorder = nullptr;
205 
207 }
208 
209 /**
210  * Returns the default pipe. This is the GraphicsPipe that all windows in the
211  * framework will be created on, unless otherwise specified in open_window().
212  * It is usually the primary graphics interface on the local machine.
213  *
214  * If the default pipe has not yet been created, this creates it.
215  *
216  * The return value is the default pipe, or NULL if no default pipe could be
217  * created.
218  */
221  nassertr(_is_open, nullptr);
222  if (!_made_default_pipe) {
223  make_default_pipe();
224  _made_default_pipe = true;
225  }
226  return _default_pipe;
227 }
228 
229 /**
230  * Returns a NodePath to the MouseAndKeyboard associated with the indicated
231  * GraphicsWindow object. If there's not yet a mouse associated with the
232  * window, creates one.
233  *
234  * This allows multiple WindowFramework objects that represent different
235  * display regions of the same GraphicsWindow to share the same mouse.
236  */
239  Mouses::iterator mi = _mouses.find(window);
240  if (mi != _mouses.end()) {
241  return (*mi).second;
242  }
243 
244  NodePath mouse;
245 
246  if (window->is_of_type(GraphicsWindow::get_class_type())) {
247  NodePath data_root = get_data_root();
248  GraphicsWindow *win = DCAST(GraphicsWindow, window);
249  MouseAndKeyboard *mouse_node = new MouseAndKeyboard(win, 0, "mouse");
250  mouse = data_root.attach_new_node(mouse_node);
251 
252  RecorderController *recorder = get_recorder();
253  if (recorder != nullptr) {
254  // If we're in recording or playback mode, associate a recorder.
255  MouseRecorder *mouse_recorder = new MouseRecorder("mouse");
256  mouse = mouse.attach_new_node(mouse_recorder);
257  recorder->add_recorder("mouse", mouse_recorder);
258  }
259  }
260 
261  _mouses[window] = mouse;
262 
263  return mouse;
264 }
265 
266 /**
267  * Removes the mouse that may have been created by an earlier call to
268  * get_mouse().
269  */
270 void PandaFramework::
271 remove_mouse(const GraphicsOutput *window) {
272  Mouses::iterator mi = _mouses.find(window);
273  if (mi != _mouses.end()) {
274  (*mi).second.remove_node();
275  _mouses.erase(mi);
276  }
277 }
278 
279 /**
280  * Sets up a handler for the indicated key. When the key is pressed in a
281  * window, the given callback will be called. The description is a one-line
282  * description of the function of the key, for display to the user.
283  */
284 void PandaFramework::
285 define_key(const string &event_name, const string &description,
286  EventHandler::EventCallbackFunction *function,
287  void *data) {
288  if (_event_handler.has_hook(event_name)) {
289  // If there is already a hook for the indicated keyname, we're most likely
290  // replacing a previous definition of a key. Search for the old
291  // definition and remove it.
292  KeyDefinitions::iterator di;
293  di = _key_definitions.begin();
294  while (di != _key_definitions.end() && (*di)._event_name != event_name) {
295  ++di;
296  }
297  if (di != _key_definitions.end()) {
298  _key_definitions.erase(di);
299  }
300  }
301 
302  // Now add a new hook for the keyname, and also add the new description.
303  _event_handler.add_hook(event_name, function, data);
304 
305  if (!description.empty()) {
306  KeyDefinition keydef;
307  keydef._event_name = event_name;
308  keydef._description = description;
309  _key_definitions.push_back(keydef);
310  }
311 }
312 
313 /**
314  * Fills in the indicated window properties structure according to the normal
315  * window properties for this application.
316  */
317 void PandaFramework::
319  // This function is largely vestigial and will be removed soon. We have
320  // moved the default window properties into WindowProperties::get_default().
321 
323  if (!_window_title.empty()) {
324  props.set_title(_window_title);
325  }
326 }
327 
328 /**
329  * Opens a window on the default graphics pipe. If the default graphics pipe
330  * can't open a window for some reason, automatically fails over to the next
331  * available graphics pipe, and updates _default_pipe accordingly. Returns
332  * NULL only if all graphics pipes fail.
333  */
336  GraphicsPipe *pipe = get_default_pipe();
337  if (pipe == nullptr) {
338  // Can't get a pipe.
339  return nullptr;
340  }
341 
342  WindowFramework *wf = open_window(pipe, nullptr);
343  if (wf == nullptr) {
344  // Ok, the default graphics pipe failed; try a little harder.
346  selection->load_aux_modules();
347 
348  int num_pipe_types = selection->get_num_pipe_types();
349  for (int i = 0; i < num_pipe_types; i++) {
350  TypeHandle pipe_type = selection->get_pipe_type(i);
351  if (pipe_type != _default_pipe->get_type()) {
352  PT(GraphicsPipe) new_pipe = selection->make_pipe(pipe_type);
353  if (new_pipe != nullptr) {
354  wf = open_window(new_pipe, nullptr);
355  if (wf != nullptr) {
356  // Here's the winner!
357  _default_pipe = new_pipe;
358  return wf;
359  }
360  }
361  }
362  }
363 
364  // Too bad; none of the pipes could open a window. Fall through and
365  // return NULL.
366  }
367 
368  return wf;
369 }
370 
371 /**
372  * Opens a new window on the indicated pipe, using the default parameters.
373  * Returns the new WindowFramework if successful, or NULL if not.
374  */
377  nassertr(_is_open, nullptr);
378 
379  WindowProperties props;
381 
382  int flags = GraphicsPipe::BF_require_window;
383  if (window_type == "offscreen") {
384  flags = GraphicsPipe::BF_refuse_window;
385  }
386 
387  return open_window(props, flags, pipe, gsg);
388 }
389 
390 /**
391  * Opens a new window using the indicated properties. (You may initialize the
392  * properties to their default values by calling get_default_window_props()
393  * first.)
394  *
395  * Returns the new WindowFramework if successful, or NULL if not.
396  */
398 open_window(const WindowProperties &props, int flags,
399  GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
400  if (pipe == nullptr) {
401  pipe = get_default_pipe();
402  if (pipe == nullptr) {
403  // Can't get a pipe.
404  return nullptr;
405  }
406  }
407 
408  nassertr(_is_open, nullptr);
409  PT(WindowFramework) wf = make_window_framework();
410  wf->set_wireframe(get_wireframe());
411  wf->set_texture(get_texture());
412  wf->set_two_sided(get_two_sided());
413  wf->set_lighting(get_lighting());
414  wf->set_perpixel(get_perpixel());
415  wf->set_background_type(get_background_type());
416 
417  GraphicsOutput *win = wf->open_window(props, flags, get_graphics_engine(),
418  pipe, gsg);
419  _engine->open_windows();
420  if (win != nullptr && !win->is_valid()) {
421  // The window won't open.
422  _engine->remove_window(win);
423  wf->close_window();
424  win = nullptr;
425  }
426 
427  if (win == nullptr) {
428  // Oops, couldn't make a window or buffer.
429  framework_cat.error()
430  << "Unable to create window.\n";
431  return nullptr;
432  }
433 
434  _windows.push_back(wf);
435  return wf;
436 }
437 
438 /**
439  * Returns the index of the first WindowFramework object found that references
440  * the indicated GraphicsOutput pointer, or -1 if none do.
441  */
443 find_window(const GraphicsOutput *win) const {
444  int n;
445  for (n = 0; n < (int)_windows.size(); n++) {
446  if (_windows[n]->get_graphics_output() == win) {
447  return n;
448  }
449  }
450 
451  return -1;
452 }
453 
454 /**
455  * Returns the index of the given WindowFramework object, or -1 if the object
456  * does not represent a window opened with this PandaFramework.
457  */
459 find_window(const WindowFramework *wf) const {
460  int n;
461  for (n = 0; n < (int)_windows.size(); n++) {
462  if (_windows[n] == wf) {
463  return n;
464  }
465  }
466 
467  return -1;
468 }
469 
470 
471 /**
472  * Closes the nth window and removes it from the list.
473  */
474 void PandaFramework::
475 close_window(int n) {
476  nassertv(n >= 0 && n < (int)_windows.size());
477  WindowFramework *wf = _windows[n];
478 
479  GraphicsOutput *win = wf->get_graphics_output();
480  if (win != nullptr) {
481  _engine->remove_window(win);
482  }
483 
484  wf->close_window();
485  _windows.erase(_windows.begin() + n);
486 }
487 
488 /**
489  * Closes all currently open windows and empties the list of windows.
490  */
491 void PandaFramework::
493  Windows::iterator wi;
494  for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
495  WindowFramework *wf = (*wi);
496 
497  GraphicsOutput *win = wf->get_graphics_output();
498  if (win != nullptr) {
499  _engine->remove_window(win);
500  }
501 
502  wf->close_window();
503  }
504 
505  Mouses::iterator mi;
506  for (mi = _mouses.begin(); mi != _mouses.end(); ++mi) {
507  (*mi).second.remove_node();
508  }
509 
510  _windows.clear();
511  _mouses.clear();
512 }
513 
514 /**
515  * Returns true if all of the opened windows have been closed by the user,
516  * false otherwise.
517  */
518 bool PandaFramework::
520  Windows::const_iterator wi;
521  for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
522  WindowFramework *wf = (*wi);
523  if (wf->get_graphics_output()->is_valid()) {
524  return false;
525  }
526  }
527 
528  return true;
529 }
530 
531 /**
532  * Returns the root of the scene graph normally reserved for parenting models
533  * and such. This scene graph may be instanced to each window's render tree
534  * as the window is created.
535  */
538  if (_models.is_empty()) {
539  _models = NodePath("models");
540  }
541  return _models;
542 }
543 
544 /**
545  * Reports the currently measured average frame rate to the indicated ostream.
546  */
547 void PandaFramework::
548 report_frame_rate(std::ostream &out) const {
550  double delta = now - _start_time;
551 
552  int frame_count = ClockObject::get_global_clock()->get_frame_count();
553  int num_frames = frame_count - _frame_count;
554  if (num_frames > 0) {
555  out << num_frames << " frames in " << delta << " seconds.\n";
556  double fps = ((double)num_frames) / delta;
557  out << fps << " fps average (" << 1000.0 / fps << "ms)\n";
558  }
559 }
560 
561 /**
562  * Resets the frame rate computation.
563  */
564 void PandaFramework::
568 }
569 
570 /**
571  * Sets the wireframe state on all windows.
572  */
573 void PandaFramework::
574 set_wireframe(bool enable) {
575  Windows::iterator wi;
576  for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
577  WindowFramework *wf = (*wi);
578  wf->set_wireframe(enable);
579  }
580 
581  _wireframe_enabled = enable;
582 }
583 
584 /**
585  * Sets the texture state on all windows.
586  */
587 void PandaFramework::
588 set_texture(bool enable) {
589  Windows::iterator wi;
590  for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
591  WindowFramework *wf = (*wi);
592  wf->set_texture(enable);
593  }
594 
595  _texture_enabled = enable;
596 }
597 
598 /**
599  * Sets the two_sided state on all windows.
600  */
601 void PandaFramework::
602 set_two_sided(bool enable) {
603  Windows::iterator wi;
604  for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
605  WindowFramework *wf = (*wi);
606  wf->set_two_sided(enable);
607  }
608 
609  _two_sided_enabled = enable;
610 }
611 
612 /**
613  * Sets the lighting state on all windows.
614  */
615 void PandaFramework::
616 set_lighting(bool enable) {
617  Windows::iterator wi;
618  for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
619  WindowFramework *wf = (*wi);
620  wf->set_lighting(enable);
621  }
622 
623  _lighting_enabled = enable;
624 }
625 
626 /**
627  * Sets the perpixel state on all windows.
628  */
629 void PandaFramework::
630 set_perpixel(bool enable) {
631  Windows::iterator wi;
632  for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
633  WindowFramework *wf = (*wi);
634  wf->set_perpixel(enable);
635  }
636 
637  _perpixel_enabled = enable;
638 }
639 
640 /**
641  * Sets the background type of all windows.
642  */
643 void PandaFramework::
644 set_background_type(WindowFramework::BackgroundType type) {
645  Windows::iterator wi;
646  for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
647  WindowFramework *wf = (*wi);
648  wf->set_background_type(type);
649  }
650 
651  _background_type = type;
652 }
653 
654 /**
655  * Hides any collision solids, or occluders, which are visible in the
656  * indicated scene graph. Returns the number of nodes hidden.
657  */
660  int num_changed = 0;
661 
662  if (node.node()->is_of_type(CollisionNode::get_class_type()) ||
663  node.node()->is_of_type(OccluderNode::get_class_type())) {
664  if (!node.is_hidden()) {
665  node.hide();
666  num_changed++;
667  }
668  }
669 
670  int num_children = node.get_num_children();
671  for (int i = 0; i < num_children; i++) {
672  num_changed += hide_collision_solids(node.get_child(i));
673  }
674 
675  return num_changed;
676 }
677 
678 /**
679  * Shows any collision solids, or occluders, which are directly hidden in the
680  * indicated scene graph. Returns the number of nodes shown.
681  */
684  int num_changed = 0;
685 
686  if (node.node()->is_of_type(CollisionNode::get_class_type()) ||
687  node.node()->is_of_type(OccluderNode::get_class_type())) {
688  if (node.get_hidden_ancestor() == node) {
689  node.show();
690  num_changed++;
691  }
692  }
693 
694  int num_children = node.get_num_children();
695  for (int i = 0; i < num_children; i++) {
696  num_changed += show_collision_solids(node.get_child(i));
697  }
698 
699  return num_changed;
700 }
701 
702 /**
703  * Sets the indicated node (normally a node within the get_models() tree) up
704  * as the highlighted node. Certain operations affect the highlighted node
705  * only.
706  */
707 void PandaFramework::
708 set_highlight(const NodePath &node) {
709  clear_highlight();
710  _highlight = node;
711  if (!_highlight.is_empty()) {
712  framework_cat.info(false) << _highlight << "\n";
713  _highlight.show_bounds();
714  _highlight.set_render_mode_filled_wireframe(LColor(1.0f, 0.0f, 0.0f, 1.0f), 200);
715  }
716 }
717 
718 /**
719  * Unhighlights the currently highlighted node, if any.
720  */
721 void PandaFramework::
723  if (!_highlight.is_empty()) {
724  _highlight.hide_bounds();
725  _highlight.clear_render_mode();
726  _highlight = NodePath();
727  }
728 }
729 
730 /**
731  * Sets callbacks on the event handler to handle all of the normal viewer
732  * keys, like t to toggle texture, ESC or q to quit, etc.
733  */
734 void PandaFramework::
736  if (!_default_keys_enabled) {
737  do_enable_default_keys();
738  _default_keys_enabled = true;
739  }
740 }
741 
742 /**
743  * Renders one frame and performs all associated processing. Returns true if
744  * we should continue rendering, false if we should exit. This is normally
745  * called only from main_loop().
746  */
747 bool PandaFramework::
748 do_frame(Thread *current_thread) {
749  nassertr(_is_open, false);
750 
751  _task_mgr.poll();
752 
753  return !_exit_flag;
754 }
755 
756 /**
757  * Called to yield control to the panda framework. This function does not
758  * return until set_exit_flag() has been called.
759  */
760 void PandaFramework::
762  Thread *current_thread = Thread::get_current_thread();
763  while (do_frame(current_thread)) {
764  }
765 }
766 
767 /**
768  * Creates a new WindowFramework object. This is provided as a hook so
769  * derived PandaFramework classes can create custom WindowFramework objects.
770  */
771 PT(WindowFramework) PandaFramework::
772 make_window_framework() {
773  return new WindowFramework(this);
774 }
775 
776 /**
777  * Creates the default GraphicsPipe that will contain all windows that are not
778  * opened on a specific pipe.
779  */
780 void PandaFramework::
781 make_default_pipe() {
782  // This depends on the shared library or libraries (DLL's to you Windows
783  // folks) that have been loaded in at runtime from the load-display andor
784  // aux-display Configrc variables.
786 
787  if (print_pipe_types) {
788  selection->print_pipe_types();
789  }
790 
791  _default_pipe = selection->make_default_pipe();
792 
793  if (_default_pipe == nullptr) {
794  nout << "No graphics pipe is available!\n"
795  << "Your Config.prc file must name at least one valid panda display\n"
796  << "library via load-display or aux-display.\n";
797  }
798 }
799 
800 /**
801  * The implementation of enable_default_keys().
802  */
803 void PandaFramework::
804 do_enable_default_keys() {
805  define_key("escape", "close window", event_esc, this);
806  define_key("q", "close window", event_esc, this);
807  define_key("f", "report frame rate", event_f, this);
808  define_key("w", "toggle wireframe mode", event_w, this);
809  define_key("t", "toggle texturing", event_t, this);
810  define_key("b", "toggle backface (double-sided) rendering", event_b, this);
811  define_key("i", "invert (reverse) single-sided faces", event_i, this);
812  define_key("l", "toggle lighting", event_l, this);
813  define_key("p", "toggle per-pixel lighting", event_p, this);
814  define_key("c", "recenter view on object", event_c, this);
815  define_key("a", "toggle animation controls", event_a, this);
816  define_key("shift-c", "toggle collision surfaces", event_C, this);
817  define_key("shift-b", "report bounding volume", event_B, this);
818  define_key("shift-l", "list hierarchy", event_L, this);
819  define_key("shift-a", "analyze hierarchy", event_A, this);
820  define_key("h", "highlight node", event_h, this);
821  define_key("arrow_up", "move highlight to parent", event_arrow_up, this);
822  define_key("arrow_down", "move highlight to child", event_arrow_down, this);
823  define_key("arrow_left", "move highlight to sibling", event_arrow_left, this);
824  define_key("arrow_right", "move highlight to sibling", event_arrow_right, this);
825  define_key("shift-s", "activate PStats", event_S, this);
826  define_key("f9", "Take screenshot", event_f9, this);
827  define_key(",", "change background color", event_comma, this);
828  define_key("?", "", event_question, this);
829  define_key("shift-/", "", event_question, this);
830 }
831 
832 /**
833  * Removes any onscreen text (like help text or screenshot filename). Returns
834  * true if there was any text in the first place, false otherwise.
835  */
836 bool PandaFramework::
837 clear_text() {
838  bool any_text = false;
839  if (!_screenshot_text.is_empty()) {
840  _screenshot_text.remove_node();
841  any_text = true;
842  }
843 
844  if (!_help_text.is_empty()) {
845  _help_text.remove_node();
846  any_text = true;
847  }
848 
849  return any_text;
850 }
851 
852 /**
853  * Default handler for ESC or q key: close the current window (and exit the
854  * application if that was the last window).
855  */
856 void PandaFramework::
857 event_esc(const Event *event, void *data) {
858  if (event->get_num_parameters() == 1) {
859  EventParameter param = event->get_parameter(0);
860  WindowFramework *wf;
861  DCAST_INTO_V(wf, param.get_ptr());
862 
863  PT(GraphicsOutput) win = wf->get_graphics_output();
864 
865  PandaFramework *self = (PandaFramework *)data;
866  self->close_window(wf);
867 
868  // Also close any other WindowFrameworks on the same window.
869  int window_index = self->find_window(win);
870  while (window_index != -1) {
871  self->close_window(window_index);
872  window_index = self->find_window(win);
873  }
874 
875  // Free up the mouse for that window.
876  self->remove_mouse(win);
877 
878  // Make sure the close request propagates through the system.
879  self->_engine->open_windows();
880 
881  // If we closed the last window, shut down.
882  if (self->all_windows_closed()) {
883  self->_exit_flag = true;
884  }
885  }
886 }
887 
888 /**
889  * Default handler for f key: report and reset frame rate.
890  */
891 void PandaFramework::
892 event_f(const Event *, void *data) {
893  PandaFramework *self = (PandaFramework *)data;
894  self->report_frame_rate(nout);
895  self->reset_frame_rate();
896 }
897 
898 /**
899  * Default handler for w key: toggle wireframe.
900  */
901 void PandaFramework::
902 event_w(const Event *event, void *) {
903  if (event->get_num_parameters() == 1) {
904  EventParameter param = event->get_parameter(0);
905  WindowFramework *wf;
906  DCAST_INTO_V(wf, param.get_ptr());
907 
908  if (!wf->get_wireframe()) {
909  wf->set_wireframe(true, true);
910  } else if (wf->get_wireframe_filled()) {
911  wf->set_wireframe(true, false);
912  } else {
913  wf->set_wireframe(false, false);
914  }
915  }
916 }
917 
918 /**
919  * Default handler for t key: toggle texture.
920  */
921 void PandaFramework::
922 event_t(const Event *event, void *) {
923  if (event->get_num_parameters() == 1) {
924  EventParameter param = event->get_parameter(0);
925  WindowFramework *wf;
926  DCAST_INTO_V(wf, param.get_ptr());
927 
928  wf->set_texture(!wf->get_texture());
929  }
930 }
931 
932 /**
933  * Default handler for b key: toggle backface (two-sided rendering).
934  */
935 void PandaFramework::
936 event_b(const Event *event, void *) {
937  if (event->get_num_parameters() == 1) {
938  EventParameter param = event->get_parameter(0);
939  WindowFramework *wf;
940  DCAST_INTO_V(wf, param.get_ptr());
941 
942  wf->set_two_sided(!wf->get_two_sided());
943  }
944 }
945 
946 /**
947  * Default handler for i key: invert one-sided faces.
948  */
949 void PandaFramework::
950 event_i(const Event *event, void *) {
951  if (event->get_num_parameters() == 1) {
952  EventParameter param = event->get_parameter(0);
953  WindowFramework *wf;
954  DCAST_INTO_V(wf, param.get_ptr());
955 
957  }
958 }
959 
960 /**
961  * Default handler for l key: toggle lighting.
962  */
963 void PandaFramework::
964 event_l(const Event *event, void *) {
965  if (event->get_num_parameters() == 1) {
966  EventParameter param = event->get_parameter(0);
967  WindowFramework *wf;
968  DCAST_INTO_V(wf, param.get_ptr());
969 
970  wf->set_lighting(!wf->get_lighting());
971  }
972 }
973 
974 /**
975  * Default handler for p key: toggle per-pixel lighting.
976  */
977 void PandaFramework::
978 event_p(const Event *event, void *) {
979  if (event->get_num_parameters() == 1) {
980  EventParameter param = event->get_parameter(0);
981  WindowFramework *wf;
982  DCAST_INTO_V(wf, param.get_ptr());
983 
984  wf->set_perpixel(!wf->get_perpixel());
985  }
986 }
987 
988 /**
989  * Default handler for c key: center the trackball over the scene, or over the
990  * highlighted part of the scene.
991  */
992 void PandaFramework::
993 event_c(const Event *event, void *data) {
994  if (event->get_num_parameters() == 1) {
995  EventParameter param = event->get_parameter(0);
996  WindowFramework *wf;
997  DCAST_INTO_V(wf, param.get_ptr());
998 
999  PandaFramework *self = (PandaFramework *)data;
1000 
1001  NodePath node = self->get_highlight();
1002  if (node.is_empty()) {
1003  node = self->get_models();
1004  }
1005  wf->center_trackball(node);
1006  }
1007 }
1008 
1009 /**
1010  * Default handler for a key: toggle the animation controls.
1011  */
1012 void PandaFramework::
1013 event_a(const Event *event, void *data) {
1014  if (event->get_num_parameters() == 1) {
1015  EventParameter param = event->get_parameter(0);
1016  WindowFramework *wf;
1017  DCAST_INTO_V(wf, param.get_ptr());
1018 
1019  wf->next_anim_control();
1020  }
1021 }
1022 
1023 /**
1024  * Default handler for shift-C key: toggle the showing of collision solids.
1025  */
1026 void PandaFramework::
1027 event_C(const Event *, void *data) {
1028  PandaFramework *self = (PandaFramework *)data;
1029 
1030  NodePath node = self->get_highlight();
1031  if (node.is_empty()) {
1032  node = self->get_models();
1033  }
1034 
1035  if (self->hide_collision_solids(node) == 0) {
1036  self->show_collision_solids(node);
1037  }
1038 }
1039 
1040 /**
1041  * Default handler for shift-B key: describe the bounding volume of the
1042  * currently selected object, or the entire scene.
1043  */
1044 void PandaFramework::
1045 event_B(const Event *, void *data) {
1046  PandaFramework *self = (PandaFramework *)data;
1047 
1048  NodePath node = self->get_highlight();
1049  if (node.is_empty()) {
1050  node = self->get_models();
1051  }
1052 
1053  node.get_bounds()->write(nout);
1054 }
1055 
1056 /**
1057  * Default handler for shift-L key: list the contents of the scene graph, or
1058  * the highlighted node.
1059  */
1060 void PandaFramework::
1061 event_L(const Event *, void *data) {
1062  PandaFramework *self = (PandaFramework *)data;
1063 
1064  NodePath node = self->get_highlight();
1065  if (node.is_empty()) {
1066  node = self->get_models();
1067  }
1068 
1069  node.ls();
1070 }
1071 
1072 /**
1073  * Default handler for shift-A key: analyze the contents of the scene graph,
1074  * or the highlighted node.
1075  */
1076 void PandaFramework::
1077 event_A(const Event *, void *data) {
1078  PandaFramework *self = (PandaFramework *)data;
1079 
1080  NodePath node = self->get_highlight();
1081  if (node.is_empty()) {
1082  node = self->get_models();
1083  }
1084 
1085  SceneGraphAnalyzer sga;
1086  sga.add_node(node.node());
1087  sga.write(nout);
1088 }
1089 
1090 /**
1091  * Default handler for h key: toggle highlight mode. In this mode, you can
1092  * walk the scene graph with the arrow keys to highlight different nodes.
1093  */
1094 void PandaFramework::
1095 event_h(const Event *, void *data) {
1096  PandaFramework *self = (PandaFramework *)data;
1097 
1098  if (self->has_highlight()) {
1099  self->clear_highlight();
1100  } else {
1101  self->set_highlight(self->get_models());
1102  }
1103 }
1104 
1105 /**
1106  * Default handler for up arrow key: in highlight mode, move the highlight to
1107  * the node's parent.
1108  */
1109 void PandaFramework::
1110 event_arrow_up(const Event *, void *data) {
1111  PandaFramework *self = (PandaFramework *)data;
1112 
1113  if (self->has_highlight()) {
1114  NodePath node = self->get_highlight();
1115  if (node.has_parent() && node != self->get_models()) {
1116  self->set_highlight(node.get_parent());
1117  }
1118  }
1119 }
1120 
1121 /**
1122  * Default handler for up arrow key: in highlight mode, move the highlight to
1123  * the node's first child.
1124  */
1125 void PandaFramework::
1126 event_arrow_down(const Event *, void *data) {
1127  PandaFramework *self = (PandaFramework *)data;
1128 
1129  if (self->has_highlight()) {
1130  NodePath node = self->get_highlight();
1131  if (node.get_num_children() > 0) {
1132  self->set_highlight(node.get_child(0));
1133  }
1134  }
1135 }
1136 
1137 /**
1138  * Default handler for up arrow key: in highlight mode, move the highlight to
1139  * the node's nearest sibling on the left.
1140  */
1141 void PandaFramework::
1142 event_arrow_left(const Event *, void *data) {
1143  PandaFramework *self = (PandaFramework *)data;
1144 
1145  if (self->has_highlight()) {
1146  NodePath node = self->get_highlight();
1147  NodePath parent = node.get_parent();
1148  if (node.has_parent() && node != self->get_models()) {
1149  int index = parent.node()->find_child(node.node());
1150  nassertv(index >= 0);
1151  int sibling = index - 1;
1152  if (sibling >= 0) {
1153  self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
1154  }
1155  }
1156  }
1157 }
1158 
1159 /**
1160  * Default handler for up arrow key: in highlight mode, move the highlight to
1161  * the node's nearest sibling on the right.
1162  */
1163 void PandaFramework::
1164 event_arrow_right(const Event *, void *data) {
1165  PandaFramework *self = (PandaFramework *)data;
1166 
1167  if (self->has_highlight()) {
1168  NodePath node = self->get_highlight();
1169  NodePath parent = node.get_parent();
1170  if (node.has_parent() && node != self->get_models()) {
1171  int index = parent.node()->find_child(node.node());
1172  nassertv(index >= 0);
1173  int num_children = parent.node()->get_num_children();
1174  int sibling = index + 1;
1175  if (sibling < num_children) {
1176  self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
1177  }
1178  }
1179  }
1180 }
1181 
1182 /**
1183  * Default handler for shift-S key: activate stats.
1184  */
1185 void PandaFramework::
1186 event_S(const Event *, void *) {
1187 #ifdef DO_PSTATS
1188  nout << "Connecting to stats host" << std::endl;
1189  PStatClient::connect();
1190 #else
1191  nout << "Stats host not supported." << std::endl;
1192 #endif
1193 }
1194 
1195 /**
1196  * Default handler for f9 key: take screenshot.
1197  */
1198 void PandaFramework::
1199 event_f9(const Event *event, void *data) {
1200  PandaFramework *self = (PandaFramework *)data;
1201 
1202  if (event->get_num_parameters() == 1) {
1203  EventParameter param = event->get_parameter(0);
1204  WindowFramework *wf;
1205  DCAST_INTO_V(wf, param.get_ptr());
1206 
1207  if (self->clear_text()) {
1208  // Render one more frame to remove the text.
1209  self->_engine->render_frame();
1210  }
1211 
1213  string text;
1214  if (filename.empty()) {
1215  text = "Screenshot failed";
1216  } else {
1217  text = filename;
1218  }
1219 
1220  // Adds the full path to the output string
1221  string output_text = (string)ExecutionEnvironment::get_cwd() + "/" + (string)text;
1222 
1223  TextNode *text_node = new TextNode("screenshot");
1224  self->_screenshot_text = NodePath(text_node);
1225  text_node->set_align(TextNode::A_center);
1226  text_node->set_shadow_color(0.0f, 0.0f, 0.0f, 1.0f);
1227  text_node->set_shadow(0.04, 0.04);
1228  text_node->set_text(output_text);
1229  self->_screenshot_text.set_scale(0.06);
1230  self->_screenshot_text.set_pos(0.0, 0.0, -0.7);
1231  self->_screenshot_text.reparent_to(wf->get_aspect_2d());
1232  std::cout << "Screenshot saved: " + output_text + "\n";
1233 
1234  // Set a do-later to remove the text in 3 seconds.
1235  self->_task_mgr.remove(self->_task_mgr.find_tasks("clear_text"));
1236  PT(GenericAsyncTask) task = new GenericAsyncTask("clear_text", task_clear_text, self);
1237  task->set_delay(3.0);
1238  self->_task_mgr.add(task);
1239  }
1240 }
1241 
1242 /**
1243  * Default handler for comma key: rotate background color.
1244  */
1245 void PandaFramework::
1246 event_comma(const Event *event, void *) {
1247  if (event->get_num_parameters() == 1) {
1248  EventParameter param = event->get_parameter(0);
1249  WindowFramework *wf;
1250  DCAST_INTO_V(wf, param.get_ptr());
1251 
1252  switch (wf->get_background_type()) {
1253  case WindowFramework::BT_other:
1254  case WindowFramework::BT_none:
1255  break;
1256 
1257  case WindowFramework::BT_white:
1258  wf->set_background_type(WindowFramework::BT_default);
1259  break;
1260 
1261  default:
1262  wf->set_background_type((WindowFramework::BackgroundType)(wf->get_background_type() + 1));
1263  }
1264  }
1265 }
1266 
1267 /**
1268  * Default handler for ? key: show the available keys.
1269  */
1270 void PandaFramework::
1271 event_question(const Event *event, void *data) {
1272  PandaFramework *self = (PandaFramework *)data;
1273  if (event->get_num_parameters() == 1) {
1274  EventParameter param = event->get_parameter(0);
1275  WindowFramework *wf;
1276  DCAST_INTO_V(wf, param.get_ptr());
1277 
1278  self->_screenshot_text.remove_node();
1279 
1280  if (!self->_help_text.is_empty()) {
1281  self->_help_text.remove_node();
1282  // This key is a toggle; remove the help text and do nothing else.
1283 
1284  } else {
1285  // Build up a string to display.
1286  std::ostringstream help;
1287  KeyDefinitions::const_iterator ki;
1288  for (ki = self->_key_definitions.begin();
1289  ki != self->_key_definitions.end();
1290  ++ki) {
1291  const KeyDefinition &keydef = (*ki);
1292  help << keydef._event_name << "\t" << keydef._description << "\n";
1293  }
1294 
1295  string help_text = help.str();
1296 
1297  TextNode *text_node = new TextNode("help");
1298  self->_help_text = NodePath(text_node);
1299  text_node->set_align(TextNode::A_left);
1300  text_node->set_shadow_color(0.0f, 0.0f, 0.0f, 1.0f);
1301  text_node->set_shadow(0.04, 0.04);
1302  text_node->set_text(help_text);
1303 
1304  LVecBase4 frame = text_node->get_frame_actual();
1305 
1306  PN_stdfloat height = frame[3] - frame[2];
1307  PN_stdfloat scale = std::min(0.06, 1.8 / height);
1308  self->_help_text.set_scale(scale);
1309 
1310  PN_stdfloat pos_scale = scale / -2.0;
1311  self->_help_text.set_pos((frame[0] + frame[1]) * pos_scale,
1312  0.0,
1313  (frame[2] + frame[3]) * pos_scale);
1314 
1315  self->_help_text.reparent_to(wf->get_aspect_2d());
1316  }
1317  }
1318 }
1319 
1320 /**
1321  * Default handler for window events: window resized or closed, etc.
1322  */
1323 void PandaFramework::
1324 event_window_event(const Event *event, void *data) {
1325  PandaFramework *self = (PandaFramework *)data;
1326  if (event->get_num_parameters() == 1) {
1327  // The parameter of the window event is the window itself, rather than the
1328  // window framework object (which is the parameter of all of the keyboard
1329  // events).
1330  EventParameter param = event->get_parameter(0);
1331  const GraphicsOutput *win;
1332  DCAST_INTO_V(win, param.get_ptr());
1333 
1334  // Is this a window we've heard about?
1335  int window_index = self->find_window(win);
1336  if (window_index == -1) {
1337  framework_cat.debug()
1338  << "Ignoring message from unknown window.\n";
1339 
1340  } else {
1341  if (!win->is_valid()) {
1342  // The window has been closed.
1343  int window_index = self->find_window(win);
1344  while (window_index != -1) {
1345  self->close_window(window_index);
1346  window_index = self->find_window(win);
1347  }
1348 
1349  // Free up the mouse for that window.
1350  self->remove_mouse(win);
1351 
1352  // If the last window was closed, exit the application.
1353  if (self->all_windows_closed() && !self->_exit_flag) {
1354  framework_cat.info()
1355  << "Last window was closed by user.\n";
1356  self->_exit_flag = true;
1357  }
1358  } else {
1359  // Adjust aspect ratio.
1360  for (int n = 0; n < (int)self->_windows.size(); n++) {
1361  if (self->_windows[n]->get_graphics_output() == win) {
1362  self->_windows[n]->adjust_dimensions();
1363  }
1364  }
1365  }
1366  }
1367  }
1368 }
1369 
1370 /**
1371  * Called once per frame to process the data graph (which handles user input
1372  * via the mouse and keyboard, etc.)
1373  */
1374 AsyncTask::DoneStatus PandaFramework::
1375 task_data_loop(GenericAsyncTask *task, void *data) {
1376  PandaFramework *self = (PandaFramework *)data;
1377 
1378  DataGraphTraverser dg_trav;
1379  dg_trav.traverse(self->_data_root.node());
1380 
1381  return AsyncTask::DS_cont;
1382 }
1383 
1384 /**
1385  * Called once per frame to process the pending events.
1386  */
1387 AsyncTask::DoneStatus PandaFramework::
1388 task_event(GenericAsyncTask *task, void *data) {
1389  PandaFramework *self = (PandaFramework *)data;
1390 
1391  throw_event("NewFrame");
1392  self->_event_handler.process_events();
1393 
1394  return AsyncTask::DS_cont;
1395 }
1396 
1397 /**
1398  * Called once per frame to render the scene.
1399  */
1400 AsyncTask::DoneStatus PandaFramework::
1401 task_igloop(GenericAsyncTask *task, void *data) {
1402  PandaFramework *self = (PandaFramework *)data;
1403 
1404  // This exists to work around a crash that happens when the PandaFramework
1405  // is destructed because the application is exited during render_frame().
1406  // The proper fix is not to instantiate PandaFramework in the global scope
1407  // but many C++ applications (including pview) do this anyway.
1408  PT(GraphicsEngine) engine = self->_engine;
1409  if (engine != nullptr) {
1410  engine->render_frame();
1411  return AsyncTask::DS_cont;
1412  } else {
1413  return AsyncTask::DS_done;
1414  }
1415 }
1416 
1417 /**
1418  * Called once per frame to ask the recorder to record the user input data, if
1419  * enabled.
1420  */
1421 AsyncTask::DoneStatus PandaFramework::
1423  PandaFramework *self = (PandaFramework *)data;
1424 
1425  if (self->_recorder != nullptr) {
1426  self->_recorder->record_frame();
1427  }
1428 
1429  return AsyncTask::DS_cont;
1430 }
1431 
1432 /**
1433  * Called once per frame to ask the recorder to play back the user input data,
1434  * if enabled.
1435  */
1436 AsyncTask::DoneStatus PandaFramework::
1437 task_play_frame(GenericAsyncTask *task, void *data) {
1438  PandaFramework *self = (PandaFramework *)data;
1439 
1440  if (self->_recorder != nullptr) {
1441  self->_recorder->play_frame();
1442  }
1443 
1444  return AsyncTask::DS_cont;
1445 }
1446 
1447 /**
1448  * Called once to remove the screenshot text from onscreen.
1449  */
1450 AsyncTask::DoneStatus PandaFramework::
1451 task_clear_text(GenericAsyncTask *task, void *data) {
1452  PandaFramework *self = (PandaFramework *)data;
1453 
1454  self->clear_text();
1455  return AsyncTask::DS_cont;
1456 }
1457 
1458 /**
1459  * This task is created automatically if garbage_collect_states is true. It
1460  * calls the needed TransformState::garbage_collect() and
1461  * RenderState::garbage_collect() methods each frame.
1462  */
1463 AsyncTask::DoneStatus PandaFramework::
1465  TransformState::garbage_collect();
1467  return AsyncTask::DS_cont;
1468 }
WindowFramework::get_background_type
BackgroundType get_background_type() const
Returns the current background type setting.
Definition: windowFramework.I:146
PandaFramework::set_two_sided
void set_two_sided(bool enable)
Sets the two_sided state on all windows.
Definition: pandaFramework.cxx:602
NodePath::get_child
NodePath get_child(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns a NodePath representing the nth child of the referenced node.
Definition: nodePath.I:337
PandaFramework::event_i
static void event_i(const Event *, void *data)
Default handler for i key: invert one-sided faces.
Definition: pandaFramework.cxx:950
RecorderController::begin_record
bool begin_record(const Filename &filename)
Begins recording data to the indicated filename.
Definition: recorderController.cxx:56
ExecutionEnvironment::get_cwd
get_cwd
Returns the name of the current working directory.
Definition: executionEnvironment.h:61
NodePath::is_hidden
bool is_hidden(DrawMask camera_mask=PandaNode::get_overall_bit()) const
Returns true if the referenced node is hidden from the indicated camera(s) either directly,...
Definition: nodePath.I:1868
GraphicsPipeSelection::load_aux_modules
void load_aux_modules()
Loads all the modules named in the aux-display Configrc variable, making as many graphics pipes as po...
Definition: graphicsPipeSelection.cxx:301
PandaFramework::event_window_event
static void event_window_event(const Event *, void *data)
Default handler for window events: window resized or closed, etc.
Definition: pandaFramework.cxx:1324
throw_event.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowFramework::set_two_sided
void set_two_sided(bool enable)
Forces two-sided rendering (true) or restores default rendering (false).
Definition: windowFramework.cxx:954
WindowFramework::get_graphics_output
GraphicsOutput * get_graphics_output() const
Returns a pointer to the underlying GraphicsOutput object.
Definition: windowFramework.I:39
occluderNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework::event_t
static void event_t(const Event *, void *data)
Default handler for t key: toggle texture.
Definition: pandaFramework.cxx:922
PandaFramework::report_frame_rate
void report_frame_rate(std::ostream &out) const
Reports the currently measured average frame rate to the indicated ostream.
Definition: pandaFramework.cxx:548
eventQueue.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath::set_render_mode_filled_wireframe
void set_render_mode_filled_wireframe(const LColor &wireframe_color, int priority=0)
Sets up the geometry at this level and below (unless overridden) to render in filled,...
Definition: nodePath.cxx:4315
MouseAndKeyboard
Reads the mouse and/or keyboard data sent from a GraphicsWindow, and transmits it down the data graph...
Definition: mouseAndKeyboard.h:41
PandaFramework::open_framework
void open_framework()
Should be called once at the beginning of the application to initialize Panda (and the framework) for...
Definition: pandaFramework.cxx:85
PandaFramework::event_b
static void event_b(const Event *, void *data)
Default handler for b key: toggle backface (two-sided rendering).
Definition: pandaFramework.cxx:936
PandaFramework::event_w
static void event_w(const Event *, void *data)
Default handler for w key: toggle wireframe.
Definition: pandaFramework.cxx:902
PandaFramework::event_comma
static void event_comma(const Event *, void *data)
Default handler for comma key: rotate background color.
Definition: pandaFramework.cxx:1246
Filename::from_os_specific
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition: filename.cxx:328
WindowFramework::get_texture
bool get_texture() const
Returns the current state of the texture flag.
Definition: windowFramework.I:106
GraphicsOutput::is_valid
bool is_valid() const
Returns true if the output is fully created and ready for rendering, false otherwise.
Definition: graphicsOutput.I:280
init_libpnmimagetypes
void init_libpnmimagetypes()
Initializes the library.
Definition: config_pnmimagetypes.cxx:193
init_libpandaegg
void init_libpandaegg()
Initializes the library.
Definition: pandaegg.cxx:19
DataGraphTraverser::traverse
void traverse(PandaNode *node)
Starts the traversal of the data graph at the indicated root node.
Definition: dataGraphTraverser.cxx:55
DataGraphTraverser
This object supervises the traversal of the data graph and the moving of data from one DataNode to it...
Definition: dataGraphTraverser.h:32
PT
PT(WindowFramework) PandaFramework
Creates a new WindowFramework object.
Definition: pandaFramework.cxx:771
WindowFramework::get_wireframe
bool get_wireframe() const
Returns the current state of the wireframe flag.
Definition: windowFramework.I:90
PandaFramework::do_frame
virtual bool do_frame(Thread *current_thread)
Renders one frame and performs all associated processing.
Definition: pandaFramework.cxx:748
TextNode::get_frame_actual
LVecBase4 get_frame_actual() const
Returns the actual dimensions of the frame around the text.
Definition: textNode.I:329
NodePath::has_parent
has_parent
Returns true if the referenced node has a parent; i.e.
Definition: nodePath.h:242
PandaFramework::get_background_type
WindowFramework::BackgroundType get_background_type() const
Returns the current background type setting.
Definition: pandaFramework.I:136
GenericAsyncTask
Associates a generic C-style function pointer with an AsyncTask object.
Definition: genericAsyncTask.h:26
WindowFramework
This encapsulates the data that is normally associated with a single window, or with a single display...
Definition: windowFramework.h:51
PandaFramework::get_graphics_engine
GraphicsEngine * get_graphics_engine()
Returns the GraphicsEngine that is used to render all the windows in the framework.
Definition: pandaFramework.I:19
sceneGraphAnalyzer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework::task_event
static AsyncTask::DoneStatus task_event(GenericAsyncTask *task, void *data)
Called once per frame to process the pending events.
Definition: pandaFramework.cxx:1388
WindowFramework::get_perpixel
bool get_perpixel() const
Returns the current state of the perpixel flag.
Definition: windowFramework.I:138
PandaFramework::task_data_loop
static AsyncTask::DoneStatus task_data_loop(GenericAsyncTask *task, void *data)
Called once per frame to process the data graph (which handles user input via the mouse and keyboard,...
Definition: pandaFramework.cxx:1375
WindowFramework::set_one_sided_reverse
void set_one_sided_reverse(bool enable)
Toggles one-sided reverse mode.
Definition: windowFramework.cxx:978
PandaFramework::define_key
void define_key(const std::string &event_name, const std::string &description, EventHandler::EventCallbackFunction *function, void *data)
Sets up a handler for the indicated key.
Definition: pandaFramework.cxx:285
pandaFramework.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
init_libchar
void init_libchar()
Initializes the library.
Definition: config_char.cxx:51
PandaNode::find_child
int find_child(PandaNode *node, Thread *current_thread=Thread::get_current_thread()) const
Returns the index of the indicated child node, if it is a child, or -1 if it is not.
Definition: pandaNode.I:90
WindowFramework::center_trackball
void center_trackball(const NodePath &object)
Centers the trackball on the indicated object, and scales the trackball motion suitably.
Definition: windowFramework.cxx:461
clockObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework::event_arrow_right
static void event_arrow_right(const Event *, void *data)
Default handler for up arrow key: in highlight mode, move the highlight to the node's nearest sibling...
Definition: pandaFramework.cxx:1164
ClockObject::get_global_clock
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
PandaFramework::event_a
static void event_a(const Event *, void *data)
Default handler for a key: toggle the animation controls.
Definition: pandaFramework.cxx:1013
WindowFramework::next_anim_control
void next_anim_control()
Rotates the animation controls through all of the available animations.
Definition: windowFramework.cxx:743
PandaFramework::task_garbage_collect
static AsyncTask::DoneStatus task_garbage_collect(GenericAsyncTask *task, void *data)
This task is created automatically if garbage_collect_states is true.
Definition: pandaFramework.cxx:1464
SceneGraphAnalyzer::write
void write(std::ostream &out, int indent_level=0) const
Describes all the data collected.
Definition: sceneGraphAnalyzer.cxx:114
PandaFramework::task_record_frame
static AsyncTask::DoneStatus task_record_frame(GenericAsyncTask *task, void *data)
Called once per frame to ask the recorder to record the user input data, if enabled.
Definition: pandaFramework.cxx:1422
PandaFramework::hide_collision_solids
static int hide_collision_solids(NodePath node)
Hides any collision solids, or occluders, which are visible in the indicated scene graph.
Definition: pandaFramework.cxx:659
PandaFramework::enable_default_keys
void enable_default_keys()
Sets callbacks on the event handler to handle all of the normal viewer keys, like t to toggle texture...
Definition: pandaFramework.cxx:735
collisionNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath::get_parent
get_parent
Returns the NodePath to the parent of the referenced node: that is, this NodePath,...
Definition: nodePath.h:242
NodePath::get_num_children
int get_num_children(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of children of the referenced node.
Definition: nodePath.I:328
WindowProperties
A container for the various kinds of properties we might ask to have on a graphics window before we o...
Definition: windowProperties.h:29
TextNode
The primary interface to this module.
Definition: textNode.h:48
PandaFramework::get_two_sided
bool get_two_sided() const
Returns the current state of the two_sided flag.
Definition: pandaFramework.I:112
LoaderOptions
Specifies parameters that may be passed to the loader.
Definition: loaderOptions.h:23
EventParameter::get_ptr
TypedWritableReferenceCount * get_ptr() const
Retrieves a pointer to the actual value stored in the parameter.
Definition: eventParameter.I:219
RecorderController
This object manages the process of recording the user's runtime inputs to a bam file so that the sess...
Definition: recorderController.h:32
PandaFramework::event_f
static void event_f(const Event *, void *data)
Default handler for f key: report and reset frame rate.
Definition: pandaFramework.cxx:892
PandaFramework::set_texture
void set_texture(bool enable)
Sets the texture state on all windows.
Definition: pandaFramework.cxx:588
dataGraphTraverser.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsPipeSelection::print_pipe_types
void print_pipe_types() const
Writes a list of the currently known GraphicsPipe types to nout, for the user's information.
Definition: graphicsPipeSelection.cxx:121
PandaFramework::task_igloop
static AsyncTask::DoneStatus task_igloop(GenericAsyncTask *task, void *data)
Called once per frame to render the scene.
Definition: pandaFramework.cxx:1401
GraphicsEngine
This class is the main interface to controlling the render process.
Definition: graphicsEngine.h:53
PandaFramework::event_A
static void event_A(const Event *, void *data)
Default handler for shift-A key: analyze the contents of the scene graph, or the highlighted node.
Definition: pandaFramework.cxx:1077
Thread::get_current_thread
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
WindowProperties::add_properties
void add_properties(const WindowProperties &other)
Sets any properties that are explicitly specified in other on this object.
Definition: windowProperties.cxx:218
WindowFramework::set_background_type
void set_background_type(BackgroundType type)
Sets the background of the window to one of the pre-canned background types (or to BT_other,...
Definition: windowFramework.cxx:1048
renderState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework
This class serves to provide a high-level framework for basic applications that use Panda in simple w...
Definition: pandaFramework.h:38
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
EventHandler::has_hook
bool has_hook(const std::string &event_name) const
Returns true if there is any hook added on the indicated event name, false otherwise.
Definition: eventHandler.cxx:197
WindowProperties::set_title
set_title
Specifies the title that should be assigned to the window.
Definition: windowProperties.h:98
RecorderController::begin_playback
bool begin_playback(const Filename &filename)
Begins playing back data from the indicated filename.
Definition: recorderController.cxx:104
WindowFramework::set_perpixel
void set_perpixel(bool enable)
Turns per-pixel lighting on (true) or off (false).
Definition: windowFramework.cxx:1026
NodePath::show
void show()
Undoes the effect of a previous hide() on this node: makes the referenced node (and the entire subgra...
Definition: nodePath.I:1788
GraphicsOutput
This is a base class for the various different classes that represent the result of a frame of render...
Definition: graphicsOutput.h:63
PandaFramework::close_window
void close_window(int n)
Closes the nth window and removes it from the list.
Definition: pandaFramework.cxx:475
NodePath::clear_render_mode
void clear_render_mode()
Completely removes any render mode adjustment that may have been set on this node via set_render_mode...
Definition: nodePath.cxx:4372
Event
A named event, possibly with parameters.
Definition: event.h:33
depthOffsetAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework::event_L
static void event_L(const Event *, void *data)
Default handler for shift-L key: list the contents of the scene graph, or the highlighted node.
Definition: pandaFramework.cxx:1061
PandaFramework::set_wireframe
void set_wireframe(bool enable)
Sets the wireframe state on all windows.
Definition: pandaFramework.cxx:574
PandaFramework::get_lighting
bool get_lighting() const
Returns the current state of the lighting flag.
Definition: pandaFramework.I:120
transformState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework::all_windows_closed
bool all_windows_closed() const
Returns true if all of the opened windows have been closed by the user, false otherwise.
Definition: pandaFramework.cxx:519
RenderState::garbage_collect
static int garbage_collect()
Performs a garbage-collection cycle.
Definition: renderState.cxx:895
SceneGraphAnalyzer::add_node
void add_node(PandaNode *node)
Adds a new node to the set of data for analysis.
Definition: sceneGraphAnalyzer.cxx:106
PandaFramework::find_window
int find_window(const GraphicsOutput *win) const
Returns the index of the first WindowFramework object found that references the indicated GraphicsOut...
Definition: pandaFramework.cxx:443
PandaFramework::event_question
static void event_question(const Event *event, void *data)
Default handler for ? key: show the available keys.
Definition: pandaFramework.cxx:1271
textNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework::set_highlight
void set_highlight(const NodePath &node)
Sets the indicated node (normally a node within the get_models() tree) up as the highlighted node.
Definition: pandaFramework.cxx:708
PandaFramework::event_arrow_up
static void event_arrow_up(const Event *, void *data)
Default handler for up arrow key: in highlight mode, move the highlight to the node's parent.
Definition: pandaFramework.cxx:1110
GraphicsPipeSelection::get_num_pipe_types
get_num_pipe_types
Returns the number of different types of GraphicsPipes that are available to create through this inte...
Definition: graphicsPipeSelection.h:41
TextEncoder::set_text
set_text
Changes the text that is stored in the encoder.
Definition: textEncoder.h:124
PandaFramework::open_window
WindowFramework * open_window()
Opens a window on the default graphics pipe.
Definition: pandaFramework.cxx:335
PandaNode::get_child
get_child
Returns the nth child node of this node.
Definition: pandaNode.h:124
PandaFramework::set_perpixel
void set_perpixel(bool enable)
Sets the perpixel state on all windows.
Definition: pandaFramework.cxx:630
PandaFramework::event_arrow_left
static void event_arrow_left(const Event *, void *data)
Default handler for up arrow key: in highlight mode, move the highlight to the node's nearest sibling...
Definition: pandaFramework.cxx:1142
SceneGraphAnalyzer
A handy class that can scrub over a scene graph and collect interesting statistics on it.
Definition: sceneGraphAnalyzer.h:37
GraphicsPipeSelection
This maintains a list of GraphicsPipes by type that are available for creation.
Definition: graphicsPipeSelection.h:33
init_libpandagl
void init_libpandagl()
Initializes the library.
Definition: pandagl.cxx:40
EventHandler::remove_all_hooks
void remove_all_hooks()
Removes all hooks assigned to all events.
Definition: eventHandler.cxx:344
GraphicsPipe
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
PandaFramework::close_framework
void close_framework()
Should be called at the end of an application to close Panda.
Definition: pandaFramework.cxx:178
PandaFramework::event_S
static void event_S(const Event *, void *data)
Default handler for shift-S key: activate stats.
Definition: pandaFramework.cxx:1186
WindowProperties::get_default
get_default
Returns the "default" WindowProperties.
Definition: windowProperties.h:58
WindowFramework::get_wireframe_filled
bool get_wireframe_filled() const
Returns the current state of the wireframe_filled flag.
Definition: windowFramework.I:98
PandaFramework::close_all_windows
void close_all_windows()
Closes all currently open windows and empties the list of windows.
Definition: pandaFramework.cxx:492
PandaFramework::clear_highlight
void clear_highlight()
Unhighlights the currently highlighted node, if any.
Definition: pandaFramework.cxx:722
PandaFramework::get_texture
bool get_texture() const
Returns the current state of the texture flag.
Definition: pandaFramework.I:104
AsyncTaskManager::poll
void poll()
Runs through all the tasks in the task list, once, if the task manager is running in single-threaded ...
Definition: asyncTaskManager.cxx:474
PandaFramework::event_f9
static void event_f9(const Event *, void *data)
Default handler for f9 key: take screenshot.
Definition: pandaFramework.cxx:1199
WindowFramework::set_lighting
void set_lighting(bool enable)
Turns lighting on (true) or off (false).
Definition: windowFramework.cxx:1002
NodePath::hide_bounds
void hide_bounds()
Stops the rendering of the bounding volume begun with show_bounds().
Definition: nodePath.cxx:5376
AsyncTaskManager
A class to manage a loose queue of isolated tasks, which can be performed either synchronously (in th...
Definition: asyncTaskManager.h:48
TextNode::set_shadow
set_shadow
Specifies that the text should be drawn with a shadow, by creating a second copy of the text and offs...
Definition: textNode.h:256
Thread::prepare_for_exit
static void prepare_for_exit()
Should be called by the main thread just before exiting the program, this blocks until any remaining ...
Definition: thread.I:283
NodePath::show_bounds
void show_bounds()
Causes the bounding volume of the bottom node and all of its descendants (that is,...
Definition: nodePath.cxx:5355
NodePath::get_hidden_ancestor
NodePath get_hidden_ancestor(DrawMask camera_mask=PandaNode::get_overall_bit(), Thread *current_thread=Thread::get_current_thread()) const
Returns the NodePath at or above the referenced node that is hidden to the indicated camera(s),...
Definition: nodePath.cxx:5108
AsyncTaskManager::add
void add(AsyncTask *task)
Adds the indicated task to the active queue.
Definition: asyncTaskManager.cxx:181
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
config_framework.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ClockObject::get_frame_count
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
Definition: clockObject.h:94
EventParameter
An optional parameter associated with an event.
Definition: eventParameter.h:35
WindowFramework::get_lighting
bool get_lighting() const
Returns the current state of the lighting flag.
Definition: windowFramework.I:130
executionEnvironment.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
RecorderController::add_recorder
void add_recorder(const std::string &name, RecorderBase *recorder)
Adds the named recorder to the set of recorders that are in use.
Definition: recorderController.I:118
graphicsPipeSelection.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework::get_mouse
NodePath get_mouse(GraphicsOutput *window)
Returns a NodePath to the MouseAndKeyboard associated with the indicated GraphicsWindow object.
Definition: pandaFramework.cxx:238
PandaFramework::event_arrow_down
static void event_arrow_down(const Event *, void *data)
Default handler for up arrow key: in highlight mode, move the highlight to the node's first child.
Definition: pandaFramework.cxx:1126
PandaFramework::task_clear_text
static AsyncTask::DoneStatus task_clear_text(GenericAsyncTask *task, void *data)
Called once to remove the screenshot text from onscreen.
Definition: pandaFramework.cxx:1451
nodePathCollection.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework::get_recorder
RecorderController * get_recorder() const
Returns the RecorderController that has been associated with the PandaFramework, if any,...
Definition: pandaFramework.I:166
ClockObject::get_frame_time
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
Definition: clockObject.h:91
pStatClient.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pandaegg.h
EventHandler::add_hook
bool add_hook(const std::string &event_name, EventFunction *function)
Adds the indicated function to the list of those that will be called when the named event is thrown.
Definition: eventHandler.cxx:166
GraphicsPipeSelection::get_global_ptr
static GraphicsPipeSelection * get_global_ptr()
Returns a pointer to the one global GraphicsPipeSelection object.
Definition: graphicsPipeSelection.I:28
PandaFramework::remove_mouse
void remove_mouse(const GraphicsOutput *window)
Removes the mouse that may have been created by an earlier call to get_mouse().
Definition: pandaFramework.cxx:271
MouseRecorder
This object records any data generated by a particular MouseAndKeyboard node on the datagraph for a s...
Definition: mouseRecorder.h:34
EventHandler
A class to monitor events from the C++ side of things.
Definition: eventHandler.h:37
PandaFramework::reset_frame_rate
void reset_frame_rate()
Resets the frame rate computation.
Definition: pandaFramework.cxx:565
NodePath::ls
void ls() const
Lists the hierarchy at and below the referenced node.
Definition: nodePath.I:399
WindowFramework::get_aspect_2d
NodePath get_aspect_2d()
Returns the node under the 2-d scene graph that is scaled to suit the window's aspect ratio.
Definition: windowFramework.cxx:299
PandaFramework::get_data_root
const NodePath & get_data_root() const
Returns the root of the data graph.
Definition: pandaFramework.I:35
PandaFramework::get_models
NodePath & get_models()
Returns the root of the scene graph normally reserved for parenting models and such.
Definition: pandaFramework.cxx:537
NodePath::attach_new_node
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
Definition: nodePath.cxx:563
PandaFramework::get_default_window_props
virtual void get_default_window_props(WindowProperties &props)
Fills in the indicated window properties structure according to the normal window properties for this...
Definition: pandaFramework.cxx:318
PandaFramework::get_default_pipe
GraphicsPipe * get_default_pipe()
Returns the default pipe.
Definition: pandaFramework.cxx:220
NodePath::hide
void hide()
Makes the referenced node (and the entire subgraph below this node) invisible to all cameras.
Definition: nodePath.I:1843
GraphicsStateGuardian
Encapsulates all the communication with a particular instance of a given rendering backend.
Definition: graphicsStateGuardian.h:65
PandaFramework::set_background_type
void set_background_type(WindowFramework::BackgroundType type)
Sets the background type of all windows.
Definition: pandaFramework.cxx:644
WindowFramework::get_two_sided
bool get_two_sided() const
Returns the current state of the two_sided flag.
Definition: windowFramework.I:114
PandaFramework::main_loop
void main_loop()
Called to yield control to the panda framework.
Definition: pandaFramework.cxx:761
PandaNode::get_num_children
get_num_children
Returns the number of child nodes this node has.
Definition: pandaNode.h:124
WindowFramework::get_one_sided_reverse
bool get_one_sided_reverse() const
Returns the current state of the one_sided_reverse flag.
Definition: windowFramework.I:122
NodePath::node
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
init_libpandadx9
void init_libpandadx9()
Initializes the library.
Definition: pandadx9.cxx:19
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
PandaFramework::get_perpixel
bool get_perpixel() const
Returns the current state of the perpixel flag.
Definition: pandaFramework.I:128
mouseRecorder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework::event_c
static void event_c(const Event *, void *data)
Default handler for c key: center the trackball over the scene, or over the highlighted part of the s...
Definition: pandaFramework.cxx:993
GraphicsWindow
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
Definition: graphicsWindow.h:40
PandaFramework::get_wireframe
bool get_wireframe() const
Returns the current state of the wireframe flag.
Definition: pandaFramework.I:96
PandaFramework::event_l
static void event_l(const Event *, void *data)
Default handler for l key: toggle lighting.
Definition: pandaFramework.cxx:964
NodePath::remove_node
void remove_node(Thread *current_thread=Thread::get_current_thread())
Disconnects the referenced node from the scene graph.
Definition: nodePath.cxx:591
PandaFramework::event_B
static void event_B(const Event *, void *data)
Default handler for shift-B key: describe the bounding volume of the currently selected object,...
Definition: pandaFramework.cxx:1045
PandaFramework::event_esc
static void event_esc(const Event *, void *data)
Default handler for ESC or q key: close the current window (and exit the application if that was the ...
Definition: pandaFramework.cxx:857
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PandaFramework::task_play_frame
static AsyncTask::DoneStatus task_play_frame(GenericAsyncTask *task, void *data)
Called once per frame to ask the recorder to play back the user input data, if enabled.
Definition: pandaFramework.cxx:1437
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
PandaFramework::event_p
static void event_p(const Event *, void *data)
Default handler for p key: toggle per-pixel lighting.
Definition: pandaFramework.cxx:978
PandaFramework::event_h
static void event_h(const Event *, void *data)
Default handler for h key: toggle highlight mode.
Definition: pandaFramework.cxx:1095
GraphicsPipeSelection::get_pipe_type
get_pipe_type
Returns the nth type of GraphicsPipe available through this interface.
Definition: graphicsPipeSelection.h:41
PandaFramework::set_lighting
void set_lighting(bool enable)
Sets the lighting state on all windows.
Definition: pandaFramework.cxx:616
GraphicsOutput::save_screenshot_default
Filename save_screenshot_default(const std::string &prefix="screenshot")
Saves a screenshot of the region to a default filename, and returns the filename, or empty string if ...
Definition: graphicsOutput.I:615
mouseAndKeyboard.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath::is_empty
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
WindowFramework::set_wireframe
void set_wireframe(bool enable, bool filled=false)
Forces wireframe state (true) or restores default rendering (false).
Definition: windowFramework.cxx:892
PandaFramework::event_C
static void event_C(const Event *, void *data)
Default handler for shift-C key: toggle the showing of collision solids.
Definition: pandaFramework.cxx:1027
WindowFramework::set_texture
void set_texture(bool enable)
Forces textures off (false) or restores default rendering (true).
Definition: windowFramework.cxx:934
PandaFramework::show_collision_solids
static int show_collision_solids(NodePath node)
Shows any collision solids, or occluders, which are directly hidden in the indicated scene graph.
Definition: pandaFramework.cxx:683