|
@@ -62,36 +62,9 @@ TextNode::
|
|
|
TextNode(const string &name) : PandaNode(name) {
|
|
TextNode(const string &name) : PandaNode(name) {
|
|
|
set_cull_callback();
|
|
set_cull_callback();
|
|
|
|
|
|
|
|
- _flags = 0;
|
|
|
|
|
- _max_rows = 0;
|
|
|
|
|
- _usage_hint = GeomEnums::UH_static;
|
|
|
|
|
- _flatten_flags = 0;
|
|
|
|
|
- if (text_flatten) {
|
|
|
|
|
- _flatten_flags |= FF_strong;
|
|
|
|
|
- }
|
|
|
|
|
- if (text_dynamic_merge) {
|
|
|
|
|
- _flatten_flags |= FF_dynamic_merge;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
if (text_small_caps) {
|
|
if (text_small_caps) {
|
|
|
TextProperties::set_small_caps(true);
|
|
TextProperties::set_small_caps(true);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
|
- _card_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
|
-
|
|
|
|
|
- _frame_width = 1.0f;
|
|
|
|
|
-
|
|
|
|
|
- _frame_ul.set(0.0f, 0.0f);
|
|
|
|
|
- _frame_lr.set(0.0f, 0.0f);
|
|
|
|
|
- _card_ul.set(0.0f, 0.0f);
|
|
|
|
|
- _card_lr.set(0.0f, 0.0f);
|
|
|
|
|
-
|
|
|
|
|
- _transform = LMatrix4::ident_mat();
|
|
|
|
|
- _coordinate_system = CS_default;
|
|
|
|
|
-
|
|
|
|
|
- _ul3d.set(0.0f, 0.0f, 0.0f);
|
|
|
|
|
- _lr3d.set(0.0f, 0.0f, 0.0f);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -102,25 +75,6 @@ TextNode::
|
|
|
TextNode(const string &name, const TextProperties ©) :
|
|
TextNode(const string &name, const TextProperties ©) :
|
|
|
PandaNode(name), TextProperties(copy)
|
|
PandaNode(name), TextProperties(copy)
|
|
|
{
|
|
{
|
|
|
- _flags = 0;
|
|
|
|
|
- _max_rows = 0;
|
|
|
|
|
- _usage_hint = GeomEnums::UH_static;
|
|
|
|
|
-
|
|
|
|
|
- _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
|
- _card_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
|
-
|
|
|
|
|
- _frame_width = 1.0f;
|
|
|
|
|
-
|
|
|
|
|
- _frame_ul.set(0.0f, 0.0f);
|
|
|
|
|
- _frame_lr.set(0.0f, 0.0f);
|
|
|
|
|
- _card_ul.set(0.0f, 0.0f);
|
|
|
|
|
- _card_lr.set(0.0f, 0.0f);
|
|
|
|
|
-
|
|
|
|
|
- _transform = LMatrix4::ident_mat();
|
|
|
|
|
- _coordinate_system = CS_default;
|
|
|
|
|
-
|
|
|
|
|
- _ul3d.set(0.0f, 0.0f, 0.0f);
|
|
|
|
|
- _lr3d.set(0.0f, 0.0f, 0.0f);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -131,25 +85,9 @@ TextNode(const TextNode ©) :
|
|
|
PandaNode(copy),
|
|
PandaNode(copy),
|
|
|
TextEncoder(copy),
|
|
TextEncoder(copy),
|
|
|
TextProperties(copy),
|
|
TextProperties(copy),
|
|
|
- _card_texture(copy._card_texture),
|
|
|
|
|
- _frame_color(copy._frame_color),
|
|
|
|
|
- _card_color(copy._card_color),
|
|
|
|
|
- _flags(copy._flags),
|
|
|
|
|
- _max_rows(copy._max_rows),
|
|
|
|
|
- _usage_hint(GeomEnums::UH_static),
|
|
|
|
|
- _frame_width(copy._frame_width),
|
|
|
|
|
- _card_border_size(copy._card_border_size),
|
|
|
|
|
- _card_border_uv_portion(copy._card_border_uv_portion),
|
|
|
|
|
- _frame_ul(copy._frame_ul),
|
|
|
|
|
- _frame_lr(copy._frame_lr),
|
|
|
|
|
- _card_ul(copy._card_ul),
|
|
|
|
|
- _card_lr(copy._card_lr),
|
|
|
|
|
- _transform(copy._transform),
|
|
|
|
|
- _coordinate_system(copy._coordinate_system),
|
|
|
|
|
- _ul3d(copy._ul3d),
|
|
|
|
|
- _lr3d(copy._lr3d)
|
|
|
|
|
|
|
+ _cycler(copy._cycler)
|
|
|
{
|
|
{
|
|
|
- invalidate_with_measure();
|
|
|
|
|
|
|
+ mark_internal_bounds_stale();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -169,6 +107,82 @@ TextNode::
|
|
|
~TextNode() {
|
|
~TextNode() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Returns the actual dimensions of the frame around the text. If the frame
|
|
|
|
|
+ * was set via set_frame_as_margin(), the result returned by this function
|
|
|
|
|
+ * reflects the size of the current text; if the frame was set via
|
|
|
|
|
+ * set_frame_actual(), this returns the values actually set.
|
|
|
|
|
+ *
|
|
|
|
|
+ * If the text has no frame at all, this returns the dimensions of the text
|
|
|
|
|
+ * itself, as if the frame were set with a margin of 0, 0, 0, 0.
|
|
|
|
|
+ */
|
|
|
|
|
+LVecBase4 TextNode::
|
|
|
|
|
+get_frame_actual() const {
|
|
|
|
|
+ CDLockedReader cdata(_cycler);
|
|
|
|
|
+ if ((cdata->_flags & (F_has_frame | F_frame_as_margin)) == F_has_frame) {
|
|
|
|
|
+ return LVecBase4(cdata->_frame_ul[0],
|
|
|
|
|
+ cdata->_frame_lr[0],
|
|
|
|
|
+ cdata->_frame_lr[1],
|
|
|
|
|
+ cdata->_frame_ul[1]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (do_needs_measure(cdata)) {
|
|
|
|
|
+ CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false);
|
|
|
|
|
+ ((TextNode *)this)->do_measure(cdataw);
|
|
|
|
|
+
|
|
|
|
|
+ LVecBase4 frame(cdataw->_text_ul[0], cdataw->_text_lr[0], cdataw->_text_lr[1], cdataw->_text_ul[1]);
|
|
|
|
|
+ if (cdataw->_flags & F_has_frame) {
|
|
|
|
|
+ frame += LVecBase4(-cdataw->_frame_ul[0], cdataw->_frame_lr[0], -cdataw->_frame_lr[1], cdataw->_frame_ul[1]);
|
|
|
|
|
+ }
|
|
|
|
|
+ return frame;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ LVecBase4 frame(cdata->_text_ul[0], cdata->_text_lr[0], cdata->_text_lr[1], cdata->_text_ul[1]);
|
|
|
|
|
+ if (cdata->_flags & F_has_frame) {
|
|
|
|
|
+ frame += LVecBase4(-cdata->_frame_ul[0], cdata->_frame_lr[0], -cdata->_frame_lr[1], cdata->_frame_ul[1]);
|
|
|
|
|
+ }
|
|
|
|
|
+ return frame;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Returns the actual dimensions of the card around the text. If the card was
|
|
|
|
|
+ * set via set_card_as_margin(), the result returned by this function reflects
|
|
|
|
|
+ * the size of the current text; if the card was set via set_card_actual(),
|
|
|
|
|
+ * this returns the values actually set.
|
|
|
|
|
+ *
|
|
|
|
|
+ * If the text has no card at all, this returns the dimensions of the text
|
|
|
|
|
+ * itself, as if the card were set with a margin of 0, 0, 0, 0.
|
|
|
|
|
+ */
|
|
|
|
|
+LVecBase4 TextNode::
|
|
|
|
|
+get_card_actual() const {
|
|
|
|
|
+ CDLockedReader cdata(_cycler);
|
|
|
|
|
+ if ((cdata->_flags & (F_has_card | F_card_as_margin)) == F_has_card) {
|
|
|
|
|
+ return LVecBase4(cdata->_card_ul[0],
|
|
|
|
|
+ cdata->_card_lr[0],
|
|
|
|
|
+ cdata->_card_lr[1],
|
|
|
|
|
+ cdata->_card_ul[1]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (do_needs_measure(cdata)) {
|
|
|
|
|
+ CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false);
|
|
|
|
|
+ ((TextNode *)this)->do_measure(cdataw);
|
|
|
|
|
+
|
|
|
|
|
+ LVecBase4 card(cdataw->_text_ul[0], cdataw->_text_lr[0], cdataw->_text_lr[1], cdataw->_text_ul[1]);
|
|
|
|
|
+ if (cdataw->_flags & F_has_card) {
|
|
|
|
|
+ card += LVecBase4(-cdataw->_card_ul[0], cdataw->_card_lr[0], -cdataw->_card_lr[1], cdataw->_card_ul[1]);
|
|
|
|
|
+ }
|
|
|
|
|
+ return card;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ LVecBase4 card(cdata->_text_ul[0], cdata->_text_lr[0], cdata->_text_lr[1], cdata->_text_ul[1]);
|
|
|
|
|
+ if (cdata->_flags & F_has_card) {
|
|
|
|
|
+ card += LVecBase4(-cdata->_card_ul[0], cdata->_card_lr[0], -cdata->_card_lr[1], cdata->_card_ul[1]);
|
|
|
|
|
+ }
|
|
|
|
|
+ return card;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Returns the width of a single character of the font, or 0.0 if the
|
|
* Returns the width of a single character of the font, or 0.0 if the
|
|
|
* character is not known. This may be a wide character (greater than 255).
|
|
* character is not known. This may be a wide character (greater than 255).
|
|
@@ -292,14 +306,15 @@ output(std::ostream &out) const {
|
|
|
void TextNode::
|
|
void TextNode::
|
|
|
write(std::ostream &out, int indent_level) const {
|
|
write(std::ostream &out, int indent_level) const {
|
|
|
PandaNode::write(out, indent_level);
|
|
PandaNode::write(out, indent_level);
|
|
|
- MutexHolder holder(_lock);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ CDReader cdata(_cycler);
|
|
|
TextProperties::write(out, indent_level + 2);
|
|
TextProperties::write(out, indent_level + 2);
|
|
|
indent(out, indent_level + 2)
|
|
indent(out, indent_level + 2)
|
|
|
- << "transform is: " << *TransformState::make_mat(_transform) << "\n";
|
|
|
|
|
|
|
+ << "transform is: " << *TransformState::make_mat(cdata->_transform) << "\n";
|
|
|
indent(out, indent_level + 2)
|
|
indent(out, indent_level + 2)
|
|
|
- << "in coordinate system " << _coordinate_system << "\n";
|
|
|
|
|
|
|
+ << "in coordinate system " << cdata->_coordinate_system << "\n";
|
|
|
indent(out, indent_level + 2)
|
|
indent(out, indent_level + 2)
|
|
|
- << "text is " << get_text() << "\n";
|
|
|
|
|
|
|
+ << "text is " << cdata->_text << "\n";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -324,8 +339,12 @@ get_internal_geom() const {
|
|
|
*/
|
|
*/
|
|
|
void TextNode::
|
|
void TextNode::
|
|
|
text_changed() {
|
|
text_changed() {
|
|
|
- MutexHolder holder(_lock);
|
|
|
|
|
- invalidate_with_measure();
|
|
|
|
|
|
|
+ // Copy the text to this class, since TextEncoder doesn't store it in a
|
|
|
|
|
+ // pipeline-cycled manner.
|
|
|
|
|
+ CDWriter cdata(_cycler);
|
|
|
|
|
+ cdata->_text = TextEncoder::get_text();
|
|
|
|
|
+ cdata->_wtext = TextEncoder::get_wtext();
|
|
|
|
|
+ invalidate_with_measure(cdata);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -356,60 +375,65 @@ get_unsafe_to_apply_attribs() const {
|
|
|
void TextNode::
|
|
void TextNode::
|
|
|
apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
|
apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
|
|
GeomTransformer &transformer) {
|
|
GeomTransformer &transformer) {
|
|
|
- MutexHolder holder(_lock);
|
|
|
|
|
- if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
|
|
|
|
- const LMatrix4 &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 != nullptr) {
|
|
|
|
|
- const ColorAttrib *ca = DCAST(ColorAttrib, attribs._color);
|
|
|
|
|
- if (ca->get_color_type() == ColorAttrib::T_flat) {
|
|
|
|
|
- const LColor &c = ca->get_color();
|
|
|
|
|
- TextProperties::set_text_color(c);
|
|
|
|
|
- TextProperties::set_shadow_color(c);
|
|
|
|
|
- _frame_color = c;
|
|
|
|
|
- _card_color = c;
|
|
|
|
|
- invalidate_no_measure();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
|
|
|
|
|
- if (attribs._color_scale != nullptr) {
|
|
|
|
|
- const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attribs._color_scale);
|
|
|
|
|
- const LVecBase4 &s = csa->get_scale();
|
|
|
|
|
- if (s != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)) {
|
|
|
|
|
- LVecBase4 tc = get_text_color();
|
|
|
|
|
- tc.componentwise_mult(s);
|
|
|
|
|
- TextProperties::set_text_color(tc);
|
|
|
|
|
|
|
|
|
|
- LVecBase4 sc = get_shadow_color();
|
|
|
|
|
- sc.componentwise_mult(s);
|
|
|
|
|
- TextProperties::set_shadow_color(sc);
|
|
|
|
|
|
|
+ Thread *current_thread = Thread::get_current_thread();
|
|
|
|
|
+ OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
|
|
|
|
|
+ CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
|
|
|
|
|
|
|
|
- _frame_color.componentwise_mult(s);
|
|
|
|
|
- _card_color.componentwise_mult(s);
|
|
|
|
|
|
|
+ if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
|
|
|
|
+ const LMatrix4 &mat = attribs._transform->get_mat();
|
|
|
|
|
+ cdata->_transform *= mat;
|
|
|
|
|
|
|
|
- invalidate_no_measure();
|
|
|
|
|
|
|
+ if ((cdata->_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.
|
|
|
|
|
+ cdata->_ul3d = cdata->_ul3d * mat;
|
|
|
|
|
+ cdata->_lr3d = cdata->_lr3d * mat;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if ((attrib_types & SceneGraphReducer::TT_color) != 0) {
|
|
|
|
|
+ if (attribs._color != nullptr) {
|
|
|
|
|
+ const ColorAttrib *ca = DCAST(ColorAttrib, attribs._color);
|
|
|
|
|
+ if (ca->get_color_type() == ColorAttrib::T_flat) {
|
|
|
|
|
+ const LColor &c = ca->get_color();
|
|
|
|
|
+ TextProperties::set_text_color(c);
|
|
|
|
|
+ TextProperties::set_shadow_color(c);
|
|
|
|
|
+ cdata->_frame_color = c;
|
|
|
|
|
+ cdata->_card_color = c;
|
|
|
|
|
+ invalidate_no_measure(cdata);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if ((attrib_types & SceneGraphReducer::TT_color_scale) != 0) {
|
|
|
|
|
+ if (attribs._color_scale != nullptr) {
|
|
|
|
|
+ const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attribs._color_scale);
|
|
|
|
|
+ const LVecBase4 &s = csa->get_scale();
|
|
|
|
|
+ if (s != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f)) {
|
|
|
|
|
+ LVecBase4 tc = get_text_color();
|
|
|
|
|
+ tc.componentwise_mult(s);
|
|
|
|
|
+ TextProperties::set_text_color(tc);
|
|
|
|
|
+
|
|
|
|
|
+ LVecBase4 sc = get_shadow_color();
|
|
|
|
|
+ sc.componentwise_mult(s);
|
|
|
|
|
+ TextProperties::set_shadow_color(sc);
|
|
|
|
|
+
|
|
|
|
|
+ cdata->_frame_color.componentwise_mult(s);
|
|
|
|
|
+ cdata->_card_color.componentwise_mult(s);
|
|
|
|
|
+
|
|
|
|
|
+ invalidate_no_measure(cdata);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- // Now propagate the attributes down to our already-generated geometry, if
|
|
|
|
|
- // we have any.
|
|
|
|
|
- if ((_flags & F_needs_rebuild) == 0 &&
|
|
|
|
|
- _internal_geom != nullptr) {
|
|
|
|
|
- SceneGraphReducer gr;
|
|
|
|
|
- gr.apply_attribs(_internal_geom, attribs, attrib_types, transformer);
|
|
|
|
|
|
|
+ // Now propagate the attributes down to our already-generated geometry, if
|
|
|
|
|
+ // we have any.
|
|
|
|
|
+ if ((cdata->_flags & F_needs_rebuild) == 0 && cdata->_internal_geom != nullptr) {
|
|
|
|
|
+ SceneGraphReducer gr;
|
|
|
|
|
+ gr.apply_attribs(cdata->_internal_geom, attribs, attrib_types, transformer);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+ CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -501,17 +525,27 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
|
|
|
// actually generating the text, if we have at least measured it.
|
|
// actually generating the text, if we have at least measured it.
|
|
|
LPoint3 vertices[8];
|
|
LPoint3 vertices[8];
|
|
|
{
|
|
{
|
|
|
- MutexHolder holder(_lock);
|
|
|
|
|
- check_measure();
|
|
|
|
|
|
|
+ LPoint3 ul3d, lr3d;
|
|
|
|
|
+ CDLockedReader cdata(_cycler);
|
|
|
|
|
+ if (do_needs_measure(cdata)) {
|
|
|
|
|
+ CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false);
|
|
|
|
|
+ ((TextNode *)this)->do_measure(cdataw);
|
|
|
|
|
+
|
|
|
|
|
+ ul3d = cdataw->_ul3d;
|
|
|
|
|
+ lr3d = cdataw->_lr3d;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ul3d = cdata->_ul3d;
|
|
|
|
|
+ lr3d = cdata->_lr3d;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- 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]);
|
|
|
|
|
|
|
+ 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);
|
|
gbv->around(vertices, vertices + 8);
|
|
@@ -542,21 +576,19 @@ r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
|
|
|
* text instead.
|
|
* text instead.
|
|
|
*/
|
|
*/
|
|
|
void TextNode::
|
|
void TextNode::
|
|
|
-do_rebuild() {
|
|
|
|
|
- nassertv(_lock.debug_is_locked());
|
|
|
|
|
- _flags &= ~(F_needs_rebuild | F_needs_measure);
|
|
|
|
|
- _internal_geom = do_generate();
|
|
|
|
|
|
|
+do_rebuild(CData *cdata) {
|
|
|
|
|
+ cdata->_flags &= ~(F_needs_rebuild | F_needs_measure);
|
|
|
|
|
+ cdata->_internal_geom = do_generate(cdata);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
/**
|
|
/**
|
|
|
* Can be called in lieu of do_rebuild() to measure the text and set up the
|
|
* Can be called in lieu of do_rebuild() to measure the text and set up the
|
|
|
* bounding boxes properly without actually assembling it.
|
|
* bounding boxes properly without actually assembling it.
|
|
|
*/
|
|
*/
|
|
|
void TextNode::
|
|
void TextNode::
|
|
|
-do_measure() {
|
|
|
|
|
|
|
+do_measure(CData *cdata) {
|
|
|
// We no longer make this a special case.
|
|
// We no longer make this a special case.
|
|
|
- do_rebuild();
|
|
|
|
|
|
|
+ do_rebuild(cdata);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -565,14 +597,12 @@ do_measure() {
|
|
|
* represent it.
|
|
* represent it.
|
|
|
*/
|
|
*/
|
|
|
PT(PandaNode) TextNode::
|
|
PT(PandaNode) TextNode::
|
|
|
-do_generate() {
|
|
|
|
|
- nassertr(_lock.debug_is_locked(), nullptr);
|
|
|
|
|
-
|
|
|
|
|
|
|
+do_generate(CData *cdata) {
|
|
|
PStatTimer timer(_text_generate_pcollector);
|
|
PStatTimer timer(_text_generate_pcollector);
|
|
|
if (text_cat.is_debug()) {
|
|
if (text_cat.is_debug()) {
|
|
|
text_cat.debug()
|
|
text_cat.debug()
|
|
|
<< "Rebuilding " << get_type() << " " << get_name()
|
|
<< "Rebuilding " << get_type() << " " << get_name()
|
|
|
- << " with '" << get_text() << "'\n";
|
|
|
|
|
|
|
+ << " with '" << cdata->_text << "'\n";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// The strategy here will be to assemble together a bunch of letters,
|
|
// The strategy here will be to assemble together a bunch of letters,
|
|
@@ -584,18 +614,18 @@ do_generate() {
|
|
|
// row, that moves the row into the right place horizontally and vertically,
|
|
// row, that moves the row into the right place horizontally and vertically,
|
|
|
// and for each row, there is another node for each character.
|
|
// and for each row, there is another node for each character.
|
|
|
|
|
|
|
|
- _ul3d.set(0.0f, 0.0f, 0.0f);
|
|
|
|
|
- _lr3d.set(0.0f, 0.0f, 0.0f);
|
|
|
|
|
|
|
+ cdata->_ul3d.set(0.0f, 0.0f, 0.0f);
|
|
|
|
|
+ cdata->_lr3d.set(0.0f, 0.0f, 0.0f);
|
|
|
|
|
|
|
|
// Now build a new sub-tree for all the text components.
|
|
// Now build a new sub-tree for all the text components.
|
|
|
- string name = get_text();
|
|
|
|
|
|
|
+ string name = cdata->_text;
|
|
|
size_t newline = name.find('\n');
|
|
size_t newline = name.find('\n');
|
|
|
if (newline != string::npos) {
|
|
if (newline != string::npos) {
|
|
|
name = name.substr(0, newline);
|
|
name = name.substr(0, newline);
|
|
|
}
|
|
}
|
|
|
PT(PandaNode) root = new PandaNode(name);
|
|
PT(PandaNode) root = new PandaNode(name);
|
|
|
|
|
|
|
|
- if (!has_text()) {
|
|
|
|
|
|
|
+ if (cdata->_wtext.empty()) {
|
|
|
return root;
|
|
return root;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -607,34 +637,32 @@ do_generate() {
|
|
|
// Compute the overall text transform matrix. We build the text in a Z-up
|
|
// Compute the overall text transform matrix. We build the text in a Z-up
|
|
|
// coordinate system and then convert it to whatever the user asked for.
|
|
// coordinate system and then convert it to whatever the user asked for.
|
|
|
LMatrix4 mat =
|
|
LMatrix4 mat =
|
|
|
- LMatrix4::convert_mat(CS_zup_right, _coordinate_system) *
|
|
|
|
|
- _transform;
|
|
|
|
|
|
|
+ LMatrix4::convert_mat(CS_zup_right, cdata->_coordinate_system) *
|
|
|
|
|
+ cdata->_transform;
|
|
|
|
|
|
|
|
CPT(TransformState) transform = TransformState::make_mat(mat);
|
|
CPT(TransformState) transform = TransformState::make_mat(mat);
|
|
|
root->set_transform(transform);
|
|
root->set_transform(transform);
|
|
|
|
|
|
|
|
- std::wstring wtext = get_wtext();
|
|
|
|
|
-
|
|
|
|
|
// Assemble the text.
|
|
// Assemble the text.
|
|
|
TextAssembler assembler(this);
|
|
TextAssembler assembler(this);
|
|
|
assembler.set_properties(*this);
|
|
assembler.set_properties(*this);
|
|
|
- assembler.set_max_rows(_max_rows);
|
|
|
|
|
- assembler.set_usage_hint(_usage_hint);
|
|
|
|
|
- assembler.set_dynamic_merge((_flatten_flags & FF_dynamic_merge) != 0);
|
|
|
|
|
- bool all_set = assembler.set_wtext(wtext);
|
|
|
|
|
|
|
+ assembler.set_max_rows(cdata->_max_rows);
|
|
|
|
|
+ assembler.set_usage_hint(cdata->_usage_hint);
|
|
|
|
|
+ assembler.set_dynamic_merge((cdata->_flatten_flags & FF_dynamic_merge) != 0);
|
|
|
|
|
+ bool all_set = assembler.set_wtext(cdata->_wtext);
|
|
|
if (all_set) {
|
|
if (all_set) {
|
|
|
// No overflow.
|
|
// No overflow.
|
|
|
- _flags &= ~F_has_overflow;
|
|
|
|
|
|
|
+ cdata->_flags &= ~F_has_overflow;
|
|
|
} else {
|
|
} else {
|
|
|
// Overflow.
|
|
// Overflow.
|
|
|
- _flags |= F_has_overflow;
|
|
|
|
|
|
|
+ cdata->_flags |= F_has_overflow;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
PT(PandaNode) text_root = assembler.assemble_text();
|
|
PT(PandaNode) text_root = assembler.assemble_text();
|
|
|
- _text_ul = assembler.get_ul();
|
|
|
|
|
- _text_lr = assembler.get_lr();
|
|
|
|
|
- _num_rows = assembler.get_num_rows();
|
|
|
|
|
- _wordwrapped_wtext = assembler.get_wordwrapped_wtext();
|
|
|
|
|
|
|
+ cdata->_text_ul = assembler.get_ul();
|
|
|
|
|
+ cdata->_text_lr = assembler.get_lr();
|
|
|
|
|
+ cdata->_num_rows = assembler.get_num_rows();
|
|
|
|
|
+ cdata->_wordwrapped_wtext = assembler.get_wordwrapped_wtext();
|
|
|
|
|
|
|
|
// Parent the text in.
|
|
// Parent the text in.
|
|
|
PT(PandaNode) text = new PandaNode("text");
|
|
PT(PandaNode) text = new PandaNode("text");
|
|
@@ -645,43 +673,45 @@ do_generate() {
|
|
|
// the user.
|
|
// the user.
|
|
|
const LVector2 &ul = assembler.get_ul();
|
|
const LVector2 &ul = assembler.get_ul();
|
|
|
const LVector2 &lr = assembler.get_lr();
|
|
const LVector2 &lr = assembler.get_lr();
|
|
|
- _ul3d.set(ul[0], 0.0f, ul[1]);
|
|
|
|
|
- _lr3d.set(lr[0], 0.0f, lr[1]);
|
|
|
|
|
|
|
+ cdata->_ul3d.set(ul[0], 0.0f, ul[1]);
|
|
|
|
|
+ cdata->_lr3d.set(lr[0], 0.0f, lr[1]);
|
|
|
|
|
|
|
|
- _ul3d = _ul3d * _transform;
|
|
|
|
|
- _lr3d = _lr3d * _transform;
|
|
|
|
|
|
|
+ cdata->_ul3d = cdata->_ul3d * cdata->_transform;
|
|
|
|
|
+ cdata->_lr3d = cdata->_lr3d * cdata->_transform;
|
|
|
|
|
|
|
|
// Incidentally, that means we don't need to measure the text now.
|
|
// Incidentally, that means we don't need to measure the text now.
|
|
|
- _flags &= ~F_needs_measure;
|
|
|
|
|
|
|
+ cdata->_flags &= ~F_needs_measure;
|
|
|
|
|
|
|
|
// Now flatten our hierarchy to get rid of the transforms we put in,
|
|
// Now flatten our hierarchy to get rid of the transforms we put in,
|
|
|
// applying them to the vertices.
|
|
// applying them to the vertices.
|
|
|
|
|
|
|
|
NodePath root_np(root);
|
|
NodePath root_np(root);
|
|
|
- if (_flatten_flags & FF_strong) {
|
|
|
|
|
|
|
+ if (cdata->_flatten_flags & FF_strong) {
|
|
|
root_np.flatten_strong();
|
|
root_np.flatten_strong();
|
|
|
- } else if (_flatten_flags & FF_medium) {
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (cdata->_flatten_flags & FF_medium) {
|
|
|
root_np.flatten_medium();
|
|
root_np.flatten_medium();
|
|
|
- } else if (_flatten_flags & FF_light) {
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (cdata->_flatten_flags & FF_light) {
|
|
|
root_np.flatten_light();
|
|
root_np.flatten_light();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Now deal with the decorations.
|
|
// Now deal with the decorations.
|
|
|
|
|
|
|
|
- if (_flags & F_has_card) {
|
|
|
|
|
|
|
+ if (cdata->_flags & F_has_card) {
|
|
|
PT(PandaNode) card_root;
|
|
PT(PandaNode) card_root;
|
|
|
- if (_flags & F_has_card_border) {
|
|
|
|
|
- card_root = make_card_with_border();
|
|
|
|
|
|
|
+ if (cdata->_flags & F_has_card_border) {
|
|
|
|
|
+ card_root = do_make_card_with_border(cdata);
|
|
|
} else {
|
|
} else {
|
|
|
- card_root = make_card();
|
|
|
|
|
|
|
+ card_root = do_make_card(cdata);
|
|
|
}
|
|
}
|
|
|
card_root->set_transform(transform);
|
|
card_root->set_transform(transform);
|
|
|
- card_root->set_attrib(ColorAttrib::make_flat(_card_color));
|
|
|
|
|
- if (_card_color[3] != 1.0f) {
|
|
|
|
|
|
|
+ card_root->set_attrib(ColorAttrib::make_flat(cdata->_card_color));
|
|
|
|
|
+ if (cdata->_card_color[3] != 1.0f) {
|
|
|
card_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
|
card_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
|
|
}
|
|
}
|
|
|
- if (_flags & F_has_card_texture) {
|
|
|
|
|
- card_root->set_attrib(TextureAttrib::make(_card_texture));
|
|
|
|
|
|
|
+ if (cdata->_flags & F_has_card_texture) {
|
|
|
|
|
+ card_root->set_attrib(TextureAttrib::make(cdata->_card_texture));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (has_bin()) {
|
|
if (has_bin()) {
|
|
@@ -697,17 +727,17 @@ do_generate() {
|
|
|
card_root->add_child(root);
|
|
card_root->add_child(root);
|
|
|
root = card_root;
|
|
root = card_root;
|
|
|
|
|
|
|
|
- if (_flags & F_card_decal) {
|
|
|
|
|
|
|
+ if (cdata->_flags & F_card_decal) {
|
|
|
card_root->set_effect(DecalEffect::make());
|
|
card_root->set_effect(DecalEffect::make());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (_flags & F_has_frame) {
|
|
|
|
|
- PT(PandaNode) frame_root = make_frame();
|
|
|
|
|
|
|
+ if (cdata->_flags & F_has_frame) {
|
|
|
|
|
+ PT(PandaNode) frame_root = do_make_frame(cdata);
|
|
|
frame_root->set_transform(transform);
|
|
frame_root->set_transform(transform);
|
|
|
root->add_child(frame_root, get_draw_order() + 1);
|
|
root->add_child(frame_root, get_draw_order() + 1);
|
|
|
- frame_root->set_attrib(ColorAttrib::make_flat(_frame_color));
|
|
|
|
|
- if (_frame_color[3] != 1.0f) {
|
|
|
|
|
|
|
+ frame_root->set_attrib(ColorAttrib::make_flat(cdata->_frame_color));
|
|
|
|
|
+ if (cdata->_frame_color[3] != 1.0f) {
|
|
|
frame_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
|
frame_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -728,38 +758,46 @@ do_generate() {
|
|
|
*/
|
|
*/
|
|
|
PT(PandaNode) TextNode::
|
|
PT(PandaNode) TextNode::
|
|
|
do_get_internal_geom() const {
|
|
do_get_internal_geom() const {
|
|
|
- MutexHolder holder(_lock);
|
|
|
|
|
- check_rebuild();
|
|
|
|
|
- return _internal_geom;
|
|
|
|
|
|
|
+ CDLockedReader cdata(_cycler);
|
|
|
|
|
+ if ((cdata->_flags & F_needs_rebuild) != 0) {
|
|
|
|
|
+ // Propagate the generated text upstream if the upstream stages have no
|
|
|
|
|
+ // changes to the text.
|
|
|
|
|
+ CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false);
|
|
|
|
|
+ ((TextNode *)this)->do_rebuild(cdataw);
|
|
|
|
|
+
|
|
|
|
|
+ return cdataw->_internal_geom;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ return cdata->_internal_geom;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Creates a frame around the text.
|
|
* Creates a frame around the text.
|
|
|
*/
|
|
*/
|
|
|
PT(PandaNode) TextNode::
|
|
PT(PandaNode) TextNode::
|
|
|
-make_frame() {
|
|
|
|
|
- nassertr(_lock.debug_is_locked(), nullptr);
|
|
|
|
|
- nassertr((_flags & F_needs_measure) == 0, nullptr);
|
|
|
|
|
|
|
+do_make_frame(const CData *cdata) {
|
|
|
|
|
+ nassertr((cdata->_flags & F_needs_measure) == 0, nullptr);
|
|
|
|
|
|
|
|
PT(GeomNode) frame_node = new GeomNode("frame");
|
|
PT(GeomNode) frame_node = new GeomNode("frame");
|
|
|
|
|
|
|
|
- PN_stdfloat left = _frame_ul[0];
|
|
|
|
|
- PN_stdfloat right = _frame_lr[0];
|
|
|
|
|
- PN_stdfloat bottom = _frame_lr[1];
|
|
|
|
|
- PN_stdfloat top = _frame_ul[1];
|
|
|
|
|
|
|
+ PN_stdfloat left = cdata->_frame_ul[0];
|
|
|
|
|
+ PN_stdfloat right = cdata->_frame_lr[0];
|
|
|
|
|
+ PN_stdfloat bottom = cdata->_frame_lr[1];
|
|
|
|
|
+ PN_stdfloat top = cdata->_frame_ul[1];
|
|
|
|
|
|
|
|
- if (_flags & F_frame_as_margin) {
|
|
|
|
|
- left = _text_ul[0] - left;
|
|
|
|
|
- right = _text_lr[0] + right;
|
|
|
|
|
- bottom = _text_lr[1] - bottom;
|
|
|
|
|
- top = _text_ul[1] + top;
|
|
|
|
|
|
|
+ if (cdata->_flags & F_frame_as_margin) {
|
|
|
|
|
+ left = cdata->_text_ul[0] - left;
|
|
|
|
|
+ right = cdata->_text_lr[0] + right;
|
|
|
|
|
+ bottom = cdata->_text_lr[1] - bottom;
|
|
|
|
|
+ top = cdata->_text_ul[1] + top;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, _frame_width);
|
|
|
|
|
|
|
+ CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, cdata->_frame_width);
|
|
|
CPT(RenderState) state = RenderState::make(thick);
|
|
CPT(RenderState) state = RenderState::make(thick);
|
|
|
|
|
|
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
|
- ("text", GeomVertexFormat::get_v3(), _usage_hint);
|
|
|
|
|
|
|
+ ("text", GeomVertexFormat::get_v3(), cdata->_usage_hint);
|
|
|
vdata->unclean_set_num_rows(4);
|
|
vdata->unclean_set_num_rows(4);
|
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
|
|
|
|
|
@@ -768,7 +806,7 @@ make_frame() {
|
|
|
vertex.set_data3(right, 0.0f, bottom);
|
|
vertex.set_data3(right, 0.0f, bottom);
|
|
|
vertex.set_data3(right, 0.0f, top);
|
|
vertex.set_data3(right, 0.0f, top);
|
|
|
|
|
|
|
|
- PT(GeomLinestrips) frame = new GeomLinestrips(_usage_hint);
|
|
|
|
|
|
|
+ PT(GeomLinestrips) frame = new GeomLinestrips(cdata->_usage_hint);
|
|
|
frame->add_consecutive_vertices(0, 4);
|
|
frame->add_consecutive_vertices(0, 4);
|
|
|
frame->add_vertex(0);
|
|
frame->add_vertex(0);
|
|
|
frame->close_primitive();
|
|
frame->close_primitive();
|
|
@@ -777,8 +815,8 @@ make_frame() {
|
|
|
geom->add_primitive(frame);
|
|
geom->add_primitive(frame);
|
|
|
frame_node->add_geom(geom, state);
|
|
frame_node->add_geom(geom, state);
|
|
|
|
|
|
|
|
- if (_flags & F_frame_corners) {
|
|
|
|
|
- PT(GeomPoints) corners = new GeomPoints(_usage_hint);
|
|
|
|
|
|
|
+ if (cdata->_flags & F_frame_corners) {
|
|
|
|
|
+ PT(GeomPoints) corners = new GeomPoints(cdata->_usage_hint);
|
|
|
corners->add_consecutive_vertices(0, 4);
|
|
corners->add_consecutive_vertices(0, 4);
|
|
|
PT(Geom) geom2 = new Geom(vdata);
|
|
PT(Geom) geom2 = new Geom(vdata);
|
|
|
geom2->add_primitive(corners);
|
|
geom2->add_primitive(corners);
|
|
@@ -792,26 +830,25 @@ make_frame() {
|
|
|
* Creates a card behind the text.
|
|
* Creates a card behind the text.
|
|
|
*/
|
|
*/
|
|
|
PT(PandaNode) TextNode::
|
|
PT(PandaNode) TextNode::
|
|
|
-make_card() {
|
|
|
|
|
- nassertr(_lock.debug_is_locked(), nullptr);
|
|
|
|
|
- nassertr((_flags & F_needs_measure) == 0, nullptr);
|
|
|
|
|
|
|
+do_make_card(const CData *cdata) {
|
|
|
|
|
+ nassertr((cdata->_flags & F_needs_measure) == 0, nullptr);
|
|
|
|
|
|
|
|
PT(GeomNode) card_node = new GeomNode("card");
|
|
PT(GeomNode) card_node = new GeomNode("card");
|
|
|
|
|
|
|
|
- PN_stdfloat left = _card_ul[0];
|
|
|
|
|
- PN_stdfloat right = _card_lr[0];
|
|
|
|
|
- PN_stdfloat bottom = _card_lr[1];
|
|
|
|
|
- PN_stdfloat top = _card_ul[1];
|
|
|
|
|
|
|
+ PN_stdfloat left = cdata->_card_ul[0];
|
|
|
|
|
+ PN_stdfloat right = cdata->_card_lr[0];
|
|
|
|
|
+ PN_stdfloat bottom = cdata->_card_lr[1];
|
|
|
|
|
+ PN_stdfloat top = cdata->_card_ul[1];
|
|
|
|
|
|
|
|
- if (_flags & F_card_as_margin) {
|
|
|
|
|
- left = _text_ul[0] - left;
|
|
|
|
|
- right = _text_lr[0] + right;
|
|
|
|
|
- bottom = _text_lr[1] - bottom;
|
|
|
|
|
- top = _text_ul[1] + top;
|
|
|
|
|
|
|
+ if (cdata->_flags & F_card_as_margin) {
|
|
|
|
|
+ left = cdata->_text_ul[0] - left;
|
|
|
|
|
+ right = cdata->_text_lr[0] + right;
|
|
|
|
|
+ bottom = cdata->_text_lr[1] - bottom;
|
|
|
|
|
+ top = cdata->_text_ul[1] + top;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
|
- ("text", GeomVertexFormat::get_v3t2(), _usage_hint);
|
|
|
|
|
|
|
+ ("text", GeomVertexFormat::get_v3t2(), cdata->_usage_hint);
|
|
|
vdata->unclean_set_num_rows(4);
|
|
vdata->unclean_set_num_rows(4);
|
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
|
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
|
|
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
|
|
@@ -826,7 +863,7 @@ make_card() {
|
|
|
texcoord.set_data2(1.0f, 1.0f);
|
|
texcoord.set_data2(1.0f, 1.0f);
|
|
|
texcoord.set_data2(1.0f, 0.0f);
|
|
texcoord.set_data2(1.0f, 0.0f);
|
|
|
|
|
|
|
|
- PT(GeomTristrips) card = new GeomTristrips(_usage_hint);
|
|
|
|
|
|
|
+ PT(GeomTristrips) card = new GeomTristrips(cdata->_usage_hint);
|
|
|
card->add_consecutive_vertices(0, 4);
|
|
card->add_consecutive_vertices(0, 4);
|
|
|
card->close_primitive();
|
|
card->close_primitive();
|
|
|
|
|
|
|
@@ -844,83 +881,88 @@ make_card() {
|
|
|
* what have you.
|
|
* what have you.
|
|
|
*/
|
|
*/
|
|
|
PT(PandaNode) TextNode::
|
|
PT(PandaNode) TextNode::
|
|
|
-make_card_with_border() {
|
|
|
|
|
- nassertr(_lock.debug_is_locked(), nullptr);
|
|
|
|
|
- nassertr((_flags & F_needs_measure) == 0, nullptr);
|
|
|
|
|
|
|
+do_make_card_with_border(const CData *cdata) {
|
|
|
|
|
+ nassertr((cdata->_flags & F_needs_measure) == 0, nullptr);
|
|
|
|
|
|
|
|
PT(GeomNode) card_node = new GeomNode("card");
|
|
PT(GeomNode) card_node = new GeomNode("card");
|
|
|
|
|
|
|
|
- PN_stdfloat left = _card_ul[0];
|
|
|
|
|
- PN_stdfloat right = _card_lr[0];
|
|
|
|
|
- PN_stdfloat bottom = _card_lr[1];
|
|
|
|
|
- PN_stdfloat top = _card_ul[1];
|
|
|
|
|
|
|
+ PN_stdfloat left = cdata->_card_ul[0];
|
|
|
|
|
+ PN_stdfloat right = cdata->_card_lr[0];
|
|
|
|
|
+ PN_stdfloat bottom = cdata->_card_lr[1];
|
|
|
|
|
+ PN_stdfloat top = cdata->_card_ul[1];
|
|
|
|
|
|
|
|
- if (_flags & F_card_as_margin) {
|
|
|
|
|
- left = _text_ul[0] - left;
|
|
|
|
|
- right = _text_lr[0] + right;
|
|
|
|
|
- bottom = _text_lr[1] - bottom;
|
|
|
|
|
- top = _text_ul[1] + top;
|
|
|
|
|
|
|
+ if (cdata->_flags & F_card_as_margin) {
|
|
|
|
|
+ left = cdata->_text_ul[0] - left;
|
|
|
|
|
+ right = cdata->_text_lr[0] + right;
|
|
|
|
|
+ bottom = cdata->_text_lr[1] - bottom;
|
|
|
|
|
+ top = cdata->_text_ul[1] + top;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * we now create three tri-strips instead of one with vertices arranged as
|
|
|
|
|
- * follows: 1 3 5 7 - one 2 4 6 8 \ two 9 11
|
|
|
|
|
- * 13 15 \ 10 12 14 16 - three
|
|
|
|
|
- */
|
|
|
|
|
|
|
+ PN_stdfloat border_size = cdata->_card_border_size;
|
|
|
|
|
+ PN_stdfloat border_uv_portion = cdata->_card_border_uv_portion;
|
|
|
|
|
+
|
|
|
|
|
+ // we now create three tri-strips instead of one
|
|
|
|
|
+ // with vertices arranged as follows:
|
|
|
|
|
+ //
|
|
|
|
|
+ // 1 3 5 7 - one
|
|
|
|
|
+ // 2 4 6 8 / \ two
|
|
|
|
|
+ // 9 11 13 15 \ /
|
|
|
|
|
+ // 10 12 14 16 - three
|
|
|
|
|
+ //
|
|
|
|
|
|
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
|
- ("text", GeomVertexFormat::get_v3t2(), _usage_hint);
|
|
|
|
|
|
|
+ ("text", GeomVertexFormat::get_v3t2(), cdata->_usage_hint);
|
|
|
vdata->unclean_set_num_rows(16);
|
|
vdata->unclean_set_num_rows(16);
|
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
|
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
|
|
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
|
|
|
|
|
|
|
|
// verts 1,2,3,4
|
|
// verts 1,2,3,4
|
|
|
vertex.set_data3(left, 0.02, top);
|
|
vertex.set_data3(left, 0.02, top);
|
|
|
- vertex.set_data3(left, 0.02, top - _card_border_size);
|
|
|
|
|
- vertex.set_data3(left + _card_border_size, 0.02, top);
|
|
|
|
|
- vertex.set_data3(left + _card_border_size, 0.02,
|
|
|
|
|
- top - _card_border_size);
|
|
|
|
|
|
|
+ vertex.set_data3(left, 0.02, top - border_size);
|
|
|
|
|
+ vertex.set_data3(left + border_size, 0.02, top);
|
|
|
|
|
+ vertex.set_data3(left + border_size, 0.02,
|
|
|
|
|
+ top - border_size);
|
|
|
// verts 5,6,7,8
|
|
// verts 5,6,7,8
|
|
|
- vertex.set_data3(right - _card_border_size, 0.02, top);
|
|
|
|
|
- vertex.set_data3(right - _card_border_size, 0.02,
|
|
|
|
|
- top - _card_border_size);
|
|
|
|
|
|
|
+ vertex.set_data3(right - border_size, 0.02, top);
|
|
|
|
|
+ vertex.set_data3(right - border_size, 0.02,
|
|
|
|
|
+ top - border_size);
|
|
|
vertex.set_data3(right, 0.02, top);
|
|
vertex.set_data3(right, 0.02, top);
|
|
|
- vertex.set_data3(right, 0.02, top - _card_border_size);
|
|
|
|
|
|
|
+ vertex.set_data3(right, 0.02, top - border_size);
|
|
|
// verts 9,10,11,12
|
|
// verts 9,10,11,12
|
|
|
- vertex.set_data3(left, 0.02, bottom + _card_border_size);
|
|
|
|
|
|
|
+ vertex.set_data3(left, 0.02, bottom + border_size);
|
|
|
vertex.set_data3(left, 0.02, bottom);
|
|
vertex.set_data3(left, 0.02, bottom);
|
|
|
- vertex.set_data3(left + _card_border_size, 0.02,
|
|
|
|
|
- bottom + _card_border_size);
|
|
|
|
|
- vertex.set_data3(left + _card_border_size, 0.02, bottom);
|
|
|
|
|
|
|
+ vertex.set_data3(left + border_size, 0.02,
|
|
|
|
|
+ bottom + border_size);
|
|
|
|
|
+ vertex.set_data3(left + border_size, 0.02, bottom);
|
|
|
// verts 13,14,15,16
|
|
// verts 13,14,15,16
|
|
|
- vertex.set_data3(right - _card_border_size, 0.02,
|
|
|
|
|
- bottom + _card_border_size);
|
|
|
|
|
- vertex.set_data3(right - _card_border_size, 0.02, bottom);
|
|
|
|
|
- vertex.set_data3(right, 0.02, bottom + _card_border_size);
|
|
|
|
|
|
|
+ vertex.set_data3(right - border_size, 0.02,
|
|
|
|
|
+ bottom + border_size);
|
|
|
|
|
+ vertex.set_data3(right - border_size, 0.02, bottom);
|
|
|
|
|
+ vertex.set_data3(right, 0.02, bottom + border_size);
|
|
|
vertex.set_data3(right, 0.02, bottom);
|
|
vertex.set_data3(right, 0.02, bottom);
|
|
|
|
|
|
|
|
texcoord.set_data2(0.0f, 1.0f); //1
|
|
texcoord.set_data2(0.0f, 1.0f); //1
|
|
|
- texcoord.set_data2(0.0f, 1.0f - _card_border_uv_portion); //2
|
|
|
|
|
- texcoord.set_data2(0.0f + _card_border_uv_portion, 1.0f); //3
|
|
|
|
|
- texcoord.set_data2(0.0f + _card_border_uv_portion,
|
|
|
|
|
- 1.0f - _card_border_uv_portion); //4
|
|
|
|
|
- texcoord.set_data2(1.0f -_card_border_uv_portion, 1.0f); //5
|
|
|
|
|
- texcoord.set_data2(1.0f -_card_border_uv_portion,
|
|
|
|
|
- 1.0f - _card_border_uv_portion); //6
|
|
|
|
|
|
|
+ texcoord.set_data2(0.0f, 1.0f - border_uv_portion); //2
|
|
|
|
|
+ texcoord.set_data2(0.0f + border_uv_portion, 1.0f); //3
|
|
|
|
|
+ texcoord.set_data2(0.0f + border_uv_portion,
|
|
|
|
|
+ 1.0f - border_uv_portion); //4
|
|
|
|
|
+ texcoord.set_data2(1.0f -border_uv_portion, 1.0f); //5
|
|
|
|
|
+ texcoord.set_data2(1.0f -border_uv_portion,
|
|
|
|
|
+ 1.0f - border_uv_portion); //6
|
|
|
texcoord.set_data2(1.0f, 1.0f); //7
|
|
texcoord.set_data2(1.0f, 1.0f); //7
|
|
|
- texcoord.set_data2(1.0f, 1.0f - _card_border_uv_portion); //8
|
|
|
|
|
|
|
+ texcoord.set_data2(1.0f, 1.0f - border_uv_portion); //8
|
|
|
|
|
|
|
|
- texcoord.set_data2(0.0f, _card_border_uv_portion); //9
|
|
|
|
|
|
|
+ texcoord.set_data2(0.0f, border_uv_portion); //9
|
|
|
texcoord.set_data2(0.0f, 0.0f); //10
|
|
texcoord.set_data2(0.0f, 0.0f); //10
|
|
|
- texcoord.set_data2(_card_border_uv_portion, _card_border_uv_portion); //11
|
|
|
|
|
- texcoord.set_data2(_card_border_uv_portion, 0.0f); //12
|
|
|
|
|
|
|
+ texcoord.set_data2(border_uv_portion, border_uv_portion); //11
|
|
|
|
|
+ texcoord.set_data2(border_uv_portion, 0.0f); //12
|
|
|
|
|
|
|
|
- texcoord.set_data2(1.0f - _card_border_uv_portion, _card_border_uv_portion);//13
|
|
|
|
|
- texcoord.set_data2(1.0f - _card_border_uv_portion, 0.0f);//14
|
|
|
|
|
- texcoord.set_data2(1.0f, _card_border_uv_portion);//15
|
|
|
|
|
|
|
+ texcoord.set_data2(1.0f - border_uv_portion, border_uv_portion);//13
|
|
|
|
|
+ texcoord.set_data2(1.0f - border_uv_portion, 0.0f);//14
|
|
|
|
|
+ texcoord.set_data2(1.0f, border_uv_portion);//15
|
|
|
texcoord.set_data2(1.0f, 0.0f);//16
|
|
texcoord.set_data2(1.0f, 0.0f);//16
|
|
|
|
|
|
|
|
- PT(GeomTristrips) card = new GeomTristrips(_usage_hint);
|
|
|
|
|
|
|
+ PT(GeomTristrips) card = new GeomTristrips(cdata->_usage_hint);
|
|
|
card->reserve_num_vertices(24);
|
|
card->reserve_num_vertices(24);
|
|
|
|
|
|
|
|
// tristrip #1
|
|
// tristrip #1
|
|
@@ -970,3 +1012,69 @@ count_geoms(PandaNode *node) {
|
|
|
|
|
|
|
|
return num_geoms;
|
|
return num_geoms;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ *
|
|
|
|
|
+ */
|
|
|
|
|
+TextNode::CData::
|
|
|
|
|
+CData() {
|
|
|
|
|
+ _flags = 0;
|
|
|
|
|
+ _max_rows = 0;
|
|
|
|
|
+ _usage_hint = GeomEnums::UH_static;
|
|
|
|
|
+ _flatten_flags = 0;
|
|
|
|
|
+ if (text_flatten) {
|
|
|
|
|
+ _flatten_flags |= FF_strong;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (text_dynamic_merge) {
|
|
|
|
|
+ _flatten_flags |= FF_dynamic_merge;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ _frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
|
+ _card_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
|
+
|
|
|
|
|
+ _frame_width = 1.0f;
|
|
|
|
|
+
|
|
|
|
|
+ _frame_ul.set(0.0f, 0.0f);
|
|
|
|
|
+ _frame_lr.set(0.0f, 0.0f);
|
|
|
|
|
+ _card_ul.set(0.0f, 0.0f);
|
|
|
|
|
+ _card_lr.set(0.0f, 0.0f);
|
|
|
|
|
+
|
|
|
|
|
+ _transform = LMatrix4::ident_mat();
|
|
|
|
|
+ _coordinate_system = CS_default;
|
|
|
|
|
+
|
|
|
|
|
+ _ul3d.set(0.0f, 0.0f, 0.0f);
|
|
|
|
|
+ _lr3d.set(0.0f, 0.0f, 0.0f);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ *
|
|
|
|
|
+ */
|
|
|
|
|
+TextNode::CData::
|
|
|
|
|
+CData(const CData ©) :
|
|
|
|
|
+ _card_texture(copy._card_texture),
|
|
|
|
|
+ _frame_color(copy._frame_color),
|
|
|
|
|
+ _card_color(copy._card_color),
|
|
|
|
|
+ _flags(copy._flags | F_needs_rebuild | F_needs_measure),
|
|
|
|
|
+ _max_rows(copy._max_rows),
|
|
|
|
|
+ _usage_hint(GeomEnums::UH_static),
|
|
|
|
|
+ _frame_width(copy._frame_width),
|
|
|
|
|
+ _card_border_size(copy._card_border_size),
|
|
|
|
|
+ _card_border_uv_portion(copy._card_border_uv_portion),
|
|
|
|
|
+ _frame_ul(copy._frame_ul),
|
|
|
|
|
+ _frame_lr(copy._frame_lr),
|
|
|
|
|
+ _card_ul(copy._card_ul),
|
|
|
|
|
+ _card_lr(copy._card_lr),
|
|
|
|
|
+ _transform(copy._transform),
|
|
|
|
|
+ _coordinate_system(copy._coordinate_system),
|
|
|
|
|
+ _ul3d(copy._ul3d),
|
|
|
|
|
+ _lr3d(copy._lr3d)
|
|
|
|
|
+{
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ *
|
|
|
|
|
+ */
|
|
|
|
|
+CycleData *TextNode::CData::
|
|
|
|
|
+make_copy() const {
|
|
|
|
|
+ return new CData(*this);
|
|
|
|
|
+}
|