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 _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 */
238get_mouse(GraphicsOutput *window) {
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 */
271remove_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 */
285define_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 */
319 // This function is largely vestigial and will be removed soon. We have
320 // moved the default window properties into WindowProperties::get_default().
321
323 if (!_window_title.empty()) {
324 props.set_title(_window_title);
325 }
326}
327
328/**
329 * Opens a window on the default graphics pipe. If the default graphics pipe
330 * can't open a window for some reason, automatically fails over to the next
331 * available graphics pipe, and updates _default_pipe accordingly. Returns
332 * NULL only if all graphics pipes fail.
333 */
335open_window() {
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 */
398open_window(const WindowProperties &props, int flags,
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 */
443find_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 */
459find_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 */
475close_window(int n) {
476 nassertv(n >= 0 && n < (int)_windows.size());
477 WindowFramework *wf = _windows[n];
478
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 */
493 Windows::iterator wi;
494 for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
495 WindowFramework *wf = (*wi);
496
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 */
519all_windows_closed() const {
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 */
537get_models() {
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 */
548report_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 */
569
570/**
571 * Sets the wireframe state on all windows.
572 */
574set_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 */
588set_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 */
602set_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 */
616set_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 */
630set_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 */
644set_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 */
708set_highlight(const NodePath &node) {
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 */
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 */
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 */
748do_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 */
761main_loop() {
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 */
771PT(WindowFramework) PandaFramework::
772make_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 */
780void PandaFramework::
781make_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 */
803void PandaFramework::
804do_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 */
836bool PandaFramework::
837clear_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 */
857event_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 */
892event_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 */
902event_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 */
922event_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 */
936event_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 */
950event_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 */
964event_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 */
978event_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 */
993event_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 */
1013event_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 */
1027event_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 */
1045event_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 */
1061event_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 */
1077event_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
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 */
1095event_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 */
1110event_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 */
1126event_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 */
1142event_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 */
1164event_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 */
1186event_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 */
1199event_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 */
1246event_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 */
1271event_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 */
1324event_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 */
1374AsyncTask::DoneStatus PandaFramework::
1375task_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 */
1387AsyncTask::DoneStatus PandaFramework::
1388task_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 */
1400AsyncTask::DoneStatus PandaFramework::
1401task_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 */
1421AsyncTask::DoneStatus PandaFramework::
1422task_record_frame(GenericAsyncTask *task, void *data) {
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 */
1436AsyncTask::DoneStatus PandaFramework::
1437task_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 */
1450AsyncTask::DoneStatus PandaFramework::
1451task_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 */
1463AsyncTask::DoneStatus PandaFramework::
1464task_garbage_collect(GenericAsyncTask *task, void *data) {
1465 TransformState::garbage_collect();
1467 return AsyncTask::DS_cont;
1468}
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.
void poll()
Runs through all the tasks in the task list, once, if the task manager is running in single-threaded ...
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.
void remove_all_hooks()
Removes all hooks assigned to all events.
bool has_hook(const std::string &event_name) const
Returns true if there is any hook added on the indicated event name, false otherwise.
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.
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_bounds()
Causes the bounding volume of the bottom node and all of its descendants (that is,...
void show()
Undoes the effect of a previous hide() on this node: makes the referenced node (and the entire subgra...
Definition nodePath.I:1796
void hide()
Makes the referenced node (and the entire subgraph below this node) invisible to all cameras.
Definition nodePath.I:1853
void hide_bounds()
Stops the rendering of the bounding volume begun with show_bounds().
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 clear_render_mode()
Completely removes any render mode adjustment that may have been set on this node via set_render_mode...
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 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,...
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
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),...
This class serves to provide a high-level framework for basic applications that use Panda in simple w...
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 ? key: show the available keys.
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
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.