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