mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
show_through()
This commit is contained in:
parent
21727aca0c
commit
725e82e6f4
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 "
|
||||
|
@ -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;
|
||||
|
@ -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()) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
{
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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 ©) :
|
||||
_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 ©) {
|
||||
_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;
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 ©) :
|
||||
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 ©) :
|
||||
_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 ©) :
|
||||
_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),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -57,10 +57,11 @@ BitArray(const BitArray ©) :
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BitArray::
|
||||
INLINE BitArray &BitArray::
|
||||
operator = (const BitArray ©) {
|
||||
_array = copy._array;
|
||||
_highest_bits = copy._highest_bits;
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -47,7 +47,7 @@ PUBLISHED:
|
||||
INLINE BitArray();
|
||||
INLINE BitArray(WordType init_value);
|
||||
INLINE BitArray(const BitArray ©);
|
||||
INLINE void operator = (const BitArray ©);
|
||||
INLINE BitArray &operator = (const BitArray ©);
|
||||
|
||||
INLINE static BitArray all_on();
|
||||
INLINE static BitArray all_off();
|
||||
|
@ -61,9 +61,10 @@ BitMask(const BitMask<WType, nbits> ©) :
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WType, int nbits>
|
||||
INLINE void BitMask<WType, nbits>::
|
||||
INLINE BitMask<WType, nbits> &BitMask<WType, nbits>::
|
||||
operator = (const BitMask<WType, nbits> ©) {
|
||||
_word = copy._word;
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -44,7 +44,7 @@ PUBLISHED:
|
||||
INLINE BitMask();
|
||||
INLINE BitMask(WordType init_value);
|
||||
INLINE BitMask(const BitMask<WType, nbits> ©);
|
||||
INLINE void operator = (const BitMask<WType, nbits> ©);
|
||||
INLINE BitMask<WType, nbits> &operator = (const BitMask<WType, nbits> ©);
|
||||
|
||||
INLINE static BitMask<WType, nbits> all_on();
|
||||
INLINE static BitMask<WType, nbits> all_off();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user