show_through()

This commit is contained in:
David Rose 2006-03-20 20:48:26 +00:00
parent 21727aca0c
commit 725e82e6f4
37 changed files with 656 additions and 127 deletions

View File

@ -47,7 +47,7 @@ CollisionNode(const string &name) :
_collide_geom(false)
{
// CollisionNodes are hidden by default.
set_draw_mask(DrawMask::all_off());
set_overall_hidden(true);
// CollisionNodes have a certain set of bits on by default.
set_into_collide_mask(get_default_collide_mask());
@ -262,6 +262,21 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionNode::is_renderable
// Access: Public, Virtual
// Description: 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 CollisionNode::
is_renderable() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: CollisionNode::output

View File

@ -51,6 +51,7 @@ public:
virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
virtual bool is_renderable() const;
virtual void output(ostream &out) const;

View File

@ -82,9 +82,6 @@ ConfigVariableBool egg_rigid_geometry
"geometry has to be vertex-animated, but there will tend to be "
"more separate pieces."));
ConfigVariableBool egg_show_collision_solids
("egg-show-collision-solids", false);
ConfigVariableBool egg_load_old_curves
("egg-load-old-curves", true,
PRC_DESC("When this is true, a <NurbsCurve> entry appearing in an egg file "

View File

@ -45,7 +45,6 @@ extern EXPCL_PANDAEGG ConfigVariableBool egg_unify;
extern EXPCL_PANDAEGG ConfigVariableDouble egg_flatten_radius;
extern EXPCL_PANDAEGG ConfigVariableBool egg_combine_geoms;
extern EXPCL_PANDAEGG ConfigVariableBool egg_rigid_geometry;
extern EXPCL_PANDAEGG ConfigVariableBool egg_show_collision_solids;
extern EXPCL_PANDAEGG ConfigVariableBool egg_load_old_curves;
extern EXPCL_PANDAEGG ConfigVariableBool egg_load_classic_nurbs_curves;
extern EXPCL_PANDAEGG ConfigVariableBool egg_accept_errors;

View File

@ -1596,10 +1596,6 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
}
node = create_group_arc(egg_group, parent, node);
if (!egg_show_collision_solids) {
node->set_draw_mask(DrawMask::all_off());
}
return node;
} else if (egg_group->get_portal_flag()) {

View File

@ -107,6 +107,9 @@ get_display_region(int n) const {
////////////////////////////////////////////////////////////////////
INLINE void Camera::
set_camera_mask(DrawMask mask) {
// You shouldn't attempt to use Panda's reserved "overall" bit as a
// camera mask.
nassertv((mask & PandaNode::get_overall_bit()).is_zero());
_camera_mask = mask;
}

View File

@ -32,7 +32,7 @@ Camera::
Camera(const string &name) :
LensNode(name),
_active(true),
_camera_mask(DrawMask::all_on()),
_camera_mask(~PandaNode::get_overall_bit()),
_initial_state(RenderState::make_empty())
{
}

View File

@ -152,7 +152,9 @@ traverse(CullTraverserData &data) {
if (data.is_in_view(_camera_mask)) {
if (pgraph_cat.is_spam()) {
pgraph_cat.spam() << "\n" << data._node_path << "\n";
pgraph_cat.spam()
<< "\n" << data._node_path
<< " " << data._draw_mask << "\n";
}
PandaNode *node = data.node();
@ -189,29 +191,33 @@ traverse(CullTraverserData &data) {
// Function: CullTraverser::traverse_below
// Access: Public
// Description: Traverses all the children of the indicated node,
// with the given data, which been converted into the
// node's space.
// with the given data, which has been converted into
// the node's space.
////////////////////////////////////////////////////////////////////
void CullTraverser::
traverse_below(CullTraverserData &data) {
_nodes_pcollector.add_level(1);
PandaNode *node = data.node();
bool visible = !(data._draw_mask & PandaNode::get_overall_bit()).is_zero() &&
!(data._draw_mask & _camera_mask).is_zero();
const RenderEffects *node_effects = node->get_effects();
bool has_decal = node_effects->has_decal();
bool has_decal = visible && node_effects->has_decal();
if (has_decal && !_depth_offset_decals) {
// Start the three-pass decal rendering if we're not using
// DepthOffsetAttribs to implement decals.
start_decal(data);
} else {
if (node->is_geom_node()) {
if (visible && node->is_geom_node()) {
_geom_nodes_pcollector.add_level(1);
GeomNode *geom_node = DCAST(GeomNode, node);
if (pgraph_cat.is_spam()) {
pgraph_cat.spam()
<< "Found " << *geom_node << " in state " << *data._state << "\n";
<< "Found " << *geom_node << " in state " << *data._state
<< " draw_mask = " << data._draw_mask << "\n";
}
// Get all the Geoms, with no decalling.

View File

@ -32,7 +32,8 @@ CullTraverserData(const NodePath &start,
_state(state),
_view_frustum(view_frustum),
_guard_band(guard_band),
_cull_planes(CullPlanes::make_empty())
_cull_planes(CullPlanes::make_empty()),
_draw_mask(DrawMask::all_on())
{
}
@ -48,7 +49,8 @@ CullTraverserData(const CullTraverserData &copy) :
_state(copy._state),
_view_frustum(copy._view_frustum),
_guard_band(copy._guard_band),
_cull_planes(copy._cull_planes)
_cull_planes(copy._cull_planes),
_draw_mask(copy._draw_mask)
{
}
@ -65,6 +67,7 @@ operator = (const CullTraverserData &copy) {
_view_frustum = copy._view_frustum;
_guard_band = copy._guard_band;
_cull_planes = copy._cull_planes;
_draw_mask = copy._draw_mask;
}
////////////////////////////////////////////////////////////////////
@ -80,7 +83,8 @@ CullTraverserData(const CullTraverserData &parent, PandaNode *child) :
_state(parent._state),
_view_frustum(parent._view_frustum),
_guard_band(parent._guard_band),
_cull_planes(parent._cull_planes)
_cull_planes(parent._cull_planes),
_draw_mask(parent._draw_mask)
{
}
@ -130,7 +134,7 @@ is_in_view(const DrawMask &camera_mask) {
return false;
}
if ((node()->get_draw_mask() & camera_mask).is_zero()) {
if (!node()->compare_draw_mask(_draw_mask, camera_mask)) {
// If there are no draw bits in common with the camera, the node
// is out.
return false;
@ -146,29 +150,3 @@ is_in_view(const DrawMask &camera_mask) {
// Otherwise, compare the bounding volume to the frustum.
return is_in_view_impl();
}
////////////////////////////////////////////////////////////////////
// Function: CullTraverserData::test_within_clip_planes
// Access: Public
// Description: Returns the BoundingVolume intersection bits
// appropriate for the intersection of the current clip
// planes with the current node.
//
// That is, if the current node is within all clip
// planes (and will not be clipped at all), returns
// BoundingVolume::IF_all. If it is completely behind
// at least one clip plane, returns
// BoundingVolume::IF_intersection. If it is partially
// behind one or more clip planes, returns
// BoundingVolume::IF_some.
////////////////////////////////////////////////////////////////////
INLINE int CullTraverserData::
test_within_clip_planes(const CullTraverser *trav) const {
const ClipPlaneAttrib *cpa = _state->get_clip_plane();
if (cpa != (ClipPlaneAttrib *)NULL) {
return test_within_clip_planes_impl(trav, cpa);
}
// No clip plane attrib; therefore, the node is not clipped at
// all.
return BoundingVolume::IF_all | BoundingVolume::IF_possible | BoundingVolume::IF_some;
}

View File

@ -62,6 +62,7 @@ apply_transform_and_state(CullTraverser *trav) {
string tag_state = node->get_tag(trav->get_tag_state_key());
node_state = node_state->compose(camera->get_tag_state(tag_state));
}
node->compose_draw_mask(_draw_mask);
apply_transform_and_state(trav, node->get_transform(),
node_state, node->get_effects(),

View File

@ -64,7 +64,6 @@ public:
CPT(TransformState) get_net_transform(const CullTraverser *trav) const;
INLINE bool is_in_view(const DrawMask &camera_mask);
INLINE int test_within_clip_planes(const CullTraverser *trav) const;
void apply_transform_and_state(CullTraverser *trav);
void apply_transform_and_state(CullTraverser *trav,
@ -79,6 +78,7 @@ public:
PT(GeometricBoundingVolume) _view_frustum;
PT(GeometricBoundingVolume) _guard_band;
CPT(CullPlanes) _cull_planes;
DrawMask _draw_mask;
private:
bool is_in_view_impl();

View File

@ -149,8 +149,7 @@ consider_node(NodePathCollection &result, FindApproxLevelEntry *&next_level,
void FindApproxLevelEntry::
consider_next_step(PandaNode *child_node, FindApproxLevelEntry *&next_level,
int increment) const {
if (!_approx_path.return_hidden() &&
child_node->get_draw_mask().is_zero()) {
if (!_approx_path.return_hidden() && child_node->is_overall_hidden()) {
// If the approx path does not allow us to return hidden nodes,
// and this node has indeed been completely hidden, then stop
// here.

View File

@ -363,6 +363,21 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
return next_transform;
}
////////////////////////////////////////////////////////////////////
// Function: GeomNode::is_renderable
// Access: Public, Virtual
// Description: 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 GeomNode::
is_renderable() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: GeomNode::get_legal_collide_mask
// Access: Published, Virtual

View File

@ -53,6 +53,7 @@ public:
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
bool &found_any,
const TransformState *transform) const;
virtual bool is_renderable() const;
virtual CollideMask get_legal_collide_mask() const;
PUBLISHED:

View File

@ -1884,11 +1884,14 @@ adjust_all_priorities(int adjustment) {
// Description: Undoes the effect of a previous hide() on this node:
// makes the referenced node (and the entire subgraph
// below this node) visible to all cameras.
//
// This will not reveal the node if a parent node has
// been hidden.
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
show() {
nassertv_always(!is_empty());
node()->set_draw_mask(DrawMask::all_on());
node()->adjust_draw_mask(DrawMask::all_off(), DrawMask::all_off(), PandaNode::get_overall_bit());
}
////////////////////////////////////////////////////////////////////
@ -1896,13 +1899,52 @@ show() {
// Access: Published
// Description: Makes the referenced node visible just to the
// cameras whose camera_mask shares the indicated bits.
// That is, this sets the indicated bits in the
// node's draw mask.
//
// This undoes the effect of a previous hide() call. It
// will not reveal the node if a parent node has been
// hidden. However, see show_through().
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
show(DrawMask camera_mask) {
nassertv_always(!is_empty());
node()->set_draw_mask(node()->get_draw_mask() | camera_mask);
camera_mask &= ~PandaNode::get_overall_bit();
node()->adjust_draw_mask(DrawMask::all_off(), DrawMask::all_off(), camera_mask);
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::show_through
// Access: Published
// Description: Makes the referenced node visible just to the
// cameras whose camera_mask shares the indicated bits.
//
// Unlike show(), this will reveal the node even if a
// parent node has been hidden, thus "showing through" a
// parent's hide().
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
show_through() {
nassertv_always(!is_empty());
node()->adjust_draw_mask(PandaNode::get_overall_bit(), DrawMask::all_off(), DrawMask::all_off());
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::show_through
// Access: Published
// Description: Makes the referenced node visible just to the
// cameras whose camera_mask shares the indicated bits.
//
// Unlike show(), this will reveal the node even if a
// parent node has been hidden via the one-parameter
// hide() method, thus "showing through" a parent's
// hide(). (However, it will not show through a
// parent's hide() call if the no-parameter form of
// hide() was used.)
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
show_through(DrawMask camera_mask) {
nassertv_always(!is_empty());
camera_mask &= ~PandaNode::get_overall_bit();
node()->adjust_draw_mask(camera_mask, DrawMask::all_off(), DrawMask::all_off());
}
////////////////////////////////////////////////////////////////////
@ -1917,7 +1959,7 @@ show(DrawMask camera_mask) {
INLINE void NodePath::
hide() {
nassertv_always(!is_empty());
node()->set_draw_mask(DrawMask::all_off());
node()->adjust_draw_mask(DrawMask::all_off(), PandaNode::get_overall_bit(), DrawMask::all_off());
}
////////////////////////////////////////////////////////////////////
@ -1925,13 +1967,17 @@ hide() {
// Access: Published
// Description: Makes the referenced node invisible just to the
// cameras whose camera_mask shares the indicated bits.
// That is, this clears the indicated bits from the
// node's draw mask.
//
// This will also hide any nodes below this node in the
// scene graph, including those nodes for which show()
// has been called, but it will not hide descendent
// nodes for which show_through() has been called.
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
hide(DrawMask camera_mask) {
nassertv_always(!is_empty());
node()->set_draw_mask(node()->get_draw_mask() & ~camera_mask);
camera_mask &= ~PandaNode::get_overall_bit();
node()->adjust_draw_mask(DrawMask::all_off(), camera_mask, DrawMask::all_off());
}
////////////////////////////////////////////////////////////////////

View File

@ -5154,7 +5154,8 @@ get_hidden_ancestor(DrawMask camera_mask) const {
comp != (NodePathComponent *)NULL;
comp = comp->get_next(pipeline_stage)) {
PandaNode *node = comp->get_node();
if ((node->get_draw_mask() & camera_mask).is_zero()) {
if (node->is_overall_hidden() ||
((node->get_draw_show_mask() | ~node->get_draw_control_mask()) & camera_mask).is_zero()) {
NodePath result;
result._head = comp;
return result;

View File

@ -738,10 +738,12 @@ PUBLISHED:
// Variants on show and hide
INLINE void show();
INLINE void show(DrawMask camera_mask);
INLINE void show_through();
INLINE void show_through(DrawMask camera_mask);
INLINE void hide();
INLINE void hide(DrawMask camera_mask);
INLINE bool is_hidden(DrawMask camera_mask = DrawMask::all_on()) const;
NodePath get_hidden_ancestor(DrawMask camera_mask = DrawMask::all_on()) const;
INLINE bool is_hidden(DrawMask camera_mask = PandaNode::get_overall_bit()) const;
NodePath get_hidden_ancestor(DrawMask camera_mask = PandaNode::get_overall_bit()) const;
void stash(int sort = 0);
void unstash(int sort = 0);

View File

@ -17,6 +17,63 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: PandaNode::compose_draw_mask
// Access: Public
// Description: Computes the result of applying this node's draw
// masks to a running draw mask, as during a traversal.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
compose_draw_mask(DrawMask &running_draw_mask) const {
CDHeavyReader cdata(_cycler_heavy);
running_draw_mask = (running_draw_mask & ~cdata->_draw_control_mask) |
(cdata->_draw_show_mask & cdata->_draw_control_mask);
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::compare_draw_mask
// Access: Public
// Description: Compares the running draw mask computed during a
// traversal with this node's net draw masks. Returns
// true if the node should be traversed into, or false
// if there is nothing at this level or below that will
// be visible to the indicated camera_mask.
////////////////////////////////////////////////////////////////////
INLINE bool PandaNode::
compare_draw_mask(DrawMask running_draw_mask, DrawMask camera_mask) const {
DrawMask net_draw_control_mask, net_draw_show_mask;
int pipeline_stage = Thread::get_current_pipeline_stage();
CDBoundsStageReader cdata(_cycler_bounds, pipeline_stage);
if (cdata->_last_update != cdata->_next_update) {
// The cache is stale; it needs to be rebuilt.
CDBoundsStageWriter cdataw =
((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
net_draw_control_mask = cdataw->_net_draw_control_mask;
net_draw_show_mask = cdataw->_net_draw_show_mask;
} else {
net_draw_control_mask = cdata->_net_draw_control_mask;
net_draw_show_mask = cdata->_net_draw_show_mask;
}
// Now the bits that are not in net_draw_control_mask--that is,
// those bits that are not changed by any of the nodes at this level
// and below--are taken from running_draw_mask, which is inherited
// from above. On the other hand, the bits that *are* in
// net_draw_control_mask--those bits that are changed by any of the
// nodes at this level and below--are taken from net_draw_show_mask,
// which is propagated upwards from below.
// This way, we will traverse into this node if it has any children
// which want to be visited by the traversal, but we will avoid
// traversing into it if all of its children are hidden to this
// camera.
DrawMask compare_mask = (running_draw_mask & ~net_draw_control_mask) | (net_draw_show_mask & net_draw_control_mask);
return !((compare_mask & _overall_bit).is_zero()) && !((compare_mask & camera_mask).is_zero());
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_num_parents
// Access: Published
@ -431,15 +488,75 @@ ls(ostream &out, int indent_level) const {
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_draw_mask
// Access: Published
// Description: Returns the hide/show bits of this particular node.
// See set_draw_mask().
// Function: PandaNode::get_overall_bit
// Access: Published, Static
// Description: Returns the special bit that, when specifically
// cleared in the node's DrawMask, indicates that the
// node is hidden to all cameras, regardless of the
// remaining DrawMask bits.
////////////////////////////////////////////////////////////////////
INLINE DrawMask PandaNode::
get_draw_mask() const {
get_overall_bit() {
return _overall_bit;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::is_overall_hidden
// Access: Published, Static
// Description: Returns true if the node has been hidden to all
// cameras by clearing its overall bit.
////////////////////////////////////////////////////////////////////
INLINE bool PandaNode::
is_overall_hidden() const {
CDHeavyReader cdata(_cycler_heavy);
return cdata->_draw_mask;
return ((cdata->_draw_show_mask | ~cdata->_draw_control_mask) & _overall_bit).is_zero();
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_overall_hidden
// Access: Published
// Description: Sets or clears the hidden flag. When the hidden flag
// is true, the node and all of its children are
// invisible to all cameras, regardless of the setting
// of any draw masks. Setting the hidden flag to false
// restores the previous visibility as established by
// the draw masks.
//
// This actually works by twiddling the reserved
// _overall_bit in the node's draw mask, which has
// special meaning.
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
set_overall_hidden(bool hidden) {
if (hidden) {
adjust_draw_mask(DrawMask::all_off(), _overall_bit, DrawMask::all_off());
} else {
adjust_draw_mask(DrawMask::all_off(), DrawMask::all_off(), _overall_bit);
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_draw_control_mask
// Access: Published
// Description: Returns the set of bits in draw_show_mask that are
// considered meaningful. See adjust_draw_mask().
////////////////////////////////////////////////////////////////////
INLINE DrawMask PandaNode::
get_draw_control_mask() const {
CDHeavyReader cdata(_cycler_heavy);
return cdata->_draw_control_mask;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_draw_show_mask
// Access: Published
// Description: Returns the hide/show bits of this particular node.
// See adjust_draw_mask().
////////////////////////////////////////////////////////////////////
INLINE DrawMask PandaNode::
get_draw_show_mask() const {
CDHeavyReader cdata(_cycler_heavy);
return cdata->_draw_show_mask;
}
////////////////////////////////////////////////////////////////////
@ -791,7 +908,8 @@ CDataLight() {
INLINE PandaNode::CDataHeavy::
CDataHeavy() {
_effects = RenderEffects::make_empty();
_draw_mask = DrawMask::all_on();
_draw_control_mask = DrawMask::all_off();
_draw_show_mask = DrawMask::all_on();
_into_collide_mask = CollideMask::all_off();
_user_bounds = NULL;
_internal_bounds = NULL;
@ -807,6 +925,8 @@ CDataHeavy() {
INLINE PandaNode::CDataBounds::
CDataBounds() {
_net_collide_mask = CollideMask::all_off();
_net_draw_control_mask = DrawMask::all_off();
_net_draw_show_mask = DrawMask::all_off();
++_next_update;
}

View File

@ -28,6 +28,11 @@
#include "clipPlaneAttrib.h"
#include "boundingSphere.h"
// This category is just temporary for debugging convenience.
NotifyCategoryDecl(drawmask, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDef(drawmask, "");
DrawMask PandaNode::_overall_bit = DrawMask::bit(31);
TypeHandle PandaNode::_type_handle;
//
@ -132,7 +137,8 @@ PandaNode(const PandaNode &copy) :
CDHeavyWriter cdata(_cycler_heavy);
cdata->_effects = copy_cdata->_effects;
cdata->_tag_data = copy_cdata->_tag_data;
cdata->_draw_mask = copy_cdata->_draw_mask;
cdata->_draw_control_mask = copy_cdata->_draw_control_mask;
cdata->_draw_show_mask = copy_cdata->_draw_show_mask;
cdata->_into_collide_mask = copy_cdata->_into_collide_mask;
cdata->_user_bounds = copy_cdata->_user_bounds;
cdata->_internal_bounds = NULL;
@ -507,6 +513,21 @@ get_visible_child() const {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::is_renderable
// Access: Public, Virtual
// Description: 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 PandaNode::
is_renderable() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::copy_subgraph
// Access: Published
@ -1380,36 +1401,124 @@ list_tags(ostream &out, const string &separator) const {
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_draw_mask
// Function: PandaNode::adjust_draw_mask
// Access: Published
// Description: Sets the hide/show bits of this particular node.
// Description: Adjusts the hide/show bits of this particular node.
//
// During the cull traversal, a node is not visited if
// none of its draw mask bits intersect with the
// camera's draw mask bits. These masks can be used to
// selectively hide and show different parts of the
// scene graph from different cameras that are otherwise
// viewing the same scene. See
// Camera::set_camera_mask().
// These three parameters can be used to adjust the
// _draw_control_mask and _draw_show_mask independently,
// which work together to provide per-camera visibility
// for the node and its descendents.
//
// _draw_control_mask indicates the bits in
// _draw_show_mask that are significant. Each different
// bit corresponds to a different camera (and these bits
// are assigned via Camera::set_camera_mask()).
//
// Where _draw_control_mask has a 1 bit, a 1 bit in
// _draw_show_mask indicates the node is visible to that
// camera, and a 0 bit indicates the node is hidden to
// that camera. Where _draw_control_mask is 0, the node
// is hidden only if a parent node is hidden.
//
// The meaning of the three parameters is as follows:
//
// * Wherever show_mask is 1, _draw_show_mask and
// _draw_control_mask will be set 1. Thus, show_mask
// indicates the set of cameras to which the node should
// be shown.
//
// * Wherever hide_mask is 1, _draw_show_mask will be
// set 0 and _draw_control_mask will be set 1. Thus,
// hide_mask indicates the set of cameras from which the
// node should be hidden.
//
// * Wherever clear_mask is 1, _draw_control_mask will
// be set 0. Thus, clear_mask indicates the set of
// cameras from which the hidden state should be
// inherited from a parent.
////////////////////////////////////////////////////////////////////
void PandaNode::
set_draw_mask(DrawMask mask) {
adjust_draw_mask(DrawMask show_mask, DrawMask hide_mask, DrawMask clear_mask) {
bool any_changed = false;
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy) {
CDHeavyStageWriter cdata(_cycler_heavy, pipeline_stage);
if (cdata->_draw_mask != mask) {
cdata->_draw_mask = mask;
DrawMask draw_control_mask = (cdata->_draw_control_mask | show_mask | hide_mask) & ~clear_mask;
DrawMask draw_show_mask = (cdata->_draw_show_mask | show_mask) & ~hide_mask;
// The uncontrolled bits are implicitly on.
draw_show_mask |= ~draw_control_mask;
if (cdata->_draw_control_mask != draw_control_mask ||
cdata->_draw_show_mask != draw_show_mask) {
cdata->_draw_control_mask = draw_control_mask;
cdata->_draw_show_mask = draw_show_mask;
any_changed = true;
}
}
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler_heavy);
if (any_changed) {
mark_bounds_stale();
draw_mask_changed();
}
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_net_draw_control_mask
// Access: Published
// Description: Returns the set of bits in get_net_draw_show_mask()
// that have been explicitly set via adjust_draw_mask(),
// rather than implicitly inherited.
//
// A 1 bit in any position of this mask indicates that
// (a) this node has renderable children, and (b) some
// child of this node has made an explicit hide() or
// show_through() call for the corresponding bit.
////////////////////////////////////////////////////////////////////
DrawMask PandaNode::
get_net_draw_control_mask() const {
int pipeline_stage = Thread::get_current_pipeline_stage();
CDBoundsStageReader cdata(_cycler_bounds, pipeline_stage);
if (cdata->_last_update != cdata->_next_update) {
// The cache is stale; it needs to be rebuilt.
CDBoundsStageWriter cdataw =
((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
return cdataw->_net_draw_control_mask;
}
return cdata->_net_draw_control_mask;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::get_net_draw_show_mask
// Access: Published
// Description: Returns the union of all draw_show_mask values--of
// renderable nodes only--at this level and below. If
// any bit in this mask is 0, there is no reason to
// traverse below this node for a camera with the
// corresponding camera_mask.
//
// The bits in this mask that do not correspond to a 1
// bit in the net_draw_control_mask are meaningless (and
// will be set to 1). For bits that *do* correspond to
// a 1 bit in the net_draw_control_mask, a 1 bit
// indicates that at least one child should be visible,
// while a 0 bit indicates that all children are hidden.
////////////////////////////////////////////////////////////////////
DrawMask PandaNode::
get_net_draw_show_mask() const {
int pipeline_stage = Thread::get_current_pipeline_stage();
CDBoundsStageReader cdata(_cycler_bounds, pipeline_stage);
if (cdata->_last_update != cdata->_next_update) {
// The cache is stale; it needs to be rebuilt.
CDBoundsStageWriter cdataw =
((PandaNode *)this)->update_bounds(pipeline_stage, cdata);
return cdataw->_net_draw_show_mask;
}
return cdata->_net_draw_show_mask;
}
////////////////////////////////////////////////////////////////////
// Function: PandaNode::set_into_collide_mask
// Access: Published
@ -1536,6 +1645,26 @@ write(ostream &out, int indent_level) const {
if (!effects->is_empty()) {
out << " " << *effects;
}
DrawMask draw_control_mask = get_draw_control_mask();
if (!draw_control_mask.is_zero()) {
DrawMask draw_show_mask = get_draw_show_mask();
if (!(draw_control_mask & _overall_bit).is_zero()) {
if (!(draw_show_mask & _overall_bit).is_zero()) {
out << " (show_through)";
} else {
out << " (hidden)";
}
}
if (!(draw_control_mask & ~_overall_bit).is_zero()) {
draw_control_mask &= ~_overall_bit;
if (!(draw_show_mask & draw_control_mask).is_zero()) {
out << " (per-camera show_through)";
}
if (!(~draw_show_mask & draw_control_mask).is_zero()) {
out << " (per-camera hidden)";
}
}
}
out << "\n";
}
@ -2633,6 +2762,10 @@ PandaNode::CDBoundsStageWriter PandaNode::
update_bounds(int pipeline_stage, PandaNode::CDBoundsStageReader &cdata) {
// We might need to try this a couple of times, in case someone else
// steps on our result.
if (drawmask_cat.is_debug()) {
drawmask_cat.debug(false)
<< *this << "::update_bounds() {\n";
}
do {
// Grab the last_update counter, then release the lock.
UpdateSeq last_update = cdata->_last_update;
@ -2643,9 +2776,32 @@ update_bounds(int pipeline_stage, PandaNode::CDBoundsStageReader &cdata) {
// Start with a clean slate, or at least with the contents of the
// node itself.
CollideMask net_collide_mask;
DrawMask net_draw_control_mask, net_draw_show_mask;
DrawMask draw_control_mask, draw_show_mask;
bool renderable = is_renderable();
{
CDHeavyStageReader cdata(_cycler_heavy, pipeline_stage);
net_collide_mask = cdata->_into_collide_mask;
draw_control_mask = net_draw_control_mask = cdata->_draw_control_mask;
draw_show_mask = net_draw_show_mask = cdata->_draw_show_mask;
}
if (!renderable) {
// This is not a "renderable" node. This means that this node
// does not itself contribute any bits to net_draw_show_mask or
// net_draw_control_mask, but it may contribute some bits to any
// renderable nodes from below.
net_draw_show_mask = DrawMask::all_off();
net_draw_control_mask = DrawMask::all_off();
}
draw_show_mask |= ~draw_control_mask;
if (drawmask_cat.is_debug()) {
drawmask_cat.debug(false)
<< "net_draw_control_mask = " << net_draw_control_mask
<< "\nnet_draw_show_mask = " << net_draw_show_mask
<< "\ndraw_control_mask = " << draw_control_mask
<< "\ndraw_show_mask = " << draw_show_mask
<< "\n";
}
CPT(RenderAttrib) off_clip_planes;
{
@ -2683,6 +2839,37 @@ update_bounds(int pipeline_stage, PandaNode::CDBoundsStageReader &cdata) {
CDBoundsStageWriter child_cdataw = child->update_bounds(pipeline_stage, child_cdata);
net_collide_mask |= child_cdataw->_net_collide_mask;
DrawMask child_control_mask = child_cdataw->_net_draw_control_mask;
DrawMask child_show_mask = child_cdataw->_net_draw_show_mask;
if (child_control_mask != DrawMask::all_off() ||
child_show_mask != DrawMask::all_off()) {
// This child includes a renderable node or subtree. Thus,
// we should propagate its draw masks.
renderable = true;
// Compute the set of control bits that are defined on this
// node, but not on the child node.
DrawMask new_control_mask = draw_control_mask & ~child_control_mask;
// Anywhere we have a control bit that our child does not,
// the child inherits our show bit.
DrawMask new_child_show_mask = (child_show_mask & ~new_control_mask) | (draw_show_mask & new_control_mask);
DrawMask new_child_control_mask = child_control_mask | new_control_mask;
// Now merge that result with our accumulated draw masks.
net_draw_control_mask |= new_child_control_mask;
net_draw_show_mask |= new_child_show_mask;
}
if (drawmask_cat.is_debug()) {
drawmask_cat.debug(false)
<< "\nchild update " << *child << ":\n"
<< "child_control_mask = " << child_control_mask
<< "\nchild_show_mask = " << child_show_mask
<< "\nnet_draw_control_mask = " << net_draw_control_mask
<< "\nnet_draw_show_mask = " << net_draw_show_mask
<< "\n";
}
off_clip_planes = orig_cp->compose_off(child_cdataw->_off_clip_planes);
child_volumes_ref.push_back(child_cdataw->_external_bounds);
child_volumes.push_back(child_cdataw->_external_bounds);
@ -2690,12 +2877,43 @@ update_bounds(int pipeline_stage, PandaNode::CDBoundsStageReader &cdata) {
} else {
// Child is good.
net_collide_mask |= child_cdata->_net_collide_mask;
// See comments in similar block above.
DrawMask child_control_mask = child_cdata->_net_draw_control_mask;
DrawMask child_show_mask = child_cdata->_net_draw_show_mask;
if (child_control_mask != DrawMask::all_off() ||
child_show_mask != DrawMask::all_off()) {
renderable = true;
DrawMask new_control_mask = draw_control_mask & ~child_control_mask;
DrawMask new_child_show_mask = (child_show_mask & ~new_control_mask) | (draw_show_mask & new_control_mask);
DrawMask new_child_control_mask = child_control_mask | new_control_mask;
net_draw_control_mask |= new_child_control_mask;
net_draw_show_mask |= new_child_show_mask;
}
if (drawmask_cat.is_debug()) {
drawmask_cat.debug(false)
<< "\nchild fresh " << *child << ":\n"
<< "child_control_mask = " << child_control_mask
<< "\nchild_show_mask = " << child_show_mask
<< "\nnet_draw_control_mask = " << net_draw_control_mask
<< "\nnet_draw_show_mask = " << net_draw_show_mask
<< "\n";
}
off_clip_planes = orig_cp->compose_off(child_cdata->_off_clip_planes);
child_volumes_ref.push_back(child_cdata->_external_bounds);
child_volumes.push_back(child_cdata->_external_bounds);
}
}
if (renderable) {
// This is a "renderable" node. That means all draw_show_mask
// bits, not specifically set on or off, should be assumed to be
// on.
net_draw_show_mask |= ~net_draw_control_mask;
}
{
// Now grab the write lock on this node.
CDBoundsStageWriter cdataw(_cycler_bounds, pipeline_stage);
@ -2704,6 +2922,27 @@ update_bounds(int pipeline_stage, PandaNode::CDBoundsStageReader &cdata) {
// Great, no one has monkeyed with these while we were computing
// the cache. Safe to store the computed values and return.
cdataw->_net_collide_mask = net_collide_mask;
if (renderable) {
// There are renderable nodes below, so the implicit draw
// bits are all on.
cdataw->_net_draw_control_mask = net_draw_control_mask;
cdataw->_net_draw_show_mask = net_draw_show_mask | ~net_draw_control_mask;
if (drawmask_cat.is_debug()) {
drawmask_cat.debug(false)
<< "renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
}
} else {
// There are no renderable nodes below, so the implicit draw
// bits are all off.
cdataw->_net_draw_control_mask = net_draw_control_mask;
cdataw->_net_draw_show_mask = net_draw_show_mask;
if (drawmask_cat.is_debug()) {
drawmask_cat.debug(false)
<< "not renderable, set mask " << cdataw->_net_draw_show_mask << "\n";
}
}
cdataw->_off_clip_planes = off_clip_planes;
// Compute the bounding sphere around all of our child
@ -2722,6 +2961,11 @@ update_bounds(int pipeline_stage, PandaNode::CDBoundsStageReader &cdata) {
cdataw->_external_bounds = gbv;
cdataw->_last_update = next_update;
if (drawmask_cat.is_debug()) {
drawmask_cat.debug(false)
<< "} " << *this << "::update_bounds();\n";
}
return cdataw;
}
@ -2946,7 +3190,8 @@ PandaNode::CDataHeavy::
CDataHeavy(const PandaNode::CDataHeavy &copy) :
_effects(copy._effects),
_tag_data(copy._tag_data),
_draw_mask(copy._draw_mask),
_draw_control_mask(copy._draw_control_mask),
_draw_show_mask(copy._draw_show_mask),
_into_collide_mask(copy._into_collide_mask),
_user_bounds(copy._user_bounds),
_internal_bounds(copy._internal_bounds),
@ -2998,7 +3243,8 @@ void PandaNode::CDataHeavy::
write_datagram(BamWriter *manager, Datagram &dg) const {
manager->write_pointer(dg, _effects);
dg.add_uint32(_draw_mask.get_word());
dg.add_uint32(_draw_control_mask.get_word());
dg.add_uint32(_draw_show_mask.get_word());
dg.add_uint32(_into_collide_mask.get_word());
dg.add_uint32(_tag_data.size());
@ -3048,7 +3294,32 @@ fillin(DatagramIterator &scan, BamReader *manager) {
// Read the effects pointer.
manager->read_pointer(scan);
_draw_mask.set_word(scan.get_uint32());
if (manager->get_file_minor_ver() < 2) {
DrawMask draw_mask;
draw_mask.set_word(scan.get_uint32());
if (draw_mask == DrawMask::all_off()) {
// Hidden.
_draw_control_mask = _overall_bit;
_draw_show_mask = ~_overall_bit;
} else if (draw_mask == DrawMask::all_on()) {
// Normally visible.
_draw_control_mask = DrawMask::all_off();
_draw_show_mask = DrawMask::all_on();
} else {
// Some per-camera combination.
draw_mask &= ~_overall_bit;
_draw_control_mask = ~draw_mask;
_draw_show_mask = draw_mask;
}
} else {
_draw_control_mask.set_word(scan.get_uint32());
_draw_show_mask.set_word(scan.get_uint32());
}
_into_collide_mask.set_word(scan.get_uint32());
// Read in the tag list.
@ -3106,6 +3377,8 @@ dec_py_refs() {
PandaNode::CDataBounds::
CDataBounds(const PandaNode::CDataBounds &copy) :
_net_collide_mask(copy._net_collide_mask),
_net_draw_control_mask(copy._net_draw_control_mask),
_net_draw_show_mask(copy._net_draw_show_mask),
_off_clip_planes(copy._off_clip_planes),
_external_bounds(copy._external_bounds),
_last_update(copy._last_update),

View File

@ -103,6 +103,11 @@ public:
virtual int get_next_visible_child(int n) const;
virtual bool has_single_child_visibility() const;
virtual int get_visible_child() const;
virtual bool is_renderable() const;
INLINE void compose_draw_mask(DrawMask &running_draw_mask) const;
INLINE bool compare_draw_mask(DrawMask running_draw_mask,
DrawMask camera_mask) const;
PUBLISHED:
PT(PandaNode) copy_subgraph() const;
@ -180,8 +185,18 @@ PUBLISHED:
void copy_tags(PandaNode *other);
void list_tags(ostream &out, const string &separator = "\n") const;
void set_draw_mask(DrawMask mask);
INLINE DrawMask get_draw_mask() const;
INLINE static DrawMask get_overall_bit();
INLINE bool is_overall_hidden() const;
INLINE void set_overall_hidden(bool overall_hidden);
void adjust_draw_mask(DrawMask show_mask,
DrawMask hide_mask,
DrawMask clear_mask);
INLINE DrawMask get_draw_control_mask() const;
INLINE DrawMask get_draw_show_mask() const;
CollideMask get_net_draw_control_mask() const;
CollideMask get_net_draw_show_mask() const;
void set_into_collide_mask(CollideMask mask);
INLINE CollideMask get_into_collide_mask() const;
@ -406,8 +421,9 @@ private:
PythonTagData _python_tag_data;
#endif // HAVE_PYTHON
// This is the draw_mask of this particular node.
DrawMask _draw_mask;
// These two together determine the per-camera visibility of this
// node. See adjust_draw_mask() for details.
DrawMask _draw_control_mask, _draw_show_mask;
// This is the mask that indicates which CollisionNodes may detect
// a collision with this particular node. By default it is zero
@ -453,14 +469,15 @@ private:
}
// This is the union of all into_collide_mask bits for any nodes
// at and below this level. It's updated automatically whenever
// _stale_bounds is true.
// at and below this level.
CollideMask _net_collide_mask;
// These are similar, for the draw mask.
DrawMask _net_draw_control_mask, _net_draw_show_mask;
// This is a ClipPlaneAttrib that represents the union of all clip
// planes that have been turned *off* at and below this level. We
// piggyback this automatic update on _stale_bounds. TODO:
// fix the circular reference counts involved here.
// planes that have been turned *off* at and below this level.
// TODO: fix the circular reference counts involved here.
CPT(RenderAttrib) _off_clip_planes;
// This is the bounding volume around the _user_bounds, the
@ -521,6 +538,8 @@ private:
CDBoundsStageWriter update_bounds(int pipeline_stage,
CDBoundsStageReader &cdata);
static DrawMask _overall_bit;
public:
// This class is returned from get_children_copy(). Use it to walk
// through the list of children, particularly with a self-modifying

View File

@ -78,7 +78,7 @@ PlaneNode(const string &name, const Planef &plane) :
_priority(0)
{
// PlaneNodes are hidden by default.
set_draw_mask(DrawMask::all_off());
set_overall_hidden(true);
set_plane(plane);
}
@ -183,6 +183,21 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PlaneNode::is_renderable
// Access: Public, Virtual
// Description: 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 PlaneNode::
is_renderable() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PlaneNode::compute_internal_bounds
// Access: Protected, Virtual

View File

@ -53,6 +53,7 @@ public:
virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
virtual bool is_renderable() const;
PUBLISHED:
INLINE void set_plane(const Planef &plane);

View File

@ -334,6 +334,21 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PortalNode::is_renderable
// Access: Public, Virtual
// Description: 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 PortalNode::
is_renderable() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PortalNode::output

View File

@ -60,6 +60,7 @@ public:
virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
virtual bool is_renderable() const;
virtual void output(ostream &out) const;

View File

@ -343,8 +343,11 @@ operator () (const PandaNode *node1, const PandaNode *node2) const {
if (node1->get_effects() != node2->get_effects()) {
return node1->get_effects() < node2->get_effects();
}
if (node1->get_draw_mask() != node2->get_draw_mask()) {
return node1->get_draw_mask() < node2->get_draw_mask();
if (node1->get_draw_control_mask() != node2->get_draw_control_mask()) {
return node1->get_draw_control_mask() < node2->get_draw_control_mask();
}
if (node1->get_draw_show_mask() != node2->get_draw_show_mask()) {
return node1->get_draw_show_mask() < node2->get_draw_show_mask();
}
return 0;
@ -452,7 +455,8 @@ consider_child(PandaNode *grandparent_node, PandaNode *parent_node,
if (parent_node->get_transform() != child_node->get_transform() ||
parent_node->get_state() != child_node->get_state() ||
parent_node->get_effects() != child_node->get_effects() ||
parent_node->get_draw_mask() != child_node->get_draw_mask()) {
parent_node->get_draw_control_mask() != child_node->get_draw_control_mask() ||
parent_node->get_draw_show_mask() != child_node->get_draw_show_mask()) {
// The two nodes have a different state; too bad.
return false;
}

View File

@ -252,6 +252,21 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::is_renderable
// Access: Public, Virtual
// Description: 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 PGItem::
is_renderable() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PGItem::compute_internal_bounds
// Access: Protected, Virtual
@ -1025,7 +1040,7 @@ play_sound(const string &event) {
////////////////////////////////////////////////////////////////////
void PGItem::
reduce_region(LVecBase4f &frame, PGItem *obscurer) const {
if (obscurer != (PGItem *)NULL && !obscurer->get_draw_mask().is_zero()) {
if (obscurer != (PGItem *)NULL && !obscurer->is_overall_hidden()) {
LVecBase4f oframe = get_relative_frame(obscurer);
// Determine the four rectangular regions on the four sides of the

View File

@ -67,6 +67,7 @@ protected:
virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
virtual bool is_renderable() const;
virtual PT(BoundingVolume) compute_internal_bounds(int pipeline_stage) const;

View File

@ -267,18 +267,18 @@ remanage() {
// Now show or hide the sliders appropriately.
if (_horizontal_slider != (PGSliderBar *)NULL) {
if (got_horizontal) {
_horizontal_slider->set_draw_mask(DrawMask::all_on());
_horizontal_slider->set_overall_hidden(false);
} else {
_horizontal_slider->set_draw_mask(DrawMask::all_off());
_horizontal_slider->set_overall_hidden(true);
_horizontal_slider->set_ratio(0.0f);
horizontal_width = 0.0f;
}
}
if (_vertical_slider != (PGSliderBar *)NULL) {
if (got_vertical) {
_vertical_slider->set_draw_mask(DrawMask::all_on());
_vertical_slider->set_overall_hidden(false);
} else {
_vertical_slider->set_draw_mask(DrawMask::all_off());
_vertical_slider->set_overall_hidden(true);
_vertical_slider->set_ratio(0.0f);
vertical_width = 0.0f;
}
@ -288,14 +288,14 @@ remanage() {
// flag again indirectly; we clear it again to avoid a feedback
// loop.
_needs_remanage = false;
}
}
// Are either or both of the scroll bars hidden?
if (got_horizontal && _horizontal_slider->get_draw_mask().is_zero()) {
if (got_horizontal && _horizontal_slider->is_overall_hidden()) {
got_horizontal = false;
horizontal_width = 0.0f;
}
if (got_vertical && _vertical_slider->get_draw_mask().is_zero()) {
if (got_vertical && _vertical_slider->is_overall_hidden()) {
got_vertical = false;
vertical_width = 0.0f;
}

View File

@ -36,8 +36,9 @@ static const unsigned short _bam_major_ver = 6;
// Bumped to major version 5 on 5/6/05 for new Geom implementation.
// Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
static const unsigned short _bam_minor_ver = 1;
static const unsigned short _bam_minor_ver = 2;
// Bumped to minor version 1 on 3/12/06 to add Texture::_compression.
// Bumped to minor version 2 on 3/17/06 to add PandaNode::_draw_control_mask.
#endif

View File

@ -57,10 +57,11 @@ BitArray(const BitArray &copy) :
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void BitArray::
INLINE BitArray &BitArray::
operator = (const BitArray &copy) {
_array = copy._array;
_highest_bits = copy._highest_bits;
return *this;
}
////////////////////////////////////////////////////////////////////

View File

@ -47,7 +47,7 @@ PUBLISHED:
INLINE BitArray();
INLINE BitArray(WordType init_value);
INLINE BitArray(const BitArray &copy);
INLINE void operator = (const BitArray &copy);
INLINE BitArray &operator = (const BitArray &copy);
INLINE static BitArray all_on();
INLINE static BitArray all_off();

View File

@ -61,9 +61,10 @@ BitMask(const BitMask<WType, nbits> &copy) :
// Description:
////////////////////////////////////////////////////////////////////
template<class WType, int nbits>
INLINE void BitMask<WType, nbits>::
INLINE BitMask<WType, nbits> &BitMask<WType, nbits>::
operator = (const BitMask<WType, nbits> &copy) {
_word = copy._word;
return *this;
}
////////////////////////////////////////////////////////////////////

View File

@ -44,7 +44,7 @@ PUBLISHED:
INLINE BitMask();
INLINE BitMask(WordType init_value);
INLINE BitMask(const BitMask<WType, nbits> &copy);
INLINE void operator = (const BitMask<WType, nbits> &copy);
INLINE BitMask<WType, nbits> &operator = (const BitMask<WType, nbits> &copy);
INLINE static BitMask<WType, nbits> all_on();
INLINE static BitMask<WType, nbits> all_off();

View File

@ -194,24 +194,10 @@ write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< "TextNode " << get_name() << "\n";
TextProperties::write(out, indent_level + 2);
out << "\n";
LVecBase3f scale, shear, hpr, trans;
if (decompose_matrix(_transform, scale, shear, hpr, trans, _coordinate_system)) {
indent(out, indent_level + 2)
<< "transform is:\n"
<< " scale: " << scale << "\n"
<< " shear: " << shear << "\n"
<< " hpr: " << hpr << "\n"
<< " trans: " << hpr << "\n";
} else {
indent(out, indent_level + 2)
<< "transform is:\n" << _transform;
}
<< "transform is: " << *TransformState::make_mat(_transform) << "\n";
indent(out, indent_level + 2)
<< "in coordinate system " << _coordinate_system << "\n";
out << "\n";
indent(out, indent_level + 2)
<< "text is " << get_text() << "\n";
}
@ -569,6 +555,21 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::is_renderable
// Access: Public, Virtual
// Description: 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 TextNode::
is_renderable() const {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: TextNode::compute_internal_bound
// Access: Protected, Virtual

View File

@ -236,6 +236,7 @@ public:
virtual bool has_cull_callback() const;
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
virtual bool is_renderable() const;
virtual PT(BoundingVolume) compute_internal_bounds(int pipeline_stage) const;

View File

@ -1029,7 +1029,7 @@ set_no_mouse() {
if (_has_mouse) {
// Hide the mouse pointer.
if (!_geometry.is_null()) {
_geometry->set_draw_mask(DrawMask::all_off());
_geometry->set_overall_hidden(true);
}
}
@ -1053,7 +1053,7 @@ set_mouse(const LVecBase2f &xy, const LVecBase2f &pixel_xy) {
_geometry->set_transform(TransformState::make_pos(LVecBase3f(xy[0], 0, xy[1])));
if (!_has_mouse) {
// Show the mouse pointer.
_geometry->set_draw_mask(DrawMask::all_on());
_geometry->set_overall_hidden(false);
}
}

View File

@ -396,7 +396,7 @@ bool BamToEgg::
apply_node_properties(EggGroup *egg_group, PandaNode *node) {
bool any_applied = false;
if (node->get_draw_mask().is_zero()) {
if (node->is_overall_hidden()) {
// This node is hidden. We'll go ahead and convert it, but we'll
// put in the "backstage" flag to mean it's not real geometry.
egg_group->add_object_type("backstage");