Panda3D
 All Classes Functions Variables Enumerations
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 ////////////////////////////////////////////////////////////////////
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 ////////////////////////////////////////////////////////////////////
462 void WindowFramework::
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 ////////////////////////////////////////////////////////////////////
491 void WindowFramework::
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  if (!extension.empty()) {
644  LoaderFileType *model_type =
645  reg->get_type_from_extension(extension);
646  if (model_type == (LoaderFileType *)NULL) {
647  // The extension isn't a known model file type; is it a known
648  // image file extension?
649  if (extension == "txo" || downcase(extension) == "dds") {
650  // A texture object. Not exactly an image, but certainly a
651  // texture.
652  is_image = true;
653 
654  } else {
655  TexturePool *texture_pool = TexturePool::get_global_ptr();
656  if (texture_pool->get_texture_type(extension) != NULL) {
657  // It is a known image file extension.
658  is_image = true;
659  }
660  }
661  }
662  }
663 
664  LoaderOptions options = PandaFramework::_loader_options;
665  if (search) {
666  options.set_flags(options.get_flags() | LoaderOptions::LF_search);
667  } else {
668  options.set_flags(options.get_flags() & ~LoaderOptions::LF_search);
669  }
670 
671  Loader loader;
672  PT(PandaNode) node;
673  if (is_image) {
674  node = load_image_as_model(filename);
675  } else {
676  node = loader.load_sync(filename, options);
677  }
678 
679  if (node == (PandaNode *)NULL) {
680  nout << "Unable to load " << filename << "\n";
681  return NodePath::not_found();
682  }
683 
684  return parent.attach_new_node(node);
685 }
686 
687 ////////////////////////////////////////////////////////////////////
688 // Function: WindowFramework::load_default_model
689 // Access: Public
690 // Description: Loads our favorite blue triangle. This is intended
691 // to provide some default geometry to have *something*
692 // to look at for testing, when no other models are
693 // provided.
694 ////////////////////////////////////////////////////////////////////
696 load_default_model(const NodePath &parent) {
697  CPT(RenderState) state = RenderState::make_empty();
698 
699  state = state->add_attrib(ColorAttrib::make_flat(LColor(0.5, 0.5, 1.0, 1.0)));
700 
701  // Get the default texture to apply to the triangle; it's compiled
702  // into the code these days.
703  string rock_floor_string((const char *)rock_floor, rock_floor_len);
704  istringstream rock_floor_strm(rock_floor_string);
705  PNMImage rock_floor_pnm;
706  if (rock_floor_pnm.read(rock_floor_strm, "rock-floor.rgb")) {
707  PT(Texture) tex = new Texture;
708  tex->set_name("rock-floor.rgb");
709  tex->load(rock_floor_pnm);
710  tex->set_minfilter(SamplerState::FT_linear);
711  tex->set_magfilter(SamplerState::FT_linear);
712  state = state->add_attrib(TextureAttrib::make(tex));
713  }
714 
715  GeomNode *geomnode = new GeomNode("tri");
716 
717  PT(GeomVertexData) vdata = new GeomVertexData
718  ("tri", GeomVertexFormat::get_v3n3cpt2(),
719  Geom::UH_static);
720  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
721  GeomVertexWriter normal(vdata, InternalName::get_normal());
722  GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
723 
724  vertex.add_data3(LVertex::rfu(0.0, 0.0, 0.0));
725  vertex.add_data3(LVertex::rfu(1.0, 0.0, 0.0));
726  vertex.add_data3(LVertex::rfu(0.0, 0.0, 1.0));
727 
728  normal.add_data3(LNormal::back());
729  normal.add_data3(LNormal::back());
730  normal.add_data3(LNormal::back());
731 
732  texcoord.add_data2(0.0, 0.0);
733  texcoord.add_data2(1.0, 0.0);
734  texcoord.add_data2(0.0, 1.0);
735 
736  PT(GeomTriangles) tri = new GeomTriangles(Geom::UH_static);
737  tri->add_consecutive_vertices(0, 3);
738  tri->close_primitive();
739 
740  PT(Geom) geom = new Geom(vdata);
741  geom->add_primitive(tri);
742 
743  geomnode->add_geom(geom, state);
744 
745  return parent.attach_new_node(geomnode);
746 }
747 
748 ////////////////////////////////////////////////////////////////////
749 // Function: WindowFramework::loop_animations
750 // Access: Public
751 // Description: Looks for characters and their matching animation
752 // files in the scene graph; binds and loops any
753 // matching animations found.
754 ////////////////////////////////////////////////////////////////////
755 void WindowFramework::
756 loop_animations(int hierarchy_match_flags) {
757  // If we happened to load up both a character file and its matching
758  // animation file, attempt to bind them together now and start the
759  // animations looping.
760  auto_bind(get_render().node(), _anim_controls, hierarchy_match_flags);
761  _anim_controls.loop_all(true);
762 }
763 
764 ////////////////////////////////////////////////////////////////////
765 // Function: WindowFramework::stagger_animations
766 // Access: Public
767 // Description: Walks through all the animations that were bound by
768 // loop_animations() and staggers their play rate
769 // slightly so that they will not remain perfectly in
770 // sync.
771 ////////////////////////////////////////////////////////////////////
774  for (int i = 0; i < _anim_controls.get_num_anims(); ++i) {
775  AnimControl *control = _anim_controls.get_anim(i);
776  double r = (double)rand() / (double)RAND_MAX;
777  r = r * 0.2 + 0.9;
778  control->set_play_rate(r);
779  }
780 }
781 
782 ////////////////////////////////////////////////////////////////////
783 // Function: WindowFramework::next_anim_control
784 // Access: Public
785 // Description: Rotates the animation controls through all of the
786 // available animations. If the animation controls are
787 // not already enabled, enables them at sets to the
788 // first animation; if they are already enabled, steps
789 // to the next animation; if that is the last animation,
790 // disables the animation controls.
791 ////////////////////////////////////////////////////////////////////
794  if (_anim_controls_enabled) {
795  destroy_anim_controls();
796 
797  if (_anim_controls.get_num_anims() == 0) {
798  set_anim_controls(false);
799  return;
800  }
801 
802  // Stop the active animation.
803  pause_button();
804  ++_anim_index;
805 
806  if (_anim_index >= _anim_controls.get_num_anims()) {
807  set_anim_controls(false);
808  _anim_controls.loop_all(true);
809  } else {
810  create_anim_controls();
811  play_button();
812  }
813  } else {
814  _anim_index = 0;
815  set_anim_controls(true);
816  if (_anim_controls.get_num_anims() > 0) {
817  play_button();
818  }
819  }
820 }
821 
822 ////////////////////////////////////////////////////////////////////
823 // Function: WindowFramework::set_anim_controls
824 // Access: Public
825 // Description: Creates an onscreen animation slider for
826 // frame-stepping through the animations.
827 ////////////////////////////////////////////////////////////////////
829 set_anim_controls(bool enable) {
830  _anim_controls_enabled = enable;
831  if (_anim_controls_enabled) {
832  create_anim_controls();
833 
834  } else {
835  destroy_anim_controls();
836  }
837 }
838 
839 ////////////////////////////////////////////////////////////////////
840 // Function: WindowFramework::adjust_dimensions
841 // Access: Public
842 // Description: Reevaluates the dimensions of the window,
843 // presumably after the window has been resized by the
844 // user or some other force. Adjusts the render film
845 // size, aspect2d scale (aspect ratio) and the
846 // dimensionsas of pixel_2d according to the
847 // new window shape, or new config setting.
848 ////////////////////////////////////////////////////////////////////
851  PN_stdfloat this_aspect_ratio = aspect_ratio;
852 
853  int x_size = 0, y_size = 0;
854  if (_window->has_size()) {
855  x_size = _window->get_sbs_left_x_size();
856  y_size = _window->get_sbs_left_y_size();
857  }
858 
859  if (this_aspect_ratio == 0.0f) {
860  // An aspect ratio of 0.0 means to try to infer it.
861  this_aspect_ratio = 1.0f;
862  if (y_size != 0) {
863  this_aspect_ratio = (float)x_size / (float)y_size;
864  }
865  }
866 
867  if (!_aspect_2d.is_empty()) {
868  _aspect_2d.set_scale(1.0f / this_aspect_ratio, 1.0f, 1.0f);
869  }
870 
871  if (!_pixel_2d.is_empty()) {
872  // Adjust the pixel 2d scale
873  if (x_size > 0){
874  _pixel_2d.set_sx(2.0f / (float)x_size);
875  }
876  _pixel_2d.set_sy(1.0f);
877  if (y_size > 0){
878  _pixel_2d.set_sz(2.0f / (float)y_size);
879  }
880  }
881 
882  Cameras::iterator ci;
883  for (ci = _cameras.begin(); ci != _cameras.end(); ++ci) {
884  Lens *lens = (*ci)->get_lens();
885  if (lens != (Lens *)NULL) {
886  if (y_size != 0) {
887  lens->set_film_size(x_size, y_size);
888  } else {
889  lens->set_aspect_ratio(this_aspect_ratio);
890  }
891  }
892  }
893 }
894 
895 ////////////////////////////////////////////////////////////////////
896 // Function: WindowFramework::split_window
897 // Access: Public
898 // Description: Divides the window into two display regions, each of
899 // which gets its own trackball and keyboard events.
900 // The new window pointer is returned.
901 //
902 // There is not an interface for recombining divided
903 // windows.
904 ////////////////////////////////////////////////////////////////////
906 split_window(SplitType split_type) {
907  DisplayRegion *new_region = NULL;
908 
909  if (split_type == ST_default) {
910  // Choose either horizontal or vertical according to the largest
911  // dimension.
912 
913  if (_display_region_3d->get_pixel_width() >
914  _display_region_3d->get_pixel_height()) {
915  split_type = ST_horizontal;
916  } else {
917  split_type = ST_vertical;
918  }
919  }
920 
921  PN_stdfloat left, right, bottom, top;
922  _display_region_3d->get_dimensions(left, right, bottom, top);
923  new_region = _display_region_3d->get_window()->make_display_region();
924 
925  if (split_type == ST_vertical) {
926  _display_region_3d->set_dimensions(left, right, bottom, (top + bottom) / 2.0f);
927  if (_display_region_2d != (DisplayRegion *)NULL) {
928  _display_region_2d->set_dimensions(left, right, bottom, (top + bottom) / 2.0f);
929  }
930 
931  new_region->set_dimensions(left, right, (top + bottom) / 2.0f, top);
932 
933  } else {
934  _display_region_3d->set_dimensions(left, (left + right) / 2.0f, bottom, top);
935  if (_display_region_2d != (DisplayRegion *)NULL) {
936  _display_region_2d->set_dimensions(left, (left + right) / 2.0f, bottom, top);
937  }
938 
939  new_region->set_dimensions((left + right) / 2.0f, right, bottom, top);
940  }
941 
942  PT(WindowFramework) wf = new WindowFramework(*this, new_region);
943  _panda_framework->_windows.push_back(wf);
944 
945  return wf;
946 }
947 
948 ////////////////////////////////////////////////////////////////////
949 // Function: WindowFramework::set_wireframe
950 // Access: Public
951 // Description: Forces wireframe state (true) or restores default
952 // rendering (false).
953 ////////////////////////////////////////////////////////////////////
954 void WindowFramework::
955 set_wireframe(bool enable, bool filled) {
956  if (enable == _wireframe_enabled && filled == _wireframe_filled) {
957  return;
958  }
959 
960  NodePath render = get_render();
961 
962  if (!_two_sided_enabled) {
963  render.clear_two_sided();
964  }
965 
966  if (enable) {
967  if (filled) {
968  render.set_attrib(RenderModeAttrib::make(
969  RenderModeAttrib::M_filled_wireframe,
970  1.4f, false, LColor(1, 1, 1, .5f)),
971  override_priority);
972  // Darken the scene so that the wireframe is clearly visible,
973  // even when the scene is completely white.
974  render.set_color_scale(LColor(0.7f, 0.7f, 0.7f, 1), override_priority);
975  } else {
976  render.set_render_mode_wireframe(override_priority);
977  render.set_two_sided(true, override_priority);
978  render.clear_color_scale();
979  }
980  } else {
981  render.clear_render_mode();
982  if (_one_sided_reverse_enabled) {
983  CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse();
984  render.node()->set_attrib(attrib);
985  }
986  render.clear_color_scale();
987  }
988 
989  _wireframe_enabled = enable;
990  _wireframe_filled = filled;
991 }
992 
993 ////////////////////////////////////////////////////////////////////
994 // Function: WindowFramework::set_texture
995 // Access: Public
996 // Description: Forces textures off (false) or restores default
997 // rendering (true).
998 ////////////////////////////////////////////////////////////////////
999 void WindowFramework::
1000 set_texture(bool enable) {
1001  if (enable == _texture_enabled) {
1002  return;
1003  }
1004 
1005  NodePath render = get_render();
1006 
1007  if (!enable) {
1008  render.set_texture_off(override_priority);
1009  } else {
1010  render.clear_texture();
1011  }
1012 
1013  _texture_enabled = enable;
1014 }
1015 
1016 ////////////////////////////////////////////////////////////////////
1017 // Function: WindowFramework::set_two_sided
1018 // Access: Public
1019 // Description: Forces two-sided rendering (true) or restores default
1020 // rendering (false).
1021 ////////////////////////////////////////////////////////////////////
1022 void WindowFramework::
1023 set_two_sided(bool enable) {
1024  if (enable == _two_sided_enabled) {
1025  return;
1026  }
1027 
1028  NodePath render = get_render();
1029 
1030  if (enable) {
1031  render.set_two_sided(true, override_priority);
1032  } else {
1033  if (!_wireframe_enabled) {
1034  render.clear_two_sided();
1035  }
1036  }
1037 
1038  _two_sided_enabled = enable;
1039  _one_sided_reverse_enabled = false;
1040 }
1041 
1042 ////////////////////////////////////////////////////////////////////
1043 // Function: WindowFramework::set_one_sided_reverse
1044 // Access: Public
1045 // Description: Toggles one-sided reverse mode. In this mode, the
1046 // front sides of one-sided polygons are culled instead
1047 // of the back side.
1048 ////////////////////////////////////////////////////////////////////
1049 void WindowFramework::
1050 set_one_sided_reverse(bool enable) {
1051  if (enable == _one_sided_reverse_enabled) {
1052  return;
1053  }
1054 
1055  NodePath render = get_render();
1056 
1057  if (!_wireframe_enabled) {
1058  if (enable) {
1059  CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse();
1060  render.node()->set_attrib(attrib);
1061  } else {
1062  render.clear_two_sided();
1063  }
1064  }
1065 
1066  _two_sided_enabled = false;
1067  _one_sided_reverse_enabled = enable;
1068 }
1069 
1070 ////////////////////////////////////////////////////////////////////
1071 // Function: WindowFramework::set_lighting
1072 // Access: Public
1073 // Description: Turns lighting on (true) or off (false).
1074 ////////////////////////////////////////////////////////////////////
1075 void WindowFramework::
1076 set_lighting(bool enable) {
1077  if (enable == _lighting_enabled) {
1078  return;
1079  }
1080 
1081  NodePath render = get_render();
1082 
1083  if (enable) {
1084  if (!_got_lights) {
1085  setup_lights();
1086  }
1087  render.set_light(_alight);
1088  render.set_light(_dlight);
1089  } else {
1090  render.clear_light();
1091  }
1092 
1093  _lighting_enabled = enable;
1094 }
1095 
1096 ////////////////////////////////////////////////////////////////////
1097 // Function: WindowFramework::set_perpixel
1098 // Access: Public
1099 // Description: Turns per-pixel lighting on (true) or off (false).
1100 ////////////////////////////////////////////////////////////////////
1101 void WindowFramework::
1102 set_perpixel(bool enable) {
1103  if (enable == _perpixel_enabled) {
1104  return;
1105  }
1106 
1107  NodePath render = get_render();
1108 
1109  if (enable) {
1110  render.set_shader_auto();
1111  } else {
1112  render.set_shader_off();
1113  }
1114 
1115  _perpixel_enabled = enable;
1116 }
1117 
1118 ////////////////////////////////////////////////////////////////////
1119 // Function: WindowFramework::set_background_type
1120 // Access: Public
1121 // Description: Sets the background of the window to one of the
1122 // pre-canned background types (or to BT_other, which
1123 // indicates the user intends to set up his own special
1124 // background mode).
1125 ////////////////////////////////////////////////////////////////////
1126 void WindowFramework::
1127 set_background_type(WindowFramework::BackgroundType type) {
1128  _background_type = type;
1129 
1130  if (_display_region_3d == (DisplayRegion *)NULL) {
1131  return;
1132  }
1133 
1134  switch (_background_type) {
1135  case BT_other:
1136  break;
1137 
1138  case BT_default:
1139  _display_region_3d->set_clear_color_active(true);
1140  _display_region_3d->set_clear_depth_active(true);
1141  _display_region_3d->set_clear_stencil_active(true);
1142  _display_region_3d->set_clear_color(_window->get_clear_color());
1143  _display_region_3d->set_clear_depth(_window->get_clear_depth());
1144  _display_region_3d->set_clear_stencil(_window->get_clear_stencil());
1145  break;
1146 
1147  case BT_black:
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(LColor(0.0f, 0.0f, 0.0f, 0.0f));
1152  _display_region_3d->set_clear_depth(1.0f);
1153  _display_region_3d->set_clear_stencil(0);
1154  break;
1155 
1156  case BT_gray:
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.3, 0.3, 0.3, 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_white:
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(1.0f, 1.0f, 1.0f, 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_none:
1175  _display_region_3d->set_clear_color_active(false);
1176  _display_region_3d->set_clear_depth_active(false);
1177  _display_region_3d->set_clear_stencil_active(false);
1178  break;
1179  }
1180 }
1181 
1182 ////////////////////////////////////////////////////////////////////
1183 // Function: WindowFramework::get_shuttle_controls_font
1184 // Access: Public, Static
1185 // Description: Returns a font that contains the shuttle controls
1186 // icons.
1187 ////////////////////////////////////////////////////////////////////
1190  if (_shuttle_controls_font == (TextFont *)NULL) {
1191  PT(TextFont) font;
1192 
1193  string shuttle_controls_string((const char *)shuttle_controls, shuttle_controls_len);
1194  istringstream in(shuttle_controls_string);
1195  BamFile bam_file;
1196  if (bam_file.open_read(in, "shuttle_controls font stream")) {
1197  PT(PandaNode) node = bam_file.read_node();
1198  if (node != (PandaNode *)NULL) {
1199  _shuttle_controls_font = new StaticTextFont(node);
1200  }
1201  }
1202  }
1203 
1204  return _shuttle_controls_font;
1205 }
1206 
1207 ////////////////////////////////////////////////////////////////////
1208 // Function: WindowFramework::make_camera
1209 // Access: Public
1210 // Description: Makes a new 3-d camera for the window.
1211 ////////////////////////////////////////////////////////////////////
1213 make_camera() {
1214  // Finally, we need a camera to associate with the display region.
1215  PT(Camera) camera = new Camera("camera");
1216  NodePath camera_np = get_camera_group().attach_new_node(camera);
1217  _cameras.push_back(camera);
1218 
1219  PT(Lens) lens = new PerspectiveLens;
1220 
1221  if (aspect_ratio != 0.0) {
1222  // If we're given an explict aspect ratio, use it
1223  lens->set_aspect_ratio(aspect_ratio);
1224 
1225  } else {
1226  // Otherwise, infer the aspect ratio from the window size. This
1227  // does assume we have square pixels on our output device.
1228  if (_window->has_size()) {
1229  int x_size = _window->get_sbs_left_x_size();
1230  int y_size = _window->get_sbs_left_y_size();
1231  if (y_size != 0) {
1232  lens->set_film_size(x_size, y_size);
1233  }
1234  }
1235  }
1236 
1237  camera->set_lens(lens);
1238 
1239  return camera_np;
1240 }
1241 
1242 ////////////////////////////////////////////////////////////////////
1243 // Function: WindowFramework::setup_lights
1244 // Access: Protected
1245 // Description: Makes light nodes and attaches them to the camera for
1246 // viewing the scene.
1247 ////////////////////////////////////////////////////////////////////
1248 void WindowFramework::
1249 setup_lights() {
1250  if (_got_lights) {
1251  return;
1252  }
1253 
1254  NodePath camera_group = get_camera_group();
1255  NodePath light_group = camera_group.attach_new_node("lights");
1256 
1257  AmbientLight *alight = new AmbientLight("ambient");
1258  alight->set_color(LColor(0.2, 0.2, 0.2, 1.0f));
1259  DirectionalLight *dlight = new DirectionalLight("directional");
1260  dlight->set_color(LColor(0.8f, 0.8f, 0.8f, 1.0f));
1261 
1262  _alight = light_group.attach_new_node(alight);
1263  _dlight = light_group.attach_new_node(dlight);
1264  _dlight.set_hpr(-10, -20, 0);
1265 
1266  _got_lights = true;
1267 }
1268 
1269 ////////////////////////////////////////////////////////////////////
1270 // Function: WindowFramework::load_image_as_model
1271 // Access: Private
1272 // Description: Loads the indicated image file as a texture, and
1273 // creates a polygon to render it. Returns the new
1274 // model.
1275 ////////////////////////////////////////////////////////////////////
1277 load_image_as_model(const Filename &filename) {
1278  PT(Texture) tex = TexturePool::load_texture(filename);
1279  if (tex == NULL) {
1280  return NULL;
1281  }
1282 
1283  // Yes, it is an image file; make a texture out of it.
1284  tex->set_minfilter(SamplerState::FT_linear_mipmap_linear);
1285  tex->set_magfilter(SamplerState::FT_linear);
1286 
1287  // Ok, now make a polygon to show the texture.
1288  bool has_alpha = true;
1289  LVecBase2 tex_scale = tex->get_tex_scale();
1290 
1291  // Get the size from the original image (the texture may have
1292  // scaled it to make a power of 2).
1293  int x_size = tex->get_orig_file_x_size();
1294  int y_size = tex->get_orig_file_y_size();
1295 
1296  // Choose the dimensions of the polygon appropriately.
1297  PN_stdfloat left,right,top,bottom;
1298  static const PN_stdfloat scale = 10.0;
1299  if (x_size > y_size) {
1300  left = -scale;
1301  right = scale;
1302  top = (scale * y_size) / x_size;
1303  bottom = -(scale * y_size) / x_size;
1304  } else if (y_size != 0) {
1305  left = -(scale * x_size) / y_size;
1306  right = (scale * x_size) / y_size;
1307  top = scale;
1308  bottom = -scale;
1309  } else {
1310  framework_cat.warning()
1311  << "Texture size is 0 0: " << *tex << "\n";
1312 
1313  left = -scale;
1314  right = scale;
1315  top = scale;
1316  bottom = -scale;
1317  }
1318 
1319  PT(GeomNode) card_node = new GeomNode("card");
1320  card_node->set_attrib(TextureAttrib::make(tex));
1321  if (has_alpha) {
1322  card_node->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
1323  }
1324 
1325  bool is_3d = false;
1326  if (tex->get_texture_type() == Texture::TT_3d_texture ||
1327  tex->get_texture_type() == Texture::TT_cube_map) {
1328  // For a 3-d texture, generate a cube, instead of a plain card.
1329  is_3d = true;
1330  }
1331 
1332  CPT(GeomVertexFormat) vformat;
1333  if (!is_3d) {
1334  // Vertices and 2-d texture coordinates, all we need.
1335  vformat = GeomVertexFormat::get_v3t2();
1336 
1337  } else {
1338  // Vertices and 3-d texture coordinates.
1339  vformat = GeomVertexFormat::register_format
1340  (new GeomVertexArrayFormat
1341  (InternalName::get_vertex(), 3,
1342  GeomEnums::NT_stdfloat, GeomEnums::C_point,
1343  InternalName::get_texcoord(), 3,
1344  GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
1345  }
1346 
1347  PT(GeomVertexData) vdata = new GeomVertexData
1348  ("card", vformat, Geom::UH_static);
1349  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
1350  GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
1351 
1352  if (!is_3d) {
1353  // A normal 2-d card.
1354  vertex.add_data3(LVertex::rfu(left, 0.02, top));
1355  vertex.add_data3(LVertex::rfu(left, 0.02, bottom));
1356  vertex.add_data3(LVertex::rfu(right, 0.02, top));
1357  vertex.add_data3(LVertex::rfu(right, 0.02, bottom));
1358 
1359  texcoord.add_data2(0.0f, tex_scale[1]);
1360  texcoord.add_data2(0.0f, 0.0f);
1361  texcoord.add_data2(tex_scale[0], tex_scale[1]);
1362  texcoord.add_data2(tex_scale[0], 0.0f);
1363 
1364  } else {
1365  // The eight vertices of a 3-d cube.
1366  vertex.add_data3(-1.0f, -1.0f, 1.0f); // 0
1367  vertex.add_data3(-1.0f, -1.0f, -1.0f); // 1
1368  vertex.add_data3(1.0f, -1.0f, -1.0f); // 2
1369  vertex.add_data3(1.0f, -1.0f, 1.0f); // 3
1370  vertex.add_data3(1.0f, 1.0f, 1.0f); // 4
1371  vertex.add_data3(1.0f, 1.0f, -1.0f); // 5
1372  vertex.add_data3(-1.0f, 1.0f, -1.0f); // 6
1373  vertex.add_data3(-1.0f, 1.0f, 1.0f); // 7
1374 
1375  texcoord.add_data3(-1.0f, -1.0f, 1.0f); // 0
1376  texcoord.add_data3(-1.0f, -1.0f, -1.0f); // 1
1377  texcoord.add_data3(1.0f, -1.0f, -1.0f); // 2
1378  texcoord.add_data3(1.0f, -1.0f, 1.0f); // 3
1379  texcoord.add_data3(1.0f, 1.0f, 1.0f); // 4
1380  texcoord.add_data3(1.0f, 1.0f, -1.0f); // 5
1381  texcoord.add_data3(-1.0f, 1.0f, -1.0f); // 6
1382  texcoord.add_data3(-1.0f, 1.0f, 1.0f); // 7
1383  }
1384 
1385  PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
1386 
1387  if (!is_3d) {
1388  // The two triangles that make up a quad.
1389  strip->add_consecutive_vertices(0, 4);
1390  strip->close_primitive();
1391 
1392  } else {
1393  // The twelve triangles (six quads) that make up a cube.
1394  strip->add_vertex(7);
1395  strip->add_vertex(0);
1396  strip->add_vertex(4);
1397  strip->add_vertex(3);
1398  strip->close_primitive();
1399 
1400  strip->add_vertex(1);
1401  strip->add_vertex(6);
1402  strip->add_vertex(2);
1403  strip->add_vertex(5);
1404  strip->close_primitive();
1405 
1406  strip->add_vertex(5);
1407  strip->add_vertex(4);
1408  strip->add_vertex(2);
1409  strip->add_vertex(3);
1410  strip->add_vertex(1);
1411  strip->add_vertex(0);
1412  strip->add_vertex(6);
1413  strip->add_vertex(7);
1414  strip->add_vertex(5);
1415  strip->add_vertex(4);
1416  strip->close_primitive();
1417  }
1418 
1419  PT(Geom) geom = new Geom(vdata);
1420  geom->add_primitive(strip);
1421 
1422  card_node->add_geom(geom);
1423 
1424  return card_node.p();
1425 }
1426 
1427 ////////////////////////////////////////////////////////////////////
1428 // Function: WindowFramework::create_anim_controls
1429 // Access: Private
1430 // Description: Creates an onscreen animation slider for
1431 // frame-stepping through the animations.
1432 ////////////////////////////////////////////////////////////////////
1433 void WindowFramework::
1434 create_anim_controls() {
1435  destroy_anim_controls();
1436 
1437  PT(PGItem) group = new PGItem("anim_controls_group");
1438  PGFrameStyle style;
1439  style.set_type(PGFrameStyle::T_flat);
1440  style.set_color(0.0f, 0.0f, 0.0f, 0.3);
1441  group->set_frame(-1.0f, 1.0f, 0.0f, 0.2);
1442  group->set_frame_style(0, style);
1443  group->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
1444  group->set_active(true);
1445 
1446  _anim_controls_group = get_aspect_2d().attach_new_node(group);
1447  _anim_controls_group.set_pos(0.0f, 0.0f, -0.9f);
1448 
1449  if (_anim_index >= _anim_controls.get_num_anims()) {
1450  PT(TextNode) label = new TextNode("label");
1451  label->set_align(TextNode::A_center);
1452  label->set_text("No animation.");
1453  NodePath tnp = _anim_controls_group.attach_new_node(label);
1454  tnp.set_pos(0.0f, 0.0f, 0.07f);
1455  tnp.set_scale(0.1f);
1456 
1457  return;
1458  }
1459 
1460  AnimControl *control = _anim_controls.get_anim(_anim_index);
1461  nassertv(control != (AnimControl *)NULL);
1462 
1463  if (control->get_num_frames() <= 1) {
1464  // Don't show the controls when the animation has only 0 or 1 frames.
1465  ostringstream text;
1466  text << _anim_controls.get_anim_name(_anim_index);
1467  text << " (" << control->get_num_frames() << " frame"
1468  << ((control->get_num_frames() == 1) ? "" : "s") << ")";
1469 
1470  PT(TextNode) label = new TextNode("label");
1471  label->set_align(TextNode::A_center);
1472  label->set_text(text.str());
1473  NodePath tnp = _anim_controls_group.attach_new_node(label);
1474  tnp.set_pos(0.0f, 0.0f, 0.07f);
1475  tnp.set_scale(0.1f);
1476 
1477  return;
1478  }
1479 
1480  PT(TextNode) label = new TextNode("anim_name");
1481  label->set_align(TextNode::A_left);
1482  label->set_text(_anim_controls.get_anim_name(_anim_index));
1483  NodePath tnp = _anim_controls_group.attach_new_node(label);
1484  tnp.set_pos(-0.95f, 0.0f, 0.15f);
1485  tnp.set_scale(0.05f);
1486 
1487  _anim_slider = new PGSliderBar("anim_slider");
1488  _anim_slider->setup_slider(false, 1.9f, 0.1f, 0.005f);
1489  _anim_slider->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
1490  _anim_slider->get_thumb_button()->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
1491 
1492  _anim_slider->set_range(0.0f, (PN_stdfloat)(control->get_num_frames() - 1));
1493  _anim_slider->set_scroll_size(0.0f);
1494  _anim_slider->set_page_size(1.0f);
1495  NodePath snp = _anim_controls_group.attach_new_node(_anim_slider);
1496  snp.set_pos(0.0f, 0.0f, 0.06f);
1497 
1498  _frame_number = new TextNode("frame_number");
1499  _frame_number->set_text_color(0.0f, 0.0f, 0.0f, 1.0f);
1500  _frame_number->set_align(TextNode::A_center);
1501  _frame_number->set_text(format_string(control->get_frame()));
1502  NodePath fnp = NodePath(_anim_slider->get_thumb_button()).attach_new_node(_frame_number);
1503  fnp.set_scale(0.05f);
1504  fnp.set_pos(0.0f, 0.0f, -0.01f);
1505 
1506  _play_rate_slider = new PGSliderBar("play_rate_slider");
1507  _play_rate_slider->setup_slider(false, 0.4, 0.05f, 0.005f);
1508  _play_rate_slider->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
1509  _play_rate_slider->get_thumb_button()->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
1510  _play_rate_slider->set_value(control->get_play_rate());
1511  NodePath pnp = _anim_controls_group.attach_new_node(_play_rate_slider);
1512  pnp.set_pos(0.75f, 0.0f, 0.15f);
1513 
1514  // Set up the jog/shuttle buttons. These use symbols from the
1515  // shuttle_controls_font file.
1516  setup_shuttle_button("9", 0, st_back_button);
1517  setup_shuttle_button(";", 1, st_pause_button);
1518  setup_shuttle_button("4", 2, st_play_button);
1519  setup_shuttle_button(":", 3, st_forward_button);
1520 
1521  _update_anim_controls_task = new GenericAsyncTask("controls", st_update_anim_controls, (void *)this);
1522  _panda_framework->get_task_mgr().add(_update_anim_controls_task);
1523 }
1524 
1525 ////////////////////////////////////////////////////////////////////
1526 // Function: WindowFramework::destroy_anim_controls
1527 // Access: Private
1528 // Description: Removes the previously-created anim controls, if any.
1529 ////////////////////////////////////////////////////////////////////
1530 void WindowFramework::
1531 destroy_anim_controls() {
1532  if (!_anim_controls_group.is_empty()) {
1533  _anim_controls_group.remove_node();
1534 
1535  _panda_framework->get_event_handler().remove_hooks_with((void *)this);
1536  if (_update_anim_controls_task != NULL) {
1537  _panda_framework->get_task_mgr().remove(_update_anim_controls_task);
1538  _update_anim_controls_task.clear();
1539  }
1540  }
1541 }
1542 
1543 ////////////////////////////////////////////////////////////////////
1544 // Function: WindowFramework::update_anim_controls
1545 // Access: Private
1546 // Description: A per-frame callback to update the anim slider for
1547 // the current frame.
1548 ////////////////////////////////////////////////////////////////////
1549 void WindowFramework::
1550 update_anim_controls() {
1551  AnimControl *control = _anim_controls.get_anim(_anim_index);
1552  nassertv(control != (AnimControl *)NULL);
1553 
1554  if (_anim_slider != NULL) {
1555  if (_anim_slider->is_button_down()) {
1556  control->pose((int)(_anim_slider->get_value() + 0.5));
1557  } else {
1558  _anim_slider->set_value((PN_stdfloat)control->get_frame());
1559  }
1560  }
1561 
1562  if (_frame_number != NULL) {
1563  _frame_number->set_text(format_string(control->get_frame()));
1564  }
1565 
1566  control->set_play_rate(_play_rate_slider->get_value());
1567 }
1568 
1569 ////////////////////////////////////////////////////////////////////
1570 // Function: WindowFramework::setup_shuttle_button
1571 // Access: Private
1572 // Description: Creates a PGButton to implement the indicated shuttle
1573 // event (play, pause, etc.).
1574 ////////////////////////////////////////////////////////////////////
1575 void WindowFramework::
1576 setup_shuttle_button(const string &label, int index,
1577  EventHandler::EventCallbackFunction *func) {
1578  PT(PGButton) button = new PGButton(label);
1579  button->set_frame(-0.05f, 0.05f, 0.0f, 0.07f);
1580 
1581  PN_stdfloat bevel = 0.005f;
1582 
1583  PGFrameStyle style;
1584  style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
1585  style.set_width(bevel, bevel);
1586 
1587  style.set_type(PGFrameStyle::T_bevel_out);
1588  button->set_frame_style(PGButton::S_ready, style);
1589 
1590  style.set_type(PGFrameStyle::T_bevel_in);
1591  button->set_frame_style(PGButton::S_depressed, style);
1592 
1593  style.set_color(0.9f, 0.9f, 0.9f, 1.0f);
1594  style.set_type(PGFrameStyle::T_bevel_out);
1595  button->set_frame_style(PGButton::S_rollover, style);
1596 
1597  if (get_shuttle_controls_font() != (TextFont *)NULL) {
1598  PT(TextNode) tn = new TextNode("label");
1599  tn->set_align(TextNode::A_center);
1600  tn->set_font(get_shuttle_controls_font());
1601  tn->set_text(label);
1602  tn->set_text_color(0.0f, 0.0f, 0.0f, 1.0f);
1603  LMatrix4 xform = LMatrix4::scale_mat(0.07f);
1604  xform.set_row(3, LVecBase3(0.0f, 0.0f, 0.016f));
1605  tn->set_transform(xform);
1606 
1607  button->get_state_def(PGButton::S_ready).attach_new_node(tn);
1608  button->get_state_def(PGButton::S_depressed).attach_new_node(tn);
1609  button->get_state_def(PGButton::S_rollover).attach_new_node(tn);
1610  }
1611 
1612  NodePath np = _anim_controls_group.attach_new_node(button);
1613  np.set_pos(0.1f * index - 0.15f, 0.0f, 0.12);
1614 
1615  _panda_framework->get_event_handler().add_hook(button->get_click_event(MouseButton::one()), func, (void *)this);
1616 }
1617 
1618 ////////////////////////////////////////////////////////////////////
1619 // Function: WindowFramework::back_button
1620 // Access: Private, Static
1621 // Description: Handler for a shuttle button.
1622 ////////////////////////////////////////////////////////////////////
1623 void WindowFramework::
1624 back_button() {
1625  AnimControl *control = _anim_controls.get_anim(_anim_index);
1626  nassertv(control != (AnimControl *)NULL);
1627  control->pose(control->get_frame() - 1);
1628 }
1629 
1630 ////////////////////////////////////////////////////////////////////
1631 // Function: WindowFramework::pause_button
1632 // Access: Private, Static
1633 // Description: Handler for a shuttle button.
1634 ////////////////////////////////////////////////////////////////////
1635 void WindowFramework::
1636 pause_button() {
1637  AnimControl *control = _anim_controls.get_anim(_anim_index);
1638  nassertv(control != (AnimControl *)NULL);
1639  control->stop();
1640 }
1641 
1642 ////////////////////////////////////////////////////////////////////
1643 // Function: WindowFramework::play_button
1644 // Access: Private, Static
1645 // Description: Handler for a shuttle button.
1646 ////////////////////////////////////////////////////////////////////
1647 void WindowFramework::
1648 play_button() {
1649  AnimControl *control = _anim_controls.get_anim(_anim_index);
1650  nassertv(control != (AnimControl *)NULL);
1651  control->loop(false);
1652 }
1653 
1654 ////////////////////////////////////////////////////////////////////
1655 // Function: WindowFramework::forward_button
1656 // Access: Private, Static
1657 // Description: Handler for a shuttle button.
1658 ////////////////////////////////////////////////////////////////////
1659 void WindowFramework::
1660 forward_button() {
1661  AnimControl *control = _anim_controls.get_anim(_anim_index);
1662  nassertv(control != (AnimControl *)NULL);
1663  control->pose(control->get_frame() + 1);
1664 }
1665 
1666 
1667 ////////////////////////////////////////////////////////////////////
1668 // Function: WindowFramework::st_update_anim_controls
1669 // Access: Private, Static
1670 // Description: The static task function.
1671 ////////////////////////////////////////////////////////////////////
1672 AsyncTask::DoneStatus WindowFramework::
1673 st_update_anim_controls(GenericAsyncTask *, void *data) {
1674  WindowFramework *self = (WindowFramework *)data;
1675  self->update_anim_controls();
1676  return AsyncTask::DS_cont;
1677 }
1678 
1679 
1680 ////////////////////////////////////////////////////////////////////
1681 // Function: WindowFramework::st_back_button
1682 // Access: Private, Static
1683 // Description: The static event handler function.
1684 ////////////////////////////////////////////////////////////////////
1685 void WindowFramework::
1686 st_back_button(const Event *, void *data) {
1687  WindowFramework *self = (WindowFramework *)data;
1688  self->back_button();
1689 }
1690 
1691 ////////////////////////////////////////////////////////////////////
1692 // Function: WindowFramework::st_pause_button
1693 // Access: Private, Static
1694 // Description: The static event handler function.
1695 ////////////////////////////////////////////////////////////////////
1696 void WindowFramework::
1697 st_pause_button(const Event *, void *data) {
1698  WindowFramework *self = (WindowFramework *)data;
1699  self->pause_button();
1700 }
1701 
1702 ////////////////////////////////////////////////////////////////////
1703 // Function: WindowFramework::st_play_button
1704 // Access: Private, Static
1705 // Description: The static event handler function.
1706 ////////////////////////////////////////////////////////////////////
1707 void WindowFramework::
1708 st_play_button(const Event *, void *data) {
1709  WindowFramework *self = (WindowFramework *)data;
1710  self->play_button();
1711 }
1712 
1713 ////////////////////////////////////////////////////////////////////
1714 // Function: WindowFramework::st_forward_button
1715 // Access: Private, Static
1716 // Description: The static event handler function.
1717 ////////////////////////////////////////////////////////////////////
1718 void WindowFramework::
1719 st_forward_button(const Event *, void *data) {
1720  WindowFramework *self = (WindowFramework *)data;
1721  self->forward_button();
1722 }
The principle public interface to reading and writing Bam disk files.
Definition: bamFile.h:45
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
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 &quot;top&quot; 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 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
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
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.
This class is just used as a convenient namespace for grouping all of these handy functions that retu...
Definition: mouseButton.h:28
NodePath get_render()
Returns the root of the 3-d scene graph.
Specifies parameters that may be passed to the loader.
Definition: loaderOptions.h:26
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.
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.
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 is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
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_attrib(const RenderAttrib *attrib, int priority=0)
Adds the indicated render attribute to the scene graph on this node.
Definition: nodePath.I:568
virtual int get_num_frames() const
Returns the number of frames in the animation.
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.
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:284
void set_lighting(bool enable)
Turns lighting on (true) or off (false).
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:100
void set_pos(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the translation component of the transform, leaving rotation and scale untouched.
Definition: nodePath.I:783
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
const LVecBase2 & get_fov() const
Returns the horizontal and vertical film size of the virtual film.
Definition: lens.I:423
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
bool is_fully_qualified() const
Returns true if the filename is fully qualified, e.g.
Definition: filename.I:682
void loop_all(bool restart)
Starts all animations looping.
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.
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:565
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
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
Definition: textureAttrib.h:34
Indicates which faces should be culled based on their vertex ordering.
int get_frame() const
Returns the current integer frame number.
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...
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
void set_display_region(DisplayRegion *dr)
Constrains the MouseWatcher to watching the mouse within a particular indicated region of the screen...
Definition: mouseWatcher.I:507
A container for the various kinds of properties we might ask to have on a graphics window before we o...
NodePath get_mouse(GraphicsOutput *window)
Returns a NodePath to the MouseAndKeyboard associated with the indicated GraphicsWindow object...
bool remove_hooks_with(void *data)
Removes all CallbackFunction hooks that have the indicated pointer as the associated data pointer...
void add_consecutive_vertices(int start, int num_vertices)
Adds a consecutive sequence of vertices, beginning at start, to the primitive.
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).
GraphicsOutput * get_window() const
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
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...
void center_trackball(const NodePath &object)
Centers the trackball on the indicated object, and scales the trackball motion suitably.
This is the class that defines a rectangular region on the screen for the MouseWatcher.
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
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. ...
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.
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.
void set_background_type(WindowFramework::BackgroundType type)
Sets the background type of all windows.
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.
AnimControl * get_anim(int n) const
Returns the nth AnimControl associated with this collection.
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.
Represents a set of settings that indicate how a texture is sampled.
Definition: samplerState.h:39
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
string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
Definition: filename.I:460
bool exists(const Filename &filename) const
Convenience function; returns true if the named file exists.
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
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
This class is just used as a convenient namespace for grouping all of these handy functions that retu...
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...
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:236
Defines a series of disconnected triangles.
Definition: geomTriangles.h:25
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
Indicates what color should be applied to renderable geometry.
Definition: colorAttrib.h:30
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
Throws Panda Events for button down/up events generated within the data graph.
Definition: buttonThrower.h:39
string get_extension() const
Returns the file extension.
Definition: filename.I:477
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
int get_num_anims() const
Returns the number of AnimControls associated with this collection.
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
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
void set_mouse_watcher(MouseWatcher *watcher)
Sets the MouseWatcher pointer that the PGTop object registers its PG items with.
Definition: pgTop.cxx:158
string get_anim_name(int n) const
Returns the name of the nth AnimControl associated with this collection.
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