mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 01:07:51 -04:00
dynamic TextFont; scene graph improvements to support this
This commit is contained in:
parent
8e63f99ee2
commit
2fa7929b45
@ -8,6 +8,7 @@
|
||||
#define TARGET pgraph
|
||||
|
||||
#define SOURCES \
|
||||
accumulatedAttribs.I accumulatedAttribs.h \
|
||||
alphaTestAttrib.I alphaTestAttrib.h \
|
||||
ambientLight.I ambientLight.h \
|
||||
bamFile.I bamFile.h \
|
||||
@ -91,6 +92,7 @@
|
||||
|
||||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
||||
#define INCLUDED_SOURCES \
|
||||
accumulatedAttribs.cxx \
|
||||
alphaTestAttrib.cxx \
|
||||
ambientLight.cxx \
|
||||
bamFile.cxx \
|
||||
@ -173,6 +175,7 @@
|
||||
workingNodePath.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
accumulatedAttribs.I accumulatedAttribs.h \
|
||||
alphaTestAttrib.I alphaTestAttrib.h \
|
||||
ambientLight.I ambientLight.h \
|
||||
bamFile.I bamFile.h \
|
||||
|
58
panda/src/pgraph/accumulatedAttribs.I
Normal file
58
panda/src/pgraph/accumulatedAttribs.I
Normal file
@ -0,0 +1,58 @@
|
||||
// Filename: accumulatedAttribs.I
|
||||
// Created by: drose (30Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AccumulatedAttribs::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AccumulatedAttribs::
|
||||
AccumulatedAttribs() {
|
||||
_transform = TransformState::make_identity();
|
||||
_other = RenderState::make_empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AccumulatedAttribs::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AccumulatedAttribs::
|
||||
AccumulatedAttribs(const AccumulatedAttribs ©) :
|
||||
_transform(copy._transform),
|
||||
_color(copy._color),
|
||||
_color_scale(copy._color_scale),
|
||||
_tex_matrix(copy._tex_matrix),
|
||||
_other(copy._other)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AccumulatedAttribs::Copy Assignment
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AccumulatedAttribs::
|
||||
operator = (const AccumulatedAttribs ©) {
|
||||
_transform = copy._transform;
|
||||
_color = copy._color;
|
||||
_color_scale = copy._color_scale;
|
||||
_tex_matrix = copy._tex_matrix;
|
||||
_other = copy._other;
|
||||
}
|
190
panda/src/pgraph/accumulatedAttribs.cxx
Normal file
190
panda/src/pgraph/accumulatedAttribs.cxx
Normal file
@ -0,0 +1,190 @@
|
||||
// Filename: accumulatedAttribs.cxx
|
||||
// Created by: drose (30Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "accumulatedAttribs.h"
|
||||
#include "sceneGraphReducer.h"
|
||||
#include "geomTransformer.h"
|
||||
#include "pandaNode.h"
|
||||
#include "colorAttrib.h"
|
||||
#include "colorScaleAttrib.h"
|
||||
#include "texMatrixAttrib.h"
|
||||
#include "config_pgraph.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AccumulatedAttribs::write
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AccumulatedAttribs::
|
||||
write(ostream &out, int attrib_types, int indent_level) const {
|
||||
if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
||||
_transform->write(out, indent_level);
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
|
||||
if (_color == (const RenderAttrib *)NULL) {
|
||||
indent(out, indent_level) << "no color\n";
|
||||
} else {
|
||||
_color->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
|
||||
if (_color_scale == (const RenderAttrib *)NULL) {
|
||||
indent(out, indent_level) << "no color scale\n";
|
||||
} else {
|
||||
_color_scale->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
|
||||
if (_tex_matrix == (const RenderAttrib *)NULL) {
|
||||
indent(out, indent_level) << "no tex matrix\n";
|
||||
} else {
|
||||
_tex_matrix->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
|
||||
_other->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AccumulatedAttribs::collect
|
||||
// Access: Public
|
||||
// Description: Collects the state and transform from the indicated
|
||||
// node and adds it to the accumulator, removing it from
|
||||
// the node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AccumulatedAttribs::
|
||||
collect(PandaNode *node, int attrib_types) {
|
||||
if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
||||
// Collect the node's transform.
|
||||
nassertv(_transform != (TransformState *)NULL);
|
||||
_transform = _transform->compose(node->get_transform());
|
||||
node->set_transform(TransformState::make_identity());
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(ColorAttrib::get_class_type());
|
||||
if (node_attrib != (const RenderAttrib *)NULL) {
|
||||
// The node has a color attribute; apply it.
|
||||
if (_color == (const RenderAttrib *)NULL) {
|
||||
_color = node_attrib;
|
||||
} else {
|
||||
_color = _color->compose(node_attrib);
|
||||
}
|
||||
node->clear_attrib(ColorAttrib::get_class_type());
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(ColorScaleAttrib::get_class_type());
|
||||
if (node_attrib != (const RenderAttrib *)NULL) {
|
||||
// The node has a color scale attribute; apply it.
|
||||
if (_color_scale == (const RenderAttrib *)NULL) {
|
||||
_color_scale = node_attrib;
|
||||
} else {
|
||||
_color_scale = _color_scale->compose(node_attrib);
|
||||
}
|
||||
node->clear_attrib(ColorScaleAttrib::get_class_type());
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(TexMatrixAttrib::get_class_type());
|
||||
if (node_attrib != (const RenderAttrib *)NULL) {
|
||||
// The node has a tex matrix attribute; apply it.
|
||||
if (_tex_matrix == (const RenderAttrib *)NULL) {
|
||||
_tex_matrix = node_attrib;
|
||||
} else {
|
||||
_tex_matrix = _tex_matrix->compose(node_attrib);
|
||||
}
|
||||
node->clear_attrib(TexMatrixAttrib::get_class_type());
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
||||
// Collect everything else.
|
||||
nassertv(_other != (RenderState *)NULL);
|
||||
_other = _other->compose(node->get_state());
|
||||
node->set_state(RenderState::make_empty());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AccumulatedAttribs::apply_to_node
|
||||
// Access: Public
|
||||
// Description: Stores the indicated attributes in the node's
|
||||
// transform and state information; does not attempt to
|
||||
// apply the properties to the vertices. Clears the
|
||||
// attributes from the accumulator for future
|
||||
// traversals.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AccumulatedAttribs::
|
||||
apply_to_node(PandaNode *node, int attrib_types) {
|
||||
if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
||||
node->set_transform(_transform->compose(node->get_transform()));
|
||||
_transform = TransformState::make_identity();
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
|
||||
if (_color != (RenderAttrib *)NULL) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(ColorAttrib::get_class_type());
|
||||
if (node_attrib != (RenderAttrib *)NULL) {
|
||||
node->set_attrib(_color->compose(node_attrib));
|
||||
} else {
|
||||
node->set_attrib(_color);
|
||||
}
|
||||
_color = (RenderAttrib *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
|
||||
if (_color_scale != (RenderAttrib *)NULL) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(ColorScaleAttrib::get_class_type());
|
||||
if (node_attrib != (RenderAttrib *)NULL) {
|
||||
node->set_attrib(_color_scale->compose(node_attrib));
|
||||
} else {
|
||||
node->set_attrib(_color_scale);
|
||||
}
|
||||
_color_scale = (RenderAttrib *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
|
||||
if (_tex_matrix != (RenderAttrib *)NULL) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(TexMatrixAttrib::get_class_type());
|
||||
if (node_attrib != (RenderAttrib *)NULL) {
|
||||
node->set_attrib(_tex_matrix->compose(node_attrib));
|
||||
} else {
|
||||
node->set_attrib(_tex_matrix);
|
||||
}
|
||||
_tex_matrix = (RenderAttrib *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
|
||||
node->set_state(_other->compose(node->get_state()));
|
||||
_other = RenderState::make_empty();
|
||||
}
|
||||
}
|
59
panda/src/pgraph/accumulatedAttribs.h
Normal file
59
panda/src/pgraph/accumulatedAttribs.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Filename: accumulatedAttribs.h
|
||||
// Created by: drose (30Jan03)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ACCUMULATEDATTRIBS_H
|
||||
#define ACCUMULATEDATTRIBS_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "transformState.h"
|
||||
#include "renderAttrib.h"
|
||||
#include "renderState.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
class PandaNode;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : AccumulatedAttribs
|
||||
// Description : This class is used by the SceneGraphReducer to
|
||||
// maintain and accumulate the set of attributes we have
|
||||
// encountered on each node that might eventually be
|
||||
// applied to the vertices at the leaves.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA AccumulatedAttribs {
|
||||
public:
|
||||
INLINE AccumulatedAttribs();
|
||||
INLINE AccumulatedAttribs(const AccumulatedAttribs ©);
|
||||
INLINE void operator = (const AccumulatedAttribs ©);
|
||||
|
||||
void write(ostream &out, int attrib_types, int indent_level) const;
|
||||
|
||||
void collect(PandaNode *node, int attrib_types);
|
||||
void apply_to_node(PandaNode *node, int attrib_types);
|
||||
|
||||
CPT(TransformState) _transform;
|
||||
CPT(RenderAttrib) _color;
|
||||
CPT(RenderAttrib) _color_scale;
|
||||
CPT(RenderAttrib) _tex_matrix;
|
||||
CPT(RenderState) _other;
|
||||
};
|
||||
|
||||
#include "accumulatedAttribs.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#include "geomNode.h"
|
||||
#include "geomTransformer.h"
|
||||
#include "sceneGraphReducer.h"
|
||||
#include "accumulatedAttribs.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "datagram.h"
|
||||
@ -154,6 +156,62 @@ make_copy() const {
|
||||
return new GeomNode(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomNode::apply_attribs_to_vertices
|
||||
// Access: Public, Virtual
|
||||
// Description: Applies whatever attributes are specified in the
|
||||
// AccumulatedAttribs object (and by the attrib_types
|
||||
// bitmask) to the vertices on this node, if
|
||||
// appropriate. If this node uses geom arrays like a
|
||||
// GeomNode, the supplied GeomTransformer may be used to
|
||||
// unify shared arrays across multiple different nodes.
|
||||
//
|
||||
// This is a generalization of xform().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeomNode::
|
||||
apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
||||
GeomTransformer &transformer) {
|
||||
if (pgraph_cat.is_debug()) {
|
||||
pgraph_cat.debug()
|
||||
<< "Transforming geometry.\n";
|
||||
}
|
||||
|
||||
if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
||||
if (!attribs._transform->is_identity()) {
|
||||
transformer.transform_vertices(this, attribs._transform->get_mat());
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
|
||||
if (attribs._color != (const RenderAttrib *)NULL) {
|
||||
const ColorAttrib *ca = DCAST(ColorAttrib, attribs._color);
|
||||
if (ca->get_color_type() == ColorAttrib::T_flat) {
|
||||
transformer.set_color(this, ca->get_color());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
|
||||
if (attribs._color_scale != (const RenderAttrib *)NULL) {
|
||||
const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attribs._color_scale);
|
||||
if (csa->get_scale() != LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)) {
|
||||
transformer.transform_colors(this, csa->get_scale());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_tex_matrix) != 0) {
|
||||
if (attribs._tex_matrix != (const RenderAttrib *)NULL) {
|
||||
const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, attribs._tex_matrix);
|
||||
if (tma->get_mat() != LMatrix4f::ident_mat()) {
|
||||
transformer.transform_texcoords(this, tma->get_mat());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_other) != 0) {
|
||||
if (!attribs._other->is_empty()) {
|
||||
transformer.apply_state(this, attribs._other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomNode::xform
|
||||
// Access: Public, Virtual
|
||||
@ -200,6 +258,59 @@ combine_with(PandaNode *other) {
|
||||
return PandaNode::combine_with(other);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomNode::calc_tight_bounds
|
||||
// Access: Public, Virtual
|
||||
// Description: This is used to support
|
||||
// NodePath::calc_tight_bounds(). It is not intended to
|
||||
// be called directly, and it has nothing to do with the
|
||||
// normal Panda bounding-volume computation.
|
||||
//
|
||||
// If the node contains any geometry, this updates
|
||||
// min_point and max_point to enclose its bounding box.
|
||||
// found_any is to be set true if the node has any
|
||||
// geometry at all, or left alone if it has none. This
|
||||
// method may be called over several nodes, so it may
|
||||
// enter with min_point, max_point, and found_any
|
||||
// already set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) GeomNode::
|
||||
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
|
||||
const TransformState *transform) const {
|
||||
CPT(TransformState) next_transform =
|
||||
PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform);
|
||||
|
||||
const LMatrix4f &mat = next_transform->get_mat();
|
||||
int num_geoms = get_num_geoms();
|
||||
for (int i = 0; i < num_geoms; i++) {
|
||||
Geom *geom = get_geom(i);
|
||||
Geom::VertexIterator vi = geom->make_vertex_iterator();
|
||||
int num_prims = geom->get_num_prims();
|
||||
|
||||
for (int p = 0; p < num_prims; p++) {
|
||||
int length = geom->get_length(p);
|
||||
for (int v = 0; v < length; v++) {
|
||||
Vertexf vertex = geom->get_next_vertex(vi) * mat;
|
||||
|
||||
if (found_any) {
|
||||
min_point.set(min(min_point[0], vertex[0]),
|
||||
min(min_point[1], vertex[1]),
|
||||
min(min_point[2], vertex[2]));
|
||||
max_point.set(max(max_point[0], vertex[0]),
|
||||
max(max_point[1], vertex[1]),
|
||||
max(max_point[2], vertex[2]));
|
||||
} else {
|
||||
min_point = vertex;
|
||||
max_point = vertex;
|
||||
found_any = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next_transform;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeomNode::add_geoms_from
|
||||
// Access: Published
|
||||
|
@ -44,8 +44,15 @@ protected:
|
||||
public:
|
||||
virtual ~GeomNode();
|
||||
virtual PandaNode *make_copy() const;
|
||||
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs,
|
||||
int attrib_types,
|
||||
GeomTransformer &transformer);
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
virtual PandaNode *combine_with(PandaNode *other);
|
||||
virtual CPT(TransformState)
|
||||
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
|
||||
bool &found_any,
|
||||
const TransformState *transform) const;
|
||||
|
||||
PUBLISHED:
|
||||
INLINE int get_num_geoms() const;
|
||||
|
@ -2788,7 +2788,7 @@ calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point) {
|
||||
nassertr_always(!is_empty(), false);
|
||||
|
||||
bool found_any = false;
|
||||
r_calc_tight_bounds(node(), min_point, max_point, found_any,
|
||||
node()->calc_tight_bounds(min_point, max_point, found_any,
|
||||
TransformState::make_identity());
|
||||
|
||||
return found_any;
|
||||
@ -3190,58 +3190,6 @@ r_force_recompute_bounds(PandaNode *node) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::r_calc_tight_bounds
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
r_calc_tight_bounds(PandaNode *node, LPoint3f &min_point, LPoint3f &max_point,
|
||||
bool &found_any, const TransformState *transform) {
|
||||
CPT(TransformState) next_transform =
|
||||
transform->compose(node->get_transform());
|
||||
if (node->is_geom_node()) {
|
||||
GeomNode *gnode;
|
||||
DCAST_INTO_V(gnode, node);
|
||||
|
||||
const LMatrix4f &mat = next_transform->get_mat();
|
||||
int num_geoms = gnode->get_num_geoms();
|
||||
for (int i = 0; i < num_geoms; i++) {
|
||||
Geom *geom = gnode->get_geom(i);
|
||||
Geom::VertexIterator vi = geom->make_vertex_iterator();
|
||||
int num_prims = geom->get_num_prims();
|
||||
|
||||
for (int p = 0; p < num_prims; p++) {
|
||||
int length = geom->get_length(p);
|
||||
for (int v = 0; v < length; v++) {
|
||||
Vertexf vertex = geom->get_next_vertex(vi) * mat;
|
||||
|
||||
if (found_any) {
|
||||
min_point.set(min(min_point[0], vertex[0]),
|
||||
min(min_point[1], vertex[1]),
|
||||
min(min_point[2], vertex[2]));
|
||||
max_point.set(max(max_point[0], vertex[0]),
|
||||
max(max_point[1], vertex[1]),
|
||||
max(max_point[2], vertex[2]));
|
||||
} else {
|
||||
min_point = vertex;
|
||||
max_point = vertex;
|
||||
found_any = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now consider children.
|
||||
PandaNode::Children cr = node->get_children();
|
||||
int num_children = cr.get_num_children();
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
r_calc_tight_bounds(cr.get_child(i), min_point, max_point,
|
||||
found_any, next_transform);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::r_find_texture
|
||||
// Access: Private
|
||||
|
@ -542,9 +542,6 @@ private:
|
||||
void r_adjust_all_priorities(PandaNode *node, int adjustment);
|
||||
|
||||
void r_force_recompute_bounds(PandaNode *node);
|
||||
void r_calc_tight_bounds(PandaNode *node,
|
||||
LPoint3f &min_point, LPoint3f &max_point,
|
||||
bool &found_any, const TransformState *transform);
|
||||
|
||||
typedef pset<Texture *> Textures;
|
||||
Texture *r_find_texture(PandaNode *node, const RenderState *state,
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "bamWriter.h"
|
||||
#include "indent.h"
|
||||
#include "geometricBoundingVolume.h"
|
||||
#include "sceneGraphReducer.h"
|
||||
#include "accumulatedAttribs.h"
|
||||
|
||||
|
||||
TypeHandle PandaNode::_type_handle;
|
||||
@ -501,6 +503,18 @@ safe_to_combine() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::safe_to_flatten_below
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if a flatten operation may safely
|
||||
// continue past this node, or false if it should drop
|
||||
// all attributes here and stop.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PandaNode::
|
||||
safe_to_flatten_below() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::preserve_name
|
||||
// Access: Public, Virtual
|
||||
@ -513,6 +527,42 @@ preserve_name() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::get_unsafe_to_apply_attribs
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the union of all attributes from
|
||||
// SceneGraphReducer::AttribTypes that may not safely be
|
||||
// applied to the vertices of this node. If this is
|
||||
// nonzero, these attributes must be dropped at this
|
||||
// node as a state change.
|
||||
//
|
||||
// This is a generalization of safe_to_transform().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PandaNode::
|
||||
get_unsafe_to_apply_attribs() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::apply_attribs_to_vertices
|
||||
// Access: Public, Virtual
|
||||
// Description: Applies whatever attributes are specified in the
|
||||
// AccumulatedAttribs object (and by the attrib_types
|
||||
// bitmask) to the vertices on this node, if
|
||||
// appropriate. If this node uses geom arrays like a
|
||||
// GeomNode, the supplied GeomTransformer may be used to
|
||||
// unify shared arrays across multiple different nodes.
|
||||
//
|
||||
// This is a generalization of xform().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaNode::
|
||||
apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
||||
GeomTransformer &transformer) {
|
||||
if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
||||
xform(attribs._transform->get_mat());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::xform
|
||||
// Access: Public, Virtual
|
||||
@ -568,6 +618,41 @@ combine_with(PandaNode *other) {
|
||||
return (PandaNode *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::calc_tight_bounds
|
||||
// Access: Public, Virtual
|
||||
// Description: This is used to support
|
||||
// NodePath::calc_tight_bounds(). It is not intended to
|
||||
// be called directly, and it has nothing to do with the
|
||||
// normal Panda bounding-volume computation.
|
||||
//
|
||||
// If the node contains any geometry, this updates
|
||||
// min_point and max_point to enclose its bounding box.
|
||||
// found_any is to be set true if the node has any
|
||||
// geometry at all, or left alone if it has none. This
|
||||
// method may be called over several nodes, so it may
|
||||
// enter with min_point, max_point, and found_any
|
||||
// already set.
|
||||
//
|
||||
// This function is recursive, and the return value is
|
||||
// the transform after it has been modified by this
|
||||
// node's transform.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) PandaNode::
|
||||
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
|
||||
const TransformState *transform) const {
|
||||
CPT(TransformState) next_transform = transform->compose(get_transform());
|
||||
|
||||
Children cr = get_children();
|
||||
int num_children = cr.get_num_children();
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
cr.get_child(i)->calc_tight_bounds(min_point, max_point,
|
||||
found_any, next_transform);
|
||||
}
|
||||
|
||||
return next_transform;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::has_cull_callback
|
||||
// Access: Public, Virtual
|
||||
|
@ -45,6 +45,8 @@ class CullTraverser;
|
||||
class CullTraverserData;
|
||||
class Light;
|
||||
class FactoryParams;
|
||||
class AccumulatedAttribs;
|
||||
class GeomTransformer;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PandaNode
|
||||
@ -71,9 +73,18 @@ public:
|
||||
virtual bool safe_to_transform() const;
|
||||
virtual bool safe_to_modify_transform() const;
|
||||
virtual bool safe_to_combine() const;
|
||||
virtual bool safe_to_flatten_below() const;
|
||||
virtual bool preserve_name() const;
|
||||
virtual int get_unsafe_to_apply_attribs() const;
|
||||
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs,
|
||||
int attrib_types,
|
||||
GeomTransformer &transformer);
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
virtual PandaNode *combine_with(PandaNode *other);
|
||||
virtual CPT(TransformState)
|
||||
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
|
||||
bool &found_any,
|
||||
const TransformState *transform) const;
|
||||
|
||||
virtual bool has_cull_callback() const;
|
||||
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "accumulatedAttribs.cxx"
|
||||
#include "ambientLight.cxx"
|
||||
#include "bamFile.cxx"
|
||||
#include "billboardEffect.cxx"
|
||||
|
@ -18,39 +18,58 @@
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::AccumulatedAttribs::Constructor
|
||||
// Access: Public
|
||||
// Function: SceneGraphReducer::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE SceneGraphReducer::AccumulatedAttribs::
|
||||
AccumulatedAttribs() {
|
||||
INLINE SceneGraphReducer::
|
||||
SceneGraphReducer() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::AccumulatedAttribs::Copy Constructor
|
||||
// Access: Public
|
||||
// Function: SceneGraphReducer::Destructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE SceneGraphReducer::AccumulatedAttribs::
|
||||
AccumulatedAttribs(const SceneGraphReducer::AccumulatedAttribs ©) :
|
||||
_transform(copy._transform),
|
||||
_color(copy._color),
|
||||
_color_scale(copy._color_scale),
|
||||
_tex_matrix(copy._tex_matrix),
|
||||
_other(copy._other)
|
||||
{
|
||||
INLINE SceneGraphReducer::
|
||||
~SceneGraphReducer() {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::apply_attribs
|
||||
// Access: Published
|
||||
// Description: Walks the scene graph, accumulating attribs of
|
||||
// the indicated types, applying them to the vertices,
|
||||
// and removing them from the scene graph. This has a
|
||||
// performance optimization benefit in itself, but is
|
||||
// especially useful to pave the way for a call to
|
||||
// flatten() and greatly improve the effectiveness of
|
||||
// the flattening operation.
|
||||
//
|
||||
// Multiply instanced geometry is duplicated before the
|
||||
// attribs are applied.
|
||||
//
|
||||
// Of course, this operation does make certain dynamic
|
||||
// operations impossible.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SceneGraphReducer::
|
||||
apply_attribs(PandaNode *node, int attrib_types) {
|
||||
AccumulatedAttribs attribs;
|
||||
r_apply_attribs(node, attribs, attrib_types, _transformer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::AccumulatedAttribs::Copy Assignment
|
||||
// Access: Public
|
||||
// Description:
|
||||
// Function: SceneGraphReducer::apply_attribs
|
||||
// Access: Published
|
||||
// Description: This flavor of apply_attribs() can be called
|
||||
// recursively from within another flatten process
|
||||
// (e.g. from PandaNode::apply_attribs_to_vertices()).
|
||||
// The parameters were presumably received from a parent
|
||||
// SceneGraphReducer object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SceneGraphReducer::AccumulatedAttribs::
|
||||
operator = (const SceneGraphReducer::AccumulatedAttribs ©) {
|
||||
_transform = copy._transform;
|
||||
_color = copy._color;
|
||||
_color_scale = copy._color_scale;
|
||||
_tex_matrix = copy._tex_matrix;
|
||||
_other = copy._other;
|
||||
INLINE void SceneGraphReducer::
|
||||
apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
|
||||
int attrib_types, GeomTransformer &transformer) {
|
||||
r_apply_attribs(node, attribs, attrib_types, transformer);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "colorAttrib.h"
|
||||
#include "texMatrixAttrib.h"
|
||||
#include "colorScaleAttrib.h"
|
||||
#include "accumulatedAttribs.h"
|
||||
|
||||
#include "geomNode.h"
|
||||
#include "pointerTo.h"
|
||||
@ -28,292 +29,15 @@
|
||||
#include "indent.h"
|
||||
#include "plist.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::AccumulatedAttribs::write
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SceneGraphReducer::AccumulatedAttribs::
|
||||
write(ostream &out, int attrib_types, int indent_level) const {
|
||||
if ((attrib_types & TT_transform) != 0) {
|
||||
_transform->write(out, indent_level);
|
||||
}
|
||||
if ((attrib_types & TT_color) != 0) {
|
||||
if (_color == (const RenderAttrib *)NULL) {
|
||||
indent(out, indent_level) << "no color\n";
|
||||
} else {
|
||||
_color->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
if ((attrib_types & TT_color_scale) != 0) {
|
||||
if (_color_scale == (const RenderAttrib *)NULL) {
|
||||
indent(out, indent_level) << "no color scale\n";
|
||||
} else {
|
||||
_color_scale->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
if ((attrib_types & TT_tex_matrix) != 0) {
|
||||
if (_tex_matrix == (const RenderAttrib *)NULL) {
|
||||
indent(out, indent_level) << "no tex matrix\n";
|
||||
} else {
|
||||
_tex_matrix->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
if ((attrib_types & TT_other) != 0) {
|
||||
_other->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::AccumulatedAttribs::collect
|
||||
// Access: Public
|
||||
// Description: Collects the state and transform from the indicated
|
||||
// node and adds it to the accumulator, removing it from
|
||||
// the node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SceneGraphReducer::AccumulatedAttribs::
|
||||
collect(PandaNode *node, int attrib_types) {
|
||||
if ((attrib_types & TT_transform) != 0) {
|
||||
// Collect the node's transform.
|
||||
nassertv(_transform != (TransformState *)NULL);
|
||||
_transform = _transform->compose(node->get_transform());
|
||||
node->set_transform(TransformState::make_identity());
|
||||
}
|
||||
|
||||
if ((attrib_types & TT_color) != 0) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(ColorAttrib::get_class_type());
|
||||
if (node_attrib != (const RenderAttrib *)NULL) {
|
||||
// The node has a color attribute; apply it.
|
||||
if (_color == (const RenderAttrib *)NULL) {
|
||||
_color = node_attrib;
|
||||
} else {
|
||||
_color = _color->compose(node_attrib);
|
||||
}
|
||||
node->clear_attrib(ColorAttrib::get_class_type());
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & TT_color_scale) != 0) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(ColorScaleAttrib::get_class_type());
|
||||
if (node_attrib != (const RenderAttrib *)NULL) {
|
||||
// The node has a color scale attribute; apply it.
|
||||
if (_color_scale == (const RenderAttrib *)NULL) {
|
||||
_color_scale = node_attrib;
|
||||
} else {
|
||||
_color_scale = _color_scale->compose(node_attrib);
|
||||
}
|
||||
node->clear_attrib(ColorScaleAttrib::get_class_type());
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & TT_tex_matrix) != 0) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(TexMatrixAttrib::get_class_type());
|
||||
if (node_attrib != (const RenderAttrib *)NULL) {
|
||||
// The node has a tex matrix attribute; apply it.
|
||||
if (_tex_matrix == (const RenderAttrib *)NULL) {
|
||||
_tex_matrix = node_attrib;
|
||||
} else {
|
||||
_tex_matrix = _tex_matrix->compose(node_attrib);
|
||||
}
|
||||
node->clear_attrib(TexMatrixAttrib::get_class_type());
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & TT_transform) != 0) {
|
||||
// Collect everything else.
|
||||
nassertv(_other != (RenderState *)NULL);
|
||||
_other = _other->compose(node->get_state());
|
||||
node->set_state(RenderState::make_empty());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::AccumulatedAttribs::apply_to_node
|
||||
// Access: Public
|
||||
// Description: Stores the indicated attributes in the node's
|
||||
// transform and state information; does not attempt to
|
||||
// apply the properties to the vertices. Clears the
|
||||
// attributes from the accumulator for future
|
||||
// traversals.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SceneGraphReducer::AccumulatedAttribs::
|
||||
apply_to_node(PandaNode *node, int attrib_types) {
|
||||
if ((attrib_types & TT_transform) != 0) {
|
||||
node->set_transform(_transform->compose(node->get_transform()));
|
||||
_transform = TransformState::make_identity();
|
||||
}
|
||||
|
||||
if ((attrib_types & TT_color) != 0) {
|
||||
if (_color != (RenderAttrib *)NULL) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(ColorAttrib::get_class_type());
|
||||
if (node_attrib != (RenderAttrib *)NULL) {
|
||||
node->set_attrib(_color->compose(node_attrib));
|
||||
} else {
|
||||
node->set_attrib(_color);
|
||||
}
|
||||
_color = (RenderAttrib *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & TT_color_scale) != 0) {
|
||||
if (_color_scale != (RenderAttrib *)NULL) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(ColorScaleAttrib::get_class_type());
|
||||
if (node_attrib != (RenderAttrib *)NULL) {
|
||||
node->set_attrib(_color_scale->compose(node_attrib));
|
||||
} else {
|
||||
node->set_attrib(_color_scale);
|
||||
}
|
||||
_color_scale = (RenderAttrib *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & TT_tex_matrix) != 0) {
|
||||
if (_tex_matrix != (RenderAttrib *)NULL) {
|
||||
const RenderAttrib *node_attrib =
|
||||
node->get_attrib(TexMatrixAttrib::get_class_type());
|
||||
if (node_attrib != (RenderAttrib *)NULL) {
|
||||
node->set_attrib(_tex_matrix->compose(node_attrib));
|
||||
} else {
|
||||
node->set_attrib(_tex_matrix);
|
||||
}
|
||||
_tex_matrix = (RenderAttrib *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((attrib_types & TT_other) != 0) {
|
||||
node->set_state(_other->compose(node->get_state()));
|
||||
_other = RenderState::make_empty();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::AccumulatedAttribs::apply_to_vertices
|
||||
// Access: Public
|
||||
// Description: Applies the indicated attributes to the node so that
|
||||
// they do not need to be stored as separate attributes
|
||||
// any more.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SceneGraphReducer::AccumulatedAttribs::
|
||||
apply_to_vertices(PandaNode *node, int attrib_types,
|
||||
GeomTransformer &transformer) {
|
||||
if (node->is_geom_node()) {
|
||||
if (pgraph_cat.is_debug()) {
|
||||
pgraph_cat.debug()
|
||||
<< "Transforming geometry.\n";
|
||||
}
|
||||
|
||||
// We treat GeomNodes as a special case, since we can apply more
|
||||
// than just a transform matrix and so we can share vertex arrays
|
||||
// across different GeomNodes.
|
||||
GeomNode *gnode = DCAST(GeomNode, node);
|
||||
if ((attrib_types & TT_transform) != 0) {
|
||||
if (!_transform->is_identity()) {
|
||||
transformer.transform_vertices(gnode, _transform->get_mat());
|
||||
}
|
||||
}
|
||||
if ((attrib_types & TT_color) != 0) {
|
||||
if (_color != (const RenderAttrib *)NULL) {
|
||||
const ColorAttrib *ca = DCAST(ColorAttrib, _color);
|
||||
if (ca->get_color_type() == ColorAttrib::T_flat) {
|
||||
transformer.set_color(gnode, ca->get_color());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((attrib_types & TT_color_scale) != 0) {
|
||||
if (_color_scale != (const RenderAttrib *)NULL) {
|
||||
const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, _color_scale);
|
||||
if (csa->get_scale() != LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)) {
|
||||
transformer.transform_colors(gnode, csa->get_scale());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((attrib_types & TT_tex_matrix) != 0) {
|
||||
if (_tex_matrix != (const RenderAttrib *)NULL) {
|
||||
const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, _tex_matrix);
|
||||
if (tma->get_mat() != LMatrix4f::ident_mat()) {
|
||||
transformer.transform_texcoords(gnode, tma->get_mat());
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((attrib_types & TT_other) != 0) {
|
||||
if (!_other->is_empty()) {
|
||||
transformer.apply_state(gnode, _other);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// This handles any kind of node other than a GeomNode.
|
||||
if ((attrib_types & TT_transform) != 0) {
|
||||
node->xform(_transform->get_mat());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SceneGraphReducer::
|
||||
SceneGraphReducer() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SceneGraphReducer::
|
||||
~SceneGraphReducer() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::apply_attribs
|
||||
// Access: Public
|
||||
// Description: Walks the scene graph, accumulating attribs of
|
||||
// the indicated types, applying them to the vertices,
|
||||
// and removing them from the scene graph. This has a
|
||||
// performance optimization benefit in itself, but is
|
||||
// especially useful to pave the way for a call to
|
||||
// flatten() and greatly improve the effectiveness of
|
||||
// the flattening operation.
|
||||
//
|
||||
// Multiply instanced geometry is duplicated before the
|
||||
// attribs are applied.
|
||||
//
|
||||
// Of course, this operation does make certain dynamic
|
||||
// operations impossible.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SceneGraphReducer::
|
||||
apply_attribs(PandaNode *node, int attrib_types) {
|
||||
AccumulatedAttribs trans;
|
||||
|
||||
trans._transform = TransformState::make_identity();
|
||||
trans._color = (ColorAttrib *)NULL;
|
||||
trans._color_scale = (ColorScaleAttrib *)NULL;
|
||||
trans._tex_matrix = (TexMatrixAttrib *)NULL;
|
||||
trans._other = RenderState::make_empty();
|
||||
|
||||
r_apply_attribs(node, attrib_types, trans);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::flatten
|
||||
// Access: Public
|
||||
// Access: Published
|
||||
// Description: Simplifies the graph by removing unnecessary nodes
|
||||
// and nodes.
|
||||
//
|
||||
// In general, a node (and its parent node) is a
|
||||
// candidate for removal if the node has no siblings and
|
||||
// the node and node have no special properties. The
|
||||
// definition of what, precisely, is a 'special
|
||||
// property' may be extended by subclassing from this
|
||||
// type and redefining consider_node() appropriately.
|
||||
// the node has no special properties.
|
||||
//
|
||||
// If combine_siblings is true, sibling nodes may also
|
||||
// be collapsed into a single node. This will further
|
||||
@ -365,8 +89,8 @@ flatten(PandaNode *root, bool combine_siblings) {
|
||||
// Description: The recursive implementation of apply_attribs().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SceneGraphReducer::
|
||||
r_apply_attribs(PandaNode *node, int attrib_types,
|
||||
SceneGraphReducer::AccumulatedAttribs trans) {
|
||||
r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
|
||||
int attrib_types, GeomTransformer &transformer) {
|
||||
if (pgraph_cat.is_debug()) {
|
||||
pgraph_cat.debug()
|
||||
<< "r_apply_attribs(" << *node << "), node's attribs are:\n";
|
||||
@ -375,13 +99,14 @@ r_apply_attribs(PandaNode *node, int attrib_types,
|
||||
node->get_effects()->write(pgraph_cat.debug(false), 2);
|
||||
}
|
||||
|
||||
trans.collect(node, attrib_types);
|
||||
AccumulatedAttribs next_attribs(attribs);
|
||||
next_attribs.collect(node, attrib_types);
|
||||
|
||||
if (pgraph_cat.is_debug()) {
|
||||
pgraph_cat.debug()
|
||||
<< "Got attribs from " << *node << "\n"
|
||||
<< "Accumulated attribs are:\n";
|
||||
trans.write(pgraph_cat.debug(false), attrib_types, 2);
|
||||
next_attribs.write(pgraph_cat.debug(false), attrib_types, 2);
|
||||
}
|
||||
|
||||
// Check to see if we can't propagate any of these attribs past
|
||||
@ -405,6 +130,7 @@ r_apply_attribs(PandaNode *node, int attrib_types,
|
||||
}
|
||||
apply_types |= TT_transform;
|
||||
}
|
||||
apply_types |= node->get_unsafe_to_apply_attribs();
|
||||
|
||||
// Also, check the children of this node. If any of them indicates
|
||||
// it is not safe to modify its transform, we must drop our
|
||||
@ -429,10 +155,10 @@ r_apply_attribs(PandaNode *node, int attrib_types,
|
||||
}
|
||||
|
||||
// Directly store whatever attributes we must,
|
||||
trans.apply_to_node(node, attrib_types & apply_types);
|
||||
next_attribs.apply_to_node(node, attrib_types & apply_types);
|
||||
|
||||
// And apply the rest to the vertices.
|
||||
trans.apply_to_vertices(node, attrib_types, _transformer);
|
||||
node->apply_attribs_to_vertices(next_attribs, attrib_types, transformer);
|
||||
|
||||
// Do we need to copy any children to flatten instances?
|
||||
bool resist_copy = false;
|
||||
@ -473,14 +199,14 @@ r_apply_attribs(PandaNode *node, int attrib_types,
|
||||
if (resist_copy) {
|
||||
// If any of our children should have been copied but weren't, we
|
||||
// need to drop the state here before continuing.
|
||||
trans.apply_to_node(node, attrib_types);
|
||||
next_attribs.apply_to_node(node, attrib_types);
|
||||
}
|
||||
|
||||
// Now it's safe to traverse through all of our children.
|
||||
nassertv(num_children == node->get_num_children());
|
||||
for (i = 0; i < num_children; i++) {
|
||||
PandaNode *child_node = node->get_child(i);
|
||||
r_apply_attribs(child_node, attrib_types, trans);
|
||||
r_apply_attribs(child_node, next_attribs, attrib_types, transformer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -637,12 +363,10 @@ flatten_siblings(PandaNode *parent_node) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::consider_child
|
||||
// Access: Protected, Virtual
|
||||
// Access: Protected
|
||||
// Description: Decides whether or not the indicated child node is a
|
||||
// suitable candidate for removal. Returns true if the
|
||||
// node may be removed, false if it should be kept. This
|
||||
// function may be extended in a user class to protect
|
||||
// special kinds of nodes from deletion.
|
||||
// node may be removed, false if it should be kept.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool SceneGraphReducer::
|
||||
consider_child(PandaNode *grandparent_node, PandaNode *parent_node,
|
||||
@ -671,7 +395,7 @@ consider_child(PandaNode *grandparent_node, PandaNode *parent_node,
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer:c:onsider_siblings
|
||||
// Access: Protected, Virtual
|
||||
// Access: Protected
|
||||
// Description: Decides whether or not the indicated sibling nodes
|
||||
// should be collapsed into a single node or not.
|
||||
// Returns true if the nodes may be collapsed, false if
|
||||
@ -688,14 +412,11 @@ consider_siblings(PandaNode *parent_node, PandaNode *child1,
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::do_flatten_child
|
||||
// Access: Protected, Virtual
|
||||
// Access: Protected
|
||||
// Description: Collapses together the indicated parent node and
|
||||
// child node and leaves the result attached to the
|
||||
// grandparent. The return value is true if the node is
|
||||
// successfully collapsed, false if we chickened out.
|
||||
//
|
||||
// This function may be extended in a user class to
|
||||
// handle special kinds of nodes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool SceneGraphReducer::
|
||||
do_flatten_child(PandaNode *grandparent_node, PandaNode *parent_node,
|
||||
@ -730,7 +451,7 @@ do_flatten_child(PandaNode *grandparent_node, PandaNode *parent_node,
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::do_flatten_siblings
|
||||
// Access: Protected, Virtual
|
||||
// Access: Protected
|
||||
// Description: Performs the work of collapsing two sibling nodes
|
||||
// together into a single node, leaving the resulting
|
||||
// node attached to the parent.
|
||||
@ -779,7 +500,7 @@ do_flatten_siblings(PandaNode *parent_node, PandaNode *child1,
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::collapse_nodes
|
||||
// Access: Protected, Virtual
|
||||
// Access: Protected
|
||||
// Description: Collapses the two nodes into a single node, if
|
||||
// possible. The 'siblings' flag is true if the two
|
||||
// nodes are siblings nodes; otherwise, node1 is a
|
||||
@ -787,9 +508,6 @@ do_flatten_siblings(PandaNode *parent_node, PandaNode *child1,
|
||||
// node, which may be either one of the source nodes, or
|
||||
// a new node altogether, or it may be NULL to indicate
|
||||
// that the collapse operation could not take place.
|
||||
//
|
||||
// This function may be extended in a user class to
|
||||
// handle combining special kinds of nodes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(PandaNode) SceneGraphReducer::
|
||||
collapse_nodes(PandaNode *node1, PandaNode *node2, bool siblings) {
|
||||
@ -799,7 +517,7 @@ collapse_nodes(PandaNode *node1, PandaNode *node2, bool siblings) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SceneGraphReducer::choose_name
|
||||
// Access: Protected, Virtual
|
||||
// Access: Protected
|
||||
// Description: Chooses a suitable name for the collapsed node, based
|
||||
// on the names of the two sources nodes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -23,11 +23,14 @@
|
||||
#include "transformState.h"
|
||||
#include "renderAttrib.h"
|
||||
#include "renderState.h"
|
||||
#include "accumulatedAttribs.h"
|
||||
#include "geomTransformer.h"
|
||||
|
||||
#include "typedObject.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
class PandaNode;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : SceneGraphReducer
|
||||
// Description : An interface for simplifying ("flattening") scene
|
||||
@ -41,8 +44,8 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA SceneGraphReducer {
|
||||
PUBLISHED:
|
||||
SceneGraphReducer();
|
||||
virtual ~SceneGraphReducer();
|
||||
INLINE SceneGraphReducer();
|
||||
INLINE ~SceneGraphReducer();
|
||||
|
||||
enum AttribTypes {
|
||||
TT_transform = 0x001,
|
||||
@ -52,52 +55,34 @@ PUBLISHED:
|
||||
TT_other = 0x010,
|
||||
};
|
||||
|
||||
void apply_attribs(PandaNode *node, int attrib_types = ~0);
|
||||
INLINE void apply_attribs(PandaNode *node, int attrib_types = ~0);
|
||||
INLINE void apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
|
||||
int attrib_types, GeomTransformer &transformer);
|
||||
|
||||
int flatten(PandaNode *root, bool combine_siblings);
|
||||
|
||||
protected:
|
||||
class AccumulatedAttribs {
|
||||
public:
|
||||
INLINE AccumulatedAttribs();
|
||||
INLINE AccumulatedAttribs(const AccumulatedAttribs ©);
|
||||
INLINE void operator = (const AccumulatedAttribs ©);
|
||||
|
||||
void write(ostream &out, int attrib_types, int indent_level) const;
|
||||
|
||||
void collect(PandaNode *node, int attrib_types);
|
||||
void apply_to_node(PandaNode *node, int attrib_types);
|
||||
void apply_to_vertices(PandaNode *node, int attrib_types,
|
||||
GeomTransformer &transfomer);
|
||||
|
||||
CPT(TransformState) _transform;
|
||||
CPT(RenderAttrib) _color;
|
||||
CPT(RenderAttrib) _color_scale;
|
||||
CPT(RenderAttrib) _tex_matrix;
|
||||
CPT(RenderState) _other;
|
||||
};
|
||||
|
||||
void r_apply_attribs(PandaNode *node, int attrib_types,
|
||||
AccumulatedAttribs trans);
|
||||
void r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
|
||||
int attrib_types, GeomTransformer &transformer);
|
||||
|
||||
int r_flatten(PandaNode *grandparent_node, PandaNode *parent_node,
|
||||
bool combine_siblings);
|
||||
int flatten_siblings(PandaNode *parent_node);
|
||||
|
||||
virtual bool consider_child(PandaNode *grandparent_node,
|
||||
bool consider_child(PandaNode *grandparent_node,
|
||||
PandaNode *parent_node, PandaNode *child_node);
|
||||
virtual bool consider_siblings(PandaNode *parent_node, PandaNode *child1,
|
||||
bool consider_siblings(PandaNode *parent_node, PandaNode *child1,
|
||||
PandaNode *child2);
|
||||
|
||||
virtual bool do_flatten_child(PandaNode *grandparent_node,
|
||||
bool do_flatten_child(PandaNode *grandparent_node,
|
||||
PandaNode *parent_node, PandaNode *child_node);
|
||||
|
||||
virtual PandaNode *do_flatten_siblings(PandaNode *parent_node,
|
||||
PandaNode *do_flatten_siblings(PandaNode *parent_node,
|
||||
PandaNode *child1, PandaNode *child2);
|
||||
|
||||
virtual PT(PandaNode) collapse_nodes(PandaNode *node1, PandaNode *node2,
|
||||
PT(PandaNode) collapse_nodes(PandaNode *node1, PandaNode *node2,
|
||||
bool siblings);
|
||||
virtual void choose_name(PandaNode *preserve, PandaNode *source1,
|
||||
void choose_name(PandaNode *preserve, PandaNode *source1,
|
||||
PandaNode *source2);
|
||||
|
||||
private:
|
||||
|
@ -779,7 +779,6 @@ TextNode *PGItem::
|
||||
get_text_node() {
|
||||
if (_text_node == (TextNode *)NULL) {
|
||||
_text_node = new TextNode("pguiText");
|
||||
_text_node->freeze();
|
||||
_text_node->set_text_color(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// The default TextNode is aligned to the left, for the
|
||||
|
@ -20,70 +20,25 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::freeze
|
||||
// Access: Published
|
||||
// Description: Freezes the TextNode in its current state, so that
|
||||
// updates will not immediately be displayed. A series
|
||||
// of state changes may then be applied in succession,
|
||||
// which will not force the TextNode to be recomputed.
|
||||
// When thaw() is later called, the TextNode will update
|
||||
// itself exactly once to reflect all the state changes
|
||||
// that were made.
|
||||
//
|
||||
// freeze() and thaw() can nest. Strictly speaking,
|
||||
// each call to freeze() increments the current freeze
|
||||
// level, while each call to thaw() decrements it. The
|
||||
// TextNode will only be updated when the current freeze
|
||||
// level is zero.
|
||||
//
|
||||
// The return value of freeze() is the freeze level
|
||||
// *before* the freeze took place. This number should
|
||||
// match the return value of the matching thaw().
|
||||
// Description: This method is deprecated and no longer does
|
||||
// anything. It is included for historical purposes
|
||||
// only and will shortly be removed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int TextNode::
|
||||
freeze() {
|
||||
if (text_cat.is_debug()) {
|
||||
text_cat.debug()
|
||||
<< "Freezing " << this->get_name() << ", level = "
|
||||
<< _freeze_level << "\n";
|
||||
}
|
||||
return _freeze_level++;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::get_freeze_level
|
||||
// Access: Published
|
||||
// Description: Returns the current freeze level. The TextNode will
|
||||
// not be updated visually unless this number is zero.
|
||||
// See freeze().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int TextNode::
|
||||
get_freeze_level() const {
|
||||
return _freeze_level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::thaw
|
||||
// Access: Published
|
||||
// Description: Allows changes made since the last freeze() to be
|
||||
// visible. Strictly speaking, this actually decrements
|
||||
// the freeze level, and updates the TextNode if the
|
||||
// level reaches zero. The return value is the new
|
||||
// freeze level after adjusting. See freeze().
|
||||
// Description: This method is deprecated and no longer does
|
||||
// anything. It is included for historical purposes
|
||||
// only and will shortly be removed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int TextNode::
|
||||
thaw() {
|
||||
if (text_cat.is_debug()) {
|
||||
text_cat.debug()
|
||||
<< "Thawing " << this->get_name() << ", level = "
|
||||
<< _freeze_level-1 << "\n";
|
||||
}
|
||||
nassertr(_freeze_level > 0, _freeze_level);
|
||||
_freeze_level--;
|
||||
|
||||
if (_freeze_level == 0 && _needs_rebuild) {
|
||||
do_rebuild();
|
||||
}
|
||||
|
||||
return _freeze_level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -95,7 +50,7 @@ INLINE void TextNode::
|
||||
set_font(TextFont *font) {
|
||||
if (_font != font) {
|
||||
_font = font;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +148,7 @@ INLINE void TextNode::
|
||||
set_slant(float slant) {
|
||||
if (_slant != slant) {
|
||||
_slant = slant;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,7 +171,7 @@ INLINE void TextNode::
|
||||
set_align(TextNode::Alignment align_type) {
|
||||
if (_align != align_type) {
|
||||
_align = align_type;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,7 +196,7 @@ set_wordwrap(float wordwrap) {
|
||||
if (!has_wordwrap() || _wordwrap_width != wordwrap) {
|
||||
_flags |= F_has_wordwrap;
|
||||
_wordwrap_width = wordwrap;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,7 +210,7 @@ INLINE void TextNode::
|
||||
clear_wordwrap() {
|
||||
if (has_wordwrap()) {
|
||||
_flags &= ~F_has_wordwrap;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,7 +254,7 @@ set_text_color(const Colorf &text_color) {
|
||||
if (!has_text_color() || _text_color != text_color) {
|
||||
_text_color = text_color;
|
||||
_flags |= F_has_text_color;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,7 +268,7 @@ INLINE void TextNode::
|
||||
clear_text_color() {
|
||||
if (has_text_color()) {
|
||||
_flags &= ~F_has_text_color;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,7 +311,7 @@ INLINE void TextNode::
|
||||
set_frame_color(const Colorf &frame_color) {
|
||||
if (_frame_color != frame_color) {
|
||||
_frame_color = frame_color;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,7 +336,7 @@ set_card_border(float size, float uv_portion) {
|
||||
_flags |= F_has_card_border;
|
||||
_card_border_size = size;
|
||||
_card_border_uv_portion = uv_portion;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -394,7 +349,7 @@ INLINE void TextNode::
|
||||
clear_card_border() {
|
||||
if (has_card_border()) {
|
||||
_flags &= ~F_has_card_border;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,7 +402,7 @@ INLINE void TextNode::
|
||||
set_card_color(const Colorf &card_color) {
|
||||
if (_card_color != card_color) {
|
||||
_card_color = card_color;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -474,7 +429,7 @@ set_card_texture(Texture *card_texture) {
|
||||
if (!has_card_texture() || _card_texture != card_texture) {
|
||||
_flags |= F_has_card_texture;
|
||||
_card_texture = card_texture;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -489,7 +444,7 @@ clear_card_texture() {
|
||||
if (has_card_texture()) {
|
||||
_flags &= ~F_has_card_texture;
|
||||
_card_texture = NULL;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -532,7 +487,7 @@ INLINE void TextNode::
|
||||
set_shadow_color(const Colorf &shadow_color) {
|
||||
if (_shadow_color != shadow_color) {
|
||||
_shadow_color = shadow_color;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
}
|
||||
|
||||
@ -560,7 +515,7 @@ set_frame_as_margin(float left, float right, float bottom, float top) {
|
||||
_flags |= (F_has_frame | F_frame_as_margin);
|
||||
_frame_ul.set(left, top);
|
||||
_frame_lr.set(right, bottom);
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -579,7 +534,7 @@ set_frame_actual(float left, float right, float bottom, float top) {
|
||||
_flags &= ~F_frame_as_margin;
|
||||
_frame_ul.set(left, top);
|
||||
_frame_lr.set(right, bottom);
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -591,7 +546,7 @@ set_frame_actual(float left, float right, float bottom, float top) {
|
||||
INLINE void TextNode::
|
||||
clear_frame() {
|
||||
_flags &= ~F_has_frame;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -650,10 +605,11 @@ INLINE LVecBase4f TextNode::
|
||||
get_frame_actual() const {
|
||||
nassertr(has_frame(), LVecBase4f(0.0, 0.0, 0.0, 0.0));
|
||||
if (is_frame_as_margin()) {
|
||||
return LVecBase4f(get_left() - _frame_ul[0],
|
||||
get_right() + _frame_lr[0],
|
||||
get_bottom() - _frame_lr[1],
|
||||
get_top() + _frame_ul[1]);
|
||||
check_measure();
|
||||
return LVecBase4f(_ul2d[0] - _frame_ul[0],
|
||||
_lr2d[0] + _frame_lr[0],
|
||||
_lr2d[1] - _frame_lr[1],
|
||||
_ul2d[1] + _frame_ul[1]);
|
||||
} else {
|
||||
return get_frame_as_set();
|
||||
}
|
||||
@ -723,7 +679,7 @@ set_card_as_margin(float left, float right, float bottom, float top) {
|
||||
_flags |= (F_has_card | F_card_as_margin);
|
||||
_card_ul.set(left, top);
|
||||
_card_lr.set(right, bottom);
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -742,7 +698,7 @@ set_card_actual(float left, float right, float bottom, float top) {
|
||||
_flags &= ~F_card_as_margin;
|
||||
_card_ul.set(left, top);
|
||||
_card_lr.set(right, bottom);
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -754,7 +710,7 @@ set_card_actual(float left, float right, float bottom, float top) {
|
||||
INLINE void TextNode::
|
||||
clear_card() {
|
||||
_flags &= ~F_has_card;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -816,13 +772,15 @@ get_card_as_set() const {
|
||||
INLINE LVecBase4f TextNode::
|
||||
get_card_actual() const {
|
||||
if (!has_card()) {
|
||||
return LVecBase4f(get_left(), get_right(), get_bottom(), get_top());
|
||||
check_measure();
|
||||
return LVecBase4f(_ul2d[0], _lr2d[0], _lr2d[1], _ul2d[1]);
|
||||
|
||||
} else if (is_card_as_margin()) {
|
||||
return LVecBase4f(get_left() - _card_ul[0],
|
||||
get_right() + _card_lr[0],
|
||||
get_bottom() - _card_lr[1],
|
||||
get_top() + _card_ul[1]);
|
||||
check_measure();
|
||||
return LVecBase4f(_ul2d[0] - _card_ul[0],
|
||||
_lr2d[0] + _card_lr[0],
|
||||
_lr2d[1] - _card_lr[1],
|
||||
_ul2d[1] + _card_ul[1]);
|
||||
} else {
|
||||
return get_card_as_set();
|
||||
}
|
||||
@ -857,7 +815,7 @@ INLINE void TextNode::
|
||||
set_shadow(float xoffset, float yoffset) {
|
||||
_flags |= F_has_shadow;
|
||||
_shadow_offset.set(xoffset, yoffset);
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -869,7 +827,7 @@ set_shadow(float xoffset, float yoffset) {
|
||||
INLINE void TextNode::
|
||||
clear_shadow() {
|
||||
_flags &= ~F_has_shadow;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -911,7 +869,7 @@ get_shadow() const {
|
||||
INLINE void TextNode::
|
||||
set_bin(const string &bin) {
|
||||
_bin = bin;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -967,7 +925,7 @@ get_bin() const {
|
||||
INLINE int TextNode::
|
||||
set_draw_order(int draw_order) {
|
||||
_draw_order = draw_order;
|
||||
rebuild(false);
|
||||
invalidate_no_measure();
|
||||
return _draw_order + 3;
|
||||
}
|
||||
|
||||
@ -990,7 +948,7 @@ get_draw_order() const {
|
||||
INLINE void TextNode::
|
||||
set_transform(const LMatrix4f &transform) {
|
||||
_transform = transform;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1012,7 +970,7 @@ get_transform() const {
|
||||
INLINE void TextNode::
|
||||
set_coordinate_system(CoordinateSystem coordinate_system) {
|
||||
_coordinate_system = coordinate_system;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1033,9 +991,11 @@ get_coordinate_system() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
set_text(const string &text) {
|
||||
if (!has_text() || _text != text) {
|
||||
_text = text;
|
||||
_flags = (_flags | F_got_text) & ~F_got_wtext;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1048,7 +1008,7 @@ clear_text() {
|
||||
_text = string();
|
||||
_wtext = wstring();
|
||||
_flags |= (F_got_text | F_got_wtext);
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1089,7 +1049,7 @@ INLINE void TextNode::
|
||||
append_text(const string &text) {
|
||||
_text = get_text() + text;
|
||||
_flags = (_flags | F_got_text) & ~F_got_wtext;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1103,7 +1063,7 @@ INLINE void TextNode::
|
||||
append_char(int character) {
|
||||
_wtext = get_wtext() + wstring(1, (wchar_t)character);
|
||||
_flags = (_flags | F_got_wtext) & ~F_got_text;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1159,48 +1119,6 @@ calc_width(const string &line) const {
|
||||
return _font->calc_width(decode_text(line));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::rebuild
|
||||
// Access: Published
|
||||
// Description: Updates the TextNode, if it is not frozen, or marks
|
||||
// the TextNode as requiring an update if it is. If the
|
||||
// text is currently frozen, nothing will be done until
|
||||
// it is thawed, unless needs_measure is true, in which
|
||||
// case the text will be re-measured even if it is
|
||||
// currently frozen.
|
||||
//
|
||||
// Normally, this function is called automatically
|
||||
// whenever any of the parameters changes. It should
|
||||
// not need to be called explicitly unless something
|
||||
// goes wrong.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
rebuild(bool needs_measure) {
|
||||
if (_freeze_level <= 0) {
|
||||
do_rebuild();
|
||||
} else {
|
||||
_needs_rebuild = true;
|
||||
|
||||
if (needs_measure) {
|
||||
measure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::measure
|
||||
// Access: Published
|
||||
// Description: Measures the extent of the text as it will be placed,
|
||||
// without actually placing it. Normally, this function
|
||||
// is called automatically whenever any of the
|
||||
// parameters changes. It should not need to be called
|
||||
// explicitly unless something goes wrong.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
measure() {
|
||||
do_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::get_left
|
||||
// Access: Published
|
||||
@ -1210,6 +1128,7 @@ measure() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float TextNode::
|
||||
get_left() const {
|
||||
check_measure();
|
||||
return _ul2d[0];
|
||||
}
|
||||
|
||||
@ -1222,6 +1141,7 @@ get_left() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float TextNode::
|
||||
get_right() const {
|
||||
check_measure();
|
||||
return _lr2d[0];
|
||||
}
|
||||
|
||||
@ -1234,6 +1154,7 @@ get_right() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float TextNode::
|
||||
get_bottom() const {
|
||||
check_measure();
|
||||
return _lr2d[1];
|
||||
}
|
||||
|
||||
@ -1246,6 +1167,7 @@ get_bottom() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float TextNode::
|
||||
get_top() const {
|
||||
check_measure();
|
||||
return _ul2d[1];
|
||||
}
|
||||
|
||||
@ -1257,7 +1179,8 @@ get_top() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float TextNode::
|
||||
get_height() const {
|
||||
return get_top() - get_bottom();
|
||||
check_measure();
|
||||
return _ul2d[1] - _lr2d[1];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1268,7 +1191,8 @@ get_height() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float TextNode::
|
||||
get_width() const {
|
||||
return get_right() - get_left();
|
||||
check_measure();
|
||||
return _lr2d[0] - _ul2d[0];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1280,6 +1204,7 @@ get_width() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE LPoint3f TextNode::
|
||||
get_upper_left_3d() const {
|
||||
check_measure();
|
||||
return _ul3d;
|
||||
}
|
||||
|
||||
@ -1292,6 +1217,7 @@ get_upper_left_3d() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE LPoint3f TextNode::
|
||||
get_lower_right_3d() const {
|
||||
check_measure();
|
||||
return _lr3d;
|
||||
}
|
||||
|
||||
@ -1304,9 +1230,23 @@ get_lower_right_3d() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int TextNode::
|
||||
get_num_rows() const {
|
||||
check_measure();
|
||||
return _num_rows;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::update
|
||||
// Access: Published
|
||||
// Description: Can be called after the TextNode has been fully
|
||||
// configured, to force the node to recompute its text
|
||||
// immediately, rather than waiting for it to be drawn.
|
||||
// This call is optional.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
update() {
|
||||
check_rebuild();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::set_wtext
|
||||
// Access: Public
|
||||
@ -1317,9 +1257,11 @@ get_num_rows() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
set_wtext(const wstring &wtext) {
|
||||
if (!has_text() || _wtext != wtext) {
|
||||
_wtext = wtext;
|
||||
_flags = (_flags | F_got_wtext) & ~F_got_text;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1347,7 +1289,7 @@ INLINE void TextNode::
|
||||
append_wtext(const wstring &wtext) {
|
||||
_wtext = get_wtext() + wtext;
|
||||
_flags = (_flags | F_got_wtext) & ~F_got_text;
|
||||
rebuild(true);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -1378,3 +1320,60 @@ wordwrap_to(const wstring &wtext, float wordwrap_width,
|
||||
nassertr(_font != (TextFont *)NULL, wtext);
|
||||
return _font->wordwrap_to(wtext, wordwrap_width, preserve_trailing_whitespace);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::invalidate_no_measure
|
||||
// Access: Private
|
||||
// Description: Called internally whenever some state on the TextNode
|
||||
// changes, requiring the internal geometry to be
|
||||
// recomputed, but which will not result in a change in
|
||||
// the size or shape of the text (for instance, the text
|
||||
// color changes).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
invalidate_no_measure() {
|
||||
_flags |= F_needs_rebuild;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::invalidate_with_measure
|
||||
// Access: Private
|
||||
// Description: Called internally whenever some state on the TextNode
|
||||
// changes, requiring the internal geometry to be
|
||||
// recomputed, and which will may result in a change in
|
||||
// the size or shape of the text (for instance, the text
|
||||
// scale changes).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
invalidate_with_measure() {
|
||||
_flags |= (F_needs_rebuild | F_needs_measure);
|
||||
mark_bound_stale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::check_rebuild
|
||||
// Access: Private
|
||||
// Description: Called internally to call do_rebuild() if necessary
|
||||
// (that is, if the internal geometry has changed
|
||||
// recently).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
check_rebuild() const {
|
||||
if ((_flags & F_needs_rebuild) != 0) {
|
||||
((TextNode *)this)->do_rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::check_measure
|
||||
// Access: Private
|
||||
// Description: Called internally to call do_measure() if necessary;
|
||||
// this will remeasure the text without necessarily
|
||||
// rebuilding it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextNode::
|
||||
check_measure() const {
|
||||
if ((_flags & F_needs_measure) != 0) {
|
||||
((TextNode *)this)->do_measure();
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,17 @@
|
||||
#include "notify.h"
|
||||
#include "transformState.h"
|
||||
#include "colorAttrib.h"
|
||||
#include "colorScaleAttrib.h"
|
||||
#include "cullBinAttrib.h"
|
||||
#include "textureAttrib.h"
|
||||
#include "transparencyAttrib.h"
|
||||
#include "sceneGraphReducer.h"
|
||||
#include "indent.h"
|
||||
#include "cullTraverser.h"
|
||||
#include "cullTraverserData.h"
|
||||
#include "geometricBoundingVolume.h"
|
||||
#include "accumulatedAttribs.h"
|
||||
#include "dcast.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
@ -83,9 +89,6 @@ TextNode(const string &name) : PandaNode(name) {
|
||||
_ul3d.set(0.0f, 0.0f, 0.0f);
|
||||
_lr3d.set(0.0f, 0.0f, 0.0f);
|
||||
_num_rows = 0;
|
||||
|
||||
_freeze_level = 0;
|
||||
_needs_rebuild = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -302,6 +305,9 @@ generate() {
|
||||
_ul3d = _ul3d * _transform;
|
||||
_lr3d = _lr3d * _transform;
|
||||
|
||||
// Incidentally, that means we don't need to measure the text now.
|
||||
_flags &= ~F_needs_measure;
|
||||
|
||||
|
||||
// Now deal with all the decorations.
|
||||
|
||||
@ -462,15 +468,212 @@ decode_text(const string &text) const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::xform
|
||||
// Function: TextNode::get_unsafe_to_apply_attribs
|
||||
// Access: Public, Virtual
|
||||
// Description: Transforms the contents of this PandaNode by the
|
||||
// indicated matrix, if it means anything to do so. For
|
||||
// most kinds of PandaNodes, this does nothing.
|
||||
// Description: Returns the union of all attributes from
|
||||
// SceneGraphReducer::AttribTypes that may not safely be
|
||||
// applied to the vertices of this node. If this is
|
||||
// nonzero, these attributes must be dropped at this
|
||||
// node as a state change.
|
||||
//
|
||||
// This is a generalization of safe_to_transform().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int TextNode::
|
||||
get_unsafe_to_apply_attribs() const {
|
||||
// We have no way to apply these kinds of attributes to our
|
||||
// TextNode, so insist they get dropped into the PandaNode's basic
|
||||
// state.
|
||||
return
|
||||
SceneGraphReducer::TT_tex_matrix |
|
||||
SceneGraphReducer::TT_other;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::apply_attribs_to_vertices
|
||||
// Access: Public, Virtual
|
||||
// Description: Applies whatever attributes are specified in the
|
||||
// AccumulatedAttribs object (and by the attrib_types
|
||||
// bitmask) to the vertices on this node, if
|
||||
// appropriate. If this node uses geom arrays like a
|
||||
// GeomNode, the supplied GeomTransformer may be used to
|
||||
// unify shared arrays across multiple different nodes.
|
||||
//
|
||||
// This is a generalization of xform().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextNode::
|
||||
xform(const LMatrix4f &mat) {
|
||||
apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
||||
GeomTransformer &transformer) {
|
||||
if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
||||
const LMatrix4f &mat = attribs._transform->get_mat();
|
||||
_transform *= mat;
|
||||
|
||||
if ((_flags & F_needs_measure) == 0) {
|
||||
// If we already have a measure, transform it too. We don't
|
||||
// need to invalidate the 2-d parts, since that's not affected
|
||||
// by the transform anyway.
|
||||
_ul3d = _ul3d * mat;
|
||||
_lr3d = _lr3d * mat;
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
|
||||
if (attribs._color != (const RenderAttrib *)NULL) {
|
||||
const ColorAttrib *ca = DCAST(ColorAttrib, attribs._color);
|
||||
if (ca->get_color_type() == ColorAttrib::T_flat) {
|
||||
const Colorf &c = ca->get_color();
|
||||
_text_color = c;
|
||||
_frame_color = c;
|
||||
_card_color = c;
|
||||
_shadow_color = c;
|
||||
_flags |= F_has_text_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
|
||||
if (attribs._color_scale != (const RenderAttrib *)NULL) {
|
||||
const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attribs._color_scale);
|
||||
const LVecBase4f &s = csa->get_scale();
|
||||
if (s != LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)) {
|
||||
_text_color[0] *= s[0];
|
||||
_text_color[1] *= s[1];
|
||||
_text_color[2] *= s[2];
|
||||
_text_color[3] *= s[3];
|
||||
_frame_color[0] *= s[0];
|
||||
_frame_color[1] *= s[1];
|
||||
_frame_color[2] *= s[2];
|
||||
_frame_color[3] *= s[3];
|
||||
_card_color[0] *= s[0];
|
||||
_card_color[1] *= s[1];
|
||||
_card_color[2] *= s[2];
|
||||
_card_color[3] *= s[3];
|
||||
_shadow_color[0] *= s[0];
|
||||
_shadow_color[1] *= s[1];
|
||||
_shadow_color[2] *= s[2];
|
||||
_shadow_color[3] *= s[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now propagate the attributes down to our already-generated
|
||||
// geometry, if we have any.
|
||||
if ((_flags & F_needs_rebuild) == 0 &&
|
||||
_internal_geom != (PandaNode *)NULL) {
|
||||
SceneGraphReducer gr;
|
||||
gr.apply_attribs(_internal_geom, attribs, attrib_types, transformer);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::calc_tight_bounds
|
||||
// Access: Public, Virtual
|
||||
// Description: This is used to support
|
||||
// NodePath::calc_tight_bounds(). It is not intended to
|
||||
// be called directly, and it has nothing to do with the
|
||||
// normal Panda bounding-volume computation.
|
||||
//
|
||||
// If the node contains any geometry, this updates
|
||||
// min_point and max_point to enclose its bounding box.
|
||||
// found_any is to be set true if the node has any
|
||||
// geometry at all, or left alone if it has none. This
|
||||
// method may be called over several nodes, so it may
|
||||
// enter with min_point, max_point, and found_any
|
||||
// already set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(TransformState) TextNode::
|
||||
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point, bool &found_any,
|
||||
const TransformState *transform) const {
|
||||
CPT(TransformState) next_transform =
|
||||
PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform);
|
||||
|
||||
check_rebuild();
|
||||
|
||||
if (_internal_geom != (PandaNode *)NULL) {
|
||||
_internal_geom->calc_tight_bounds(min_point, max_point,
|
||||
found_any, next_transform);
|
||||
}
|
||||
|
||||
return next_transform;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::has_cull_callback
|
||||
// Access: Protected, Virtual
|
||||
// Description: Should be overridden by derived classes to return
|
||||
// true if cull_callback() has been defined. Otherwise,
|
||||
// returns false to indicate cull_callback() does not
|
||||
// need to be called for this node during the cull
|
||||
// traversal.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TextNode::
|
||||
has_cull_callback() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::cull_callback
|
||||
// Access: Protected, Virtual
|
||||
// Description: If has_cull_callback() returns true, this function
|
||||
// will be called during the cull traversal to perform
|
||||
// any additional operations that should be performed at
|
||||
// cull time. This may include additional manipulation
|
||||
// of render state or additional visible/invisible
|
||||
// decisions, or any other arbitrary operation.
|
||||
//
|
||||
// By the time this function is called, the node has
|
||||
// already passed the bounding-volume test for the
|
||||
// viewing frustum, and the node's transform and state
|
||||
// have already been applied to the indicated
|
||||
// CullTraverserData object.
|
||||
//
|
||||
// The return value is true if this node should be
|
||||
// visible, or false if it should be culled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TextNode::
|
||||
cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
||||
check_rebuild();
|
||||
if (_internal_geom != (PandaNode *)NULL) {
|
||||
// Render the text with this node.
|
||||
CullTraverserData next_data(data, _internal_geom);
|
||||
trav->traverse(next_data);
|
||||
}
|
||||
|
||||
// Now continue to render everything else below this node.
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextNode::recompute_internal_bound
|
||||
// Access: Protected, Virtual
|
||||
// Description: Called when needed to recompute the node's
|
||||
// _internal_bound object. Nodes that contain anything
|
||||
// of substance should redefine this to do the right
|
||||
// thing.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BoundingVolume *TextNode::
|
||||
recompute_internal_bound() {
|
||||
// First, get ourselves a fresh, empty bounding volume.
|
||||
BoundingVolume *bound = PandaNode::recompute_internal_bound();
|
||||
nassertr(bound != (BoundingVolume *)NULL, bound);
|
||||
|
||||
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
|
||||
|
||||
// Now enclose the bounding box around the text. We can do this
|
||||
// without actually generating the text, if we have at least
|
||||
// measured it.
|
||||
check_measure();
|
||||
|
||||
LPoint3f vertices[8];
|
||||
vertices[0].set(_ul3d[0], _ul3d[1], _ul3d[2]);
|
||||
vertices[1].set(_ul3d[0], _ul3d[1], _lr3d[2]);
|
||||
vertices[2].set(_ul3d[0], _lr3d[1], _ul3d[2]);
|
||||
vertices[3].set(_ul3d[0], _lr3d[1], _lr3d[2]);
|
||||
vertices[4].set(_lr3d[0], _ul3d[1], _ul3d[2]);
|
||||
vertices[5].set(_lr3d[0], _ul3d[1], _lr3d[2]);
|
||||
vertices[6].set(_lr3d[0], _lr3d[1], _ul3d[2]);
|
||||
vertices[7].set(_lr3d[0], _lr3d[1], _lr3d[2]);
|
||||
|
||||
gbv->around(vertices, vertices + 8);
|
||||
|
||||
return bound;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -596,23 +799,8 @@ expand_amp_sequence(StringDecoder &decoder) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextNode::
|
||||
do_rebuild() {
|
||||
_needs_rebuild = false;
|
||||
|
||||
remove_all_children();
|
||||
|
||||
PT(PandaNode) new_text = generate();
|
||||
if (new_text != (PandaNode *)NULL) {
|
||||
add_child(new_text);
|
||||
|
||||
/*
|
||||
// And we flatten one more time, to remove the new node itself if
|
||||
// possible (it might be an unneeded node above multiple
|
||||
// children). This flatten operation should be fairly
|
||||
// lightweight; it's already pretty flat.
|
||||
SceneGraphReducer gr(RenderRelation::get_class_type());
|
||||
gr.flatten(this, false);
|
||||
*/
|
||||
}
|
||||
_flags &= ~(F_needs_rebuild | F_needs_measure);
|
||||
_internal_geom = generate();
|
||||
}
|
||||
|
||||
|
||||
@ -625,6 +813,8 @@ do_rebuild() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TextNode::
|
||||
do_measure() {
|
||||
_flags &= ~F_needs_measure;
|
||||
|
||||
_ul2d.set(0.0f, 0.0f);
|
||||
_lr2d.set(0.0f, 0.0f);
|
||||
_ul3d.set(0.0f, 0.0f, 0.0f);
|
||||
|
@ -38,22 +38,19 @@ class StringDecoder;
|
||||
// represent the indicated text.
|
||||
//
|
||||
// The TextNode may be used in one of two ways.
|
||||
// Naively, it may be parented to the scene graph
|
||||
// directly; used in this way, you can optionally call
|
||||
// freeze() and thaw() between changing many parameters
|
||||
// in the text at once, to avoid unnecessary expensive
|
||||
// regeneration with each parameter change. However, it
|
||||
// will work, if slowly, even if you never call freeze()
|
||||
// and thaw().
|
||||
// Naively, it may simply be parented directly into the
|
||||
// scene graph and rendered as if it were a GeomNode; in
|
||||
// this mode, the actual polygon geometry that renders
|
||||
// the text is not directly visible or accessible, but
|
||||
// remains hidden within the TextNode.
|
||||
//
|
||||
// The second way TextNode may be used is as a text
|
||||
// generator. To use it in this way, call freeze() once
|
||||
// on the TextNode when you create it, and never call
|
||||
// thaw(). Do not parent the TextNode to the scene
|
||||
// graph; instea, set the properties of the text and
|
||||
// call generate() to return a node which you may parent
|
||||
// wherever you like. Each time you call generate() a
|
||||
// new node is returned.
|
||||
// generator. To use it in this way, do not parent the
|
||||
// TextNode to the scene graph; instead, set the
|
||||
// properties of the text and call generate() to return
|
||||
// an ordinary node, containing ordinary geometry, which
|
||||
// you may use however you like. Each time you call
|
||||
// generate() a new node is returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA TextNode : public PandaNode {
|
||||
PUBLISHED:
|
||||
@ -73,7 +70,6 @@ PUBLISHED:
|
||||
};
|
||||
|
||||
INLINE int freeze();
|
||||
INLINE int get_freeze_level() const;
|
||||
INLINE int thaw();
|
||||
|
||||
INLINE void set_font(TextFont *font);
|
||||
@ -188,9 +184,6 @@ PUBLISHED:
|
||||
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
INLINE void rebuild(bool needs_measure);
|
||||
INLINE void measure();
|
||||
|
||||
// The following functions return information about the text that
|
||||
// was last built (and is currently visible).
|
||||
INLINE float get_left() const;
|
||||
@ -206,6 +199,7 @@ PUBLISHED:
|
||||
INLINE int get_num_rows() const;
|
||||
|
||||
PT(PandaNode) generate();
|
||||
INLINE void update();
|
||||
|
||||
public:
|
||||
// Direct support for wide-character strings.
|
||||
@ -222,12 +216,29 @@ public:
|
||||
wstring decode_text(const string &text) const;
|
||||
|
||||
// From parent class PandaNode
|
||||
virtual void xform(const LMatrix4f &mat);
|
||||
virtual int get_unsafe_to_apply_attribs() const;
|
||||
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs,
|
||||
int attrib_types,
|
||||
GeomTransformer &transformer);
|
||||
virtual CPT(TransformState)
|
||||
calc_tight_bounds(LPoint3f &min_point, LPoint3f &max_point,
|
||||
bool &found_any,
|
||||
const TransformState *transform) const;
|
||||
|
||||
virtual bool has_cull_callback() const;
|
||||
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
|
||||
|
||||
virtual BoundingVolume *recompute_internal_bound();
|
||||
|
||||
private:
|
||||
wstring decode_text_impl(StringDecoder &decoder) const;
|
||||
int expand_amp_sequence(StringDecoder &decoder) const;
|
||||
|
||||
INLINE void invalidate_no_measure();
|
||||
INLINE void invalidate_with_measure();
|
||||
INLINE void check_rebuild() const;
|
||||
INLINE void check_measure() const;
|
||||
|
||||
void do_rebuild();
|
||||
void do_measure();
|
||||
|
||||
@ -246,6 +257,7 @@ private:
|
||||
PT(PandaNode) make_card_with_border();
|
||||
|
||||
PT(TextFont) _font;
|
||||
PT(PandaNode) _internal_geom;
|
||||
|
||||
Encoding _encoding;
|
||||
float _slant;
|
||||
@ -271,6 +283,8 @@ private:
|
||||
F_expand_amp = 0x0800,
|
||||
F_got_text = 0x1000,
|
||||
F_got_wtext = 0x2000,
|
||||
F_needs_rebuild = 0x4000,
|
||||
F_needs_measure = 0x8000,
|
||||
};
|
||||
|
||||
int _flags;
|
||||
@ -296,8 +310,6 @@ private:
|
||||
LPoint2f _ul2d, _lr2d;
|
||||
LPoint3f _ul3d, _lr3d;
|
||||
int _num_rows;
|
||||
int _freeze_level;
|
||||
bool _needs_rebuild;
|
||||
|
||||
public:
|
||||
static Encoding _default_encoding;
|
||||
|
Loading…
x
Reference in New Issue
Block a user