Panda3D
windowFramework.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 windowFramework.cxx
10  * @author drose
11  * @date 2002-04-02
12  */
13 
14 #include "windowFramework.h"
15 #include "pandaFramework.h"
16 #include "displayRegion.h"
17 #include "buttonThrower.h"
18 #include "transform2sg.h"
19 #include "dSearchPath.h"
20 #include "filename.h"
21 #include "loader.h"
22 #include "keyboardButton.h"
23 #include "geom.h"
24 #include "geomTriangles.h"
25 #include "geomTristrips.h"
26 #include "geomVertexData.h"
27 #include "geomVertexFormat.h"
28 #include "geomVertexWriter.h"
29 #include "texturePool.h"
30 #include "textureAttrib.h"
31 #include "colorAttrib.h"
32 #include "perspectiveLens.h"
33 #include "orthographicLens.h"
34 #include "auto_bind.h"
35 #include "ambientLight.h"
36 #include "directionalLight.h"
37 #include "lightAttrib.h"
38 #include "boundingSphere.h"
39 #include "deg_2_rad.h"
40 #include "config_framework.h"
41 #include "cullFaceAttrib.h"
42 #include "rescaleNormalAttrib.h"
43 #include "shadeModelAttrib.h"
44 #include "pgTop.h"
45 #include "geomNode.h"
46 #include "texture.h"
47 #include "texturePool.h"
48 #include "loaderFileTypeRegistry.h"
49 #include "pnmImage.h"
50 #include "virtualFileSystem.h"
51 #include "string_utils.h"
52 #include "bamFile.h"
53 #include "staticTextFont.h"
54 #include "mouseButton.h"
55 
56 // This is generated data for the standard texture we apply to the blue
57 // triangle.
58 #include "rock_floor.rgb_src.c"
59 
60 // This is generated data for shuttle_controls.bam, a bamified version of
61 // shuttle_controls.egg (found in the models tree). It's compiled in
62 // shuttle_controls.bam_src.c.
63 #include "shuttle_controls.bam_src.c"
64 
65 using std::istringstream;
66 using std::ostringstream;
67 using std::string;
68 
69 // This number is chosen arbitrarily to override any settings in model files.
70 static const int override_priority = 100;
71 
72 PT(TextFont) WindowFramework::_shuttle_controls_font = nullptr;
73 TypeHandle WindowFramework::_type_handle;
74 
75 /**
76  *
77  */
78 WindowFramework::
79 WindowFramework(PandaFramework *panda_framework) :
80  _panda_framework(panda_framework)
81 {
82  _got_keyboard = false;
83  _got_trackball = false;
84  _got_lights = false;
85  _anim_controls_enabled = false;
86  _anim_index = 0;
87  _wireframe_enabled = false;
88  _wireframe_filled = false;
89  _texture_enabled = true;
90  _two_sided_enabled = false;
91  _one_sided_reverse_enabled = false;
92  _lighting_enabled = false;
93  _perpixel_enabled = false;
94  _background_type = BT_default;
95 }
96 
97 /**
98  *
99  */
100 WindowFramework::
101 WindowFramework(const WindowFramework &copy, DisplayRegion *display_region) :
102  _panda_framework(copy._panda_framework),
103  _window(copy._window),
104  _display_region_3d(display_region)
105 {
106  _got_keyboard = false;
107  _got_trackball = false;
108  _got_lights = false;
109  _anim_controls_enabled = false;
110  _anim_index = 0;
111  _wireframe_enabled = false;
112  _texture_enabled = true;
113  _two_sided_enabled = false;
114  _one_sided_reverse_enabled = false;
115  _lighting_enabled = false;
116  _perpixel_enabled = false;
117  _background_type = BT_default;
118 
119  set_background_type(copy._background_type);
120  // Set up a 3-d camera for the window by default.
121  NodePath camera_np = make_camera();
122  _display_region_3d->set_camera(camera_np);
123 }
124 
125 /**
126  *
127  */
128 WindowFramework::
129 ~WindowFramework() {
130  close_window();
131 }
132 
133 /**
134  * Opens the actual window or buffer. This is normally called only from
135  * PandaFramework::open_window().
136  */
137 GraphicsOutput *WindowFramework::
138 open_window(const WindowProperties &props, int flags, GraphicsEngine *engine,
140  const FrameBufferProperties &fbprops) {
141  nassertr(_window == nullptr, _window);
142 
143  static int next_window_index = 1;
144  ostringstream stream;
145  stream << "window" << next_window_index;
146  next_window_index++;
147  string name = stream.str();
148 
149  _window = nullptr;
150  GraphicsOutput *winout =
151  engine->make_output(pipe, name, 0, fbprops,
152  props, flags, gsg, nullptr);
153  if (winout != nullptr) {
154  _window = winout;
155  // _window->request_properties(props);
156 
157  // Create a display region that covers the entire window.
158  _display_region_3d = _window->make_display_region();
159 
160  // Make sure the DisplayRegion does the clearing, not the window, so we
161  // can have multiple DisplayRegions of different colors.
162  _window->set_clear_color_active(false);
163  _window->set_clear_depth_active(false);
164  _window->set_clear_stencil_active(false);
165 
166  // Set up a 3-d camera for the window by default.
167  NodePath camera_np = make_camera();
168  _display_region_3d->set_camera(camera_np);
169 
170  set_background_type(_background_type);
171 
172  if (show_frame_rate_meter) {
173  _frame_rate_meter = new FrameRateMeter("frame_rate_meter");
174  _frame_rate_meter->setup_window(_window);
175  }
176  if (show_scene_graph_analyzer_meter) {
177  _scene_graph_analyzer_meter = new SceneGraphAnalyzerMeter("scene_graph_analyzer_meter", get_render().node());
178  _scene_graph_analyzer_meter->setup_window(_window);
179  }
180  }
181 
182  return _window;
183 }
184 
185 /**
186  * Closes the window or buffer. This is normally called from
187  * PandaFramework::close_window().
188  */
189 void WindowFramework::
190 close_window() {
191  _window.clear();
192  _camera_group.remove_node();
193  _render.remove_node();
194  _render_2d.remove_node();
195  _mouse.remove_node();
196 
197  _alight.clear();
198  _dlight.clear();
199  _got_keyboard = false;
200  _got_trackball = false;
201  _got_lights = false;
202 
203  _wireframe_enabled = false;
204  _texture_enabled = true;
205  _two_sided_enabled = false;
206  _one_sided_reverse_enabled = false;
207  _lighting_enabled = false;
208  _perpixel_enabled = false;
209 
210  if (_frame_rate_meter != nullptr) {
211  _frame_rate_meter->clear_window();
212  _frame_rate_meter = nullptr;
213  }
214  if (_scene_graph_analyzer_meter != nullptr) {
215  _scene_graph_analyzer_meter->clear_window();
216  _scene_graph_analyzer_meter = nullptr;
217  }
218 }
219 
220 /**
221  * Returns the node above the collection of 3-d cameras in the scene graph.
222  * This node may be moved around to represent the viewpoint.
223  */
226  if (_camera_group.is_empty()) {
227  _camera_group = get_render().attach_new_node("camera_group");
228  }
229  return _camera_group;
230 }
231 
232 /**
233  * Returns the root of the 3-d scene graph.
234  */
236 get_render() {
237  if (_render.is_empty()) {
238  _render = NodePath("render");
239 
240  _render.node()->set_attrib(RescaleNormalAttrib::make_default());
241  _render.node()->set_attrib(ShadeModelAttrib::make(ShadeModelAttrib::M_smooth));
242 
243  // This is maybe here temporarily, and maybe not.
244  _render.set_two_sided(0);
245  }
246  return _render;
247 }
248 
249 /**
250  * Returns the root of the 2-d scene graph.
251  */
253 get_render_2d() {
254  if (_render_2d.is_empty()) {
255  _render_2d = NodePath("render_2d");
256 
257  // Some standard properties for the 2-d display.
258 
259  _render_2d.set_depth_write(0);
260  _render_2d.set_depth_test(0);
261  _render_2d.set_material_off(1);
262  _render_2d.set_two_sided(1);
263 
264  // Now set up a 2-d camera to view render_2d.
265 
266  // Create a display region that matches the size of the 3-d display
267  // region.
268  PN_stdfloat l, r, b, t;
269  _display_region_3d->get_dimensions(l, r, b, t);
270  _display_region_2d = _window->make_mono_display_region(l, r, b, t);
271  _display_region_2d->set_sort(10);
272 
273  // Finally, we need a camera to associate with the display region.
274  PT(Camera) camera = new Camera("camera2d");
275  NodePath camera_np = _render_2d.attach_new_node(camera);
276 
277  PT(Lens) lens = new OrthographicLens;
278 
279  static const PN_stdfloat left = -1.0f;
280  static const PN_stdfloat right = 1.0f;
281  static const PN_stdfloat bottom = -1.0f;
282  static const PN_stdfloat top = 1.0f;
283  lens->set_film_size(right - left, top - bottom);
284  lens->set_film_offset((right + left) * 0.5, (top + bottom) * 0.5);
285  lens->set_near_far(-1000, 1000);
286 
287  camera->set_lens(lens);
288  _display_region_2d->set_camera(camera_np);
289  }
290 
291  return _render_2d;
292 }
293 
294 /**
295  * Returns the node under the 2-d scene graph that is scaled to suit the
296  * window's aspect ratio.
297  */
299 get_aspect_2d() {
300  if (_aspect_2d.is_empty()) {
301  PGTop *top = new PGTop("aspect_2d");
302  _aspect_2d = get_render_2d().attach_new_node(top);
303 
304  // Tell the PGTop about our MouseWatcher object, so the PGui system can
305  // operate.
306  PandaNode *mouse_node = get_mouse().node();
307  if (mouse_node->is_of_type(MouseWatcher::get_class_type())) {
308  top->set_mouse_watcher(DCAST(MouseWatcher, mouse_node));
309  }
310 
311  PN_stdfloat this_aspect_ratio = aspect_ratio;
312  if (this_aspect_ratio == 0.0f) {
313  // An aspect ratio of 0.0 means to try to infer it.
314  this_aspect_ratio = 1.0f;
315 
316  if (_window->has_size()) {
317  int x_size = _window->get_sbs_left_x_size();
318  int y_size = _window->get_sbs_left_y_size();
319  if (y_size != 0) {
320  this_aspect_ratio = (PN_stdfloat)x_size / (PN_stdfloat)y_size;
321  }
322  }
323  }
324 
325  _aspect_2d.set_scale(1.0f / this_aspect_ratio, 1.0f, 1.0f);
326  }
327 
328  return _aspect_2d;
329 }
330 
331 /**
332  * Returns a special root that uses units in pixels that are relative to the
333  * window. The upperleft corner of the window is (0, 0), the lowerleft corner
334  * is (xsize, -ysize), in this coordinate system.
335  */
337 get_pixel_2d() {
338  if (_pixel_2d.is_empty()) {
339  PGTop *top = new PGTop("pixel_2d");
340  _pixel_2d = get_render_2d().attach_new_node(top);
341  _pixel_2d.set_pos(-1, 0, 1);
342 
343  if (_window->has_size()) {
344  int x_size = _window->get_sbs_left_x_size();
345  int y_size = _window->get_sbs_left_y_size();
346  if (x_size > 0){
347  _pixel_2d.set_sx(2.0f / (float)x_size);
348  }
349  _pixel_2d.set_sy(1.0f);
350  if (y_size > 0){
351  _pixel_2d.set_sz(2.0f / (float)y_size);
352  }
353  }
354  }
355 
356  return _pixel_2d;
357 }
358 
359 /**
360  * Returns the node in the data graph corresponding to the mouse associated
361  * with this window.
362  */
364 get_mouse() {
365  if (_mouse.is_empty()) {
366  NodePath mouse = _panda_framework->get_mouse(_window);
367 
368  // Create a MouseWatcher to filter the mouse input. We do this mainly so
369  // we can constrain the mouse input to our particular display region, if
370  // we have one. This means the node we return from get_mouse() is
371  // actually a MouseWatcher, but since it presents the same interface as a
372  // Mouse, no one should mind.
373 
374  // Another advantage to using a MouseWatcher is that the PGTop of aspect2d
375  // likes it better.
376  PT(MouseWatcher) mw = new MouseWatcher("watcher");
377 
378  if (_window->get_side_by_side_stereo()) {
379  // If the window has side-by-side stereo enabled, then we should
380  // constrain the MouseWatcher to the window's DisplayRegion. This will
381  // enable the MouseWatcher to track the left and right halves of the
382  // screen individually.
383  mw->set_display_region(_window->get_overlay_display_region());
384  }
385 
386  _mouse = mouse.attach_new_node(mw);
387  }
388  return _mouse;
389 }
390 
391 /**
392  * Returns the node in the data graph corresponding to the ButtonThrower
393  * object associated with this window.
394  */
397  return _button_thrower;
398 }
399 
400 /**
401  * Creates a ButtonThrower to listen to button presses and throw them as
402  * events.
403  */
405 enable_keyboard() {
406  if (_got_keyboard) {
407  return;
408  }
409 
410  if (_window->is_of_type(GraphicsWindow::get_class_type()) &&
411  DCAST(GraphicsWindow, _window)->get_num_input_devices() > 0) {
412  NodePath mouse = get_mouse();
413 
414  // Create a button thrower to listen for our keyboard events and associate
415  // this WindowFramework pointer with each one.
416  PT(ButtonThrower) bt = new ButtonThrower("kb-events");
417  bt->add_parameter(EventParameter(this));
418  ModifierButtons mods;
419  mods.add_button(KeyboardButton::shift());
420  mods.add_button(KeyboardButton::control());
421  mods.add_button(KeyboardButton::alt());
422  mods.add_button(KeyboardButton::meta());
423  bt->set_modifier_buttons(mods);
424  _button_thrower = mouse.attach_new_node(bt);
425  }
426 
427  _got_keyboard = true;
428 }
429 
430 /**
431  * Sets up the mouse to trackball around the camera.
432  */
434 setup_trackball() {
435  if (_got_trackball) {
436  return;
437  }
438 
439  if (_window->is_of_type(GraphicsWindow::get_class_type()) &&
440  DCAST(GraphicsWindow, _window)->get_num_input_devices() > 0) {
441  NodePath mouse = get_mouse();
442  NodePath camera = get_camera_group();
443 
444  _trackball = new Trackball("trackball");
445  _trackball->set_pos(LVector3::forward() * 50.0);
446  mouse.attach_new_node(_trackball);
447 
448  PT(Transform2SG) tball2cam = new Transform2SG("tball2cam");
449  tball2cam->set_node(camera.node());
450  _trackball->add_child(tball2cam);
451  }
452 
453  _got_trackball = true;
454 }
455 
456 /**
457  * Centers the trackball on the indicated object, and scales the trackball
458  * motion suitably.
459  */
461 center_trackball(const NodePath &object) {
462  if (_trackball == nullptr) {
463  return;
464  }
465 
466  PT(BoundingVolume) volume = object.get_bounds();
467  // We expect at least a geometric bounding volume around the world.
468  nassertv(volume != nullptr);
469  nassertv(volume->is_of_type(GeometricBoundingVolume::get_class_type()));
470  CPT(GeometricBoundingVolume) gbv = DCAST(GeometricBoundingVolume, volume);
471 
472  if (object.has_parent()) {
473  CPT(TransformState) net_transform = object.get_parent().get_net_transform();
474  PT(GeometricBoundingVolume) new_gbv = DCAST(GeometricBoundingVolume, gbv->make_copy());
475  new_gbv->xform(net_transform->get_mat());
476  gbv = new_gbv;
477  }
478 
479  // Determine the bounding sphere around the object.
480  if (gbv->is_infinite()) {
481  framework_cat.warning()
482  << "Infinite bounding volume for " << object << "\n";
483  return;
484  }
485 
486  if (gbv->is_empty()) {
487  framework_cat.warning()
488  << "Empty bounding volume for " << object << "\n";
489  return;
490  }
491 
492  // The BoundingVolume might be a sphere (it's likely), but since it might
493  // not, we'll take no chances and make our own sphere.
494  PT(BoundingSphere) sphere = new BoundingSphere(gbv->get_approx_center(), 0.0f);
495  if (!sphere->extend_by(gbv)) {
496  framework_cat.warning()
497  << "Cannot determine bounding volume of " << object << "\n";
498  return;
499  }
500 
501  LPoint3 center = sphere->get_center();
502  PN_stdfloat radius = sphere->get_radius();
503 
504  PN_stdfloat distance = 50.0f;
505 
506  // Choose a suitable distance to view the whole volume in our frame. This
507  // is based on the camera lens in use. Determine the lens based on the
508  // first camera; this will be the default camera.
509  Lens *lens = nullptr;
510  if (!_cameras.empty()) {
511  Cameras::const_iterator ci;
512  for (ci = _cameras.begin();
513  ci != _cameras.end() && lens == nullptr;
514  ++ci) {
515  lens = (*ci)->get_lens();
516  }
517  }
518 
519  if (lens != nullptr) {
520  LVecBase2 fov = lens->get_fov();
521  distance = radius / ctan(deg_2_rad(std::min(fov[0], fov[1]) / 2.0f));
522 
523  // Ensure the far plane is far enough back to see the entire object.
524  PN_stdfloat ideal_far_plane = distance + radius * 1.5;
525  lens->set_far(std::max(lens->get_default_far(), ideal_far_plane));
526 
527  // And that the near plane is far enough forward.
528  PN_stdfloat ideal_near_plane = distance - radius;
529  lens->set_near(std::min(lens->get_default_near(), ideal_near_plane));
530  }
531 
532  _trackball->set_origin(center);
533  _trackball->set_pos(LVector3::forward() * distance);
534 
535  // Also set the movement scale on the trackball to be consistent with the
536  // size of the model and the lens field-of-view.
537  _trackball->set_forward_scale(distance * 0.006);
538 }
539 
540 /**
541  * Loads up all the model files listed in the indicated argument list. If
542  * first_arg is supplied, it is the first argument in the list to consider.
543  *
544  * Returns true if all models loaded successfully, or false if at least one of
545  * them had an error.
546  */
548 load_models(const NodePath &parent, int argc, char *argv[], int first_arg) {
549  pvector<Filename> files;
550 
551  for (int i = first_arg; i < argc && argv[i] != nullptr; i++) {
552  files.push_back(Filename::from_os_specific(argv[i]));
553  }
554 
555  return load_models(parent, files);
556 }
557 
558 /**
559  * Loads up all the model files listed in the indicated argument list.
560  *
561  * Returns true if all models loaded successfully, or false if at least one of
562  * them had an error.
563  */
565 load_models(const NodePath &parent, const pvector<Filename> &files) {
566  bool all_ok = true;
567 
569  for (fi = files.begin(); fi != files.end(); ++fi) {
570  const Filename &filename = (*fi);
571  NodePath model = load_model(parent, filename);
572  if (model.is_empty()) {
573  all_ok = false;
574  }
575  }
576 
577  return all_ok;
578 }
579 
580 /**
581  * Loads up the indicated model and returns the new NodePath, or the empty
582  * NodePath if the model could not be loaded.
583  */
585 load_model(const NodePath &parent, Filename filename) {
586  framework_cat.info() << "Loading " << filename << "\n";
587 
588  // If the filename already exists where it is, or if it is fully qualified,
589  // don't search along the model path for it.
591  bool search = !(filename.is_fully_qualified() || vfs->exists(filename));
592 
593  // We allow loading image files here. Check to see if it might be an image
594  // file, based on the filename extension.
595  bool is_image = false;
596  string extension = filename.get_extension();
597 #ifdef HAVE_ZLIB
598  if (extension == "pz" || extension == "gz") {
599  extension = Filename(filename.get_basename_wo_extension()).get_extension();
600  }
601 #endif // HAVE_ZLIB
602  TexturePool *texture_pool = TexturePool::get_global_ptr();
603  LoaderFileType *model_type = nullptr;
604 
605  if (!extension.empty()) {
607  model_type = reg->get_type_from_extension(extension);
608 
609  if (model_type == nullptr) {
610  // The extension isn't a known model file type; is it a known image file
611  // extension?
612  TexturePool *texture_pool = TexturePool::get_global_ptr();
613  if (texture_pool->get_texture_type(extension) != nullptr) {
614  // It is a known image file extension.
615  is_image = true;
616  }
617  }
618  }
619 
620  LoaderOptions options = PandaFramework::_loader_options;
621  if (search) {
622  options.set_flags(options.get_flags() | LoaderOptions::LF_search);
623  } else {
624  options.set_flags(options.get_flags() & ~LoaderOptions::LF_search);
625  }
626 
627  Loader loader;
628  PT(PandaNode) node;
629  if (is_image) {
630  node = load_image_as_model(filename);
631  } else {
632  node = loader.load_sync(filename, options);
633 
634  // It failed to load. Is it because the extension isn't recognised? If
635  // so, then we just got done printing out the known scene types, and we
636  // should also print out the supported texture types.
637  if (node == nullptr && !is_image && model_type == nullptr) {
638  texture_pool->write_texture_types(nout, 2);
639  }
640  }
641 
642  if (node == nullptr) {
643  nout << "Unable to load " << filename << "\n";
644  return NodePath::not_found();
645  }
646 
647  return parent.attach_new_node(node);
648 }
649 
650 /**
651  * Loads our favorite blue triangle. This is intended to provide some default
652  * geometry to have *something* to look at for testing, when no other models
653  * are provided.
654  */
656 load_default_model(const NodePath &parent) {
657  CPT(RenderState) state = RenderState::make_empty();
658 
659  state = state->add_attrib(ColorAttrib::make_flat(LColor(0.5, 0.5, 1.0, 1.0)));
660 
661  // Get the default texture to apply to the triangle; it's compiled into the
662  // code these days.
663  string rock_floor_string((const char *)rock_floor, rock_floor_len);
664  istringstream rock_floor_strm(rock_floor_string);
665  PNMImage rock_floor_pnm;
666  if (rock_floor_pnm.read(rock_floor_strm, "rock-floor.rgb")) {
667  PT(Texture) tex = new Texture;
668  tex->set_name("rock-floor.rgb");
669  tex->load(rock_floor_pnm);
670  tex->set_minfilter(SamplerState::FT_linear);
671  tex->set_magfilter(SamplerState::FT_linear);
672  state = state->add_attrib(TextureAttrib::make(tex));
673  }
674 
675  GeomNode *geomnode = new GeomNode("tri");
676 
677  PT(GeomVertexData) vdata = new GeomVertexData
679  Geom::UH_static);
680  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
681  GeomVertexWriter normal(vdata, InternalName::get_normal());
682  GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
683 
684  vertex.add_data3(LVertex::rfu(0.0, 0.0, 0.0));
685  vertex.add_data3(LVertex::rfu(1.0, 0.0, 0.0));
686  vertex.add_data3(LVertex::rfu(0.0, 0.0, 1.0));
687 
688  normal.add_data3(LNormal::back());
689  normal.add_data3(LNormal::back());
690  normal.add_data3(LNormal::back());
691 
692  texcoord.add_data2(0.0, 0.0);
693  texcoord.add_data2(1.0, 0.0);
694  texcoord.add_data2(0.0, 1.0);
695 
696  PT(GeomTriangles) tri = new GeomTriangles(Geom::UH_static);
697  tri->add_consecutive_vertices(0, 3);
698  tri->close_primitive();
699 
700  PT(Geom) geom = new Geom(vdata);
701  geom->add_primitive(tri);
702 
703  geomnode->add_geom(geom, state);
704 
705  return parent.attach_new_node(geomnode);
706 }
707 
708 /**
709  * Looks for characters and their matching animation files in the scene graph;
710  * binds and loops any matching animations found.
711  */
713 loop_animations(int hierarchy_match_flags) {
714  // If we happened to load up both a character file and its matching
715  // animation file, attempt to bind them together now and start the
716  // animations looping.
717  auto_bind(get_render().node(), _anim_controls, hierarchy_match_flags);
718  _anim_controls.loop_all(true);
719 }
720 
721 /**
722  * Walks through all the animations that were bound by loop_animations() and
723  * staggers their play rate slightly so that they will not remain perfectly in
724  * sync.
725  */
728  for (int i = 0; i < _anim_controls.get_num_anims(); ++i) {
729  AnimControl *control = _anim_controls.get_anim(i);
730  double r = (double)rand() / (double)RAND_MAX;
731  r = r * 0.2 + 0.9;
732  control->set_play_rate(r);
733  }
734 }
735 
736 /**
737  * Rotates the animation controls through all of the available animations. If
738  * the animation controls are not already enabled, enables them at sets to the
739  * first animation; if they are already enabled, steps to the next animation;
740  * if that is the last animation, disables the animation controls.
741  */
744  if (_anim_controls_enabled) {
745  destroy_anim_controls();
746 
747  if (_anim_controls.get_num_anims() == 0) {
748  set_anim_controls(false);
749  return;
750  }
751 
752  // Stop the active animation.
753  pause_button();
754  ++_anim_index;
755 
756  if (_anim_index >= _anim_controls.get_num_anims()) {
757  set_anim_controls(false);
758  _anim_controls.loop_all(true);
759  } else {
760  create_anim_controls();
761  play_button();
762  }
763  } else {
764  _anim_index = 0;
765  set_anim_controls(true);
766  if (_anim_controls.get_num_anims() > 0) {
767  play_button();
768  }
769  }
770 }
771 
772 /**
773  * Creates an onscreen animation slider for frame-stepping through the
774  * animations.
775  */
777 set_anim_controls(bool enable) {
778  _anim_controls_enabled = enable;
779  if (_anim_controls_enabled) {
780  create_anim_controls();
781 
782  } else {
783  destroy_anim_controls();
784  }
785 }
786 
787 /**
788  * Reevaluates the dimensions of the window, presumably after the window has
789  * been resized by the user or some other force. Adjusts the render film
790  * size, aspect2d scale (aspect ratio) and the dimensionsas of pixel_2d
791  * according to the new window shape, or new config setting.
792  */
795  PN_stdfloat this_aspect_ratio = aspect_ratio;
796 
797  int x_size = 0, y_size = 0;
798  if (_window->has_size()) {
799  x_size = _window->get_sbs_left_x_size();
800  y_size = _window->get_sbs_left_y_size();
801  }
802 
803  if (this_aspect_ratio == 0.0f) {
804  // An aspect ratio of 0.0 means to try to infer it.
805  this_aspect_ratio = 1.0f;
806  if (y_size != 0) {
807  this_aspect_ratio = (float)x_size / (float)y_size;
808  }
809  }
810 
811  if (!_aspect_2d.is_empty()) {
812  _aspect_2d.set_scale(1.0f / this_aspect_ratio, 1.0f, 1.0f);
813  }
814 
815  if (!_pixel_2d.is_empty()) {
816  // Adjust the pixel 2d scale
817  if (x_size > 0){
818  _pixel_2d.set_sx(2.0f / (float)x_size);
819  }
820  _pixel_2d.set_sy(1.0f);
821  if (y_size > 0){
822  _pixel_2d.set_sz(2.0f / (float)y_size);
823  }
824  }
825 
826  Cameras::iterator ci;
827  for (ci = _cameras.begin(); ci != _cameras.end(); ++ci) {
828  Lens *lens = (*ci)->get_lens();
829  if (lens != nullptr) {
830  if (y_size != 0) {
831  lens->set_film_size(x_size, y_size);
832  } else {
833  lens->set_aspect_ratio(this_aspect_ratio);
834  }
835  }
836  }
837 }
838 
839 /**
840  * Divides the window into two display regions, each of which gets its own
841  * trackball and keyboard events. The new window pointer is returned.
842  *
843  * There is not an interface for recombining divided windows.
844  */
846 split_window(SplitType split_type) {
847  DisplayRegion *new_region = nullptr;
848 
849  if (split_type == ST_default) {
850  // Choose either horizontal or vertical according to the largest
851  // dimension.
852 
853  if (_display_region_3d->get_pixel_width() >
854  _display_region_3d->get_pixel_height()) {
855  split_type = ST_horizontal;
856  } else {
857  split_type = ST_vertical;
858  }
859  }
860 
861  PN_stdfloat left, right, bottom, top;
862  _display_region_3d->get_dimensions(left, right, bottom, top);
863  new_region = _display_region_3d->get_window()->make_display_region();
864 
865  if (split_type == ST_vertical) {
866  _display_region_3d->set_dimensions(left, right, bottom, (top + bottom) / 2.0f);
867  if (_display_region_2d != nullptr) {
868  _display_region_2d->set_dimensions(left, right, bottom, (top + bottom) / 2.0f);
869  }
870 
871  new_region->set_dimensions(left, right, (top + bottom) / 2.0f, top);
872 
873  } else {
874  _display_region_3d->set_dimensions(left, (left + right) / 2.0f, bottom, top);
875  if (_display_region_2d != nullptr) {
876  _display_region_2d->set_dimensions(left, (left + right) / 2.0f, bottom, top);
877  }
878 
879  new_region->set_dimensions((left + right) / 2.0f, right, bottom, top);
880  }
881 
882  PT(WindowFramework) wf = new WindowFramework(*this, new_region);
883  _panda_framework->_windows.push_back(wf);
884 
885  return wf;
886 }
887 
888 /**
889  * Forces wireframe state (true) or restores default rendering (false).
890  */
892 set_wireframe(bool enable, bool filled) {
893  if (enable == _wireframe_enabled && filled == _wireframe_filled) {
894  return;
895  }
896 
897  NodePath render = get_render();
898 
899  if (!_two_sided_enabled) {
900  render.clear_two_sided();
901  }
902 
903  if (enable) {
904  if (filled) {
905  render.set_attrib(RenderModeAttrib::make(
906  RenderModeAttrib::M_filled_wireframe,
907  1.4f, false, LColor(1, 1, 1, .5f)),
908  override_priority);
909  // Darken the scene so that the wireframe is clearly visible, even when
910  // the scene is completely white.
911  render.set_color_scale(LColor(0.7f, 0.7f, 0.7f, 1), override_priority);
912  } else {
913  render.set_render_mode_wireframe(override_priority);
914  render.set_two_sided(true, override_priority);
915  render.clear_color_scale();
916  }
917  } else {
918  render.clear_render_mode();
919  if (_one_sided_reverse_enabled) {
920  CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse();
921  render.node()->set_attrib(attrib);
922  }
923  render.clear_color_scale();
924  }
925 
926  _wireframe_enabled = enable;
927  _wireframe_filled = filled;
928 }
929 
930 /**
931  * Forces textures off (false) or restores default rendering (true).
932  */
934 set_texture(bool enable) {
935  if (enable == _texture_enabled) {
936  return;
937  }
938 
939  NodePath render = get_render();
940 
941  if (!enable) {
942  render.set_texture_off(override_priority);
943  } else {
944  render.clear_texture();
945  }
946 
947  _texture_enabled = enable;
948 }
949 
950 /**
951  * Forces two-sided rendering (true) or restores default rendering (false).
952  */
954 set_two_sided(bool enable) {
955  if (enable == _two_sided_enabled) {
956  return;
957  }
958 
959  NodePath render = get_render();
960 
961  if (enable) {
962  render.set_two_sided(true, override_priority);
963  } else {
964  if (!_wireframe_enabled) {
965  render.clear_two_sided();
966  }
967  }
968 
969  _two_sided_enabled = enable;
970  _one_sided_reverse_enabled = false;
971 }
972 
973 /**
974  * Toggles one-sided reverse mode. In this mode, the front sides of one-sided
975  * polygons are culled instead of the back side.
976  */
978 set_one_sided_reverse(bool enable) {
979  if (enable == _one_sided_reverse_enabled) {
980  return;
981  }
982 
983  NodePath render = get_render();
984 
985  if (!_wireframe_enabled) {
986  if (enable) {
987  CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse();
988  render.node()->set_attrib(attrib);
989  } else {
990  render.clear_two_sided();
991  }
992  }
993 
994  _two_sided_enabled = false;
995  _one_sided_reverse_enabled = enable;
996 }
997 
998 /**
999  * Turns lighting on (true) or off (false).
1000  */
1002 set_lighting(bool enable) {
1003  if (enable == _lighting_enabled) {
1004  return;
1005  }
1006 
1007  NodePath render = get_render();
1008 
1009  if (enable) {
1010  if (!_got_lights) {
1011  setup_lights();
1012  }
1013  render.set_light(_alight);
1014  render.set_light(_dlight);
1015  } else {
1016  render.clear_light();
1017  }
1018 
1019  _lighting_enabled = enable;
1020 }
1021 
1022 /**
1023  * Turns per-pixel lighting on (true) or off (false).
1024  */
1026 set_perpixel(bool enable) {
1027  if (enable == _perpixel_enabled) {
1028  return;
1029  }
1030 
1031  NodePath render = get_render();
1032 
1033  if (enable) {
1034  render.set_shader_auto();
1035  } else {
1036  render.set_shader_off();
1037  }
1038 
1039  _perpixel_enabled = enable;
1040 }
1041 
1042 /**
1043  * Sets the background of the window to one of the pre-canned background types
1044  * (or to BT_other, which indicates the user intends to set up his own special
1045  * background mode).
1046  */
1048 set_background_type(WindowFramework::BackgroundType type) {
1049  _background_type = type;
1050 
1051  if (_display_region_3d == nullptr) {
1052  return;
1053  }
1054 
1055  switch (_background_type) {
1056  case BT_other:
1057  break;
1058 
1059  case BT_default:
1060  _display_region_3d->set_clear_color_active(true);
1061  _display_region_3d->set_clear_depth_active(true);
1062  _display_region_3d->set_clear_stencil_active(true);
1063  _display_region_3d->set_clear_color(_window->get_clear_color());
1064  _display_region_3d->set_clear_depth(_window->get_clear_depth());
1065  _display_region_3d->set_clear_stencil(_window->get_clear_stencil());
1066  break;
1067 
1068  case BT_black:
1069  _display_region_3d->set_clear_color_active(true);
1070  _display_region_3d->set_clear_depth_active(true);
1071  _display_region_3d->set_clear_stencil_active(true);
1072  _display_region_3d->set_clear_color(LColor(0.0f, 0.0f, 0.0f, 0.0f));
1073  _display_region_3d->set_clear_depth(1.0f);
1074  _display_region_3d->set_clear_stencil(0);
1075  break;
1076 
1077  case BT_gray:
1078  _display_region_3d->set_clear_color_active(true);
1079  _display_region_3d->set_clear_depth_active(true);
1080  _display_region_3d->set_clear_stencil_active(true);
1081  _display_region_3d->set_clear_color(LColor(0.3, 0.3, 0.3, 0.0f));
1082  _display_region_3d->set_clear_depth(1.0f);
1083  _display_region_3d->set_clear_stencil(0);
1084  break;
1085 
1086  case BT_white:
1087  _display_region_3d->set_clear_color_active(true);
1088  _display_region_3d->set_clear_depth_active(true);
1089  _display_region_3d->set_clear_stencil_active(true);
1090  _display_region_3d->set_clear_color(LColor(1.0f, 1.0f, 1.0f, 0.0f));
1091  _display_region_3d->set_clear_depth(1.0f);
1092  _display_region_3d->set_clear_stencil(0);
1093  break;
1094 
1095  case BT_none:
1096  _display_region_3d->set_clear_color_active(false);
1097  _display_region_3d->set_clear_depth_active(false);
1098  _display_region_3d->set_clear_stencil_active(false);
1099  break;
1100  }
1101 }
1102 
1103 /**
1104  * Returns a font that contains the shuttle controls icons.
1105  */
1108  if (_shuttle_controls_font == nullptr) {
1109  PT(TextFont) font;
1110 
1111  string shuttle_controls_string((const char *)shuttle_controls, shuttle_controls_len);
1112  istringstream in(shuttle_controls_string);
1113  BamFile bam_file;
1114  if (bam_file.open_read(in, "shuttle_controls font stream")) {
1115  PT(PandaNode) node = bam_file.read_node();
1116  if (node != nullptr) {
1117  _shuttle_controls_font = new StaticTextFont(node);
1118  }
1119  }
1120  }
1121 
1122  return _shuttle_controls_font;
1123 }
1124 
1125 /**
1126  * Makes a new 3-d camera for the window.
1127  */
1129 make_camera() {
1130  // Finally, we need a camera to associate with the display region.
1131  PT(Camera) camera = new Camera("camera");
1132  NodePath camera_np = get_camera_group().attach_new_node(camera);
1133  _cameras.push_back(camera);
1134 
1135  PT(Lens) lens = new PerspectiveLens;
1136 
1137  if (aspect_ratio != 0.0) {
1138  // If we're given an explict aspect ratio, use it
1139  lens->set_aspect_ratio(aspect_ratio);
1140 
1141  } else {
1142  // Otherwise, infer the aspect ratio from the window size. This does
1143  // assume we have square pixels on our output device.
1144  if (_window->has_size()) {
1145  int x_size = _window->get_sbs_left_x_size();
1146  int y_size = _window->get_sbs_left_y_size();
1147  if (y_size != 0) {
1148  lens->set_film_size(x_size, y_size);
1149  }
1150  }
1151  }
1152 
1153  camera->set_lens(lens);
1154 
1155  return camera_np;
1156 }
1157 
1158 /**
1159  * Makes light nodes and attaches them to the camera for viewing the scene.
1160  */
1161 void WindowFramework::
1162 setup_lights() {
1163  if (_got_lights) {
1164  return;
1165  }
1166 
1167  NodePath camera_group = get_camera_group();
1168  NodePath light_group = camera_group.attach_new_node("lights");
1169 
1170  AmbientLight *alight = new AmbientLight("ambient");
1171  alight->set_color(LColor(0.2, 0.2, 0.2, 1.0f));
1172  DirectionalLight *dlight = new DirectionalLight("directional");
1173  dlight->set_color(LColor(0.8f, 0.8f, 0.8f, 1.0f));
1174 
1175  _alight = light_group.attach_new_node(alight);
1176  _dlight = light_group.attach_new_node(dlight);
1177  _dlight.set_hpr(-10, -20, 0);
1178 
1179  _got_lights = true;
1180 }
1181 
1182 /**
1183  * Loads the indicated image file as a texture, and creates a polygon to
1184  * render it. Returns the new model.
1185  */
1186 PT(PandaNode) WindowFramework::
1187 load_image_as_model(const Filename &filename) {
1188  PT(Texture) tex = TexturePool::load_texture(filename);
1189  if (tex == nullptr) {
1190  return nullptr;
1191  }
1192 
1193  // Yes, it is an image file; make a texture out of it.
1194  tex->set_minfilter(SamplerState::FT_linear_mipmap_linear);
1195  tex->set_magfilter(SamplerState::FT_linear);
1196  tex->set_wrap_u(SamplerState::WM_clamp);
1197  tex->set_wrap_v(SamplerState::WM_clamp);
1198  tex->set_wrap_w(SamplerState::WM_clamp);
1199 
1200  // Ok, now make a polygon to show the texture.
1201  bool has_alpha = true;
1202  LVecBase2 tex_scale = tex->get_tex_scale();
1203 
1204  // Get the size from the original image (the texture may have scaled it to
1205  // make a power of 2).
1206  int x_size = tex->get_orig_file_x_size();
1207  int y_size = tex->get_orig_file_y_size();
1208 
1209  // Choose the dimensions of the polygon appropriately.
1210  PN_stdfloat left,right,top,bottom;
1211  static const PN_stdfloat scale = 10.0;
1212  if (x_size > y_size) {
1213  left = -scale;
1214  right = scale;
1215  top = (scale * y_size) / x_size;
1216  bottom = -(scale * y_size) / x_size;
1217  } else if (y_size != 0) {
1218  left = -(scale * x_size) / y_size;
1219  right = (scale * x_size) / y_size;
1220  top = scale;
1221  bottom = -scale;
1222  } else {
1223  framework_cat.warning()
1224  << "Texture size is 0 0: " << *tex << "\n";
1225 
1226  left = -scale;
1227  right = scale;
1228  top = scale;
1229  bottom = -scale;
1230  }
1231 
1232  PT(GeomNode) card_node = new GeomNode("card");
1233  card_node->set_attrib(TextureAttrib::make(tex));
1234  if (has_alpha) {
1235  card_node->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
1236  }
1237 
1238  bool is_3d = false;
1239  if (tex->get_texture_type() == Texture::TT_3d_texture ||
1240  tex->get_texture_type() == Texture::TT_cube_map) {
1241  // For a 3-d texture, generate a cube, instead of a plain card.
1242  is_3d = true;
1243  }
1244 
1245  CPT(GeomVertexFormat) vformat;
1246  if (!is_3d) {
1247  // Vertices and 2-d texture coordinates, all we need.
1248  vformat = GeomVertexFormat::get_v3t2();
1249 
1250  } else {
1251  // Vertices and 3-d texture coordinates.
1252  vformat = GeomVertexFormat::register_format
1254  (InternalName::get_vertex(), 3,
1255  GeomEnums::NT_stdfloat, GeomEnums::C_point,
1256  InternalName::get_texcoord(), 3,
1257  GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
1258  }
1259 
1260  PT(GeomVertexData) vdata = new GeomVertexData
1261  ("card", vformat, Geom::UH_static);
1262  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
1263  GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
1264 
1265  if (!is_3d) {
1266  // A normal 2-d card.
1267  vertex.add_data3(LVertex::rfu(left, 0.02, top));
1268  vertex.add_data3(LVertex::rfu(left, 0.02, bottom));
1269  vertex.add_data3(LVertex::rfu(right, 0.02, top));
1270  vertex.add_data3(LVertex::rfu(right, 0.02, bottom));
1271 
1272  texcoord.add_data2(0.0f, tex_scale[1]);
1273  texcoord.add_data2(0.0f, 0.0f);
1274  texcoord.add_data2(tex_scale[0], tex_scale[1]);
1275  texcoord.add_data2(tex_scale[0], 0.0f);
1276 
1277  } else {
1278  // The eight vertices of a 3-d cube.
1279  vertex.add_data3(-1.0f, -1.0f, 1.0f); // 0
1280  vertex.add_data3(-1.0f, -1.0f, -1.0f); // 1
1281  vertex.add_data3(1.0f, -1.0f, -1.0f); // 2
1282  vertex.add_data3(1.0f, -1.0f, 1.0f); // 3
1283  vertex.add_data3(1.0f, 1.0f, 1.0f); // 4
1284  vertex.add_data3(1.0f, 1.0f, -1.0f); // 5
1285  vertex.add_data3(-1.0f, 1.0f, -1.0f); // 6
1286  vertex.add_data3(-1.0f, 1.0f, 1.0f); // 7
1287 
1288  texcoord.add_data3(-1.0f, -1.0f, 1.0f); // 0
1289  texcoord.add_data3(-1.0f, -1.0f, -1.0f); // 1
1290  texcoord.add_data3(1.0f, -1.0f, -1.0f); // 2
1291  texcoord.add_data3(1.0f, -1.0f, 1.0f); // 3
1292  texcoord.add_data3(1.0f, 1.0f, 1.0f); // 4
1293  texcoord.add_data3(1.0f, 1.0f, -1.0f); // 5
1294  texcoord.add_data3(-1.0f, 1.0f, -1.0f); // 6
1295  texcoord.add_data3(-1.0f, 1.0f, 1.0f); // 7
1296  }
1297 
1298  PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
1299 
1300  if (!is_3d) {
1301  // The two triangles that make up a quad.
1302  strip->add_consecutive_vertices(0, 4);
1303  strip->close_primitive();
1304 
1305  } else {
1306  // The twelve triangles (six quads) that make up a cube.
1307  strip->add_vertex(7);
1308  strip->add_vertex(0);
1309  strip->add_vertex(4);
1310  strip->add_vertex(3);
1311  strip->close_primitive();
1312 
1313  strip->add_vertex(1);
1314  strip->add_vertex(6);
1315  strip->add_vertex(2);
1316  strip->add_vertex(5);
1317  strip->close_primitive();
1318 
1319  strip->add_vertex(5);
1320  strip->add_vertex(4);
1321  strip->add_vertex(2);
1322  strip->add_vertex(3);
1323  strip->add_vertex(1);
1324  strip->add_vertex(0);
1325  strip->add_vertex(6);
1326  strip->add_vertex(7);
1327  strip->add_vertex(5);
1328  strip->add_vertex(4);
1329  strip->close_primitive();
1330  }
1331 
1332  PT(Geom) geom = new Geom(vdata);
1333  geom->add_primitive(strip);
1334 
1335  card_node->add_geom(geom);
1336 
1337  return card_node;
1338 }
1339 
1340 /**
1341  * Creates an onscreen animation slider for frame-stepping through the
1342  * animations.
1343  */
1344 void WindowFramework::
1345 create_anim_controls() {
1346  destroy_anim_controls();
1347 
1348  PT(PGItem) group = new PGItem("anim_controls_group");
1349  PGFrameStyle style;
1350  style.set_type(PGFrameStyle::T_flat);
1351  style.set_color(0.0f, 0.0f, 0.0f, 0.3);
1352  group->set_frame(-1.0f, 1.0f, 0.0f, 0.2);
1353  group->set_frame_style(0, style);
1354  group->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
1355  group->set_active(true);
1356 
1357  _anim_controls_group = get_aspect_2d().attach_new_node(group);
1358  _anim_controls_group.set_pos(0.0f, 0.0f, -0.9f);
1359 
1360  if (_anim_index >= _anim_controls.get_num_anims()) {
1361  PT(TextNode) label = new TextNode("label");
1362  label->set_align(TextNode::A_center);
1363  label->set_text("No animation.");
1364  NodePath tnp = _anim_controls_group.attach_new_node(label);
1365  tnp.set_pos(0.0f, 0.0f, 0.07f);
1366  tnp.set_scale(0.1f);
1367 
1368  return;
1369  }
1370 
1371  AnimControl *control = _anim_controls.get_anim(_anim_index);
1372  nassertv(control != nullptr);
1373 
1374  if (control->get_num_frames() <= 1) {
1375  // Don't show the controls when the animation has only 0 or 1 frames.
1376  ostringstream text;
1377  text << _anim_controls.get_anim_name(_anim_index);
1378  text << " (" << control->get_num_frames() << " frame"
1379  << ((control->get_num_frames() == 1) ? "" : "s") << ")";
1380 
1381  PT(TextNode) label = new TextNode("label");
1382  label->set_align(TextNode::A_center);
1383  label->set_text(text.str());
1384  NodePath tnp = _anim_controls_group.attach_new_node(label);
1385  tnp.set_pos(0.0f, 0.0f, 0.07f);
1386  tnp.set_scale(0.1f);
1387 
1388  return;
1389  }
1390 
1391  PT(TextNode) label = new TextNode("anim_name");
1392  label->set_align(TextNode::A_left);
1393  label->set_text(_anim_controls.get_anim_name(_anim_index));
1394  NodePath tnp = _anim_controls_group.attach_new_node(label);
1395  tnp.set_pos(-0.95f, 0.0f, 0.15f);
1396  tnp.set_scale(0.05f);
1397 
1398  _anim_slider = new PGSliderBar("anim_slider");
1399  _anim_slider->setup_slider(false, 1.9f, 0.1f, 0.005f);
1400  _anim_slider->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
1401  _anim_slider->get_thumb_button()->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
1402 
1403  _anim_slider->set_range(0.0f, (PN_stdfloat)(control->get_num_frames() - 1));
1404  _anim_slider->set_scroll_size(0.0f);
1405  _anim_slider->set_page_size(1.0f);
1406  NodePath snp = _anim_controls_group.attach_new_node(_anim_slider);
1407  snp.set_pos(0.0f, 0.0f, 0.06f);
1408 
1409  _frame_number = new TextNode("frame_number");
1410  _frame_number->set_text_color(0.0f, 0.0f, 0.0f, 1.0f);
1411  _frame_number->set_align(TextNode::A_center);
1412  _frame_number->set_text(format_string(control->get_frame()));
1413  NodePath fnp = NodePath(_anim_slider->get_thumb_button()).attach_new_node(_frame_number);
1414  fnp.set_scale(0.05f);
1415  fnp.set_pos(0.0f, 0.0f, -0.01f);
1416 
1417  _play_rate_slider = new PGSliderBar("play_rate_slider");
1418  _play_rate_slider->setup_slider(false, 0.4, 0.05f, 0.005f);
1419  _play_rate_slider->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
1420  _play_rate_slider->get_thumb_button()->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
1421  _play_rate_slider->set_value(control->get_play_rate());
1422  NodePath pnp = _anim_controls_group.attach_new_node(_play_rate_slider);
1423  pnp.set_pos(0.75f, 0.0f, 0.15f);
1424 
1425  // Set up the jogshuttle buttons. These use symbols from the
1426  // shuttle_controls_font file.
1427  setup_shuttle_button("9", 0, st_back_button);
1428  setup_shuttle_button(";", 1, st_pause_button);
1429  setup_shuttle_button("4", 2, st_play_button);
1430  setup_shuttle_button(":", 3, st_forward_button);
1431 
1432  _update_anim_controls_task = new GenericAsyncTask("controls", st_update_anim_controls, (void *)this);
1433  _panda_framework->get_task_mgr().add(_update_anim_controls_task);
1434 }
1435 
1436 /**
1437  * Removes the previously-created anim controls, if any.
1438  */
1439 void WindowFramework::
1440 destroy_anim_controls() {
1441  if (!_anim_controls_group.is_empty()) {
1442  _anim_controls_group.remove_node();
1443 
1444  _panda_framework->get_event_handler().remove_hooks_with((void *)this);
1445  if (_update_anim_controls_task != nullptr) {
1446  _panda_framework->get_task_mgr().remove(_update_anim_controls_task);
1447  _update_anim_controls_task.clear();
1448  }
1449  }
1450 }
1451 
1452 /**
1453  * A per-frame callback to update the anim slider for the current frame.
1454  */
1455 void WindowFramework::
1456 update_anim_controls() {
1457  AnimControl *control = _anim_controls.get_anim(_anim_index);
1458  nassertv(control != nullptr);
1459 
1460  if (_anim_slider != nullptr) {
1461  if (_anim_slider->is_button_down()) {
1462  control->pose((int)(_anim_slider->get_value() + 0.5));
1463  } else {
1464  _anim_slider->set_value((PN_stdfloat)control->get_frame());
1465  }
1466  }
1467 
1468  if (_frame_number != nullptr) {
1469  _frame_number->set_text(format_string(control->get_frame()));
1470  }
1471 
1472  control->set_play_rate(_play_rate_slider->get_value());
1473 }
1474 
1475 /**
1476  * Creates a PGButton to implement the indicated shuttle event (play, pause,
1477  * etc.).
1478  */
1479 void WindowFramework::
1480 setup_shuttle_button(const string &label, int index,
1481  EventHandler::EventCallbackFunction *func) {
1482  PT(PGButton) button = new PGButton(label);
1483  button->set_frame(-0.05f, 0.05f, 0.0f, 0.07f);
1484 
1485  PN_stdfloat bevel = 0.005f;
1486 
1487  PGFrameStyle style;
1488  style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
1489  style.set_width(bevel, bevel);
1490 
1491  style.set_type(PGFrameStyle::T_bevel_out);
1492  button->set_frame_style(PGButton::S_ready, style);
1493 
1494  style.set_type(PGFrameStyle::T_bevel_in);
1495  button->set_frame_style(PGButton::S_depressed, style);
1496 
1497  style.set_color(0.9f, 0.9f, 0.9f, 1.0f);
1498  style.set_type(PGFrameStyle::T_bevel_out);
1499  button->set_frame_style(PGButton::S_rollover, style);
1500 
1501  if (get_shuttle_controls_font() != nullptr) {
1502  PT(TextNode) tn = new TextNode("label");
1503  tn->set_align(TextNode::A_center);
1504  tn->set_font(get_shuttle_controls_font());
1505  tn->set_text(label);
1506  tn->set_text_color(0.0f, 0.0f, 0.0f, 1.0f);
1507  LMatrix4 xform = LMatrix4::scale_mat(0.07f);
1508  xform.set_row(3, LVecBase3(0.0f, 0.0f, 0.016f));
1509  tn->set_transform(xform);
1510 
1511  button->get_state_def(PGButton::S_ready).attach_new_node(tn);
1512  button->get_state_def(PGButton::S_depressed).attach_new_node(tn);
1513  button->get_state_def(PGButton::S_rollover).attach_new_node(tn);
1514  }
1515 
1516  NodePath np = _anim_controls_group.attach_new_node(button);
1517  np.set_pos(0.1f * index - 0.15f, 0.0f, 0.12);
1518 
1519  _panda_framework->get_event_handler().add_hook(button->get_click_event(MouseButton::one()), func, (void *)this);
1520 }
1521 
1522 /**
1523  * Handler for a shuttle button.
1524  */
1525 void WindowFramework::
1526 back_button() {
1527  AnimControl *control = _anim_controls.get_anim(_anim_index);
1528  nassertv(control != nullptr);
1529  control->pose(control->get_frame() - 1);
1530 }
1531 
1532 /**
1533  * Handler for a shuttle button.
1534  */
1535 void WindowFramework::
1536 pause_button() {
1537  AnimControl *control = _anim_controls.get_anim(_anim_index);
1538  nassertv(control != nullptr);
1539  control->stop();
1540 }
1541 
1542 /**
1543  * Handler for a shuttle button.
1544  */
1545 void WindowFramework::
1546 play_button() {
1547  AnimControl *control = _anim_controls.get_anim(_anim_index);
1548  nassertv(control != nullptr);
1549  control->loop(false);
1550 }
1551 
1552 /**
1553  * Handler for a shuttle button.
1554  */
1555 void WindowFramework::
1556 forward_button() {
1557  AnimControl *control = _anim_controls.get_anim(_anim_index);
1558  nassertv(control != nullptr);
1559  control->pose(control->get_frame() + 1);
1560 }
1561 
1562 
1563 /**
1564  * The static task function.
1565  */
1566 AsyncTask::DoneStatus WindowFramework::
1567 st_update_anim_controls(GenericAsyncTask *, void *data) {
1568  WindowFramework *self = (WindowFramework *)data;
1569  self->update_anim_controls();
1570  return AsyncTask::DS_cont;
1571 }
1572 
1573 
1574 /**
1575  * The static event handler function.
1576  */
1577 void WindowFramework::
1578 st_back_button(const Event *, void *data) {
1579  WindowFramework *self = (WindowFramework *)data;
1580  self->back_button();
1581 }
1582 
1583 /**
1584  * The static event handler function.
1585  */
1586 void WindowFramework::
1587 st_pause_button(const Event *, void *data) {
1588  WindowFramework *self = (WindowFramework *)data;
1589  self->pause_button();
1590 }
1591 
1592 /**
1593  * The static event handler function.
1594  */
1595 void WindowFramework::
1596 st_play_button(const Event *, void *data) {
1597  WindowFramework *self = (WindowFramework *)data;
1598  self->play_button();
1599 }
1600 
1601 /**
1602  * The static event handler function.
1603  */
1604 void WindowFramework::
1605 st_forward_button(const Event *, void *data) {
1606  WindowFramework *self = (WindowFramework *)data;
1607  self->forward_button();
1608 }
Geom
A container for geometry primitives.
Definition: geom.h:54
NodePath::clear_texture
void clear_texture()
Completely removes any texture adjustment that may have been set via set_texture() or set_texture_off...
Definition: nodePath.cxx:3002
geomVertexData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
MouseButton::one
static ButtonHandle one()
Returns the ButtonHandle associated with the first mouse button.
Definition: mouseButton.cxx:43
ModifierButtons
This class monitors the state of a number of individual buttons and tracks whether each button is kno...
Definition: modifierButtons.h:26
NodePath::clear
void clear()
Sets this NodePath to the empty NodePath.
Definition: nodePath.I:119
EventHandler::remove_hooks_with
bool remove_hooks_with(void *data)
Removes all CallbackFunction hooks that have the indicated pointer as the associated data pointer.
Definition: eventHandler.cxx:317
texturePool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FrameBufferProperties
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
Definition: frameBufferProperties.h:26
shadeModelAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowFramework::load_model
NodePath load_model(const NodePath &parent, Filename filename)
Loads up the indicated model and returns the new NodePath, or the empty NodePath if the model could n...
Definition: windowFramework.cxx:585
Loader
A convenient class for loading models from disk, in bam or egg format (or any of a number of other fo...
Definition: loader.h:42
rescaleNormalAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowFramework::set_two_sided
void set_two_sided(bool enable)
Forces two-sided rendering (true) or restores default rendering (false).
Definition: windowFramework.cxx:954
AnimInterface::set_play_rate
set_play_rate
Changes the rate at which the animation plays.
Definition: animInterface.h:66
perspectiveLens.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
MouseWatcher
This TFormer maintains a list of rectangular regions on the screen that are considered special mouse ...
Definition: mouseWatcher.h:61
LoaderFileType
This is the base class for a family of scene-graph file types that the Loader supports.
Definition: loaderFileType.h:33
pvector< Filename >
NodePath::clear_color_scale
void clear_color_scale()
Completely removes any color scale from the referenced node.
Definition: nodePath.cxx:2040
AnimInterface::get_num_frames
get_num_frames
Returns the number of frames in the animation.
Definition: animInterface.h:68
PGTop::set_mouse_watcher
void set_mouse_watcher(MouseWatcher *watcher)
Sets the MouseWatcher pointer that the PGTop object registers its PG items with.
Definition: pgTop.cxx:132
Filename::from_os_specific
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition: filename.cxx:328
GeomVertexData
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
Definition: geomVertexData.h:68
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BoundingSphere
This defines a bounding sphere, consisting of a center and a radius.
Definition: boundingSphere.h:25
Lens::set_aspect_ratio
set_aspect_ratio
Sets the aspect ratio of the lens.
Definition: lens.h:106
WindowFramework::adjust_dimensions
void adjust_dimensions()
Reevaluates the dimensions of the window, presumably after the window has been resized by the user or...
Definition: windowFramework.cxx:794
DrawableRegion::set_clear_color_active
void set_clear_color_active(bool clear_color_active)
Toggles the flag that indicates whether the color buffer should be cleared every frame.
Definition: drawableRegion.I:80
buttonThrower.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
AnimControlCollection::get_anim
get_anim
Returns the nth AnimControl associated with this collection.
Definition: animControlCollection.h:45
Camera
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
PGItem
This is the base class for all the various kinds of gui widget objects.
Definition: pgItem.h:53
pnmImage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowFramework::load_models
bool load_models(const NodePath &parent, int argc, char *argv[], int first_arg=1)
Loads up all the model files listed in the indicated argument list.
Definition: windowFramework.cxx:548
NodePath::set_hpr
void set_hpr(PN_stdfloat h, PN_stdfloat p, PN_stdfloat r)
Sets the rotation component of the transform, leaving translation and scale untouched.
Definition: nodePath.I:651
WindowFramework::get_camera_group
NodePath get_camera_group()
Returns the node above the collection of 3-d cameras in the scene graph.
Definition: windowFramework.cxx:225
WindowFramework::enable_keyboard
void enable_keyboard()
Creates a ButtonThrower to listen to button presses and throw them as events.
Definition: windowFramework.cxx:405
BamFile::open_read
bool open_read(const Filename &bam_filename, bool report_errors=true)
Attempts to open the indicated filename for reading.
Definition: bamFile.cxx:51
GenericAsyncTask
Associates a generic C-style function pointer with an AsyncTask object.
Definition: genericAsyncTask.h:26
GraphicsEngine::make_output
GraphicsOutput * make_output(GraphicsPipe *pipe, const std::string &name, int sort, const FrameBufferProperties &fb_prop, const WindowProperties &win_prop, int flags, GraphicsStateGuardian *gsg=nullptr, GraphicsOutput *host=nullptr)
Creates a new window (or buffer) and returns it.
Definition: graphicsEngine.cxx:257
WindowFramework
This encapsulates the data that is normally associated with a single window, or with a single display...
Definition: windowFramework.h:51
NodePath::set_texture_off
void set_texture_off(int priority=0)
Sets the geometry at this level and below to render using no texture, on any stage.
Definition: nodePath.cxx:2961
PandaFramework::get_task_mgr
AsyncTaskManager & get_task_mgr()
Returns the Task Manager object that manages tasks in the framework.
Definition: pandaFramework.I:52
mouseButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath::set_light
void set_light(const NodePath &light, int priority=0)
Adds the indicated Light or PolylightNode to the list of lights that illuminate geometry at this node...
Definition: nodePath.cxx:2194
WindowFramework::set_one_sided_reverse
void set_one_sided_reverse(bool enable)
Toggles one-sided reverse mode.
Definition: windowFramework.cxx:978
pandaFramework.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowFramework::center_trackball
void center_trackball(const NodePath &object)
Centers the trackball on the indicated object, and scales the trackball motion suitably.
Definition: windowFramework.cxx:461
FrameRateMeter
This is a special TextNode that automatically updates itself with the current frame rate.
Definition: frameRateMeter.h:37
Filename::get_basename_wo_extension
std::string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
Definition: filename.I:386
GeomVertexWriter::add_data3
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row.
Definition: geomVertexWriter.I:1132
colorAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowFramework::next_anim_control
void next_anim_control()
Rotates the animation controls through all of the available animations.
Definition: windowFramework.cxx:743
GeomVertexWriter
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
Definition: geomVertexWriter.h:55
RenderAttrib
This is the base class for a number of render attributes (other than transform) that may be set on sc...
Definition: renderAttrib.h:51
DisplayRegion
A rectangular subregion within a window for rendering into.
Definition: displayRegion.h:57
AnimControlCollection::loop_all
void loop_all(bool restart)
Starts all animations looping.
Definition: animControlCollection.cxx:179
GraphicsOutput::make_display_region
DisplayRegion * make_display_region()
Creates a new DisplayRegion that covers the entire window.
Definition: graphicsOutput.I:513
PGSliderBar
This is a particular kind of PGItem that draws a little bar with a slider that moves from left to rig...
Definition: pgSliderBar.h:31
Texture
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
WindowProperties
A container for the various kinds of properties we might ask to have on a graphics window before we o...
Definition: windowProperties.h:29
filename.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Trackball
Trackball acts like Performer in trackball mode.
Definition: trackball.h:35
Lens::get_fov
get_fov
Returns the horizontal and vertical film size of the virtual film.
Definition: lens.h:101
auto_bind.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextNode
The primary interface to this module.
Definition: textNode.h:48
PNMImage::read
bool read(const Filename &filename, PNMFileType *type=nullptr, bool report_unknown_type=true)
Reads the indicated image filename.
Definition: pnmImage.cxx:278
NodePath::not_found
static NodePath not_found()
Creates a NodePath with the ET_not_found error type set.
Definition: nodePath.I:129
keyboardButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VirtualFileSystem::exists
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists.
Definition: virtualFileSystem.I:18
orthographicLens.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LoaderOptions
Specifies parameters that may be passed to the loader.
Definition: loaderOptions.h:23
PNMImage
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
Definition: pnmImage.h:58
WindowFramework::loop_animations
void loop_animations(int hierarchy_match_flags=PartGroup::HMF_ok_part_extra|PartGroup::HMF_ok_anim_extra)
Looks for characters and their matching animation files in the scene graph; binds and loops any match...
Definition: windowFramework.cxx:713
TexturePool
This is the preferred interface for loading textures from image files.
Definition: texturePool.h:37
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
WindowFramework::get_shuttle_controls_font
static TextFont * get_shuttle_controls_font()
Returns a font that contains the shuttle controls icons.
Definition: windowFramework.cxx:1107
GraphicsEngine
This class is the main interface to controlling the render process.
Definition: graphicsEngine.h:53
bamFile.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowFramework::split_window
WindowFramework * split_window(SplitType split_type=ST_default)
Divides the window into two display regions, each of which gets its own trackball and keyboard events...
Definition: windowFramework.cxx:846
WindowFramework::set_background_type
void set_background_type(BackgroundType type)
Sets the background of the window to one of the pre-canned background types (or to BT_other,...
Definition: windowFramework.cxx:1048
PandaFramework
This class serves to provide a high-level framework for basic applications that use Panda in simple w...
Definition: pandaFramework.h:38
AmbientLight
A light source that seems to illuminate all points in space at once.
Definition: ambientLight.h:26
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
GeomNode
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
WindowFramework::set_perpixel
void set_perpixel(bool enable)
Turns per-pixel lighting on (true) or off (false).
Definition: windowFramework.cxx:1026
WindowFramework::get_pixel_2d
NodePath get_pixel_2d()
Returns a special root that uses units in pixels that are relative to the window.
Definition: windowFramework.cxx:337
GraphicsOutput
This is a base class for the various different classes that represent the result of a frame of render...
Definition: graphicsOutput.h:63
NodePath::set_scale
void set_scale(PN_stdfloat scale)
Sets the scale component of the transform, leaving translation and rotation untouched.
Definition: nodePath.I:675
NodePath::set_depth_write
void set_depth_write(bool depth_write, int priority=0)
Specifically sets or disables the writing to the depth buffer on this particular node.
Definition: nodePath.cxx:4563
NodePath::clear_render_mode
void clear_render_mode()
Completely removes any render mode adjustment that may have been set on this node via set_render_mode...
Definition: nodePath.cxx:4372
Event
A named event, possibly with parameters.
Definition: event.h:33
displayRegion.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode::set_attrib
void set_attrib(const RenderAttrib *attrib, int override=0)
Adds the indicated render attribute to the scene graph on this node.
Definition: pandaNode.cxx:938
AnimControlCollection::get_num_anims
get_num_anims
Returns the number of AnimControls associated with this collection.
Definition: animControlCollection.h:45
TexturePool::load_texture
static Texture * load_texture(const Filename &filename, int primary_file_num_channels=0, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads the given filename up into a texture, if it has not already been loaded, and returns the new te...
Definition: texturePool.I:47
PGFrameStyle::set_width
void set_width(PN_stdfloat x, PN_stdfloat y)
Sets the width parameter, which has meaning only for certain frame types.
Definition: pgFrameStyle.I:139
PGFrameStyle
Definition: pgFrameStyle.h:29
VirtualFileSystem
A hierarchy of directories and files that appears to be one continuous file system,...
Definition: virtualFileSystem.h:40
Lens::set_film_size
set_film_size
Sets the horizontal size of the film without changing its shape.
Definition: lens.h:82
NodePath::set_color_scale
void set_color_scale(const LVecBase4 &scale, int priority=0)
Sets the color scale component of the transform, leaving translation and rotation untouched.
Definition: nodePath.cxx:2080
WindowFramework::make_camera
NodePath make_camera()
Makes a new 3-d camera for the window.
Definition: windowFramework.cxx:1129
TransformState
Indicates a coordinate-system transform on vertices.
Definition: transformState.h:54
Lens::get_default_far
static PN_stdfloat get_default_far()
Returns the default far plane distance that will be assigned to each newly- created lens.
Definition: lens.cxx:157
PGTop
The "top" node of the new Panda GUI system.
Definition: pgTop.h:38
GeometricBoundingVolume
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
Definition: geometricBoundingVolume.h:29
NodePath::set_depth_test
void set_depth_test(bool depth_test, int priority=0)
Specifically sets or disables the testing of the depth buffer on this particular node.
Definition: nodePath.cxx:4506
AnimInterface::loop
void loop(bool restart)
Starts the entire animation looping.
Definition: animInterface.I:45
boundingSphere.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DisplayRegion::set_dimensions
set_dimensions
Changes the portion of the framebuffer this DisplayRegion corresponds to.
Definition: displayRegion.h:83
GeomVertexFormat::get_v3n3cpt2
static const GeomVertexFormat * get_v3n3cpt2()
Returns a standard vertex format with a 2-component texture coordinate pair, a packed color,...
Definition: geomVertexFormat.I:315
GeomVertexFormat::get_v3t2
static const GeomVertexFormat * get_v3t2()
Returns a standard vertex format with a 2-component texture coordinate pair and a 3-component vertex ...
Definition: geomVertexFormat.I:269
cullFaceAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomTriangles.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexWriter::add_data2
void add_data2(PN_stdfloat x, PN_stdfloat y)
Sets the write row to a particular 2-component value, and advances the write row.
Definition: geomVertexWriter.I:1100
GraphicsPipe
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
Lens::set_far
set_far
Defines the position of the far plane (or cylinder, sphere, whatever).
Definition: lens.h:114
Lens
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
WindowFramework::get_render_2d
NodePath get_render_2d()
Returns the root of the 2-d scene graph.
Definition: windowFramework.cxx:253
transform2sg.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DirectionalLight
A light shining from infinitely far away in a particular direction, like sunlight.
Definition: directionalLight.h:25
ambientLight.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
windowFramework.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PerspectiveLens
A perspective-type lens: a normal camera.
Definition: perspectiveLens.h:25
geom.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
staticTextFont.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TexturePool::get_global_ptr
static TexturePool * get_global_ptr()
Initializes and/or returns the global pointer to the one TexturePool object in the system.
Definition: texturePool.cxx:146
PGFrameStyle::set_color
void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a)
Sets the dominant color of the frame.
Definition: pgFrameStyle.I:80
OrthographicLens
An orthographic lens.
Definition: orthographicLens.h:30
GeomVertexFormat
This class defines the physical layout of the vertex data stored within a Geom.
Definition: geomVertexFormat.h:55
LoaderFileTypeRegistry
This class maintains the set of all known LoaderFileTypes in the universe.
Definition: loaderFileTypeRegistry.h:28
WindowFramework::set_lighting
void set_lighting(bool enable)
Turns lighting on (true) or off (false).
Definition: windowFramework.cxx:1002
GeomTriangles
Defines a series of disconnected triangles.
Definition: geomTriangles.h:23
AnimControlCollection::get_anim_name
get_anim_name
Returns the name of the nth AnimControl associated with this collection.
Definition: animControlCollection.h:46
PT
PT(PandaNode) WindowFramework
Loads the indicated image file as a texture, and creates a polygon to render it.
Definition: windowFramework.cxx:1186
AsyncTaskManager::add
void add(AsyncTask *task)
Adds the indicated task to the active queue.
Definition: asyncTaskManager.cxx:181
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
Lens::set_near
set_near
Defines the position of the near plane (or cylinder, sphere, whatever).
Definition: lens.h:113
config_framework.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EventParameter
An optional parameter associated with an event.
Definition: eventParameter.h:35
BamFile
The principle public interface to reading and writing Bam disk files.
Definition: bamFile.h:41
PGButton
This is a particular kind of PGItem that is specialized to behave like a normal button object.
Definition: pgButton.h:29
Lens::get_default_near
static PN_stdfloat get_default_near()
Returns the default near plane distance that will be assigned to each newly-created lens.
Definition: lens.cxx:148
WindowFramework::get_render
NodePath get_render()
Returns the root of the 3-d scene graph.
Definition: windowFramework.cxx:236
PandaFramework::get_mouse
NodePath get_mouse(GraphicsOutput *window)
Returns a NodePath to the MouseAndKeyboard associated with the indicated GraphicsWindow object.
Definition: pandaFramework.cxx:238
textureAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pgTop.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
VirtualFileSystem::get_global_ptr
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
Definition: virtualFileSystem.cxx:741
AnimInterface::get_play_rate
get_play_rate
Returns the rate at which the animation plays.
Definition: animInterface.h:66
virtualFileSystem.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
texture.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EventHandler::add_hook
bool add_hook(const std::string &event_name, EventFunction *function)
Adds the indicated function to the list of those that will be called when the named event is thrown.
Definition: eventHandler.cxx:166
NodePath::set_material_off
void set_material_off(int priority=0)
Sets the geometry at this level and below to render using no material.
Definition: nodePath.cxx:4128
AnimControl
Controls the timing of a character animation.
Definition: animControl.h:38
WindowFramework::load_default_model
NodePath load_default_model(const NodePath &parent)
Loads our favorite blue triangle.
Definition: windowFramework.cxx:656
PGFrameStyle::set_type
void set_type(Type type)
Sets the basic type of frame.
Definition: pgFrameStyle.I:64
loaderFileTypeRegistry.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ModifierButtons::add_button
bool add_button(ButtonHandle button)
Adds the indicated button to the set of buttons that will be monitored for upness and downness.
Definition: modifierButtons.cxx:180
NodePath::set_two_sided
void set_two_sided(bool two_sided, int priority=0)
Specifically sets or disables two-sided rendering mode on this particular node.
Definition: nodePath.cxx:4445
SceneGraphAnalyzerMeter
This is a special TextNode that automatically updates itself with output from a SceneGraphAnalyzer in...
Definition: sceneGraphAnalyzerMeter.h:39
deg_2_rad.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
WindowFramework::get_aspect_2d
NodePath get_aspect_2d()
Returns the node under the 2-d scene graph that is scaled to suit the window's aspect ratio.
Definition: windowFramework.cxx:299
GeomTristrips
Defines a series of triangle strips.
Definition: geomTristrips.h:23
PandaFramework::get_event_handler
EventHandler & get_event_handler()
Returns the EventHandler object that serves events in the framework.
Definition: pandaFramework.I:44
AnimInterface::stop
void stop()
Stops a currently playing or looping animation right where it is.
Definition: animInterface.I:91
Light::set_color
set_color
Sets the basic color of the light.
Definition: light.h:49
geomTristrips.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath::attach_new_node
NodePath attach_new_node(PandaNode *node, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Attaches a new node, with or without existing parents, to the scene graph below the referenced node o...
Definition: nodePath.cxx:563
loader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LoaderFileTypeRegistry::get_global_ptr
static LoaderFileTypeRegistry * get_global_ptr()
Returns a pointer to the global LoaderFileTypeRegistry object.
Definition: loaderFileTypeRegistry.cxx:270
DisplayRegion::get_window
get_window
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
Definition: displayRegion.h:88
WindowFramework::get_mouse
NodePath get_mouse()
Returns the node in the data graph corresponding to the mouse associated with this window.
Definition: windowFramework.cxx:364
geomNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsStateGuardian
Encapsulates all the communication with a particular instance of a given rendering backend.
Definition: graphicsStateGuardian.h:65
geomVertexFormat.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lightAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextFont
An encapsulation of a font; i.e.
Definition: textFont.h:32
directionalLight.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
dSearchPath.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaFramework::set_background_type
void set_background_type(WindowFramework::BackgroundType type)
Sets the background type of all windows.
Definition: pandaFramework.cxx:644
WindowFramework::get_button_thrower
NodePath get_button_thrower()
Returns the node in the data graph corresponding to the ButtonThrower object associated with this win...
Definition: windowFramework.cxx:396
NodePath::clear_light
void clear_light()
Completely removes any lighting operations that may have been set via set_light() or set_light_off() ...
Definition: nodePath.cxx:2306
NodePath::clear_two_sided
void clear_two_sided()
Completely removes any two-sided adjustment that may have been set on this node via set_two_sided().
Definition: nodePath.cxx:4464
BoundingVolume
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
Definition: boundingVolume.h:41
WindowFramework::setup_trackball
void setup_trackball()
Sets up the mouse to trackball around the camera.
Definition: windowFramework.cxx:434
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
StaticTextFont
A StaticTextFont is loaded up from a model that was previously generated via egg-mkfont,...
Definition: staticTextFont.h:38
NodePath::node
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
GeomNode::add_geom
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition: geomNode.cxx:586
AsyncTaskManager::remove
bool remove(AsyncTask *task)
Removes the indicated task from the active queue.
Definition: asyncTaskManager.cxx:311
AnimInterface::pose
void pose(double frame)
Sets the animation to the indicated frame and holds it there.
Definition: animInterface.I:103
Filename::get_extension
std::string get_extension() const
Returns the file extension.
Definition: filename.I:400
WindowFramework::stagger_animations
void stagger_animations()
Walks through all the animations that were bound by loop_animations() and staggers their play rate sl...
Definition: windowFramework.cxx:727
WindowFramework::set_anim_controls
void set_anim_controls(bool enable)
Creates an onscreen animation slider for frame-stepping through the animations.
Definition: windowFramework.cxx:777
GraphicsWindow
A window, fullscreen or on a desktop, into which a graphics device sends its output for interactive d...
Definition: graphicsWindow.h:40
GeomVertexArrayFormat
This describes the structure of a single array within a Geom data.
Definition: geomVertexArrayFormat.h:47
TexturePool::write_texture_types
void write_texture_types(std::ostream &out, int indent_level) const
Outputs a list of the available texture types to the indicated output stream.
Definition: texturePool.cxx:113
NodePath::remove_node
void remove_node(Thread *current_thread=Thread::get_current_thread())
Disconnects the referenced node from the scene graph.
Definition: nodePath.cxx:591
TexturePool::get_texture_type
MakeTextureFunc * get_texture_type(const std::string &extension) const
Returns the factory function to construct a new texture of the type appropriate for the indicated fil...
Definition: texturePool.cxx:84
Transform2SG
input: Transform (matrix)
Definition: transform2sg.h:28
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
AnimInterface::get_frame
get_frame
Returns the current integer frame number.
Definition: animInterface.h:70
LoaderFileTypeRegistry::get_type_from_extension
LoaderFileType * get_type_from_extension(const std::string &extension)
Determines the type of the file based on the indicated extension (without a leading dot).
Definition: loaderFileTypeRegistry.cxx:173
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
ButtonThrower
Throws Panda Events for button down/up events generated within the data graph.
Definition: buttonThrower.h:35
Filename::is_fully_qualified
bool is_fully_qualified() const
Returns true if the filename is fully qualified, e.g.
Definition: filename.I:562
NodePath::is_empty
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
WindowFramework::set_wireframe
void set_wireframe(bool enable, bool filled=false)
Forces wireframe state (true) or restores default rendering (false).
Definition: windowFramework.cxx:892
NodePath::set_render_mode_wireframe
void set_render_mode_wireframe(int priority=0)
Sets up the geometry at this level and below (unless overridden) to render in wireframe mode.
Definition: nodePath.cxx:4290
WindowFramework::set_texture
void set_texture(bool enable)
Forces textures off (false) or restores default rendering (true).
Definition: windowFramework.cxx:934
auto_bind
void auto_bind(PandaNode *root_node, AnimControlCollection &controls, int hierarchy_match_flags)
Walks the scene graph or subgraph beginning at the indicated node, and attempts to bind any AnimBundl...
Definition: auto_bind.cxx:123