00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "textNode.h"
00016 #include "textGlyph.h"
00017 #include "stringDecoder.h"
00018 #include "config_text.h"
00019 #include "textAssembler.h"
00020
00021 #include "compose_matrix.h"
00022 #include "geom.h"
00023 #include "geomLinestrips.h"
00024 #include "geomPoints.h"
00025 #include "geomTristrips.h"
00026 #include "geomVertexWriter.h"
00027 #include "geomNode.h"
00028 #include "pnotify.h"
00029 #include "transformState.h"
00030 #include "colorAttrib.h"
00031 #include "colorScaleAttrib.h"
00032 #include "cullBinAttrib.h"
00033 #include "textureAttrib.h"
00034 #include "transparencyAttrib.h"
00035 #include "sceneGraphReducer.h"
00036 #include "indent.h"
00037 #include "cullTraverser.h"
00038 #include "cullTraverserData.h"
00039 #include "geometricBoundingVolume.h"
00040 #include "accumulatedAttribs.h"
00041 #include "renderState.h"
00042 #include "renderModeAttrib.h"
00043 #include "decalEffect.h"
00044 #include "dcast.h"
00045 #include "bamFile.h"
00046 #include "zStream.h"
00047 #include "pStatCollector.h"
00048 #include "pStatTimer.h"
00049 #include "boundingSphere.h"
00050
00051 #include <stdio.h>
00052
00053 TypeHandle TextNode::_type_handle;
00054
00055 PStatCollector TextNode::_text_generate_pcollector("*:Generate Text");
00056
00057
00058
00059
00060
00061
00062 TextNode::
00063 TextNode(const string &name) : PandaNode(name) {
00064 set_cull_callback();
00065
00066 _flags = 0;
00067 _max_rows = 0;
00068 _usage_hint = GeomEnums::UH_static;
00069 _flatten_flags = 0;
00070 if (text_flatten) {
00071 _flatten_flags |= FF_strong;
00072 }
00073 if (text_dynamic_merge) {
00074 _flatten_flags |= FF_dynamic_merge;
00075 }
00076
00077 if (text_small_caps) {
00078 set_small_caps(true);
00079 }
00080
00081 _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
00082 _card_color.set(1.0f, 1.0f, 1.0f, 1.0f);
00083
00084 _frame_width = 1.0f;
00085
00086 _frame_ul.set(0.0f, 0.0f);
00087 _frame_lr.set(0.0f, 0.0f);
00088 _card_ul.set(0.0f, 0.0f);
00089 _card_lr.set(0.0f, 0.0f);
00090
00091 _transform = LMatrix4::ident_mat();
00092 _coordinate_system = CS_default;
00093
00094 _ul3d.set(0.0f, 0.0f, 0.0f);
00095 _lr3d.set(0.0f, 0.0f, 0.0f);
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105 TextNode::
00106 TextNode(const string &name, const TextProperties ©) :
00107 PandaNode(name), TextProperties(copy)
00108 {
00109 _flags = 0;
00110 _max_rows = 0;
00111 _usage_hint = GeomEnums::UH_static;
00112
00113 _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
00114 _card_color.set(1.0f, 1.0f, 1.0f, 1.0f);
00115
00116 _frame_width = 1.0f;
00117
00118 _frame_ul.set(0.0f, 0.0f);
00119 _frame_lr.set(0.0f, 0.0f);
00120 _card_ul.set(0.0f, 0.0f);
00121 _card_lr.set(0.0f, 0.0f);
00122
00123 _transform = LMatrix4::ident_mat();
00124 _coordinate_system = CS_default;
00125
00126 _ul3d.set(0.0f, 0.0f, 0.0f);
00127 _lr3d.set(0.0f, 0.0f, 0.0f);
00128 }
00129
00130
00131
00132
00133
00134
00135 TextNode::
00136 TextNode(const TextNode ©) :
00137 PandaNode(copy),
00138 TextEncoder(copy),
00139 TextProperties(copy),
00140 _card_texture(copy._card_texture),
00141 _frame_color(copy._frame_color),
00142 _card_color(copy._card_color),
00143 _flags(copy._flags),
00144 _max_rows(copy._max_rows),
00145 _usage_hint(GeomEnums::UH_static),
00146 _frame_width(copy._frame_width),
00147 _card_border_size(copy._card_border_size),
00148 _card_border_uv_portion(copy._card_border_uv_portion),
00149 _frame_ul(copy._frame_ul),
00150 _frame_lr(copy._frame_lr),
00151 _card_ul(copy._card_ul),
00152 _card_lr(copy._card_lr),
00153 _transform(copy._transform),
00154 _coordinate_system(copy._coordinate_system),
00155 _ul3d(copy._ul3d),
00156 _lr3d(copy._lr3d)
00157 {
00158 invalidate_with_measure();
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 PandaNode *TextNode::
00170 make_copy() const {
00171 return new TextNode(*this);
00172 }
00173
00174
00175
00176
00177
00178
00179 TextNode::
00180 ~TextNode() {
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190 PN_stdfloat TextNode::
00191 calc_width(wchar_t character) const {
00192 TextFont *font = get_font();
00193 if (font == (TextFont *)NULL) {
00194 return 0.0f;
00195 }
00196
00197 return TextAssembler::calc_width(character, *this);
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 bool TextNode::
00219 has_exact_character(wchar_t character) const {
00220 TextFont *font = get_font();
00221 if (font == (TextFont *)NULL) {
00222 return false;
00223 }
00224
00225 return TextAssembler::has_exact_character(character, *this);
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 bool TextNode::
00242 has_character(wchar_t character) const {
00243 TextFont *font = get_font();
00244 if (font == (TextFont *)NULL) {
00245 return false;
00246 }
00247
00248 return TextAssembler::has_character(character, *this);
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 bool TextNode::
00273 is_whitespace(wchar_t character) const {
00274 TextFont *font = get_font();
00275 if (font == (TextFont *)NULL) {
00276 return false;
00277 }
00278
00279 return TextAssembler::is_whitespace(character, *this);
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 PN_stdfloat TextNode::
00291 calc_width(const wstring &line) const {
00292 PN_stdfloat width = 0.0f;
00293
00294 wstring::const_iterator si;
00295 for (si = line.begin(); si != line.end(); ++si) {
00296 width += calc_width(*si);
00297 }
00298
00299 return width;
00300 }
00301
00302
00303
00304
00305
00306
00307 void TextNode::
00308 output(ostream &out) const {
00309 PandaNode::output(out);
00310
00311 check_rebuild();
00312 int geom_count = 0;
00313 if (_internal_geom != (PandaNode *)NULL) {
00314 geom_count = count_geoms(_internal_geom);
00315 }
00316
00317 out << " (" << geom_count << " geoms)";
00318 }
00319
00320
00321
00322
00323
00324
00325 void TextNode::
00326 write(ostream &out, int indent_level) const {
00327 PandaNode::write(out, indent_level);
00328 TextProperties::write(out, indent_level + 2);
00329 indent(out, indent_level + 2)
00330 << "transform is: " << *TransformState::make_mat(_transform) << "\n";
00331 indent(out, indent_level + 2)
00332 << "in coordinate system " << _coordinate_system << "\n";
00333 indent(out, indent_level + 2)
00334 << "text is " << get_text() << "\n";
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344 PT(PandaNode) TextNode::
00345 generate() {
00346 PStatTimer timer(_text_generate_pcollector);
00347 if (text_cat.is_debug()) {
00348 text_cat.debug()
00349 << "Rebuilding " << get_type() << " " << get_name()
00350 << " with '" << get_text() << "'\n";
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 _ul3d.set(0.0f, 0.0f, 0.0f);
00364 _lr3d.set(0.0f, 0.0f, 0.0f);
00365
00366
00367 string name = get_text();
00368 size_t newline = name.find('\n');
00369 if (newline != string::npos) {
00370 name = name.substr(0, newline);
00371 }
00372 PT(PandaNode) root = new PandaNode(name);
00373
00374 if (!has_text()) {
00375 return root;
00376 }
00377
00378 TextFont *font = get_font();
00379 if (font == (TextFont *)NULL) {
00380 return root;
00381 }
00382
00383
00384
00385
00386 LMatrix4 mat =
00387 LMatrix4::convert_mat(CS_zup_right, _coordinate_system) *
00388 _transform;
00389
00390 CPT(TransformState) transform = TransformState::make_mat(mat);
00391 root->set_transform(transform);
00392
00393 wstring wtext = get_wtext();
00394
00395
00396 TextAssembler assembler(this);
00397 assembler.set_properties(*this);
00398 assembler.set_max_rows(_max_rows);
00399 assembler.set_usage_hint(_usage_hint);
00400 assembler.set_dynamic_merge((_flatten_flags & FF_dynamic_merge) != 0);
00401 bool all_set = assembler.set_wtext(wtext);
00402 if (all_set) {
00403
00404 _flags &= ~F_has_overflow;
00405 } else {
00406
00407 _flags |= F_has_overflow;
00408 }
00409
00410 PT(PandaNode) text_root = assembler.assemble_text();
00411 _text_ul = assembler.get_ul();
00412 _text_lr = assembler.get_lr();
00413 _num_rows = assembler.get_num_rows();
00414 _wordwrapped_wtext = assembler.get_wordwrapped_wtext();
00415
00416
00417 PT(PandaNode) text = new PandaNode("text");
00418 root->add_child(text, get_draw_order() + 2);
00419 text->add_child(text_root);
00420
00421
00422
00423 const LVector2 &ul = assembler.get_ul();
00424 const LVector2 &lr = assembler.get_lr();
00425 _ul3d.set(ul[0], 0.0f, ul[1]);
00426 _lr3d.set(lr[0], 0.0f, lr[1]);
00427
00428 _ul3d = _ul3d * _transform;
00429 _lr3d = _lr3d * _transform;
00430
00431
00432 _flags &= ~F_needs_measure;
00433
00434
00435
00436
00437 NodePath root_np(root);
00438 if (_flatten_flags & FF_strong) {
00439 root_np.flatten_strong();
00440 } else if (_flatten_flags & FF_medium) {
00441 root_np.flatten_medium();
00442 } else if (_flatten_flags & FF_light) {
00443 root_np.flatten_light();
00444 }
00445
00446
00447
00448 if (has_card()) {
00449 PT(PandaNode) card_root;
00450 if (has_card_border()) {
00451 card_root = make_card_with_border();
00452 } else {
00453 card_root = make_card();
00454 }
00455 card_root->set_transform(transform);
00456 card_root->set_attrib(ColorAttrib::make_flat(get_card_color()));
00457 if (get_card_color()[3] != 1.0f) {
00458 card_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00459 }
00460 if (has_card_texture()) {
00461 card_root->set_attrib(TextureAttrib::make(get_card_texture()));
00462 }
00463
00464 if (has_bin()) {
00465 card_root->set_attrib(CullBinAttrib::make(get_bin(), get_draw_order()));
00466 }
00467
00468
00469 SceneGraphReducer gr;
00470 gr.apply_attribs(card_root);
00471
00472
00473
00474 card_root->add_child(root);
00475 root = card_root;
00476
00477 if (get_card_decal()) {
00478 card_root->set_effect(DecalEffect::make());
00479 }
00480 }
00481
00482 if (has_frame()) {
00483 PT(PandaNode) frame_root = make_frame();
00484 frame_root->set_transform(transform);
00485 root->add_child(frame_root, get_draw_order() + 1);
00486 frame_root->set_attrib(ColorAttrib::make_flat(get_frame_color()));
00487 if (get_frame_color()[3] != 1.0f) {
00488 frame_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
00489 }
00490
00491 if (has_bin()) {
00492 frame_root->set_attrib(CullBinAttrib::make(get_bin(), get_draw_order() + 1));
00493 }
00494
00495 SceneGraphReducer gr;
00496 gr.apply_attribs(frame_root);
00497 }
00498
00499 return root;
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 PandaNode *TextNode::
00515 get_internal_geom() const {
00516
00517
00518 text_cat.info()
00519 << "TextNode::get_internal_geom() called.\n";
00520 check_rebuild();
00521 return _internal_geom;
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 int TextNode::
00536 get_unsafe_to_apply_attribs() const {
00537
00538
00539
00540 return
00541 SceneGraphReducer::TT_tex_matrix |
00542 SceneGraphReducer::TT_other;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 void TextNode::
00558 apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
00559 GeomTransformer &transformer) {
00560 if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
00561 const LMatrix4 &mat = attribs._transform->get_mat();
00562 _transform *= mat;
00563
00564 if ((_flags & F_needs_measure) == 0) {
00565
00566
00567
00568 _ul3d = _ul3d * mat;
00569 _lr3d = _lr3d * mat;
00570 }
00571 }
00572 if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
00573 if (attribs._color != (const RenderAttrib *)NULL) {
00574 const ColorAttrib *ca = DCAST(ColorAttrib, attribs._color);
00575 if (ca->get_color_type() == ColorAttrib::T_flat) {
00576 const LColor &c = ca->get_color();
00577 set_text_color(c);
00578 set_frame_color(c);
00579 set_card_color(c);
00580 set_shadow_color(c);
00581 }
00582 }
00583 }
00584 if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
00585 if (attribs._color_scale != (const RenderAttrib *)NULL) {
00586 const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attribs._color_scale);
00587 const LVecBase4 &s = csa->get_scale();
00588 if (s != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)) {
00589 LVecBase4 tc = get_text_color();
00590 tc[0] *= s[0];
00591 tc[1] *= s[1];
00592 tc[2] *= s[2];
00593 tc[3] *= s[3];
00594 set_text_color(tc);
00595 LVecBase4 sc = get_shadow_color();
00596 sc[0] *= s[0];
00597 sc[1] *= s[1];
00598 sc[2] *= s[2];
00599 sc[3] *= s[3];
00600 set_shadow_color(sc);
00601 LVecBase4 fc = get_frame_color();
00602 fc[0] *= s[0];
00603 fc[1] *= s[1];
00604 fc[2] *= s[2];
00605 fc[3] *= s[3];
00606 set_frame_color(fc);
00607 LVecBase4 cc = get_card_color();
00608 cc[0] *= s[0];
00609 cc[1] *= s[1];
00610 cc[2] *= s[2];
00611 cc[3] *= s[3];
00612 set_card_color(cc);
00613 }
00614 }
00615 }
00616
00617
00618
00619 if ((_flags & F_needs_rebuild) == 0 &&
00620 _internal_geom != (PandaNode *)NULL) {
00621 SceneGraphReducer gr;
00622 gr.apply_attribs(_internal_geom, attribs, attrib_types, transformer);
00623 }
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642 CPT(TransformState) TextNode::
00643 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
00644 const TransformState *transform, Thread *current_thread) const {
00645 CPT(TransformState) next_transform =
00646 PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
00647 current_thread);
00648
00649 check_rebuild();
00650
00651 if (_internal_geom != (PandaNode *)NULL) {
00652 _internal_geom->calc_tight_bounds(min_point, max_point,
00653 found_any, next_transform, current_thread);
00654 }
00655
00656 return next_transform;
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684 bool TextNode::
00685 cull_callback(CullTraverser *trav, CullTraverserData &data) {
00686 check_rebuild();
00687 if (_internal_geom != (PandaNode *)NULL) {
00688
00689 CullTraverserData next_data(data, _internal_geom);
00690 trav->traverse(next_data);
00691 }
00692
00693
00694 return true;
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 bool TextNode::
00708 is_renderable() const {
00709 return true;
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 void TextNode::
00721 compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
00722 int &internal_vertices,
00723 int pipeline_stage,
00724 Thread *current_thread) const {
00725
00726 PT(BoundingVolume) bound = new BoundingSphere;
00727
00728 GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
00729
00730
00731
00732
00733 check_measure();
00734
00735 LPoint3 vertices[8];
00736 vertices[0].set(_ul3d[0], _ul3d[1], _ul3d[2]);
00737 vertices[1].set(_ul3d[0], _ul3d[1], _lr3d[2]);
00738 vertices[2].set(_ul3d[0], _lr3d[1], _ul3d[2]);
00739 vertices[3].set(_ul3d[0], _lr3d[1], _lr3d[2]);
00740 vertices[4].set(_lr3d[0], _ul3d[1], _ul3d[2]);
00741 vertices[5].set(_lr3d[0], _ul3d[1], _lr3d[2]);
00742 vertices[6].set(_lr3d[0], _lr3d[1], _ul3d[2]);
00743 vertices[7].set(_lr3d[0], _lr3d[1], _lr3d[2]);
00744
00745 gbv->around(vertices, vertices + 8);
00746
00747 internal_bounds = bound;
00748 internal_vertices = 0;
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 void TextNode::
00760 r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
00761 GeomTransformer &transformer, Thread *current_thread) {
00762 check_rebuild();
00763
00764 PandaNode *child = _internal_geom;
00765 if (child != (PandaNode *)NULL) {
00766 CPT(RenderState) child_state = node_state->compose(child->get_state());
00767 child->r_prepare_scene(gsg, child_state, transformer, current_thread);
00768 }
00769
00770 PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread);
00771 }
00772
00773
00774
00775
00776
00777
00778
00779 void TextNode::
00780 do_rebuild() {
00781 _flags &= ~(F_needs_rebuild | F_needs_measure);
00782 _internal_geom = generate();
00783 }
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 void TextNode::
00794 do_measure() {
00795
00796 do_rebuild();
00797 }
00798
00799
00800
00801
00802
00803
00804 PT(PandaNode) TextNode::
00805 make_frame() {
00806 PT(GeomNode) frame_node = new GeomNode("frame");
00807
00808 LVector4 dimensions = get_frame_actual();
00809 PN_stdfloat left = dimensions[0];
00810 PN_stdfloat right = dimensions[1];
00811 PN_stdfloat bottom = dimensions[2];
00812 PN_stdfloat top = dimensions[3];
00813
00814 CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, _frame_width);
00815 CPT(RenderState) state = RenderState::make(thick);
00816
00817 PT(GeomVertexData) vdata = new GeomVertexData
00818 ("text", GeomVertexFormat::get_v3(), get_usage_hint());
00819 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00820
00821 vertex.add_data3(left, 0.0f, top);
00822 vertex.add_data3(left, 0.0f, bottom);
00823 vertex.add_data3(right, 0.0f, bottom);
00824 vertex.add_data3(right, 0.0f, top);
00825
00826 PT(GeomLinestrips) frame = new GeomLinestrips(get_usage_hint());
00827 frame->add_consecutive_vertices(0, 4);
00828 frame->add_vertex(0);
00829 frame->close_primitive();
00830
00831 PT(Geom) geom = new Geom(vdata);
00832 geom->add_primitive(frame);
00833 frame_node->add_geom(geom, state);
00834
00835 if (get_frame_corners()) {
00836 PT(GeomPoints) corners = new GeomPoints(get_usage_hint());
00837 corners->add_consecutive_vertices(0, 4);
00838 PT(Geom) geom2 = new Geom(vdata);
00839 geom2->add_primitive(corners);
00840 frame_node->add_geom(geom2, state);
00841 }
00842
00843 return frame_node.p();
00844 }
00845
00846
00847
00848
00849
00850
00851 PT(PandaNode) TextNode::
00852 make_card() {
00853 PT(GeomNode) card_node = new GeomNode("card");
00854
00855 LVector4 dimensions = get_card_actual();
00856 PN_stdfloat left = dimensions[0];
00857 PN_stdfloat right = dimensions[1];
00858 PN_stdfloat bottom = dimensions[2];
00859 PN_stdfloat top = dimensions[3];
00860
00861 PT(GeomVertexData) vdata = new GeomVertexData
00862 ("text", GeomVertexFormat::get_v3t2(), get_usage_hint());
00863 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00864 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00865
00866 vertex.add_data3(left, 0.0f, top);
00867 vertex.add_data3(left, 0.0f, bottom);
00868 vertex.add_data3(right, 0.0f, top);
00869 vertex.add_data3(right, 0.0f, bottom);
00870
00871 texcoord.add_data2(0.0f, 1.0f);
00872 texcoord.add_data2(0.0f, 0.0f);
00873 texcoord.add_data2(1.0f, 1.0f);
00874 texcoord.add_data2(1.0f, 0.0f);
00875
00876 PT(GeomTristrips) card = new GeomTristrips(get_usage_hint());
00877 card->add_consecutive_vertices(0, 4);
00878 card->close_primitive();
00879
00880 PT(Geom) geom = new Geom(vdata);
00881 geom->add_primitive(card);
00882
00883 card_node->add_geom(geom);
00884
00885 return card_node.p();
00886 }
00887
00888
00889
00890
00891
00892
00893
00894
00895 PT(PandaNode) TextNode::
00896 make_card_with_border() {
00897 PT(GeomNode) card_node = new GeomNode("card");
00898
00899 LVector4 dimensions = get_card_actual();
00900 PN_stdfloat left = dimensions[0];
00901 PN_stdfloat right = dimensions[1];
00902 PN_stdfloat bottom = dimensions[2];
00903 PN_stdfloat top = dimensions[3];
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914 PT(GeomVertexData) vdata = new GeomVertexData
00915 ("text", GeomVertexFormat::get_v3t2(), get_usage_hint());
00916 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00917 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
00918
00919
00920 vertex.add_data3(left, 0.02, top);
00921 vertex.add_data3(left, 0.02, top - _card_border_size);
00922 vertex.add_data3(left + _card_border_size, 0.02, top);
00923 vertex.add_data3(left + _card_border_size, 0.02,
00924 top - _card_border_size);
00925
00926 vertex.add_data3(right - _card_border_size, 0.02, top);
00927 vertex.add_data3(right - _card_border_size, 0.02,
00928 top - _card_border_size);
00929 vertex.add_data3(right, 0.02, top);
00930 vertex.add_data3(right, 0.02, top - _card_border_size);
00931
00932 vertex.add_data3(left, 0.02, bottom + _card_border_size);
00933 vertex.add_data3(left, 0.02, bottom);
00934 vertex.add_data3(left + _card_border_size, 0.02,
00935 bottom + _card_border_size);
00936 vertex.add_data3(left + _card_border_size, 0.02, bottom);
00937
00938 vertex.add_data3(right - _card_border_size, 0.02,
00939 bottom + _card_border_size);
00940 vertex.add_data3(right - _card_border_size, 0.02, bottom);
00941 vertex.add_data3(right, 0.02, bottom + _card_border_size);
00942 vertex.add_data3(right, 0.02, bottom);
00943
00944 texcoord.add_data2(0.0f, 1.0f);
00945 texcoord.add_data2(0.0f, 1.0f - _card_border_uv_portion);
00946 texcoord.add_data2(0.0f + _card_border_uv_portion, 1.0f);
00947 texcoord.add_data2(0.0f + _card_border_uv_portion,
00948 1.0f - _card_border_uv_portion);
00949 texcoord.add_data2(1.0f -_card_border_uv_portion, 1.0f);
00950 texcoord.add_data2(1.0f -_card_border_uv_portion,
00951 1.0f - _card_border_uv_portion);
00952 texcoord.add_data2(1.0f, 1.0f);
00953 texcoord.add_data2(1.0f, 1.0f - _card_border_uv_portion);
00954
00955 texcoord.add_data2(0.0f, _card_border_uv_portion);
00956 texcoord.add_data2(0.0f, 0.0f);
00957 texcoord.add_data2(_card_border_uv_portion, _card_border_uv_portion);
00958 texcoord.add_data2(_card_border_uv_portion, 0.0f);
00959
00960 texcoord.add_data2(1.0f - _card_border_uv_portion, _card_border_uv_portion);
00961 texcoord.add_data2(1.0f - _card_border_uv_portion, 0.0f);
00962 texcoord.add_data2(1.0f, _card_border_uv_portion);
00963 texcoord.add_data2(1.0f, 0.0f);
00964
00965 PT(GeomTristrips) card = new GeomTristrips(get_usage_hint());
00966
00967
00968 card->add_consecutive_vertices(0, 8);
00969 card->close_primitive();
00970
00971
00972 card->add_vertex(1);
00973 card->add_vertex(8);
00974 card->add_vertex(3);
00975 card->add_vertex(10);
00976 card->add_vertex(5);
00977 card->add_vertex(12);
00978 card->add_vertex(7);
00979 card->add_vertex(14);
00980 card->close_primitive();
00981
00982
00983 card->add_consecutive_vertices(8, 8);
00984 card->close_primitive();
00985
00986 PT(Geom) geom = new Geom(vdata);
00987 geom->add_primitive(card);
00988
00989 card_node->add_geom(geom);
00990
00991 return card_node.p();
00992 }
00993
00994
00995
00996
00997
00998
00999
01000
01001 int TextNode::
01002 count_geoms(PandaNode *node) {
01003 int num_geoms = 0;
01004
01005 if (node->is_geom_node()) {
01006 GeomNode *geom_node = DCAST(GeomNode, node);
01007 num_geoms += geom_node->get_num_geoms();
01008 }
01009
01010 Children children = node->get_children();
01011 for (int i = 0; i < children.get_num_children(); ++i) {
01012 num_geoms += count_geoms(children.get_child(i));
01013 }
01014
01015 return num_geoms;
01016 }