729 lines
25 KiB
C++
729 lines
25 KiB
C++
// Filename: pandaFramework.cxx
|
|
// Created by: drose (02Apr02)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://www.panda3d.org/license.txt .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d@yahoogroups.com .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pandaFramework.h"
|
|
#include "clockObject.h"
|
|
#include "pStatClient.h"
|
|
#include "eventQueue.h"
|
|
#include "dataGraphTraverser.h"
|
|
#include "interactiveGraphicsPipe.h"
|
|
#include "config_framework.h"
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
PandaFramework::
|
|
PandaFramework() :
|
|
_event_handler(EventQueue::get_global_event_queue())
|
|
{
|
|
_is_open = false;
|
|
_made_default_pipe = false;
|
|
_data_root = NodePath("data");
|
|
_window_title = "Panda";
|
|
_start_time = 0.0;
|
|
_frame_count = 0;
|
|
_wireframe_enabled = false;
|
|
_texture_enabled = true;
|
|
_two_sided_enabled = false;
|
|
_lighting_enabled = false;
|
|
_default_keys_enabled = false;
|
|
_exit_flag = false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::Destructor
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
PandaFramework::
|
|
~PandaFramework() {
|
|
if (_is_open) {
|
|
close_framework();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::open_framework
|
|
// Access: Public
|
|
// Description: Should be called once at the beginning of the
|
|
// application to initialize Panda (and the framework)
|
|
// for use. The command-line arguments should be passed
|
|
// in so Panda can remove any arguments that it
|
|
// recognizes as special control parameters.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
open_framework(int &argc, char **&argv) {
|
|
if (_is_open) {
|
|
return;
|
|
}
|
|
|
|
_is_open = true;
|
|
|
|
reset_frame_rate();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::close_framework
|
|
// Access: Public
|
|
// Description: Should be called at the end of an application to
|
|
// close Panda. This is optional, as the destructor
|
|
// will do the same thing.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
close_framework() {
|
|
if (!_is_open) {
|
|
return;
|
|
}
|
|
|
|
close_all_windows();
|
|
// We should define this function on GraphicsEngine.
|
|
// _engine.remove_all_windows();
|
|
_event_handler.remove_all_hooks();
|
|
|
|
_is_open = false;
|
|
_made_default_pipe = false;
|
|
_default_pipe.clear();
|
|
|
|
_start_time = 0.0;
|
|
_frame_count = 0;
|
|
_wireframe_enabled = false;
|
|
_two_sided_enabled = false;
|
|
_lighting_enabled = false;
|
|
_default_keys_enabled = false;
|
|
_exit_flag = false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::get_default_pipe
|
|
// Access: Public
|
|
// Description: Returns the default pipe. This is the GraphicsPipe
|
|
// that all windows in the framework will be created on,
|
|
// unless otherwise specified in open_window(). It is
|
|
// usually the primary graphics interface on the local
|
|
// machine.
|
|
//
|
|
// If the default pipe has not yet been created, this
|
|
// creates it.
|
|
//
|
|
// The return value is the default pipe, or NULL if no
|
|
// default pipe could be created.
|
|
////////////////////////////////////////////////////////////////////
|
|
GraphicsPipe *PandaFramework::
|
|
get_default_pipe() {
|
|
nassertr(_is_open, NULL);
|
|
if (!_made_default_pipe) {
|
|
make_default_pipe();
|
|
_made_default_pipe = true;
|
|
}
|
|
return _default_pipe;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::get_default_window_props
|
|
// Access: Public, Virtual
|
|
// Description: Fills in the indicated window properties structure
|
|
// according to the normal window properties for this
|
|
// application.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
get_default_window_props(GraphicsWindow::Properties &props) {
|
|
props._xorg = 0;
|
|
props._yorg = 0;
|
|
props._xsize = win_width;
|
|
props._ysize = win_height;
|
|
props._fullscreen = fullscreen;
|
|
props._title = _window_title;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::open_window
|
|
// Access: Public
|
|
// Description: Opens a new window, using the default parameters.
|
|
// Returns the new WindowFramework if successful, or
|
|
// NULL if not.
|
|
////////////////////////////////////////////////////////////////////
|
|
WindowFramework *PandaFramework::
|
|
open_window(GraphicsPipe *pipe) {
|
|
nassertr(_is_open, NULL);
|
|
|
|
GraphicsWindow::Properties props;
|
|
get_default_window_props(props);
|
|
|
|
return open_window(props, pipe);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::open_window
|
|
// Access: Public
|
|
// Description: Opens a new window using the indicated properties.
|
|
// (You may initialize the properties to their default
|
|
// values by calling get_default_window_props() first.)
|
|
//
|
|
// Returns the new WindowFramework if successful, or
|
|
// NULL if not.
|
|
////////////////////////////////////////////////////////////////////
|
|
WindowFramework *PandaFramework::
|
|
open_window(const GraphicsWindow::Properties &props, GraphicsPipe *pipe) {
|
|
if (pipe == (GraphicsPipe *)NULL) {
|
|
pipe = get_default_pipe();
|
|
if (pipe == (GraphicsPipe *)NULL) {
|
|
// Can't get a pipe.
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
nassertr(_is_open, NULL);
|
|
WindowFramework *wf = make_window_framework();
|
|
_windows.push_back(wf);
|
|
|
|
GraphicsWindow *win = wf->open_window(props, pipe);
|
|
if (win != (GraphicsWindow *)NULL) {
|
|
_engine.add_window(win);
|
|
}
|
|
|
|
return wf;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::close_window
|
|
// Access: Public
|
|
// Description: Closes the nth window and removes it from the list.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
close_window(int n) {
|
|
nassertv(n >= 0 && n < (int)_windows.size());
|
|
WindowFramework *wf = _windows[n];
|
|
|
|
GraphicsWindow *win = wf->get_graphics_window();
|
|
if (win != (GraphicsWindow *)NULL) {
|
|
_engine.remove_window(win);
|
|
}
|
|
|
|
wf->close_window();
|
|
delete wf;
|
|
_windows.erase(_windows.begin() + n);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::close_all_windows
|
|
// Access: Public
|
|
// Description: Closes all currently open windows and empties the
|
|
// list of windows.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
close_all_windows() {
|
|
Windows::iterator wi;
|
|
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
|
WindowFramework *wf = (*wi);
|
|
|
|
GraphicsWindow *win = wf->get_graphics_window();
|
|
if (win != (GraphicsWindow *)NULL) {
|
|
_engine.remove_window(win);
|
|
}
|
|
|
|
wf->close_window();
|
|
delete wf;
|
|
}
|
|
|
|
_windows.clear();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::get_models
|
|
// Access: Public
|
|
// Description: Returns the root of the scene graph normally reserved
|
|
// for parenting models and such. This scene graph may
|
|
// be instanced to each window's render tree as the
|
|
// window is created.
|
|
////////////////////////////////////////////////////////////////////
|
|
const NodePath &PandaFramework::
|
|
get_models() {
|
|
if (_models.is_empty()) {
|
|
_models = NodePath("models");
|
|
}
|
|
return _models;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::report_frame_rate
|
|
// Access: Public
|
|
// Description: Reports the currently measured average frame rate to
|
|
// the indicated ostream.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
report_frame_rate(ostream &out) const {
|
|
double now = ClockObject::get_global_clock()->get_frame_time();
|
|
double delta = now - _start_time;
|
|
|
|
int frame_count = ClockObject::get_global_clock()->get_frame_count();
|
|
int num_frames = frame_count - _frame_count;
|
|
if (num_frames > 0) {
|
|
out << num_frames << " frames in " << delta << " seconds.\n";
|
|
double fps = ((double)num_frames) / delta;
|
|
out << fps << " fps average (" << 1000.0 / fps << "ms)\n";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::reset_frame_rate
|
|
// Access: Public
|
|
// Description: Resets the frame rate computation.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
reset_frame_rate() {
|
|
_start_time = ClockObject::get_global_clock()->get_frame_time();
|
|
_frame_count = ClockObject::get_global_clock()->get_frame_count();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::set_wireframe
|
|
// Access: Public
|
|
// Description: Sets the wireframe state on all windows.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
set_wireframe(bool enable) {
|
|
Windows::iterator wi;
|
|
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
|
WindowFramework *wf = (*wi);
|
|
wf->set_wireframe(enable);
|
|
}
|
|
|
|
_wireframe_enabled = enable;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::set_texture
|
|
// Access: Public
|
|
// Description: Sets the texture state on all windows.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
set_texture(bool enable) {
|
|
Windows::iterator wi;
|
|
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
|
WindowFramework *wf = (*wi);
|
|
wf->set_texture(enable);
|
|
}
|
|
|
|
_texture_enabled = enable;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::set_two_sided
|
|
// Access: Public
|
|
// Description: Sets the two_sided state on all windows.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
set_two_sided(bool enable) {
|
|
Windows::iterator wi;
|
|
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
|
WindowFramework *wf = (*wi);
|
|
wf->set_two_sided(enable);
|
|
}
|
|
|
|
_two_sided_enabled = enable;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::set_lighting
|
|
// Access: Public
|
|
// Description: Sets the lighting state on all windows.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
set_lighting(bool enable) {
|
|
Windows::iterator wi;
|
|
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
|
WindowFramework *wf = (*wi);
|
|
wf->set_lighting(enable);
|
|
}
|
|
|
|
_lighting_enabled = enable;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::set_highlight
|
|
// Access: Public
|
|
// Description: Sets the indicated node (normally a node within the
|
|
// get_models() tree) up as the highlighted node.
|
|
// Certain operations affect the highlighted node only.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
set_highlight(const NodePath &node) {
|
|
clear_highlight();
|
|
_highlight = node;
|
|
if (!_highlight.is_empty()) {
|
|
framework_cat.info(false) << _highlight << "\n";
|
|
_highlight.show_bounds();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::clear_highlight
|
|
// Access: Public
|
|
// Description: Unhighlights the currently highlighted node, if any.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
clear_highlight() {
|
|
if (!_highlight.is_empty()) {
|
|
_highlight.hide_bounds();
|
|
_highlight = NodePath();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::enable_default_keys
|
|
// Access: Public
|
|
// Description: Sets callbacks on the event handler to handle all of
|
|
// the normal viewer keys, like t to toggle texture, ESC
|
|
// or q to quit, etc.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
enable_default_keys() {
|
|
if (!_default_keys_enabled) {
|
|
do_enable_default_keys();
|
|
_default_keys_enabled = true;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::do_frame
|
|
// Access: Public, Virtual
|
|
// Description: Renders one frame and performs all associated
|
|
// processing. Returns true if we should continue
|
|
// rendering, false if we should exit. This is normally
|
|
// called only from main_loop().
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PandaFramework::
|
|
do_frame() {
|
|
nassertr(_is_open, false);
|
|
DataGraphTraverser dg_trav;
|
|
dg_trav.traverse(_data_root.node());
|
|
_event_handler.process_events();
|
|
_engine.render_frame();
|
|
|
|
return !_exit_flag;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::main_loop
|
|
// Access: Public
|
|
// Description: Called to yield control to the panda framework. This
|
|
// function does not return until set_exit_flag() has
|
|
// been called.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
main_loop() {
|
|
while (do_frame()) {
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::make_window_framework
|
|
// Access: Protected, Virtual
|
|
// Description: Creates a new WindowFramework object. This is
|
|
// provided as a hook so derived PandaFramework classes
|
|
// can create custom WindowFramework objects.
|
|
////////////////////////////////////////////////////////////////////
|
|
WindowFramework *PandaFramework::
|
|
make_window_framework() {
|
|
return new WindowFramework(this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::make_default_pipe
|
|
// Access: Protected, Virtual
|
|
// Description: Creates the default GraphicsPipe that will contain
|
|
// all windows that are not opened on a specific pipe.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
make_default_pipe() {
|
|
// We use the GraphicsPipe factory to make us a renderable pipe
|
|
// without knowing exactly what kind of pipes we have available. We
|
|
// don't care, so long as we can render to it interactively.
|
|
|
|
// This depends on the shared library or libraries (DLL's to you
|
|
// Windows folks) that have been loaded in at runtime from the
|
|
// load-display Configrc variable.
|
|
GraphicsPipe::resolve_modules();
|
|
|
|
nout << "Known pipe types:" << endl;
|
|
GraphicsPipe::get_factory().write_types(nout, 2);
|
|
|
|
_default_pipe = GraphicsPipe::get_factory().
|
|
make_instance(InteractiveGraphicsPipe::get_class_type());
|
|
|
|
if (_default_pipe == (GraphicsPipe*)NULL) {
|
|
nout << "No interactive pipe is available! Check your Configrc!\n";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::do_enable_default_keys
|
|
// Access: Protected, Virtual
|
|
// Description: The implementation of enable_default_keys().
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
do_enable_default_keys() {
|
|
_event_handler.add_hook("escape", event_esc, this);
|
|
_event_handler.add_hook("q", event_esc, this);
|
|
_event_handler.add_hook("f", event_f, this);
|
|
_event_handler.add_hook("w", event_w, this);
|
|
_event_handler.add_hook("t", event_t, this);
|
|
_event_handler.add_hook("b", event_b, this);
|
|
_event_handler.add_hook("l", event_l, this);
|
|
_event_handler.add_hook("c", event_c, this);
|
|
_event_handler.add_hook("shift-l", event_L, this);
|
|
_event_handler.add_hook("h", event_h, this);
|
|
_event_handler.add_hook("arrow_up", event_arrow_up, this);
|
|
_event_handler.add_hook("arrow_down", event_arrow_down, this);
|
|
_event_handler.add_hook("arrow_left", event_arrow_left, this);
|
|
_event_handler.add_hook("arrow_right", event_arrow_right, this);
|
|
_event_handler.add_hook("shift-s", event_S, this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_esc
|
|
// Access: Protected, Static
|
|
// Description: Default handler for ESC or q key: exit the
|
|
// application.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_esc(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
self->_exit_flag = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_f
|
|
// Access: Protected, Static
|
|
// Description: Default handler for f key: report and reset frame
|
|
// rate.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_f(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
self->report_frame_rate(nout);
|
|
self->reset_frame_rate();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_w
|
|
// Access: Protected, Static
|
|
// Description: Default handler for w key: toggle wireframe.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_w(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
self->set_wireframe(!self->get_wireframe());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_t
|
|
// Access: Protected, Static
|
|
// Description: Default handler for t key: toggle texture.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_t(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
self->set_texture(!self->get_texture());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_b
|
|
// Access: Protected, Static
|
|
// Description: Default handler for b key: toggle backface (two-sided
|
|
// rendering).
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_b(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
self->set_two_sided(!self->get_two_sided());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_l
|
|
// Access: Protected, Static
|
|
// Description: Default handler for l key: toggle lighting.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_l(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
self->set_lighting(!self->get_lighting());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_c
|
|
// Access: Protected, Static
|
|
// Description: Default handler for c key: center the trackball over
|
|
// the scene, or over the highlighted part of the scene.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_c(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
|
|
NodePath node = self->get_highlight();
|
|
if (node.is_empty()) {
|
|
node = self->get_models();
|
|
}
|
|
|
|
Windows::iterator wi;
|
|
for (wi = self->_windows.begin(); wi != self->_windows.end(); ++wi) {
|
|
WindowFramework *wf = (*wi);
|
|
wf->center_trackball(node);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_L
|
|
// Access: Protected, Static
|
|
// Description: Default handler for shift-L key: list the contents of
|
|
// the scene graph, or the highlighted node.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_L(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
|
|
NodePath node = self->get_highlight();
|
|
if (node.is_empty()) {
|
|
node = self->get_models();
|
|
}
|
|
|
|
node.ls();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_h
|
|
// Access: Protected, Static
|
|
// Description: Default handler for h key: toggle highlight mode. In
|
|
// this mode, you can walk the scene graph with the
|
|
// arrow keys to highlight different nodes.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_h(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
|
|
if (self->has_highlight()) {
|
|
self->clear_highlight();
|
|
} else {
|
|
self->set_highlight(self->get_models());
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_arrow_up
|
|
// Access: Protected, Static
|
|
// Description: Default handler for up arrow key: in highlight mode,
|
|
// move the highlight to the node's parent.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_arrow_up(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
|
|
if (self->has_highlight()) {
|
|
NodePath node = self->get_highlight();
|
|
if (node.has_parent() && node != self->get_models()) {
|
|
self->set_highlight(node.get_parent());
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_arrow_down
|
|
// Access: Protected, Static
|
|
// Description: Default handler for up arrow key: in highlight mode,
|
|
// move the highlight to the node's first child.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_arrow_down(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
|
|
if (self->has_highlight()) {
|
|
NodePath node = self->get_highlight();
|
|
if (node.get_num_children() > 0) {
|
|
self->set_highlight(node.get_child(0));
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_arrow_left
|
|
// Access: Protected, Static
|
|
// Description: Default handler for up arrow key: in highlight mode,
|
|
// move the highlight to the node's nearest sibling on
|
|
// the left.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_arrow_left(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
|
|
if (self->has_highlight()) {
|
|
NodePath node = self->get_highlight();
|
|
NodePath parent = node.get_parent();
|
|
if (node.has_parent() && node != self->get_models()) {
|
|
int index = parent.node()->find_child(node.node());
|
|
nassertv(index >= 0);
|
|
int sibling = index - 1;
|
|
if (sibling >= 0) {
|
|
self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_arrow_right
|
|
// Access: Protected, Static
|
|
// Description: Default handler for up arrow key: in highlight mode,
|
|
// move the highlight to the node's nearest sibling on
|
|
// the right.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_arrow_right(CPT_Event, void *data) {
|
|
PandaFramework *self = (PandaFramework *)data;
|
|
|
|
if (self->has_highlight()) {
|
|
NodePath node = self->get_highlight();
|
|
NodePath parent = node.get_parent();
|
|
if (node.has_parent() && node != self->get_models()) {
|
|
int index = parent.node()->find_child(node.node());
|
|
nassertv(index >= 0);
|
|
int num_children = parent.node()->get_num_children();
|
|
int sibling = index + 1;
|
|
if (sibling < num_children) {
|
|
self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PandaFramework::event_S
|
|
// Access: Protected, Static
|
|
// Description: Default handler for shift-S key: activate stats.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PandaFramework::
|
|
event_S(CPT_Event, void *data) {
|
|
#ifdef DO_PSTATS
|
|
nout << "Connecting to stats host" << endl;
|
|
PStatClient::connect();
|
|
#else
|
|
nout << "Stats host not supported." << endl;
|
|
#endif
|
|
}
|