56 PStatCollector TextNode::_text_generate_pcollector(
"*:Generate Text");
62 TextNode(
const string &name) :
PandaNode(name) {
67 _usage_hint = GeomEnums::UH_static;
70 _flatten_flags |= FF_strong;
72 if (text_dynamic_merge) {
73 _flatten_flags |= FF_dynamic_merge;
76 if (text_small_caps) {
80 _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
81 _card_color.set(1.0f, 1.0f, 1.0f, 1.0f);
85 _frame_ul.set(0.0f, 0.0f);
86 _frame_lr.set(0.0f, 0.0f);
87 _card_ul.set(0.0f, 0.0f);
88 _card_lr.set(0.0f, 0.0f);
90 _transform = LMatrix4::ident_mat();
91 _coordinate_system = CS_default;
93 _ul3d.set(0.0f, 0.0f, 0.0f);
94 _lr3d.set(0.0f, 0.0f, 0.0f);
107 _usage_hint = GeomEnums::UH_static;
109 _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
110 _card_color.set(1.0f, 1.0f, 1.0f, 1.0f);
114 _frame_ul.set(0.0f, 0.0f);
115 _frame_lr.set(0.0f, 0.0f);
116 _card_ul.set(0.0f, 0.0f);
117 _card_lr.set(0.0f, 0.0f);
119 _transform = LMatrix4::ident_mat();
120 _coordinate_system = CS_default;
122 _ul3d.set(0.0f, 0.0f, 0.0f);
123 _lr3d.set(0.0f, 0.0f, 0.0f);
134 _card_texture(copy._card_texture),
135 _frame_color(copy._frame_color),
136 _card_color(copy._card_color),
138 _max_rows(copy._max_rows),
140 _frame_width(copy._frame_width),
141 _card_border_size(copy._card_border_size),
142 _card_border_uv_portion(copy._card_border_uv_portion),
143 _frame_ul(copy._frame_ul),
144 _frame_lr(copy._frame_lr),
145 _card_ul(copy._card_ul),
146 _card_lr(copy._card_lr),
147 _transform(copy._transform),
148 _coordinate_system(copy._coordinate_system),
152 invalidate_with_measure();
179 if (font ==
nullptr) {
201 if (font ==
nullptr) {
220 if (font ==
nullptr) {
244 if (font ==
nullptr) {
259 if (font ==
nullptr) {
263 PN_stdfloat width = 0.0f;
265 std::wstring::const_iterator si;
266 for (si = line.begin(); si != line.end(); ++si) {
277 output(std::ostream &out)
const {
278 PandaNode::output(out);
280 PT(
PandaNode) internal_geom = do_get_internal_geom();
282 if (internal_geom !=
nullptr) {
283 geom_count = count_geoms(internal_geom);
286 out <<
" (" << geom_count <<
" geoms)";
293 write(std::ostream &out,
int indent_level)
const {
294 PandaNode::write(out, indent_level);
296 TextProperties::write(out, indent_level + 2);
297 indent(out, indent_level + 2)
298 <<
"transform is: " << *TransformState::make_mat(_transform) <<
"\n";
299 indent(out, indent_level + 2)
300 <<
"in coordinate system " << _coordinate_system <<
"\n";
301 indent(out, indent_level + 2)
302 <<
"text is " <<
get_text() <<
"\n";
314 get_internal_geom()
const {
318 <<
"TextNode::get_internal_geom() called.\n";
319 return do_get_internal_geom();
328 invalidate_with_measure();
343 SceneGraphReducer::TT_tex_matrix |
344 SceneGraphReducer::TT_other;
360 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
361 const LMatrix4 &mat = attribs._transform->get_mat();
364 if ((_flags & F_needs_measure) == 0) {
372 if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
373 if (attribs._color !=
nullptr) {
377 TextProperties::set_text_color(c);
378 TextProperties::set_shadow_color(c);
381 invalidate_no_measure();
385 if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
386 if (attribs._color_scale !=
nullptr) {
389 if (s != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)) {
390 LVecBase4 tc = get_text_color();
391 tc.componentwise_mult(s);
392 TextProperties::set_text_color(tc);
394 LVecBase4 sc = get_shadow_color();
395 sc.componentwise_mult(s);
396 TextProperties::set_shadow_color(sc);
398 _frame_color.componentwise_mult(s);
399 _card_color.componentwise_mult(s);
401 invalidate_no_measure();
408 if ((_flags & F_needs_rebuild) == 0 &&
409 _internal_geom !=
nullptr) {
411 gr.
apply_attribs(_internal_geom, attribs, attrib_types, transformer);
427 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point,
bool &found_any,
430 PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
433 PT(
PandaNode) geom = do_get_internal_geom();
434 if (geom !=
nullptr) {
435 geom->calc_tight_bounds(min_point, max_point,
436 found_any, next_transform, current_thread);
439 return next_transform;
463 PT(
PandaNode) internal_geom = do_get_internal_geom();
464 if (internal_geom !=
nullptr) {
492 int &internal_vertices,
494 Thread *current_thread)
const {
507 vertices[0].set(_ul3d[0], _ul3d[1], _ul3d[2]);
508 vertices[1].set(_ul3d[0], _ul3d[1], _lr3d[2]);
509 vertices[2].set(_ul3d[0], _lr3d[1], _ul3d[2]);
510 vertices[3].set(_ul3d[0], _lr3d[1], _lr3d[2]);
511 vertices[4].set(_lr3d[0], _ul3d[1], _ul3d[2]);
512 vertices[5].set(_lr3d[0], _ul3d[1], _lr3d[2]);
513 vertices[6].set(_lr3d[0], _lr3d[1], _ul3d[2]);
514 vertices[7].set(_lr3d[0], _lr3d[1], _lr3d[2]);
517 gbv->
around(vertices, vertices + 8);
519 internal_bounds = bound;
520 internal_vertices = 0;
531 PT(
PandaNode) child = do_get_internal_geom();
532 if (child !=
nullptr) {
533 CPT(
RenderState) child_state = node_state->compose(child->get_state());
534 child->r_prepare_scene(gsg, child_state, transformer, current_thread);
547 _flags &= ~(F_needs_rebuild | F_needs_measure);
548 _internal_geom = do_generate();
572 if (text_cat.is_debug()) {
574 <<
"Rebuilding " << get_type() <<
" " << get_name()
575 <<
" with '" <<
get_text() <<
"'\n";
587 _ul3d.set(0.0f, 0.0f, 0.0f);
588 _lr3d.set(0.0f, 0.0f, 0.0f);
592 size_t newline = name.find(
'\n');
593 if (newline != string::npos) {
594 name = name.substr(0, newline);
603 if (font ==
nullptr) {
610 LMatrix4::convert_mat(CS_zup_right, _coordinate_system) *
614 root->set_transform(transform);
620 assembler.set_properties(*
this);
621 assembler.set_max_rows(_max_rows);
622 assembler.set_usage_hint(_usage_hint);
623 assembler.set_dynamic_merge((_flatten_flags & FF_dynamic_merge) != 0);
624 bool all_set = assembler.set_wtext(wtext);
627 _flags &= ~F_has_overflow;
630 _flags |= F_has_overflow;
633 PT(
PandaNode) text_root = assembler.assemble_text();
634 _text_ul = assembler.get_ul();
635 _text_lr = assembler.get_lr();
636 _num_rows = assembler.get_num_rows();
637 _wordwrapped_wtext = assembler.get_wordwrapped_wtext();
641 root->add_child(text, get_draw_order() + 2);
642 text->add_child(text_root);
646 const LVector2 &ul = assembler.get_ul();
647 const LVector2 &lr = assembler.get_lr();
648 _ul3d.set(ul[0], 0.0f, ul[1]);
649 _lr3d.set(lr[0], 0.0f, lr[1]);
651 _ul3d = _ul3d * _transform;
652 _lr3d = _lr3d * _transform;
655 _flags &= ~F_needs_measure;
661 if (_flatten_flags & FF_strong) {
662 root_np.flatten_strong();
663 }
else if (_flatten_flags & FF_medium) {
664 root_np.flatten_medium();
665 }
else if (_flatten_flags & FF_light) {
666 root_np.flatten_light();
671 if (_flags & F_has_card) {
673 if (_flags & F_has_card_border) {
674 card_root = make_card_with_border();
676 card_root = make_card();
678 card_root->set_transform(transform);
679 card_root->set_attrib(ColorAttrib::make_flat(_card_color));
680 if (_card_color[3] != 1.0f) {
681 card_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
683 if (_flags & F_has_card_texture) {
684 card_root->set_attrib(TextureAttrib::make(_card_texture));
688 card_root->set_attrib(CullBinAttrib::make(get_bin(), get_draw_order()));
697 card_root->add_child(root);
700 if (_flags & F_card_decal) {
701 card_root->set_effect(DecalEffect::make());
705 if (_flags & F_has_frame) {
707 frame_root->set_transform(transform);
708 root->add_child(frame_root, get_draw_order() + 1);
709 frame_root->set_attrib(ColorAttrib::make_flat(_frame_color));
710 if (_frame_color[3] != 1.0f) {
711 frame_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
715 frame_root->set_attrib(CullBinAttrib::make(get_bin(), get_draw_order() + 1));
730 do_get_internal_geom()
const {
733 return _internal_geom;
742 nassertr((_flags & F_needs_measure) == 0,
nullptr);
746 PN_stdfloat left = _frame_ul[0];
747 PN_stdfloat right = _frame_lr[0];
748 PN_stdfloat bottom = _frame_lr[1];
749 PN_stdfloat top = _frame_ul[1];
751 if (_flags & F_frame_as_margin) {
752 left = _text_ul[0] - left;
753 right = _text_lr[0] + right;
754 bottom = _text_lr[1] - bottom;
755 top = _text_ul[1] + top;
758 CPT(
RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, _frame_width);
763 vdata->unclean_set_num_rows(4);
766 vertex.set_data3(left, 0.0f, top);
767 vertex.set_data3(left, 0.0f, bottom);
768 vertex.set_data3(right, 0.0f, bottom);
769 vertex.set_data3(right, 0.0f, top);
772 frame->add_consecutive_vertices(0, 4);
773 frame->add_vertex(0);
774 frame->close_primitive();
777 geom->add_primitive(frame);
778 frame_node->add_geom(geom, state);
780 if (_flags & F_frame_corners) {
782 corners->add_consecutive_vertices(0, 4);
784 geom2->add_primitive(corners);
785 frame_node->add_geom(geom2, state);
797 nassertr((_flags & F_needs_measure) == 0,
nullptr);
801 PN_stdfloat left = _card_ul[0];
802 PN_stdfloat right = _card_lr[0];
803 PN_stdfloat bottom = _card_lr[1];
804 PN_stdfloat top = _card_ul[1];
806 if (_flags & F_card_as_margin) {
807 left = _text_ul[0] - left;
808 right = _text_lr[0] + right;
809 bottom = _text_lr[1] - bottom;
810 top = _text_ul[1] + top;
815 vdata->unclean_set_num_rows(4);
819 vertex.set_data3(left, 0.0f, top);
820 vertex.set_data3(left, 0.0f, bottom);
821 vertex.set_data3(right, 0.0f, top);
822 vertex.set_data3(right, 0.0f, bottom);
824 texcoord.set_data2(0.0f, 1.0f);
825 texcoord.set_data2(0.0f, 0.0f);
826 texcoord.set_data2(1.0f, 1.0f);
827 texcoord.set_data2(1.0f, 0.0f);
830 card->add_consecutive_vertices(0, 4);
831 card->close_primitive();
834 geom->add_primitive(card);
836 card_node->add_geom(geom);
847 make_card_with_border() {
849 nassertr((_flags & F_needs_measure) == 0,
nullptr);
853 PN_stdfloat left = _card_ul[0];
854 PN_stdfloat right = _card_lr[0];
855 PN_stdfloat bottom = _card_lr[1];
856 PN_stdfloat top = _card_ul[1];
858 if (_flags & F_card_as_margin) {
859 left = _text_ul[0] - left;
860 right = _text_lr[0] + right;
861 bottom = _text_lr[1] - bottom;
862 top = _text_ul[1] + top;
873 vdata->unclean_set_num_rows(16);
878 vertex.set_data3(left, 0.02, top);
879 vertex.set_data3(left, 0.02, top - _card_border_size);
880 vertex.set_data3(left + _card_border_size, 0.02, top);
881 vertex.set_data3(left + _card_border_size, 0.02,
882 top - _card_border_size);
884 vertex.set_data3(right - _card_border_size, 0.02, top);
885 vertex.set_data3(right - _card_border_size, 0.02,
886 top - _card_border_size);
887 vertex.set_data3(right, 0.02, top);
888 vertex.set_data3(right, 0.02, top - _card_border_size);
890 vertex.set_data3(left, 0.02, bottom + _card_border_size);
891 vertex.set_data3(left, 0.02, bottom);
892 vertex.set_data3(left + _card_border_size, 0.02,
893 bottom + _card_border_size);
894 vertex.set_data3(left + _card_border_size, 0.02, bottom);
896 vertex.set_data3(right - _card_border_size, 0.02,
897 bottom + _card_border_size);
898 vertex.set_data3(right - _card_border_size, 0.02, bottom);
899 vertex.set_data3(right, 0.02, bottom + _card_border_size);
900 vertex.set_data3(right, 0.02, bottom);
902 texcoord.set_data2(0.0f, 1.0f);
903 texcoord.set_data2(0.0f, 1.0f - _card_border_uv_portion);
904 texcoord.set_data2(0.0f + _card_border_uv_portion, 1.0f);
905 texcoord.set_data2(0.0f + _card_border_uv_portion,
906 1.0f - _card_border_uv_portion);
907 texcoord.set_data2(1.0f -_card_border_uv_portion, 1.0f);
908 texcoord.set_data2(1.0f -_card_border_uv_portion,
909 1.0f - _card_border_uv_portion);
910 texcoord.set_data2(1.0f, 1.0f);
911 texcoord.set_data2(1.0f, 1.0f - _card_border_uv_portion);
913 texcoord.set_data2(0.0f, _card_border_uv_portion);
914 texcoord.set_data2(0.0f, 0.0f);
915 texcoord.set_data2(_card_border_uv_portion, _card_border_uv_portion);
916 texcoord.set_data2(_card_border_uv_portion, 0.0f);
918 texcoord.set_data2(1.0f - _card_border_uv_portion, _card_border_uv_portion);
919 texcoord.set_data2(1.0f - _card_border_uv_portion, 0.0f);
920 texcoord.set_data2(1.0f, _card_border_uv_portion);
921 texcoord.set_data2(1.0f, 0.0f);
924 card->reserve_num_vertices(24);
927 card->add_consecutive_vertices(0, 8);
928 card->close_primitive();
934 card->add_vertex(10);
936 card->add_vertex(12);
938 card->add_vertex(14);
939 card->close_primitive();
942 card->add_consecutive_vertices(8, 8);
943 card->close_primitive();
946 geom->add_primitive(card);
948 card_node->add_geom(geom);
967 for (
size_t i = 0; i < children.get_num_children(); ++i) {
968 num_geoms += count_geoms(children.get_child(i));