16 #include "textGlyph.h" 17 #include "stringDecoder.h" 18 #include "config_text.h" 19 #include "textAssembler.h" 21 #include "compose_matrix.h" 23 #include "geomLinestrips.h" 24 #include "geomPoints.h" 25 #include "geomTristrips.h" 26 #include "geomVertexWriter.h" 29 #include "transformState.h" 30 #include "colorAttrib.h" 31 #include "colorScaleAttrib.h" 32 #include "cullBinAttrib.h" 33 #include "textureAttrib.h" 34 #include "transparencyAttrib.h" 35 #include "sceneGraphReducer.h" 37 #include "cullTraverser.h" 38 #include "cullTraverserData.h" 39 #include "geometricBoundingVolume.h" 40 #include "accumulatedAttribs.h" 41 #include "renderState.h" 42 #include "renderModeAttrib.h" 43 #include "decalEffect.h" 47 #include "pStatCollector.h" 48 #include "pStatTimer.h" 49 #include "boundingSphere.h" 55 PStatCollector TextNode::_text_generate_pcollector(
"*:Generate Text");
63 TextNode(
const string &name) :
PandaNode(name) {
68 _usage_hint = GeomEnums::UH_static;
71 _flatten_flags |= FF_strong;
73 if (text_dynamic_merge) {
74 _flatten_flags |= FF_dynamic_merge;
77 if (text_small_caps) {
81 _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
82 _card_color.set(1.0f, 1.0f, 1.0f, 1.0f);
86 _frame_ul.set(0.0f, 0.0f);
87 _frame_lr.set(0.0f, 0.0f);
88 _card_ul.set(0.0f, 0.0f);
89 _card_lr.set(0.0f, 0.0f);
92 _coordinate_system = CS_default;
94 _ul3d.set(0.0f, 0.0f, 0.0f);
95 _lr3d.set(0.0f, 0.0f, 0.0f);
111 _usage_hint = GeomEnums::UH_static;
113 _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
114 _card_color.set(1.0f, 1.0f, 1.0f, 1.0f);
118 _frame_ul.set(0.0f, 0.0f);
119 _frame_lr.set(0.0f, 0.0f);
120 _card_ul.set(0.0f, 0.0f);
121 _card_lr.set(0.0f, 0.0f);
124 _coordinate_system = CS_default;
126 _ul3d.set(0.0f, 0.0f, 0.0f);
127 _lr3d.set(0.0f, 0.0f, 0.0f);
140 _card_texture(copy._card_texture),
141 _frame_color(copy._frame_color),
142 _card_color(copy._card_color),
144 _max_rows(copy._max_rows),
145 _usage_hint(GeomEnums::UH_static),
146 _frame_width(copy._frame_width),
147 _card_border_size(copy._card_border_size),
148 _card_border_uv_portion(copy._card_border_uv_portion),
149 _frame_ul(copy._frame_ul),
150 _frame_lr(copy._frame_lr),
151 _card_ul(copy._card_ul),
152 _card_lr(copy._card_lr),
153 _transform(copy._transform),
154 _coordinate_system(copy._coordinate_system),
158 invalidate_with_measure();
292 PN_stdfloat width = 0.0f;
294 wstring::const_iterator si;
295 for (si = line.begin(); si != line.end(); ++si) {
308 output(ostream &out)
const {
309 PandaNode::output(out);
313 if (_internal_geom != (
PandaNode *)NULL) {
314 geom_count = count_geoms(_internal_geom);
317 out <<
" (" << geom_count <<
" geoms)";
326 write(ostream &out,
int indent_level)
const {
327 PandaNode::write(out, indent_level);
328 TextProperties::write(out, indent_level + 2);
329 indent(out, indent_level + 2)
330 <<
"transform is: " << *TransformState::make_mat(_transform) <<
"\n";
331 indent(out, indent_level + 2)
332 <<
"in coordinate system " << _coordinate_system <<
"\n";
333 indent(out, indent_level + 2)
334 <<
"text is " <<
get_text() <<
"\n";
347 if (text_cat.is_debug()) {
349 <<
"Rebuilding " << get_type() <<
" " << get_name()
350 <<
" with '" <<
get_text() <<
"'\n";
363 _ul3d.set(0.0f, 0.0f, 0.0f);
364 _lr3d.set(0.0f, 0.0f, 0.0f);
368 size_t newline = name.find(
'\n');
369 if (newline != string::npos) {
370 name = name.substr(0, newline);
390 CPT(TransformState) transform = TransformState::make_mat(mat);
391 root->set_transform(transform);
401 bool all_set = assembler.
set_wtext(wtext);
404 _flags &= ~F_has_overflow;
407 _flags |= F_has_overflow;
410 PT(
PandaNode) text_root = assembler.assemble_text();
411 _text_ul = assembler.
get_ul();
412 _text_lr = assembler.
get_lr();
419 text->add_child(text_root);
425 _ul3d.set(ul[0], 0.0f, ul[1]);
426 _lr3d.set(lr[0], 0.0f, lr[1]);
428 _ul3d = _ul3d * _transform;
429 _lr3d = _lr3d * _transform;
432 _flags &= ~F_needs_measure;
438 if (_flatten_flags & FF_strong) {
440 }
else if (_flatten_flags & FF_medium) {
442 }
else if (_flatten_flags & FF_light) {
450 if (has_card_border()) {
451 card_root = make_card_with_border();
453 card_root = make_card();
455 card_root->set_transform(transform);
456 card_root->set_attrib(ColorAttrib::make_flat(get_card_color()));
457 if (get_card_color()[3] != 1.0f) {
458 card_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
460 if (has_card_texture()) {
461 card_root->set_attrib(TextureAttrib::make(get_card_texture()));
474 card_root->add_child(root);
478 card_root->set_effect(DecalEffect::make());
484 frame_root->set_transform(transform);
486 frame_root->set_attrib(ColorAttrib::make_flat(get_frame_color()));
487 if (get_frame_color()[3] != 1.0f) {
488 frame_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
519 <<
"TextNode::get_internal_geom() called.\n";
521 return _internal_geom;
541 SceneGraphReducer::TT_tex_matrix |
542 SceneGraphReducer::TT_other;
560 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
561 const LMatrix4 &mat = attribs._transform->get_mat();
564 if ((_flags & F_needs_measure) == 0) {
572 if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
584 if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
585 if (attribs._color_scale != (
const RenderAttrib *)NULL) {
588 if (s !=
LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)) {
600 set_shadow_color(sc);
619 if ((_flags & F_needs_rebuild) == 0 &&
622 gr.
apply_attribs(_internal_geom, attribs, attrib_types, transformer);
642 CPT(TransformState) TextNode::
643 calc_tight_bounds(
LPoint3 &min_point,
LPoint3 &max_point,
bool &found_any,
644 const TransformState *transform,
Thread *current_thread)
const {
645 CPT(TransformState) next_transform =
646 PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
651 if (_internal_geom != (
PandaNode *)NULL) {
652 _internal_geom->calc_tight_bounds(min_point, max_point,
653 found_any, next_transform, current_thread);
656 return next_transform;
687 if (_internal_geom != (
PandaNode *)NULL) {
722 int &internal_vertices,
724 Thread *current_thread)
const {
736 vertices[0].set(_ul3d[0], _ul3d[1], _ul3d[2]);
737 vertices[1].set(_ul3d[0], _ul3d[1], _lr3d[2]);
738 vertices[2].set(_ul3d[0], _lr3d[1], _ul3d[2]);
739 vertices[3].set(_ul3d[0], _lr3d[1], _lr3d[2]);
740 vertices[4].set(_lr3d[0], _ul3d[1], _ul3d[2]);
741 vertices[5].set(_lr3d[0], _ul3d[1], _lr3d[2]);
742 vertices[6].set(_lr3d[0], _lr3d[1], _ul3d[2]);
743 vertices[7].set(_lr3d[0], _lr3d[1], _lr3d[2]);
745 gbv->
around(vertices, vertices + 8);
747 internal_bounds = bound;
748 internal_vertices = 0;
766 CPT(
RenderState) child_state = node_state->compose(child->get_state());
781 _flags &= ~(F_needs_rebuild | F_needs_measure);
782 _internal_geom = generate();
809 PN_stdfloat left = dimensions[0];
810 PN_stdfloat right = dimensions[1];
811 PN_stdfloat bottom = dimensions[2];
812 PN_stdfloat top = dimensions[3];
814 CPT(
RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, _frame_width);
827 frame->add_consecutive_vertices(0, 4);
828 frame->add_vertex(0);
829 frame->close_primitive();
832 geom->add_primitive(frame);
833 frame_node->add_geom(geom, state);
835 if (get_frame_corners()) {
837 corners->add_consecutive_vertices(0, 4);
839 geom2->add_primitive(corners);
840 frame_node->add_geom(geom2, state);
843 return frame_node.p();
856 PN_stdfloat left = dimensions[0];
857 PN_stdfloat right = dimensions[1];
858 PN_stdfloat bottom = dimensions[2];
859 PN_stdfloat top = dimensions[3];
877 card->add_consecutive_vertices(0, 4);
878 card->close_primitive();
881 geom->add_primitive(card);
883 card_node->add_geom(geom);
885 return card_node.p();
896 make_card_with_border() {
900 PN_stdfloat left = dimensions[0];
901 PN_stdfloat right = dimensions[1];
902 PN_stdfloat bottom = dimensions[2];
903 PN_stdfloat top = dimensions[3];
921 vertex.
add_data3(left, 0.02, top - _card_border_size);
922 vertex.
add_data3(left + _card_border_size, 0.02, top);
923 vertex.
add_data3(left + _card_border_size, 0.02,
924 top - _card_border_size);
926 vertex.
add_data3(right - _card_border_size, 0.02, top);
927 vertex.
add_data3(right - _card_border_size, 0.02,
928 top - _card_border_size);
930 vertex.
add_data3(right, 0.02, top - _card_border_size);
932 vertex.
add_data3(left, 0.02, bottom + _card_border_size);
934 vertex.
add_data3(left + _card_border_size, 0.02,
935 bottom + _card_border_size);
936 vertex.
add_data3(left + _card_border_size, 0.02, bottom);
938 vertex.
add_data3(right - _card_border_size, 0.02,
939 bottom + _card_border_size);
940 vertex.
add_data3(right - _card_border_size, 0.02, bottom);
941 vertex.
add_data3(right, 0.02, bottom + _card_border_size);
945 texcoord.
add_data2(0.0f, 1.0f - _card_border_uv_portion);
946 texcoord.
add_data2(0.0f + _card_border_uv_portion, 1.0f);
947 texcoord.
add_data2(0.0f + _card_border_uv_portion,
948 1.0f - _card_border_uv_portion);
949 texcoord.
add_data2(1.0f -_card_border_uv_portion, 1.0f);
950 texcoord.
add_data2(1.0f -_card_border_uv_portion,
951 1.0f - _card_border_uv_portion);
953 texcoord.
add_data2(1.0f, 1.0f - _card_border_uv_portion);
955 texcoord.
add_data2(0.0f, _card_border_uv_portion);
957 texcoord.
add_data2(_card_border_uv_portion, _card_border_uv_portion);
958 texcoord.
add_data2(_card_border_uv_portion, 0.0f);
960 texcoord.
add_data2(1.0f - _card_border_uv_portion, _card_border_uv_portion);
961 texcoord.
add_data2(1.0f - _card_border_uv_portion, 0.0f);
962 texcoord.
add_data2(1.0f, _card_border_uv_portion);
968 card->add_consecutive_vertices(0, 8);
969 card->close_primitive();
975 card->add_vertex(10);
977 card->add_vertex(12);
979 card->add_vertex(14);
980 card->close_primitive();
983 card->add_consecutive_vertices(8, 8);
984 card->close_primitive();
987 geom->add_primitive(card);
989 card_node->add_geom(geom);
991 return card_node.p();
1012 num_geoms += count_geoms(children.
get_child(i));
int get_num_children() const
Returns the number of children of the node.
static const LMatrix4f & ident_mat()
Returns an identity matrix.
A basic node of the scene graph or data graph.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
bool has_character(wchar_t character) const
Returns true if the named character exists in the font or can be synthesized by Panda, false otherwise.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
static bool has_character(wchar_t character, const TextProperties &properties)
Returns true if the named character exists in the font or can be synthesized by Panda, false otherwise.
const LColor & get_color() const
If the type is T_flat or T_off, this returns the color that will be applied to geometry.
Defines a series of disconnected points.
const LVecBase4 & get_scale() const
Returns the scale to be applied to colors.
void set_small_caps(bool small_caps)
Sets the small_caps flag.
This class can be used to convert text between multiple representations, e.g.
const LVector2 & get_ul() const
Returns the upper-left corner of the assembled text, in 2-d text coordinates.
This defines a bounding sphere, consisting of a center and a radius.
TextFont * get_font() const
Returns the font currently in use, if any.
void add_data2(PN_stdfloat x, PN_stdfloat y)
Sets the write row to a particular 2-component value, and advances the write row. ...
An interface for simplifying ("flattening") scene graphs by eliminating unneeded nodes and collapsing...
This collects together the pieces of data that are accumulated for each node while walking the scene ...
Defines a series of triangle strips.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
static bool is_whitespace(wchar_t character, const TextProperties &properties)
Returns true if the indicated character represents whitespace in the font, or false if anything visib...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
int get_num_rows() const
Returns the number of rows of text after it has all been wordwrapped and assembled.
int get_num_geoms() const
Returns the number of geoms in the node.
Type get_color_type() const
Returns the type of color specified by this ColorAttrib.
static const LMatrix4f & convert_mat(CoordinateSystem from, CoordinateSystem to)
Returns a matrix that transforms from the indicated coordinate system to the indicated coordinate sys...
void set_properties(const TextProperties &properties)
Specifies the default TextProperties that are applied to the text in the absence of any nested proper...
virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer, Thread *current_thread)
The recursive implementation of prepare_scene().
void traverse(const NodePath &root)
Begins the traversal from the indicated node.
An encapsulation of a font; i.e.
virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, GeomTransformer &transformer)
Applies whatever attributes are specified in the AccumulatedAttribs object (and by the attrib_types b...
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
const wstring & get_wtext() const
Returns the text associated with the TextEncoder, as a wide-character string.
A lightweight class that represents a single element that may be timed and/or counted via stats...
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
static bool has_exact_character(wchar_t character, const TextProperties &properties)
Returns true if the named character exists in the font exactly as named, false otherwise.
bool get_card_decal() const
Returns the card_decal flag.
LVecBase4 get_frame_actual() const
Returns the actual dimensions of the frame around the text.
bool set_wtext(const wstring &wtext)
Accepts a new text string and associated properties structure, and precomputes the wordwrapping layou...
static PN_stdfloat calc_width(wchar_t character, const TextProperties &properties)
Returns the width of a single character, according to its associated font.
This class is used by the SceneGraphReducer to maintain and accumulate the set of attributes we have ...
This is a 4-by-4 transform matrix.
int get_draw_order() const
Returns the drawing order set with set_draw_order().
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
This class is not normally used directly by user code, but is used by the TextNode to lay out a block...
virtual int get_unsafe_to_apply_attribs() const
Returns the union of all attributes from SceneGraphReducer::AttribTypes that may not safely be applie...
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row. ...
This is a four-component vector distance.
int flatten_light()
Lightly flattens out the hierarchy below this node by applying transforms, colors, and texture matrices from the nodes onto the vertices, but does not remove any nodes.
LVecBase4 get_card_actual() const
Returns the actual dimensions of the card around the text.
const LVector2 & get_lr() const
Returns the lower-right corner of the assembled text, in 2-d text coordinates.
Applies a scale to colors in the scene graph and on vertices.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
This is the base class for all three-component vectors and points.
void set_max_rows(int max_rows)
If max_rows is greater than zero, no more than max_rows will be accepted.
void apply_attribs(PandaNode *node, int attrib_types=~(TT_clip_plane|TT_cull_face|TT_apply_texture_color))
Walks the scene graph, accumulating attribs of the indicated types, applying them to the vertices...
PandaNode * get_internal_geom() const
Returns the actual node that is used internally to render the text, if the TextNode is parented withi...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
int flatten_strong()
The strongest possible flattening.
This is a two-component vector offset.
Children get_children(Thread *current_thread=Thread::get_current_thread()) const
Returns an object that can be used to walk through the list of children of the node.
A thread; that is, a lightweight process.
Defines a series of line strips.
The primary interface to this module.
This defines the set of visual properties that may be assigned to the individual characters of the te...
const string & get_bin() const
Returns the drawing bin set with set_bin(), or empty string if no bin has been set.
Indicates what color should be applied to renderable geometry.
void set_usage_hint(Geom::UsageHint usage_hint)
Specifies the UsageHint that will be applied to generated geometry.
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
bool has_exact_character(wchar_t character) const
Returns true if the named character exists in the font exactly as named, false otherwise.
virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer, Thread *current_thread)
The recursive implementation of prepare_scene().
PandaNode * get_child(int n) const
Returns the nth child of the node.
TypeHandle is the identifier used to differentiate C++ class types.
virtual bool is_geom_node() const
A simple downcast check.
wstring get_wordwrapped_wtext() const
Returns a wstring that represents the contents of the text, with newlines inserted according to the w...
int flatten_medium()
A more thorough flattening than flatten_light(), this first applies all the transforms, colors, and texture matrices from the nodes onto the vertices, and then removes unneeded grouping nodes–nodes that have exactly one child, for instance, but have no special properties in themselves.
bool around(const GeometricBoundingVolume **first, const GeometricBoundingVolume **last)
Resets the volume to enclose only the volumes indicated.
PN_stdfloat calc_width(wchar_t character) const
Returns the width of a single character of the font, or 0.0 if the character is not known...
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
bool has_bin() const
Returns true if an explicit drawing bin has been set via set_bin(), false otherwise.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
bool is_whitespace(wchar_t character) const
Returns true if the indicated character represents whitespace in the font, or false if anything visib...
A node that holds Geom objects, renderable pieces of geometry.
void set_dynamic_merge(bool dynamic_merge)
Sets the dynamic_merge flag.
string get_text() const
Returns the current text, as encoded via the current encoding system.
virtual void compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, int &internal_vertices, int pipeline_stage, Thread *current_thread) const
Called when needed to recompute the node's _internal_bound object.
Geom::UsageHint get_usage_hint() const
Returns the UsageHint that will be applied to generated geometry.