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 
322  props.add_properties(WindowProperties::get_default());
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 }
void write(std::ostream &out, int indent_level=0) const
Describes all the data collected.
void report_frame_rate(std::ostream &out) const
Reports the currently measured average frame rate to the indicated ostream.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool get_wireframe_filled() const
Returns the current state of the wireframe_filled flag.
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
void remove_all_hooks()
Removes all hooks assigned to all events.
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
static AsyncTask::DoneStatus task_clear_text(GenericAsyncTask *task, void *data)
Called once to remove the screenshot text from onscreen.
static void event_w(const Event *, void *data)
Default handler for w key: toggle wireframe.
static AsyncTask::DoneStatus task_garbage_collect(GenericAsyncTask *task, void *data)
This task is created automatically if garbage_collect_states is true.
bool begin_playback(const Filename &filename)
Begins playing back data from the indicated filename.
void set_two_sided(bool enable)
Sets the two_sided state on all windows.
static void event_i(const Event *, void *data)
Default handler for i key: invert one-sided faces.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void enable_default_keys()
Sets callbacks on the event handler to handle all of the normal viewer keys, like t to toggle texture...
void set_perpixel(bool enable)
Turns per-pixel lighting on (true) or off (false).
static void event_f9(const Event *, void *data)
Default handler for f9 key: take screenshot.
WindowFramework::BackgroundType get_background_type() const
Returns the current background type setting.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void init_libpandadx9()
Initializes the library.
Definition: pandadx9.cxx:19
A class to monitor events from the C++ side of things.
Definition: eventHandler.h:37
void reset_frame_rate()
Resets the frame rate computation.
An optional parameter associated with an event.
bool get_wireframe() const
Returns the current state of the wireframe flag.
NodePath & get_models()
Returns the root of the scene graph normally reserved for parenting models and such.
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
void close_framework()
Should be called at the end of an application to close Panda.
static AsyncTask::DoneStatus task_event(GenericAsyncTask *task, void *data)
Called once per frame to process the pending events.
A class to manage a loose queue of isolated tasks, which can be performed either synchronously (in th...
int find_window(const GraphicsOutput *win) const
Returns the index of the first WindowFramework object found that references the indicated GraphicsOut...
GraphicsPipe * get_default_pipe()
Returns the default pipe.
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.
static void event_C(const Event *, void *data)
Default handler for shift-C key: toggle the showing of collision solids.
Specifies parameters that may be passed to the loader.
Definition: loaderOptions.h:23
static void event_comma(const Event *, void *data)
Default handler for comma key: rotate background color.
NodePath get_aspect_2d()
Returns the node under the 2-d scene graph that is scaled to suit the window's aspect ratio.
GraphicsOutput * get_graphics_output() const
Returns a pointer to the underlying GraphicsOutput object.
static void event_a(const Event *, void *data)
Default handler for a key: toggle the animation controls.
void init_libpnmimagetypes()
Initializes the library.
void add_node(PandaNode *node)
Adds a new node to the set of data for analysis.
bool get_perpixel() const
Returns the current state of the perpixel flag.
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:5093
This encapsulates the data that is normally associated with a single window, or with a single display...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
virtual void get_default_window_props(WindowProperties &props)
Fills in the indicated window properties structure according to the normal window properties for this...
void print_pipe_types() const
Writes a list of the currently known GraphicsPipe types to nout, for the user's information.
void hide_bounds()
Stops the rendering of the bounding volume begun with show_bounds().
Definition: nodePath.cxx:5361
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void show_bounds()
Causes the bounding volume of the bottom node and all of its descendants (that is,...
Definition: nodePath.cxx:5340
void set_lighting(bool enable)
Turns lighting on (true) or off (false).
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...
get_parent
Returns the NodePath to the parent of the referenced node: that is, this NodePath,...
Definition: nodePath.h:244
Reads the mouse and/or keyboard data sent from a GraphicsWindow, and transmits it down the data graph...
void open_framework()
Should be called once at the beginning of the application to initialize Panda (and the framework) for...
void init_libpandaegg()
Initializes the library.
Definition: pandaegg.cxx:19
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
bool get_one_sided_reverse() const
Returns the current state of the one_sided_reverse flag.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void show()
Undoes the effect of a previous hide() on this node: makes the referenced node (and the entire subgra...
Definition: nodePath.I:1788
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,...
bool get_texture() const
Returns the current state of the texture flag.
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
void set_wireframe(bool enable, bool filled=false)
Forces wireframe state (true) or restores default rendering (false).
void set_one_sided_reverse(bool enable)
Toggles one-sided reverse mode.
bool is_valid() const
Returns true if the output is fully created and ready for rendering, false otherwise.
set_text
Changes the text that is stored in the encoder.
Definition: textEncoder.h:124
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 ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void event_f(const Event *, void *data)
Default handler for f key: report and reset frame rate.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const NodePath & get_data_root() const
Returns the root of the data graph.
bool get_two_sided() const
Returns the current state of the two_sided flag.
get_num_children
Returns the number of child nodes this node has.
Definition: pandaNode.h:124
A container for the various kinds of properties we might ask to have on a graphics window before we o...
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.
NodePath get_mouse(GraphicsOutput *window)
Returns a NodePath to the MouseAndKeyboard associated with the indicated GraphicsWindow object.
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.
LVecBase4 get_frame_actual() const
Returns the actual dimensions of the frame around the text.
Definition: textNode.I:329
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
A handy class that can scrub over a scene graph and collect interesting statistics on it.
bool get_lighting() const
Returns the current state of the lighting flag.
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
static void event_B(const Event *, void *data)
Default handler for shift-B key: describe the bounding volume of the currently selected object,...
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
Definition: clockObject.h:94
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
bool has_hook(const std::string &event_name) const
Returns true if there is any hook added on the indicated event name, false otherwise.
void set_two_sided(bool enable)
Forces two-sided rendering (true) or restores default rendering (false).
void add(AsyncTask *task)
Adds the indicated task to the active queue.
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
static int garbage_collect()
Performs a garbage-collection cycle.
This maintains a list of GraphicsPipes by type that are available for creation.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void center_trackball(const NodePath &object)
Centers the trackball on the indicated object, and scales the trackball motion suitably.
static AsyncTask::DoneStatus task_igloop(GenericAsyncTask *task, void *data)
Called once per frame to render the scene.
void main_loop()
Called to yield control to the panda framework.
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:4357
void next_anim_control()
Rotates the animation controls through all of the available animations.
void clear_highlight()
Unhighlights the currently highlighted node, if any.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
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
void set_highlight(const NodePath &node)
Sets the indicated node (normally a node within the get_models() tree) up as the highlighted node.
void set_texture(bool enable)
Sets the texture state on all windows.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BackgroundType get_background_type() const
Returns the current background type setting.
Associates a generic C-style function pointer with an AsyncTask object.
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.
WindowFramework * open_window()
Opens a window on the default graphics pipe.
static GraphicsPipeSelection * get_global_ptr()
Returns a pointer to the one global GraphicsPipeSelection object.
void set_background_type(WindowFramework::BackgroundType type)
Sets the background type of all windows.
static int show_collision_solids(NodePath node)
Shows any collision solids, or occluders, which are directly hidden in the indicated scene graph.
void init_libchar()
Initializes the library.
Definition: config_char.cxx:51
void close_window(int n)
Closes the nth window and removes it from the list.
void set_perpixel(bool enable)
Sets the perpixel state on all windows.
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...
TypedWritableReferenceCount * get_ptr() const
Retrieves a pointer to the actual value stored in the parameter.
This is a base class for the various different classes that represent the result of a frame of render...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void event_p(const Event *, void *data)
Default handler for p key: toggle per-pixel lighting.
static void event_b(const Event *, void *data)
Default handler for b key: toggle backface (two-sided rendering).
static void event_S(const Event *, void *data)
Default handler for shift-S key: activate stats.
get_num_pipe_types
Returns the number of different types of GraphicsPipes that are available to create through this inte...
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.
bool get_lighting() const
Returns the current state of the lighting flag.
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 ...
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:4300
static void event_window_event(const Event *, void *data)
Default handler for window events: window resized or closed, etc.
void set_background_type(BackgroundType type)
Sets the background of the window to one of the pre-canned background types (or to BT_other,...
static void event_t(const Event *, void *data)
Default handler for t key: toggle texture.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void event_l(const Event *, void *data)
Default handler for l key: toggle lighting.
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
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
void set_texture(bool enable)
Forces textures off (false) or restores default rendering (true).
void load_aux_modules()
Loads all the modules named in the aux-display Configrc variable, making as many graphics pipes as po...
void add_properties(const WindowProperties &other)
Sets any properties that are explicitly specified in other on this object.
A thread; that is, a lightweight process.
Definition: thread.h:46
A named event, possibly with parameters.
Definition: event.h:33
void remove_node(Thread *current_thread=Thread::get_current_thread())
Disconnects the referenced node from the scene graph.
Definition: nodePath.cxx:591
void set_lighting(bool enable)
Sets the lighting state on all windows.
bool begin_record(const Filename &filename)
Begins recording data to the indicated filename.
The primary interface to this module.
Definition: textNode.h:48
Encapsulates all the communication with a particular instance of a given rendering backend.
PT(WindowFramework) PandaFramework
Creates a new WindowFramework object.
static void event_h(const Event *, void *data)
Default handler for h key: toggle highlight mode.
RecorderController * get_recorder() const
Returns the RecorderController that has been associated with the PandaFramework, if any,...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
This object manages the process of recording the user's runtime inputs to a bam file so that the sess...
static void event_question(const Event *event, void *data)
Default handler for ? key: show the available keys.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This object records any data generated by a particular MouseAndKeyboard node on the datagraph for a s...
Definition: mouseRecorder.h:34
void close_all_windows()
Closes all currently open windows and empties the list of windows.
void remove_mouse(const GraphicsOutput *window)
Removes the mouse that may have been created by an earlier call to get_mouse().
This class serves to provide a high-level framework for basic applications that use Panda in simple w...
This class is the main interface to controlling the render process.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_child
Returns the nth child node of this node.
Definition: pandaNode.h:124
get_pipe_type
Returns the nth type of GraphicsPipe available through this interface.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
has_parent
Returns true if the referenced node has a parent; i.e.
Definition: nodePath.h:244
GraphicsEngine * get_graphics_engine()
Returns the GraphicsEngine that is used to render all the windows in the framework.
bool get_two_sided() const
Returns the current state of the two_sided flag.
bool get_perpixel() const
Returns the current state of the perpixel flag.
void hide()
Makes the referenced node (and the entire subgraph below this node) invisible to all cameras.
Definition: nodePath.I:1843
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void ls() const
Lists the hierarchy at and below the referenced node.
Definition: nodePath.I:399
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_wireframe(bool enable)
Sets the wireframe state on all windows.
bool all_windows_closed() const
Returns true if all of the opened windows have been closed by the user, false otherwise.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
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
set_title
Specifies the title that should be assigned to the window.
void add_recorder(const std::string &name, RecorderBase *recorder)
Adds the named recorder to the set of recorders that are in use.
void init_libpandagl()
Initializes the library.
Definition: pandagl.cxx:40
static int hide_collision_solids(NodePath node)
Hides any collision solids, or occluders, which are visible in the indicated scene graph.
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
virtual bool do_frame(Thread *current_thread)
Renders one frame and performs all associated processing.
void traverse(PandaNode *node)
Starts the traversal of the data graph at the indicated root node.
bool get_wireframe() const
Returns the current state of the wireframe flag.
This object supervises the traversal of the data graph and the moving of data from one DataNode to it...
void poll()
Runs through all the tasks in the task list, once, if the task manager is running in single-threaded ...
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...
bool get_texture() const
Returns the current state of the texture flag.