open_toontown_panda3d/panda/src/pgui/pgTop.cxx

148 lines
4.6 KiB
C++

/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file pgTop.cxx
* @author drose
* @date 2002-03-13
*/
#include "pgTop.h"
#include "pgMouseWatcherGroup.h"
#include "pgCullTraverser.h"
#include "cullBinAttrib.h"
#include "omniBoundingVolume.h"
TypeHandle PGTop::_type_handle;
/**
*
*/
PGTop::
PGTop(const string &name) :
PandaNode(name)
{
set_cull_callback();
_start_sort = 0;
// A PGTop node normally has an infinite bounding volume. Screw culling.
set_internal_bounds(new OmniBoundingVolume());
set_final(true);
// Also, screw state sorting. By default, everything under PGTop will be
// unsorted: rendered in scene graph order. This is closer to what the user
// wants anyway in a 2-d scene graph.
set_attrib(CullBinAttrib::make("unsorted", 0));
}
/**
*
*/
PGTop::
~PGTop() {
set_mouse_watcher((MouseWatcher *)NULL);
}
/**
* Returns a newly-allocated Node that is a shallow copy of this one. It will
* be a different Node pointer, but its internal data may or may not be shared
* with that of the original Node.
*/
PandaNode *PGTop::
make_copy() const {
return new PGTop(*this);
}
/**
* This function will be called during the cull traversal to perform any
* additional operations that should be performed at cull time. This may
* include additional manipulation of render state or additional
* visible/invisible decisions, or any other arbitrary operation.
*
* Note that this function will *not* be called unless set_cull_callback() is
* called in the constructor of the derived class. It is necessary to call
* set_cull_callback() to indicated that we require cull_callback() to be
* called.
*
* By the time this function is called, the node has already passed the
* bounding-volume test for the viewing frustum, and the node's transform and
* state have already been applied to the indicated CullTraverserData object.
*
* The return value is true if this node should be visible, or false if it
* should be culled.
*/
bool PGTop::
cull_callback(CullTraverser *trav, CullTraverserData &data) {
// We create a new MouseWatcherGroup for the purposes of collecting a new
// set of regions visible onscreen.
PT(PGMouseWatcherGroup) old_watcher_group;
if (_watcher_group != (PGMouseWatcherGroup *)NULL) {
_watcher_group->clear_top(this);
old_watcher_group = _watcher_group;
_watcher_group = new PGMouseWatcherGroup(this);
}
// Now subsitute for the normal CullTraverser a special one of our own
// choosing. This just carries around a pointer back to the PGTop node, for
// the convenience of PGItems to register themselves as they are drawn.
PGCullTraverser pg_trav(this, trav);
pg_trav.local_object();
pg_trav._sort_index = _start_sort;
pg_trav.traverse_below(data);
pg_trav.end_traverse();
// Now tell the watcher about the new set of regions. Strictly speaking, we
// shouldn't do this until the frame that we're about to render has been
// presented; otherwise, we may make regions active before they are actually
// visible. But no one has complained about this so far.
if (_watcher_group != (PGMouseWatcherGroup *)NULL) {
nassertr(_watcher != (MouseWatcher *)NULL, false);
_watcher->replace_group(old_watcher_group, _watcher_group);
}
// We've taken care of the traversal, thank you.
return false;
}
/**
* Returns true if there is some value to visiting this particular node during
* the cull traversal for any camera, false otherwise. This will be used to
* optimize the result of get_net_draw_show_mask(), so that any subtrees that
* contain only nodes for which is_renderable() is false need not be visited.
*/
bool PGTop::
is_renderable() const {
// We flag the PGTop as renderable, even though it technically doesn't have
// anything to render, but we do need the traverser to visit it every frame.
return true;
}
/**
* Sets the MouseWatcher pointer that the PGTop object registers its PG items
* with. This must be set before the PG items are active.
*/
void PGTop::
set_mouse_watcher(MouseWatcher *watcher) {
if (_watcher_group != (PGMouseWatcherGroup *)NULL) {
_watcher_group->clear_top(this);
}
if (_watcher != (MouseWatcher *)NULL) {
_watcher->remove_group(_watcher_group);
}
_watcher = watcher;
_watcher_group = (PGMouseWatcherGroup *)NULL;
if (_watcher != (MouseWatcher *)NULL) {
_watcher_group = new PGMouseWatcherGroup(this);
_watcher->add_group(_watcher_group);
}
}