00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "windowFramework.h"
00016 #include "pandaFramework.h"
00017 #include "displayRegion.h"
00018 #include "buttonThrower.h"
00019 #include "transform2sg.h"
00020 #include "dSearchPath.h"
00021 #include "filename.h"
00022 #include "loader.h"
00023 #include "keyboardButton.h"
00024 #include "geom.h"
00025 #include "geomTriangles.h"
00026 #include "geomTristrips.h"
00027 #include "geomVertexData.h"
00028 #include "geomVertexFormat.h"
00029 #include "geomVertexWriter.h"
00030 #include "texturePool.h"
00031 #include "textureAttrib.h"
00032 #include "colorAttrib.h"
00033 #include "perspectiveLens.h"
00034 #include "orthographicLens.h"
00035 #include "auto_bind.h"
00036 #include "ambientLight.h"
00037 #include "directionalLight.h"
00038 #include "lightAttrib.h"
00039 #include "boundingSphere.h"
00040 #include "deg_2_rad.h"
00041 #include "config_framework.h"
00042 #include "cullFaceAttrib.h"
00043 #include "rescaleNormalAttrib.h"
00044 #include "shadeModelAttrib.h"
00045 #include "pgTop.h"
00046 #include "geomNode.h"
00047 #include "texture.h"
00048 #include "videoTexture.h"
00049 #include "movieTexture.h"
00050 #include "texturePool.h"
00051 #include "loaderFileTypeRegistry.h"
00052 #include "pnmImage.h"
00053 #include "virtualFileSystem.h"
00054 #include "string_utils.h"
00055 #include "bamFile.h"
00056 #include "staticTextFont.h"
00057 #include "mouseButton.h"
00058
00059
00060
00061 #include "rock_floor.rgb.c"
00062
00063
00064
00065
00066 #include "shuttle_controls.bam.c"
00067
00068
00069
00070 static const int override_priority = 100;
00071
00072 PT(TextFont) WindowFramework::_shuttle_controls_font = NULL;
00073 TypeHandle WindowFramework::_type_handle;
00074
00075
00076
00077
00078
00079
00080 WindowFramework::
00081 WindowFramework(PandaFramework *panda_framework) :
00082 _panda_framework(panda_framework)
00083 {
00084 _alight = (AmbientLight *)NULL;
00085 _dlight = (DirectionalLight *)NULL;
00086 _got_keyboard = false;
00087 _got_trackball = false;
00088 _got_lights = false;
00089 _anim_controls_enabled = false;
00090 _anim_index = 0;
00091 _wireframe_enabled = false;
00092 _texture_enabled = true;
00093 _two_sided_enabled = false;
00094 _one_sided_reverse_enabled = false;
00095 _lighting_enabled = false;
00096 _perpixel_enabled = false;
00097 _background_type = BT_default;
00098 }
00099
00100
00101
00102
00103
00104
00105 WindowFramework::
00106 WindowFramework(const WindowFramework ©, DisplayRegion *display_region) :
00107 _panda_framework(copy._panda_framework),
00108 _window(copy._window),
00109 _display_region_3d(display_region)
00110 {
00111 _alight = (AmbientLight *)NULL;
00112 _dlight = (DirectionalLight *)NULL;
00113 _got_keyboard = false;
00114 _got_trackball = false;
00115 _got_lights = false;
00116 _anim_controls_enabled = false;
00117 _anim_index = 0;
00118 _wireframe_enabled = false;
00119 _texture_enabled = true;
00120 _two_sided_enabled = false;
00121 _one_sided_reverse_enabled = false;
00122 _lighting_enabled = false;
00123 _perpixel_enabled = false;
00124 _background_type = BT_default;
00125
00126 set_background_type(copy._background_type);
00127
00128 NodePath camera_np = make_camera();
00129 _display_region_3d->set_camera(camera_np);
00130 }
00131
00132
00133
00134
00135
00136
00137 WindowFramework::
00138 ~WindowFramework() {
00139 close_window();
00140 }
00141
00142
00143
00144
00145
00146
00147
00148 GraphicsOutput *WindowFramework::
00149 open_window(const WindowProperties &props, int flags, GraphicsEngine *engine,
00150 GraphicsPipe *pipe, GraphicsStateGuardian *gsg) {
00151 nassertr(_window == (GraphicsOutput *)NULL, _window);
00152
00153 static int next_window_index = 1;
00154 ostringstream stream;
00155 stream << "window" << next_window_index;
00156 next_window_index++;
00157 string name = stream.str();
00158
00159 _window = 0;
00160 GraphicsOutput *winout =
00161 engine->make_output(pipe, name, 0,
00162 FrameBufferProperties::get_default(),
00163 props, flags, gsg, NULL);
00164 if (winout != (GraphicsOutput *)NULL) {
00165 _window = winout;
00166
00167
00168
00169 _display_region_3d = _window->make_display_region();
00170
00171
00172
00173 _window->set_clear_color_active(false);
00174 _window->set_clear_depth_active(false);
00175 _window->set_clear_stencil_active(false);
00176
00177
00178 NodePath camera_np = make_camera();
00179 _display_region_3d->set_camera(camera_np);
00180
00181 set_background_type(_background_type);
00182
00183 if (show_frame_rate_meter) {
00184 _frame_rate_meter = new FrameRateMeter("frame_rate_meter");
00185 _frame_rate_meter->setup_window(_window);
00186 }
00187 if (show_scene_graph_analyzer_meter) {
00188 _scene_graph_analyzer_meter = new SceneGraphAnalyzerMeter("scene_graph_analyzer_meter", get_render().node());
00189 _scene_graph_analyzer_meter->setup_window(_window);
00190 }
00191 }
00192
00193 return _window;
00194 }
00195
00196
00197
00198
00199
00200
00201
00202 void WindowFramework::
00203 close_window() {
00204 _window.clear();
00205 _camera_group.remove_node();
00206 _render.remove_node();
00207 _render_2d.remove_node();
00208 _mouse.remove_node();
00209
00210 _alight = (AmbientLight *)NULL;
00211 _dlight = (DirectionalLight *)NULL;
00212 _got_keyboard = false;
00213 _got_trackball = false;
00214 _got_lights = false;
00215
00216 _wireframe_enabled = false;
00217 _texture_enabled = true;
00218 _two_sided_enabled = false;
00219 _one_sided_reverse_enabled = false;
00220 _lighting_enabled = false;
00221 _perpixel_enabled = false;
00222
00223 if (_frame_rate_meter != (FrameRateMeter *)NULL) {
00224 _frame_rate_meter->clear_window();
00225 _frame_rate_meter = (FrameRateMeter *)NULL;
00226 }
00227 if (_scene_graph_analyzer_meter != (SceneGraphAnalyzerMeter *)NULL) {
00228 _scene_graph_analyzer_meter->clear_window();
00229 _scene_graph_analyzer_meter = (SceneGraphAnalyzerMeter *)NULL;
00230 }
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240 NodePath WindowFramework::
00241 get_camera_group() {
00242 if (_camera_group.is_empty()) {
00243 _camera_group = get_render().attach_new_node("camera_group");
00244 }
00245 return _camera_group;
00246 }
00247
00248
00249
00250
00251
00252
00253 NodePath WindowFramework::
00254 get_render() {
00255 if (_render.is_empty()) {
00256 _render = NodePath("render");
00257
00258 _render.node()->set_attrib(RescaleNormalAttrib::make_default());
00259 _render.node()->set_attrib(ShadeModelAttrib::make(ShadeModelAttrib::M_smooth));
00260
00261
00262 _render.set_two_sided(0);
00263 }
00264 return _render;
00265 }
00266
00267
00268
00269
00270
00271
00272 NodePath WindowFramework::
00273 get_render_2d() {
00274 if (_render_2d.is_empty()) {
00275 _render_2d = NodePath("render_2d");
00276
00277
00278
00279 _render_2d.set_depth_write(0);
00280 _render_2d.set_depth_test(0);
00281 _render_2d.set_material_off(1);
00282 _render_2d.set_two_sided(1);
00283
00284
00285
00286
00287
00288 float l, r, b, t;
00289 _display_region_3d->get_dimensions(l, r, b, t);
00290 _display_region_2d = _window->make_mono_display_region(l, r, b, t);
00291 _display_region_2d->set_sort(10);
00292
00293
00294 PT(Camera) camera = new Camera("camera2d");
00295 NodePath camera_np = _render_2d.attach_new_node(camera);
00296
00297 PT(Lens) lens = new OrthographicLens;
00298
00299 static const float left = -1.0f;
00300 static const float right = 1.0f;
00301 static const float bottom = -1.0f;
00302 static const float top = 1.0f;
00303 lens->set_film_size(right - left, top - bottom);
00304 lens->set_film_offset((right + left) * 0.5, (top + bottom) * 0.5);
00305 lens->set_near_far(-1000, 1000);
00306
00307 camera->set_lens(lens);
00308 _display_region_2d->set_camera(camera_np);
00309 }
00310
00311 return _render_2d;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320 NodePath WindowFramework::
00321 get_aspect_2d() {
00322 if (_aspect_2d.is_empty()) {
00323 PGTop *top = new PGTop("aspect_2d");
00324 _aspect_2d = get_render_2d().attach_new_node(top);
00325
00326
00327
00328 PandaNode *mouse_node = get_mouse().node();
00329 if (mouse_node->is_of_type(MouseWatcher::get_class_type())) {
00330 top->set_mouse_watcher(DCAST(MouseWatcher, mouse_node));
00331 }
00332
00333 float this_aspect_ratio = aspect_ratio;
00334 if (this_aspect_ratio == 0.0f) {
00335
00336 this_aspect_ratio = 1.0f;
00337
00338 if (_window->has_size()) {
00339 int x_size = _window->get_x_size();
00340 int y_size = _window->get_y_size();
00341 if (y_size != 0) {
00342 this_aspect_ratio = (float)x_size / (float)y_size;
00343 }
00344 }
00345 }
00346
00347 _aspect_2d.set_scale(1.0f / this_aspect_ratio, 1.0f, 1.0f);
00348 }
00349
00350 return _aspect_2d;
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 NodePath WindowFramework::
00360 get_mouse() {
00361 if (_mouse.is_empty()) {
00362 NodePath mouse = _panda_framework->get_mouse(_window);
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 PT(MouseWatcher) mw = new MouseWatcher("watcher");
00373 mw->set_display_region(_display_region_3d);
00374 _mouse = mouse.attach_new_node(mw);
00375 }
00376 return _mouse;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385 NodePath WindowFramework::
00386 get_button_thrower() {
00387 return _button_thrower;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396 void WindowFramework::
00397 enable_keyboard() {
00398 if (_got_keyboard) {
00399 return;
00400 }
00401
00402 if (_window->is_of_type(GraphicsWindow::get_class_type()) &&
00403 DCAST(GraphicsWindow, _window)->get_num_input_devices() > 0) {
00404 NodePath mouse = get_mouse();
00405
00406
00407
00408 PT(ButtonThrower) bt = new ButtonThrower("kb-events");
00409 bt->add_parameter(EventParameter(this));
00410 ModifierButtons mods;
00411 mods.add_button(KeyboardButton::shift());
00412 mods.add_button(KeyboardButton::control());
00413 mods.add_button(KeyboardButton::alt());
00414 mods.add_button(KeyboardButton::meta());
00415 bt->set_modifier_buttons(mods);
00416 _button_thrower = mouse.attach_new_node(bt);
00417 }
00418
00419 _got_keyboard = true;
00420 }
00421
00422
00423
00424
00425
00426
00427 void WindowFramework::
00428 setup_trackball() {
00429 if (_got_trackball) {
00430 return;
00431 }
00432
00433 if (_window->is_of_type(GraphicsWindow::get_class_type()) &&
00434 DCAST(GraphicsWindow, _window)->get_num_input_devices() > 0) {
00435 NodePath mouse = get_mouse();
00436 NodePath camera = get_camera_group();
00437
00438 _trackball = new Trackball("trackball");
00439 _trackball->set_pos(LVector3f::forward() * 50.0);
00440 mouse.attach_new_node(_trackball);
00441
00442 PT(Transform2SG) tball2cam = new Transform2SG("tball2cam");
00443 tball2cam->set_node(camera.node());
00444 _trackball->add_child(tball2cam);
00445 }
00446
00447 _got_trackball = true;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456 void WindowFramework::
00457 center_trackball(const NodePath &object) {
00458 if (_trackball == (Trackball *)NULL) {
00459 return;
00460 }
00461
00462 PT(BoundingVolume) volume = object.get_bounds();
00463
00464 nassertv(volume != (BoundingVolume *)NULL);
00465 nassertv(volume->is_of_type(GeometricBoundingVolume::get_class_type()));
00466 CPT(GeometricBoundingVolume) gbv = DCAST(GeometricBoundingVolume, volume);
00467
00468 if (object.has_parent()) {
00469 CPT(TransformState) net_transform = object.get_parent().get_net_transform();
00470 PT(GeometricBoundingVolume) new_gbv = DCAST(GeometricBoundingVolume, gbv->make_copy());
00471 new_gbv->xform(net_transform->get_mat());
00472 gbv = new_gbv;
00473 }
00474
00475
00476 if (gbv->is_infinite()) {
00477 framework_cat.warning()
00478 << "Infinite bounding volume for " << object << "\n";
00479 return;
00480 }
00481
00482 if (gbv->is_empty()) {
00483 framework_cat.warning()
00484 << "Empty bounding volume for " << object << "\n";
00485 return;
00486 }
00487
00488
00489
00490 PT(BoundingSphere) sphere = new BoundingSphere(gbv->get_approx_center(), 0.0f);
00491 if (!sphere->extend_by(gbv)) {
00492 framework_cat.warning()
00493 << "Cannot determine bounding volume of " << object << "\n";
00494 return;
00495 }
00496
00497 LPoint3f center = sphere->get_center();
00498 float radius = sphere->get_radius();
00499
00500 float distance = 50.0f;
00501
00502
00503
00504
00505 Lens *lens = (Lens *)NULL;
00506 if (!_cameras.empty()) {
00507 Cameras::const_iterator ci;
00508 for (ci = _cameras.begin();
00509 ci != _cameras.end() && lens == (Lens *)NULL;
00510 ++ci) {
00511 lens = (*ci)->get_lens();
00512 }
00513 }
00514
00515 if (lens != (Lens *)NULL) {
00516 LVecBase2f fov = lens->get_fov();
00517 distance = radius / ctan(deg_2_rad(min(fov[0], fov[1]) / 2.0f));
00518
00519
00520 float ideal_far_plane = distance + radius * 1.5;
00521 lens->set_far(max(lens->get_default_far(), ideal_far_plane));
00522
00523
00524 float ideal_near_plane = distance - radius;
00525 lens->set_near(min(lens->get_default_near(), ideal_near_plane));
00526 }
00527
00528 _trackball->set_origin(center);
00529 _trackball->set_pos(LVector3f::forward() * distance);
00530
00531
00532
00533 _trackball->set_forward_scale(distance * 0.006);
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 bool WindowFramework::
00547 load_models(const NodePath &parent, int argc, char *argv[], int first_arg) {
00548 pvector<Filename> files;
00549
00550 for (int i = first_arg; i < argc && argv[i] != (char *)NULL; i++) {
00551 files.push_back(Filename::from_os_specific(argv[i]));
00552 }
00553
00554 return load_models(parent, files);
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 bool WindowFramework::
00567 load_models(const NodePath &parent, const pvector<Filename> &files) {
00568 bool all_ok = true;
00569
00570 pvector<Filename>::const_iterator fi;
00571 for (fi = files.begin(); fi != files.end(); ++fi) {
00572 const Filename &filename = (*fi);
00573 NodePath model = load_model(parent, filename);
00574 if (model.is_empty()) {
00575 all_ok = false;
00576 }
00577 }
00578
00579 return all_ok;
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589 NodePath WindowFramework::
00590 load_model(const NodePath &parent, Filename filename) {
00591 nout << "Loading " << filename << "\n";
00592
00593
00594
00595 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00596 bool search = !(filename.is_fully_qualified() || vfs->exists(filename));
00597
00598
00599
00600 bool is_image = false;
00601 string extension = filename.get_extension();
00602 #ifdef HAVE_ZLIB
00603 if (extension == "pz") {
00604 extension = Filename(filename.get_basename_wo_extension()).get_extension();
00605 }
00606 #endif // HAVE_ZLIB
00607 if (!extension.empty()) {
00608 LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr();
00609 LoaderFileType *model_type =
00610 reg->get_type_from_extension(extension);
00611 if (model_type == (LoaderFileType *)NULL) {
00612
00613
00614 if (extension == "txo" || downcase(extension) == "dds") {
00615
00616
00617 is_image = true;
00618
00619 } else {
00620 TexturePool *texture_pool = TexturePool::get_global_ptr();
00621 if (texture_pool->get_texture_type(extension) != NULL) {
00622
00623 is_image = true;
00624 }
00625 }
00626 }
00627 }
00628
00629 LoaderOptions options = PandaFramework::_loader_options;
00630 if (search) {
00631 options.set_flags(options.get_flags() | LoaderOptions::LF_search);
00632 } else {
00633 options.set_flags(options.get_flags() & ~LoaderOptions::LF_search);
00634 }
00635
00636 Loader loader;
00637 PT(PandaNode) node;
00638 if (is_image) {
00639 node = load_image_as_model(filename);
00640 } else {
00641 node = loader.load_sync(filename, options);
00642 }
00643
00644 if (node == (PandaNode *)NULL) {
00645 nout << "Unable to load " << filename << "\n";
00646 return NodePath::not_found();
00647 }
00648
00649 return parent.attach_new_node(node);
00650 }
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 NodePath WindowFramework::
00661 load_default_model(const NodePath &parent) {
00662 CPT(RenderState) state = RenderState::make_empty();
00663
00664 state = state->add_attrib(ColorAttrib::make_flat(Colorf(0.5, 0.5, 1.0, 1.0)));
00665
00666
00667
00668 string rock_floor_string((const char *)rock_floor, rock_floor_len);
00669 istringstream rock_floor_strm(rock_floor_string);
00670 PNMImage rock_floor_pnm;
00671 if (rock_floor_pnm.read(rock_floor_strm, "rock-floor.rgb")) {
00672 PT(Texture) tex = new Texture;
00673 tex->set_name("rock-floor.rgb");
00674 tex->load(rock_floor_pnm);
00675 tex->set_minfilter(Texture::FT_linear);
00676 tex->set_magfilter(Texture::FT_linear);
00677 state = state->add_attrib(TextureAttrib::make(tex));
00678 }
00679
00680 GeomNode *geomnode = new GeomNode("tri");
00681
00682 PT(GeomVertexData) vdata = new GeomVertexData
00683 ("tri", GeomVertexFormat::get_v3n3cpt2(),
00684 Geom::UH_static);
00685 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00686 GeomVertexWriter normal(vdata, InternalName::get_normal());
00687 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00688
00689 vertex.add_data3f(Vertexf::rfu(0.0, 0.0, 0.0));
00690 vertex.add_data3f(Vertexf::rfu(1.0, 0.0, 0.0));
00691 vertex.add_data3f(Vertexf::rfu(0.0, 0.0, 1.0));
00692
00693 normal.add_data3f(Normalf::back());
00694 normal.add_data3f(Normalf::back());
00695 normal.add_data3f(Normalf::back());
00696
00697 texcoord.add_data2f(0.0, 0.0);
00698 texcoord.add_data2f(1.0, 0.0);
00699 texcoord.add_data2f(0.0, 1.0);
00700
00701 PT(GeomTriangles) tri = new GeomTriangles(Geom::UH_static);
00702 tri->add_consecutive_vertices(0, 3);
00703 tri->close_primitive();
00704
00705 PT(Geom) geom = new Geom(vdata);
00706 geom->add_primitive(tri);
00707
00708 geomnode->add_geom(geom, state);
00709
00710 return parent.attach_new_node(geomnode);
00711 }
00712
00713
00714
00715
00716
00717
00718
00719
00720 void WindowFramework::
00721 loop_animations(int hierarchy_match_flags) {
00722
00723
00724
00725 auto_bind(get_render().node(), _anim_controls, hierarchy_match_flags);
00726 _anim_controls.loop_all(true);
00727 }
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737 void WindowFramework::
00738 stagger_animations() {
00739 for (int i = 0; i < _anim_controls.get_num_anims(); ++i) {
00740 AnimControl *control = _anim_controls.get_anim(i);
00741 double r = (double)rand() / (double)RAND_MAX;
00742 r = r * 0.2 + 0.9;
00743 control->set_play_rate(r);
00744 }
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 void WindowFramework::
00758 next_anim_control() {
00759 if (_anim_controls_enabled) {
00760 destroy_anim_controls();
00761
00762 ++_anim_index;
00763 if (_anim_index >= _anim_controls.get_num_anims()) {
00764 set_anim_controls(false);
00765 } else {
00766 create_anim_controls();
00767 }
00768 } else {
00769 _anim_index = 0;
00770 set_anim_controls(true);
00771 }
00772 }
00773
00774
00775
00776
00777
00778
00779
00780 void WindowFramework::
00781 set_anim_controls(bool enable) {
00782 _anim_controls_enabled = enable;
00783 if (_anim_controls_enabled) {
00784 create_anim_controls();
00785
00786 } else {
00787 destroy_anim_controls();
00788 }
00789 }
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 void WindowFramework::
00801 adjust_aspect_ratio() {
00802 float this_aspect_ratio = aspect_ratio;
00803 int x_size = 0, y_size = 0;
00804 if (this_aspect_ratio == 0.0f) {
00805
00806 this_aspect_ratio = 1.0f;
00807
00808 if (_window->has_size()) {
00809 x_size = _window->get_x_size();
00810 y_size = _window->get_y_size();
00811 if (y_size != 0) {
00812 this_aspect_ratio = (float)x_size / (float)y_size;
00813 }
00814 }
00815 }
00816
00817 if (!_aspect_2d.is_empty()) {
00818 _aspect_2d.set_scale(1.0f / this_aspect_ratio, 1.0f, 1.0f);
00819 }
00820
00821 Cameras::iterator ci;
00822 for (ci = _cameras.begin(); ci != _cameras.end(); ++ci) {
00823 Lens *lens = (*ci)->get_lens();
00824 if (lens != (Lens *)NULL) {
00825 if (y_size != 0) {
00826 lens->set_film_size(x_size, y_size);
00827 } else {
00828 lens->set_aspect_ratio(this_aspect_ratio);
00829 }
00830 }
00831 }
00832 }
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844 WindowFramework *WindowFramework::
00845 split_window(SplitType split_type) {
00846 DisplayRegion *new_region = NULL;
00847
00848 if (split_type == ST_default) {
00849
00850
00851
00852 if (_display_region_3d->get_pixel_width() >
00853 _display_region_3d->get_pixel_height()) {
00854 split_type = ST_horizontal;
00855 } else {
00856 split_type = ST_vertical;
00857 }
00858 }
00859
00860 float left, right, bottom, top;
00861 _display_region_3d->get_dimensions(left, right, bottom, top);
00862 new_region = _display_region_3d->get_window()->make_display_region();
00863
00864 if (split_type == ST_vertical) {
00865 _display_region_3d->set_dimensions(left, right, bottom, (top + bottom) / 2.0f);
00866 if (_display_region_2d != (DisplayRegion *)NULL) {
00867 _display_region_2d->set_dimensions(left, right, bottom, (top + bottom) / 2.0f);
00868 }
00869
00870 new_region->set_dimensions(left, right, (top + bottom) / 2.0f, top);
00871
00872 } else {
00873 _display_region_3d->set_dimensions(left, (left + right) / 2.0f, bottom, top);
00874 if (_display_region_2d != (DisplayRegion *)NULL) {
00875 _display_region_2d->set_dimensions(left, (left + right) / 2.0f, bottom, top);
00876 }
00877
00878 new_region->set_dimensions((left + right) / 2.0f, right, bottom, top);
00879 }
00880
00881 PT(WindowFramework) wf = new WindowFramework(*this, new_region);
00882 _panda_framework->_windows.push_back(wf);
00883
00884 return wf;
00885 }
00886
00887
00888
00889
00890
00891
00892
00893 void WindowFramework::
00894 set_wireframe(bool enable) {
00895 if (enable == _wireframe_enabled) {
00896 return;
00897 }
00898
00899 NodePath render = get_render();
00900
00901 if (enable) {
00902 render.set_render_mode_wireframe(override_priority);
00903 render.set_two_sided(true, override_priority);
00904 } else {
00905 render.clear_render_mode();
00906 if (!_two_sided_enabled) {
00907 render.clear_two_sided();
00908 }
00909 if (_one_sided_reverse_enabled) {
00910 CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse();
00911 render.node()->set_attrib(attrib);
00912 }
00913 }
00914
00915 _wireframe_enabled = enable;
00916 }
00917
00918
00919
00920
00921
00922
00923
00924 void WindowFramework::
00925 set_texture(bool enable) {
00926 if (enable == _texture_enabled) {
00927 return;
00928 }
00929
00930 NodePath render = get_render();
00931
00932 if (!enable) {
00933 render.set_texture_off(override_priority);
00934 } else {
00935 render.clear_texture();
00936 }
00937
00938 _texture_enabled = enable;
00939 }
00940
00941
00942
00943
00944
00945
00946
00947 void WindowFramework::
00948 set_two_sided(bool enable) {
00949 if (enable == _two_sided_enabled) {
00950 return;
00951 }
00952
00953 NodePath render = get_render();
00954
00955 if (enable) {
00956 render.set_two_sided(true, override_priority);
00957 } else {
00958 if (!_wireframe_enabled) {
00959 render.clear_two_sided();
00960 }
00961 }
00962
00963 _two_sided_enabled = enable;
00964 _one_sided_reverse_enabled = false;
00965 }
00966
00967
00968
00969
00970
00971
00972
00973
00974 void WindowFramework::
00975 set_one_sided_reverse(bool enable) {
00976 if (enable == _one_sided_reverse_enabled) {
00977 return;
00978 }
00979
00980 NodePath render = get_render();
00981
00982 if (!_wireframe_enabled) {
00983 if (enable) {
00984 CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse();
00985 render.node()->set_attrib(attrib);
00986 } else {
00987 render.clear_two_sided();
00988 }
00989 }
00990
00991 _two_sided_enabled = false;
00992 _one_sided_reverse_enabled = enable;
00993 }
00994
00995
00996
00997
00998
00999
01000 void WindowFramework::
01001 set_lighting(bool enable) {
01002 if (enable == _lighting_enabled) {
01003 return;
01004 }
01005
01006 NodePath render = get_render();
01007
01008 if (enable) {
01009 if (!_got_lights) {
01010 setup_lights();
01011 }
01012 render.set_light(_alight);
01013 render.set_light(_dlight);
01014 } else {
01015 render.clear_light();
01016 }
01017
01018 _lighting_enabled = enable;
01019 }
01020
01021
01022
01023
01024
01025
01026 void WindowFramework::
01027 set_perpixel(bool enable) {
01028 if (enable == _perpixel_enabled) {
01029 return;
01030 }
01031
01032 NodePath render = get_render();
01033
01034 if (enable) {
01035 render.set_shader_auto();
01036 } else {
01037 render.set_shader_off();
01038 }
01039
01040 _perpixel_enabled = enable;
01041 }
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051 void WindowFramework::
01052 set_background_type(WindowFramework::BackgroundType type) {
01053 _background_type = type;
01054
01055 if (_display_region_3d == (DisplayRegion *)NULL) {
01056 return;
01057 }
01058
01059 switch (_background_type) {
01060 case BT_other:
01061 break;
01062
01063 case BT_default:
01064 _display_region_3d->set_clear_color_active(true);
01065 _display_region_3d->set_clear_depth_active(true);
01066 _display_region_3d->set_clear_stencil_active(true);
01067 _display_region_3d->set_clear_color(_window->get_clear_color());
01068 _display_region_3d->set_clear_depth(_window->get_clear_depth());
01069 _display_region_3d->set_clear_stencil(_window->get_clear_stencil());
01070 break;
01071
01072 case BT_black:
01073 _display_region_3d->set_clear_color_active(true);
01074 _display_region_3d->set_clear_depth_active(true);
01075 _display_region_3d->set_clear_stencil_active(true);
01076 _display_region_3d->set_clear_color(Colorf(0.0f, 0.0f, 0.0f, 0.0f));
01077 _display_region_3d->set_clear_depth(1.0f);
01078 _display_region_3d->set_clear_stencil(0);
01079 break;
01080
01081 case BT_gray:
01082 _display_region_3d->set_clear_color_active(true);
01083 _display_region_3d->set_clear_depth_active(true);
01084 _display_region_3d->set_clear_stencil_active(true);
01085 _display_region_3d->set_clear_color(Colorf(0.3f, 0.3f, 0.3f, 0.0f));
01086 _display_region_3d->set_clear_depth(1.0f);
01087 _display_region_3d->set_clear_stencil(0);
01088 break;
01089
01090 case BT_white:
01091 _display_region_3d->set_clear_color_active(true);
01092 _display_region_3d->set_clear_depth_active(true);
01093 _display_region_3d->set_clear_stencil_active(true);
01094 _display_region_3d->set_clear_color(Colorf(1.0f, 1.0f, 1.0f, 0.0f));
01095 _display_region_3d->set_clear_depth(1.0f);
01096 _display_region_3d->set_clear_stencil(0);
01097 break;
01098
01099 case BT_none:
01100 _display_region_3d->set_clear_color_active(false);
01101 _display_region_3d->set_clear_depth_active(false);
01102 _display_region_3d->set_clear_stencil_active(false);
01103 break;
01104 }
01105 }
01106
01107
01108
01109
01110
01111
01112
01113 TextFont *WindowFramework::
01114 get_shuttle_controls_font() {
01115 if (_shuttle_controls_font == (TextFont *)NULL) {
01116 PT(TextFont) font;
01117
01118 string shuttle_controls_string((const char *)shuttle_controls, shuttle_controls_len);
01119 istringstream in(shuttle_controls_string);
01120 BamFile bam_file;
01121 if (bam_file.open_read(in, "shuttle_controls font stream")) {
01122 PT(PandaNode) node = bam_file.read_node();
01123 if (node != (PandaNode *)NULL) {
01124 _shuttle_controls_font = new StaticTextFont(node);
01125 }
01126 }
01127 }
01128
01129 return _shuttle_controls_font;
01130 }
01131
01132
01133
01134
01135
01136
01137 NodePath WindowFramework::
01138 make_camera() {
01139
01140 PT(Camera) camera = new Camera("camera");
01141 NodePath camera_np = get_camera_group().attach_new_node(camera);
01142 _cameras.push_back(camera);
01143
01144 PT(Lens) lens = new PerspectiveLens;
01145
01146 if (aspect_ratio != 0.0) {
01147
01148 lens->set_aspect_ratio(aspect_ratio);
01149
01150 } else {
01151
01152
01153 if (_window->has_size()) {
01154 int x_size = _window->get_x_size();
01155 int y_size = _window->get_y_size();
01156 if (y_size != 0) {
01157 lens->set_film_size(x_size, y_size);
01158 }
01159 }
01160 }
01161
01162 camera->set_lens(lens);
01163
01164 return camera_np;
01165 }
01166
01167
01168
01169
01170
01171
01172
01173 void WindowFramework::
01174 setup_lights() {
01175 if (_got_lights) {
01176 return;
01177 }
01178
01179 NodePath camera_group = get_camera_group();
01180 NodePath light_group = camera_group.attach_new_node("lights");
01181
01182 AmbientLight *alight = new AmbientLight("ambient");
01183 alight->set_color(Colorf(0.2f, 0.2f, 0.2f, 1.0f));
01184 DirectionalLight *dlight = new DirectionalLight("directional");
01185 dlight->set_color(Colorf(0.8f, 0.8f, 0.8f, 1.0f));
01186
01187 _alight = light_group.attach_new_node(alight);
01188 _dlight = light_group.attach_new_node(dlight);
01189 _dlight.set_hpr(-10, -20, 0);
01190
01191 _got_lights = true;
01192 }
01193
01194
01195
01196
01197
01198
01199
01200
01201 PT(PandaNode) WindowFramework::
01202 load_image_as_model(const Filename &filename) {
01203 PT(Texture) tex = TexturePool::load_texture(filename);
01204 if (tex == NULL) {
01205 return NULL;
01206 }
01207
01208 int x_size = tex->get_x_size() - tex->get_pad_x_size();
01209 int y_size = tex->get_y_size() - tex->get_pad_y_size();
01210 int full_x = tex->get_x_size();
01211 int full_y = tex->get_y_size();
01212 bool has_alpha = true;
01213 LVecBase2f tex_scale((x_size)*1.0f/full_x, (y_size*1.0f)/full_y);
01214
01215 if (tex->is_of_type(VideoTexture::get_class_type())) {
01216
01217 VideoTexture *vtex = DCAST(VideoTexture, tex);
01218 x_size = vtex->get_video_width();
01219 y_size = vtex->get_video_height();
01220 tex_scale = vtex->get_tex_scale();
01221 } else {
01222
01223
01224 x_size = tex->get_orig_file_x_size();
01225 y_size = tex->get_orig_file_y_size();
01226 }
01227
01228
01229 tex->set_minfilter(Texture::FT_linear_mipmap_linear);
01230 tex->set_magfilter(Texture::FT_linear);
01231
01232
01233
01234
01235 float left,right,top,bottom;
01236 if (x_size > y_size) {
01237 float scale = 10.0;
01238 left = -scale;
01239 right = scale;
01240 top = (scale * y_size) / x_size;
01241 bottom = -(scale * y_size) / x_size;
01242 } else {
01243 float scale = 10.0;
01244 left = -(scale * x_size) / y_size;
01245 right = (scale * x_size) / y_size;
01246 top = scale;
01247 bottom = -scale;
01248 }
01249
01250 PT(GeomNode) card_node = new GeomNode("card");
01251 card_node->set_attrib(TextureAttrib::make(tex));
01252 if (has_alpha) {
01253 card_node->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
01254 }
01255
01256 PT(GeomVertexData) vdata = new GeomVertexData
01257 ("card", GeomVertexFormat::get_v3t2(),
01258 Geom::UH_static);
01259 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
01260 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
01261
01262 vertex.add_data3f(Vertexf::rfu(left, 0.02f, top));
01263 vertex.add_data3f(Vertexf::rfu(left, 0.02f, bottom));
01264 vertex.add_data3f(Vertexf::rfu(right, 0.02f, top));
01265 vertex.add_data3f(Vertexf::rfu(right, 0.02f, bottom));
01266
01267 texcoord.add_data2f(0.0f, tex_scale[1]);
01268 texcoord.add_data2f(0.0f, 0.0f);
01269 texcoord.add_data2f(tex_scale[0], tex_scale[1]);
01270 texcoord.add_data2f(tex_scale[0], 0.0f);
01271
01272 PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
01273 strip->add_consecutive_vertices(0, 4);
01274 strip->close_primitive();
01275
01276 PT(Geom) geom = new Geom(vdata);
01277 geom->add_primitive(strip);
01278
01279 card_node->add_geom(geom);
01280
01281 return card_node.p();
01282 }
01283
01284
01285
01286
01287
01288
01289
01290 void WindowFramework::
01291 create_anim_controls() {
01292 destroy_anim_controls();
01293
01294 PT(PGItem) group = new PGItem("anim_controls_group");
01295 PGFrameStyle style;
01296 style.set_type(PGFrameStyle::T_flat);
01297 style.set_color(0.0f, 0.0f, 0.0f, 0.3f);
01298 group->set_frame(-1.0f, 1.0f, 0.0f, 0.2f);
01299 group->set_frame_style(0, style);
01300 group->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
01301 group->set_active(true);
01302
01303 _anim_controls_group = get_aspect_2d().attach_new_node(group);
01304 _anim_controls_group.set_pos(0.0f, 0.0f, -0.9f);
01305
01306 if (_anim_index >= _anim_controls.get_num_anims()) {
01307 PT(TextNode) label = new TextNode("label");
01308 label->set_align(TextNode::A_center);
01309 label->set_text("No animation.");
01310 NodePath tnp = _anim_controls_group.attach_new_node(label);
01311 tnp.set_pos(0.0f, 0.0f, 0.07f);
01312 tnp.set_scale(0.1f);
01313
01314 return;
01315 }
01316
01317 AnimControl *control = _anim_controls.get_anim(_anim_index);
01318 nassertv(control != (AnimControl *)NULL);
01319
01320 PT(TextNode) label = new TextNode("anim_name");
01321 label->set_align(TextNode::A_left);
01322 label->set_text(_anim_controls.get_anim_name(_anim_index));
01323 NodePath tnp = _anim_controls_group.attach_new_node(label);
01324 tnp.set_pos(-0.95f, 0.0f, 0.15f);
01325 tnp.set_scale(0.05f);
01326
01327 _anim_slider = new PGSliderBar("anim_slider");
01328 _anim_slider->setup_slider(false, 1.9f, 0.1f, 0.005f);
01329 _anim_slider->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
01330 _anim_slider->get_thumb_button()->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
01331
01332 _anim_slider->set_range(0.0f, (float)(control->get_num_frames() - 1));
01333 _anim_slider->set_scroll_size(0.0f);
01334 _anim_slider->set_page_size(1.0f);
01335 NodePath snp = _anim_controls_group.attach_new_node(_anim_slider);
01336 snp.set_pos(0.0f, 0.0f, 0.06f);
01337
01338 _frame_number = new TextNode("frame_number");
01339 _frame_number->set_text_color(0.0f, 0.0f, 0.0f, 1.0f);
01340 _frame_number->set_align(TextNode::A_center);
01341 _frame_number->set_text(format_string(control->get_frame()));
01342 NodePath fnp = NodePath(_anim_slider->get_thumb_button()).attach_new_node(_frame_number);
01343 fnp.set_scale(0.05f);
01344 fnp.set_pos(0.0f, 0.0f, -0.01f);
01345
01346 _play_rate_slider = new PGSliderBar("play_rate_slider");
01347 _play_rate_slider->setup_slider(false, 0.4f, 0.05f, 0.005f);
01348 _play_rate_slider->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
01349 _play_rate_slider->get_thumb_button()->set_suppress_flags(MouseWatcherRegion::SF_mouse_button);
01350 _play_rate_slider->set_value(control->get_play_rate());
01351 NodePath pnp = _anim_controls_group.attach_new_node(_play_rate_slider);
01352 pnp.set_pos(0.75f, 0.0f, 0.15f);
01353
01354
01355
01356 setup_shuttle_button("9", 0, st_back_button);
01357 setup_shuttle_button(";", 1, st_pause_button);
01358 setup_shuttle_button("4", 2, st_play_button);
01359 setup_shuttle_button(":", 3, st_forward_button);
01360
01361 _update_anim_controls_task = new GenericAsyncTask("controls", st_update_anim_controls, (void *)this);
01362 _panda_framework->get_task_mgr().add(_update_anim_controls_task);
01363 }
01364
01365
01366
01367
01368
01369
01370 void WindowFramework::
01371 destroy_anim_controls() {
01372 if (!_anim_controls_group.is_empty()) {
01373 _anim_controls_group.remove_node();
01374
01375 _panda_framework->get_event_handler().remove_hooks_with((void *)this);
01376 if (_update_anim_controls_task != NULL) {
01377 _panda_framework->get_task_mgr().remove(_update_anim_controls_task);
01378 _update_anim_controls_task.clear();
01379 }
01380 }
01381 }
01382
01383
01384
01385
01386
01387
01388
01389 void WindowFramework::
01390 update_anim_controls() {
01391 AnimControl *control = _anim_controls.get_anim(_anim_index);
01392 nassertv(control != (AnimControl *)NULL);
01393
01394 if (_anim_slider->is_button_down()) {
01395 control->pose((int)(_anim_slider->get_value() + 0.5));
01396 } else {
01397 _anim_slider->set_value((float)control->get_frame());
01398 }
01399
01400 _frame_number->set_text(format_string(control->get_frame()));
01401
01402 control->set_play_rate(_play_rate_slider->get_value());
01403 }
01404
01405
01406
01407
01408
01409
01410
01411 void WindowFramework::
01412 setup_shuttle_button(const string &label, int index,
01413 EventHandler::EventCallbackFunction *func) {
01414 PT(PGButton) button = new PGButton(label);
01415 button->set_frame(-0.05f, 0.05f, 0.0f, 0.07f);
01416
01417 float bevel = 0.005f;
01418
01419 PGFrameStyle style;
01420 style.set_color(0.8f, 0.8f, 0.8f, 1.0f);
01421 style.set_width(bevel, bevel);
01422
01423 style.set_type(PGFrameStyle::T_bevel_out);
01424 button->set_frame_style(PGButton::S_ready, style);
01425
01426 style.set_type(PGFrameStyle::T_bevel_in);
01427 button->set_frame_style(PGButton::S_depressed, style);
01428
01429 style.set_color(0.9f, 0.9f, 0.9f, 1.0f);
01430 style.set_type(PGFrameStyle::T_bevel_out);
01431 button->set_frame_style(PGButton::S_rollover, style);
01432
01433 if (get_shuttle_controls_font() != (TextFont *)NULL) {
01434 PT(TextNode) tn = new TextNode("label");
01435 tn->set_align(TextNode::A_center);
01436 tn->set_font(get_shuttle_controls_font());
01437 tn->set_text(label);
01438 tn->set_text_color(0.0f, 0.0f, 0.0f, 1.0f);
01439 LMatrix4f xform = LMatrix4f::scale_mat(0.07f);
01440 xform.set_row(3, LVecBase3f(0.0f, 0.0f, 0.016f));
01441 tn->set_transform(xform);
01442
01443 button->get_state_def(PGButton::S_ready).attach_new_node(tn);
01444 button->get_state_def(PGButton::S_depressed).attach_new_node(tn);
01445 button->get_state_def(PGButton::S_rollover).attach_new_node(tn);
01446 }
01447
01448 NodePath np = _anim_controls_group.attach_new_node(button);
01449 np.set_pos(0.1f * index - 0.15f, 0.0f, 0.12f);
01450
01451 _panda_framework->get_event_handler().add_hook(button->get_click_event(MouseButton::one()), func, (void *)this);
01452 }
01453
01454
01455
01456
01457
01458
01459 void WindowFramework::
01460 back_button() {
01461 AnimControl *control = _anim_controls.get_anim(_anim_index);
01462 nassertv(control != (AnimControl *)NULL);
01463 control->pose(control->get_frame() - 1);
01464 }
01465
01466
01467
01468
01469
01470
01471 void WindowFramework::
01472 pause_button() {
01473 AnimControl *control = _anim_controls.get_anim(_anim_index);
01474 nassertv(control != (AnimControl *)NULL);
01475 control->stop();
01476 }
01477
01478
01479
01480
01481
01482
01483 void WindowFramework::
01484 play_button() {
01485 AnimControl *control = _anim_controls.get_anim(_anim_index);
01486 nassertv(control != (AnimControl *)NULL);
01487 control->loop(false);
01488 }
01489
01490
01491
01492
01493
01494
01495 void WindowFramework::
01496 forward_button() {
01497 AnimControl *control = _anim_controls.get_anim(_anim_index);
01498 nassertv(control != (AnimControl *)NULL);
01499 control->pose(control->get_frame() + 1);
01500 }
01501
01502
01503
01504
01505
01506
01507
01508 AsyncTask::DoneStatus WindowFramework::
01509 st_update_anim_controls(GenericAsyncTask *, void *data) {
01510 WindowFramework *self = (WindowFramework *)data;
01511 self->update_anim_controls();
01512 return AsyncTask::DS_cont;
01513 }
01514
01515
01516
01517
01518
01519
01520
01521 void WindowFramework::
01522 st_back_button(const Event *, void *data) {
01523 WindowFramework *self = (WindowFramework *)data;
01524 self->back_button();
01525 }
01526
01527
01528
01529
01530
01531
01532 void WindowFramework::
01533 st_pause_button(const Event *, void *data) {
01534 WindowFramework *self = (WindowFramework *)data;
01535 self->pause_button();
01536 }
01537
01538
01539
01540
01541
01542
01543 void WindowFramework::
01544 st_play_button(const Event *, void *data) {
01545 WindowFramework *self = (WindowFramework *)data;
01546 self->play_button();
01547 }
01548
01549
01550
01551
01552
01553
01554 void WindowFramework::
01555 st_forward_button(const Event *, void *data) {
01556 WindowFramework *self = (WindowFramework *)data;
01557 self->forward_button();
01558 }