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