From ac4faf3d74638ad2d48d23a156973782c247e8b0 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 12 Dec 2020 14:05:36 +0100 Subject: [PATCH] text: Make TextNode pipeline-cycled Fixes #1070 Note that text property changes are not pipeline-cycled at the moment. --- panda/src/text/textNode.I | 621 +++++++++++++++++------------------ panda/src/text/textNode.cxx | 628 +++++++++++++++++++++--------------- panda/src/text/textNode.h | 101 +++--- 3 files changed, 745 insertions(+), 605 deletions(-) diff --git a/panda/src/text/textNode.I b/panda/src/text/textNode.I index 1d02442451..188fb009a4 100644 --- a/panda/src/text/textNode.I +++ b/panda/src/text/textNode.I @@ -33,9 +33,9 @@ get_line_height() const { */ INLINE void TextNode:: set_max_rows(int max_rows) { - MutexHolder holder(_lock); - _max_rows = max_rows; - invalidate_with_measure(); + CDWriter cdata(_cycler); + cdata->_max_rows = max_rows; + invalidate_with_measure(cdata); } /** @@ -44,9 +44,7 @@ set_max_rows(int max_rows) { */ INLINE void TextNode:: clear_max_rows() { - MutexHolder holder(_lock); - _max_rows = 0; - invalidate_with_measure(); + set_max_rows(0); } /** @@ -55,8 +53,7 @@ clear_max_rows() { */ INLINE bool TextNode:: has_max_rows() const { - MutexHolder holder(_lock); - return _max_rows > 0; + return get_max_rows() > 0; } /** @@ -65,8 +62,8 @@ has_max_rows() const { */ INLINE int TextNode:: get_max_rows() const { - MutexHolder holder(_lock); - return _max_rows; + CDReader cdata(_cycler); + return cdata->_max_rows; } /** @@ -75,9 +72,14 @@ get_max_rows() const { */ INLINE bool TextNode:: has_overflow() const { - MutexHolder holder(_lock); - check_measure(); - return (_flags & F_has_overflow) != 0; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return (cdataw->_flags & F_has_overflow) != 0; + } else { + return (cdata->_flags & F_has_overflow) != 0; + } } /** @@ -93,10 +95,10 @@ set_frame_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) { */ INLINE void TextNode:: set_frame_color(const LColor &frame_color) { - MutexHolder holder(_lock); - if (_frame_color != frame_color) { - _frame_color = frame_color; - invalidate_no_measure(); + CDWriter cdata(_cycler); + if (cdata->_frame_color != frame_color) { + cdata->_frame_color = frame_color; + invalidate_no_measure(cdata); } } @@ -105,8 +107,8 @@ set_frame_color(const LColor &frame_color) { */ INLINE LColor TextNode:: get_frame_color() const { - MutexHolder holder(_lock); - return _frame_color; + CDReader cdata(_cycler); + return cdata->_frame_color; } /** @@ -114,12 +116,12 @@ get_frame_color() const { */ INLINE void TextNode:: set_card_border(PN_stdfloat size, PN_stdfloat uv_portion) { - MutexHolder holder(_lock); - if ((_flags & F_has_card_border) == 0 || _card_border_size != size || _card_border_uv_portion != uv_portion) { - _flags |= F_has_card_border; - _card_border_size = size; - _card_border_uv_portion = uv_portion; - invalidate_no_measure(); + CDWriter cdata(_cycler); + if ((cdata->_flags & F_has_card_border) == 0 || cdata->_card_border_size != size || cdata->_card_border_uv_portion != uv_portion) { + cdata->_flags |= F_has_card_border; + cdata->_card_border_size = size; + cdata->_card_border_uv_portion = uv_portion; + invalidate_no_measure(cdata); } } @@ -128,10 +130,10 @@ set_card_border(PN_stdfloat size, PN_stdfloat uv_portion) { */ INLINE void TextNode:: clear_card_border() { - MutexHolder holder(_lock); - if (_flags & F_has_card_border) { - _flags &= ~F_has_card_border; - invalidate_no_measure(); + CDWriter cdata(_cycler); + if (cdata->_flags & F_has_card_border) { + cdata->_flags &= ~F_has_card_border; + invalidate_no_measure(cdata); } } @@ -140,8 +142,8 @@ clear_card_border() { */ INLINE PN_stdfloat TextNode:: get_card_border_size() const { - MutexHolder holder(_lock); - return _card_border_size; + CDReader cdata(_cycler); + return cdata->_card_border_size; } /** @@ -149,8 +151,8 @@ get_card_border_size() const { */ INLINE PN_stdfloat TextNode:: get_card_border_uv_portion() const { - MutexHolder holder(_lock); - return _card_border_uv_portion; + CDReader cdata(_cycler); + return cdata->_card_border_uv_portion; } /** @@ -158,8 +160,8 @@ get_card_border_uv_portion() const { */ INLINE bool TextNode:: has_card_border() const { - MutexHolder holder(_lock); - return (_flags & F_has_card_border) != 0; + CDReader cdata(_cycler); + return (cdata->_flags & F_has_card_border) != 0; } /** @@ -175,10 +177,10 @@ set_card_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) { */ INLINE void TextNode:: set_card_color(const LColor &card_color) { - MutexHolder holder(_lock); - if (_card_color != card_color) { - _card_color = card_color; - invalidate_no_measure(); + CDWriter cdata(_cycler); + if (cdata->_card_color != card_color) { + cdata->_card_color = card_color; + invalidate_no_measure(cdata); } } @@ -187,8 +189,8 @@ set_card_color(const LColor &card_color) { */ INLINE LColor TextNode:: get_card_color() const { - MutexHolder holder(_lock); - return _card_color; + CDReader cdata(_cycler); + return cdata->_card_color; } /** @@ -199,11 +201,11 @@ set_card_texture(Texture *card_texture) { if (card_texture == nullptr) { clear_card_texture(); } else { - MutexHolder holder(_lock); - if ((_flags & F_has_card_texture) == 0 || _card_texture != card_texture) { - _flags |= F_has_card_texture; - _card_texture = card_texture; - invalidate_no_measure(); + CDWriter cdata(_cycler); + if ((cdata->_flags & F_has_card_texture) == 0 || cdata->_card_texture != card_texture) { + cdata->_flags |= F_has_card_texture; + cdata->_card_texture = card_texture; + invalidate_no_measure(cdata); } } } @@ -213,11 +215,11 @@ set_card_texture(Texture *card_texture) { */ INLINE void TextNode:: clear_card_texture() { - MutexHolder holder(_lock); - if (_flags & F_has_card_texture) { - _flags &= ~F_has_card_texture; - _card_texture = nullptr; - invalidate_no_measure(); + CDWriter cdata(_cycler); + if (cdata->_flags & F_has_card_texture) { + cdata->_flags &= ~F_has_card_texture; + cdata->_card_texture = nullptr; + invalidate_no_measure(cdata); } } @@ -226,8 +228,8 @@ clear_card_texture() { */ INLINE bool TextNode:: has_card_texture() const { - MutexHolder holder(_lock); - return (_flags & F_has_card_texture) != 0; + CDReader cdata(_cycler); + return (cdata->_flags & F_has_card_texture) != 0; } /** @@ -235,8 +237,8 @@ has_card_texture() const { */ INLINE Texture *TextNode:: get_card_texture() const { - MutexHolder holder(_lock); - return _card_texture; + CDReader cdata(_cycler); + return cdata->_card_texture; } /** @@ -247,11 +249,11 @@ get_card_texture() const { */ INLINE void TextNode:: set_frame_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) { - MutexHolder holder(_lock); - _flags |= (F_has_frame | F_frame_as_margin); - _frame_ul.set(left, top); - _frame_lr.set(right, bottom); - invalidate_no_measure(); + CDWriter cdata(_cycler); + cdata->_flags |= (F_has_frame | F_frame_as_margin); + cdata->_frame_ul.set(left, top); + cdata->_frame_lr.set(right, bottom); + invalidate_no_measure(cdata); } /** @@ -262,12 +264,12 @@ set_frame_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_ */ INLINE void TextNode:: set_frame_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) { - MutexHolder holder(_lock); - _flags |= F_has_frame; - _flags &= ~F_frame_as_margin; - _frame_ul.set(left, top); - _frame_lr.set(right, bottom); - invalidate_no_measure(); + CDWriter cdata(_cycler); + cdata->_flags |= F_has_frame; + cdata->_flags &= ~F_frame_as_margin; + cdata->_frame_ul.set(left, top); + cdata->_frame_lr.set(right, bottom); + invalidate_no_measure(cdata); } /** @@ -275,9 +277,9 @@ set_frame_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_std */ INLINE void TextNode:: clear_frame() { - MutexHolder holder(_lock); - _flags &= ~F_has_frame; - invalidate_no_measure(); + CDWriter cdata(_cycler); + cdata->_flags &= ~F_has_frame; + invalidate_no_measure(cdata); } /** @@ -285,8 +287,8 @@ clear_frame() { */ INLINE bool TextNode:: has_frame() const { - MutexHolder holder(_lock); - return (_flags & F_has_frame) != 0; + CDReader cdata(_cycler); + return (cdata->_flags & F_has_frame) != 0; } /** @@ -298,9 +300,9 @@ has_frame() const { */ INLINE bool TextNode:: is_frame_as_margin() const { - MutexHolder holder(_lock); - nassertr((_flags & F_has_frame) != 0, false); - return (_flags & F_frame_as_margin) != 0; + CDReader cdata(_cycler); + nassertr((cdata->_flags & F_has_frame) != 0, false); + return (cdata->_flags & F_frame_as_margin) != 0; } /** @@ -311,37 +313,12 @@ is_frame_as_margin() const { */ INLINE LVecBase4 TextNode:: get_frame_as_set() const { - MutexHolder holder(_lock); - nassertr((_flags & F_has_frame) != 0, LVecBase4(0.0, 0.0, 0.0, 0.0)); - return LVecBase4(_frame_ul[0], _frame_lr[0], _frame_lr[1], _frame_ul[1]); -} - -/** - * 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. - */ -INLINE LVecBase4 TextNode:: -get_frame_actual() const { - MutexHolder holder(_lock); - if (_flags & F_has_frame) { - if (_flags & F_frame_as_margin) { - check_measure(); - return LVecBase4(_text_ul[0] - _frame_ul[0], - _text_lr[0] + _frame_lr[0], - _text_lr[1] - _frame_lr[1], - _text_ul[1] + _frame_ul[1]); - } else { - return LVecBase4(_frame_ul[0], _frame_lr[0], _frame_lr[1], _frame_ul[1]); - } - } else { - check_measure(); - return LVecBase4(_text_ul[0], _text_lr[0], _text_lr[1], _text_ul[1]); - } + CDReader cdata(_cycler); + nassertr((cdata->_flags & F_has_frame) != 0, LVecBase4(0.0, 0.0, 0.0, 0.0)); + return LVecBase4(cdata->_frame_ul[0], + cdata->_frame_lr[0], + cdata->_frame_lr[1], + cdata->_frame_ul[1]); } /** @@ -349,9 +326,9 @@ get_frame_actual() const { */ INLINE void TextNode:: set_frame_line_width(PN_stdfloat frame_width) { - MutexHolder holder(_lock); - _frame_width = frame_width; - invalidate_no_measure(); + CDWriter cdata(_cycler); + cdata->_frame_width = frame_width; + invalidate_no_measure(cdata); } /** @@ -359,8 +336,8 @@ set_frame_line_width(PN_stdfloat frame_width) { */ INLINE PN_stdfloat TextNode:: get_frame_line_width() const { - MutexHolder holder(_lock); - return _frame_width; + CDReader cdata(_cycler); + return cdata->_frame_width; } /** @@ -370,13 +347,13 @@ get_frame_line_width() const { */ INLINE void TextNode:: set_frame_corners(bool corners) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler); if (corners) { - _flags |= F_frame_corners; + cdata->_flags |= F_frame_corners; } else { - _flags &= ~F_frame_corners; + cdata->_flags &= ~F_frame_corners; } - invalidate_no_measure(); + invalidate_no_measure(cdata); } /** @@ -384,8 +361,8 @@ set_frame_corners(bool corners) { */ INLINE bool TextNode:: get_frame_corners() const { - MutexHolder holder(_lock); - return (_flags & F_frame_corners) != 0; + CDReader cdata(_cycler); + return (cdata->_flags & F_frame_corners) != 0; } /** @@ -396,11 +373,11 @@ get_frame_corners() const { */ INLINE void TextNode:: set_card_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) { - MutexHolder holder(_lock); - _flags |= (F_has_card | F_card_as_margin); - _card_ul.set(left, top); - _card_lr.set(right, bottom); - invalidate_no_measure(); + CDWriter cdata(_cycler); + cdata->_flags |= (F_has_card | F_card_as_margin); + cdata->_card_ul.set(left, top); + cdata->_card_lr.set(right, bottom); + invalidate_no_measure(cdata); } /** @@ -411,12 +388,12 @@ set_card_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_s */ INLINE void TextNode:: set_card_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) { - MutexHolder holder(_lock); - _flags |= F_has_card; - _flags &= ~F_card_as_margin; - _card_ul.set(left, top); - _card_lr.set(right, bottom); - invalidate_no_measure(); + CDWriter cdata(_cycler); + cdata->_flags |= F_has_card; + cdata->_flags &= ~F_card_as_margin; + cdata->_card_ul.set(left, top); + cdata->_card_lr.set(right, bottom); + invalidate_no_measure(cdata); } /** @@ -426,13 +403,13 @@ set_card_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdf */ INLINE void TextNode:: set_card_decal(bool card_decal) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler); if (card_decal) { - _flags |= F_card_decal; + cdata->_flags |= F_card_decal; } else { - _flags &= ~F_card_decal; + cdata->_flags &= ~F_card_decal; } - invalidate_no_measure(); + invalidate_no_measure(cdata); } /** @@ -440,9 +417,9 @@ set_card_decal(bool card_decal) { */ INLINE void TextNode:: clear_card() { - MutexHolder holder(_lock); - _flags &= ~F_has_card; - invalidate_no_measure(); + CDWriter cdata(_cycler); + cdata->_flags &= ~F_has_card; + invalidate_no_measure(cdata); } /** @@ -450,8 +427,8 @@ clear_card() { */ INLINE bool TextNode:: has_card() const { - MutexHolder holder(_lock); - return (_flags & F_has_card) != 0; + CDReader cdata(_cycler); + return (cdata->_flags & F_has_card) != 0; } /** @@ -459,8 +436,8 @@ has_card() const { */ INLINE bool TextNode:: get_card_decal() const { - MutexHolder holder(_lock); - return (_flags & F_card_decal) != 0; + CDReader cdata(_cycler); + return (cdata->_flags & F_card_decal) != 0; } /** @@ -472,9 +449,9 @@ get_card_decal() const { */ INLINE bool TextNode:: is_card_as_margin() const { - MutexHolder holder(_lock); - nassertr((_flags & F_has_card) != 0, false); - return (_flags & F_card_as_margin) != 0; + CDReader cdata(_cycler); + nassertr((cdata->_flags & F_has_card) != 0, false); + return (cdata->_flags & F_card_as_margin) != 0; } /** @@ -485,37 +462,12 @@ is_card_as_margin() const { */ INLINE LVecBase4 TextNode:: get_card_as_set() const { - MutexHolder holder(_lock); - nassertr((_flags & F_has_card) != 0, LVecBase4(0.0, 0.0, 0.0, 0.0)); - return LVecBase4(_card_ul[0], _card_lr[0], _card_lr[1], _card_ul[1]); -} - -/** - * 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. - */ -INLINE LVecBase4 TextNode:: -get_card_actual() const { - MutexHolder holder(_lock); - if (_flags & F_has_card) { - if (_flags & F_card_as_margin) { - check_measure(); - return LVecBase4(_text_ul[0] - _card_ul[0], - _text_lr[0] + _card_lr[0], - _text_lr[1] - _card_lr[1], - _text_ul[1] + _card_ul[1]); - } else { - return LVecBase4(_card_ul[0], _card_lr[0], _card_lr[1], _card_ul[1]); - } - } else { - check_measure(); - return LVecBase4(_text_ul[0], _text_lr[0], _text_lr[1], _text_ul[1]); - } + CDReader cdata(_cycler); + nassertr((cdata->_flags & F_has_card) != 0, LVecBase4(0.0, 0.0, 0.0, 0.0)); + return LVecBase4(cdata->_card_ul[0], + cdata->_card_lr[0], + cdata->_card_lr[1], + cdata->_card_ul[1]); } /** @@ -528,9 +480,9 @@ INLINE LVecBase4 TextNode:: get_card_transformed() const { LVecBase4 card = get_card_actual(); - MutexHolder holder(_lock); - LPoint3 ul = LPoint3(card[0], 0.0, card[3]) * _transform; - LPoint3 lr = LPoint3(card[1], 0.0, card[2]) * _transform; + CDReader cdata(_cycler); + LPoint3 ul = LPoint3(card[0], 0.0, card[3]) * cdata->_transform; + LPoint3 lr = LPoint3(card[1], 0.0, card[2]) * cdata->_transform; return LVecBase4(ul[0], lr[0], lr[2], ul[2]); } @@ -540,9 +492,9 @@ get_card_transformed() const { */ INLINE void TextNode:: set_transform(const LMatrix4 &transform) { - MutexHolder holder(_lock); - _transform = transform; - invalidate_with_measure(); + CDWriter cdata(_cycler); + cdata->_transform = transform; + invalidate_with_measure(cdata); } /** @@ -550,8 +502,8 @@ set_transform(const LMatrix4 &transform) { */ INLINE LMatrix4 TextNode:: get_transform() const { - MutexHolder holder(_lock); - return _transform; + CDReader cdata(_cycler); + return cdata->_transform; } /** @@ -559,9 +511,9 @@ get_transform() const { */ INLINE void TextNode:: set_coordinate_system(CoordinateSystem coordinate_system) { - MutexHolder holder(_lock); - _coordinate_system = coordinate_system; - invalidate_with_measure(); + CDWriter cdata(_cycler); + cdata->_coordinate_system = coordinate_system; + invalidate_with_measure(cdata); } /** @@ -569,8 +521,8 @@ set_coordinate_system(CoordinateSystem coordinate_system) { */ INLINE CoordinateSystem TextNode:: get_coordinate_system() const { - MutexHolder holder(_lock); - return _coordinate_system; + CDReader cdata(_cycler); + return cdata->_coordinate_system; } /** @@ -581,9 +533,9 @@ get_coordinate_system() const { */ INLINE void TextNode:: set_usage_hint(Geom::UsageHint usage_hint) { - MutexHolder holder(_lock); - _usage_hint = usage_hint; - invalidate_no_measure(); + CDWriter cdata(_cycler); + cdata->_usage_hint = usage_hint; + invalidate_no_measure(cdata); } /** @@ -592,8 +544,8 @@ set_usage_hint(Geom::UsageHint usage_hint) { */ INLINE Geom::UsageHint TextNode:: get_usage_hint() const { - MutexHolder holder(_lock); - return _usage_hint; + CDReader cdata(_cycler); + return cdata->_usage_hint; } /** @@ -633,8 +585,8 @@ get_usage_hint() const { */ INLINE void TextNode:: set_flatten_flags(int flatten_flags) { - MutexHolder holder(_lock); - _flatten_flags = flatten_flags; + CDWriter cdata(_cycler); + cdata->_flatten_flags = flatten_flags; } /** @@ -642,8 +594,8 @@ set_flatten_flags(int flatten_flags) { */ INLINE int TextNode:: get_flatten_flags() const { - MutexHolder holder(_lock); - return _flatten_flags; + CDReader cdata(_cycler); + return cdata->_flatten_flags; } /** @@ -652,9 +604,9 @@ get_flatten_flags() const { */ INLINE void TextNode:: set_font(TextFont *font) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_font(font); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -662,9 +614,9 @@ set_font(TextFont *font) { */ INLINE void TextNode:: clear_font() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_font(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -683,9 +635,9 @@ clear_font() { */ INLINE void TextNode:: set_small_caps(bool small_caps) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_small_caps(small_caps); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -693,9 +645,9 @@ set_small_caps(bool small_caps) { */ INLINE void TextNode:: clear_small_caps() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler); TextProperties::clear_small_caps(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -705,9 +657,9 @@ clear_small_caps() { */ INLINE void TextNode:: set_small_caps_scale(PN_stdfloat small_caps_scale) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_small_caps_scale(small_caps_scale); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -715,9 +667,9 @@ set_small_caps_scale(PN_stdfloat small_caps_scale) { */ INLINE void TextNode:: clear_small_caps_scale() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_small_caps_scale(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -725,9 +677,9 @@ clear_small_caps_scale() { */ INLINE void TextNode:: set_slant(PN_stdfloat slant) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_slant(slant); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -735,9 +687,9 @@ set_slant(PN_stdfloat slant) { */ INLINE void TextNode:: clear_slant() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_slant(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -745,9 +697,9 @@ clear_slant() { */ INLINE void TextNode:: set_align(TextNode::Alignment align_type) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_align(align_type); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -755,9 +707,9 @@ set_align(TextNode::Alignment align_type) { */ INLINE void TextNode:: clear_align() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_align(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -766,9 +718,9 @@ clear_align() { */ INLINE void TextNode:: set_indent(PN_stdfloat indent) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_indent(indent); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -776,9 +728,9 @@ set_indent(PN_stdfloat indent) { */ INLINE void TextNode:: clear_indent() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_indent(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -787,9 +739,9 @@ clear_indent() { */ INLINE void TextNode:: set_wordwrap(PN_stdfloat wordwrap) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_wordwrap(wordwrap); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -798,9 +750,9 @@ set_wordwrap(PN_stdfloat wordwrap) { */ INLINE void TextNode:: clear_wordwrap() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_wordwrap(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -808,9 +760,9 @@ clear_wordwrap() { */ INLINE void TextNode:: set_text_color(const LColor &text_color) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_text_color(text_color); - invalidate_no_measure(); + invalidate_no_measure(cdata); } /** @@ -827,9 +779,9 @@ set_text_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) { */ INLINE void TextNode:: clear_text_color() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_text_color(); - invalidate_no_measure(); + invalidate_no_measure(cdata); } /** @@ -845,9 +797,9 @@ set_shadow_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) { */ INLINE void TextNode:: set_shadow_color(const LColor &shadow_color) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_shadow_color(shadow_color); - invalidate_no_measure(); + invalidate_no_measure(cdata); } /** @@ -855,9 +807,9 @@ set_shadow_color(const LColor &shadow_color) { */ INLINE void TextNode:: clear_shadow_color() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_shadow_color(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -875,9 +827,9 @@ set_shadow(PN_stdfloat xoffset, PN_stdfloat yoffset) { */ INLINE void TextNode:: set_shadow(const LVecBase2 &shadow_offset) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_shadow(shadow_offset); - invalidate_no_measure(); + invalidate_no_measure(cdata); } /** @@ -885,9 +837,9 @@ set_shadow(const LVecBase2 &shadow_offset) { */ INLINE void TextNode:: clear_shadow() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_shadow(); - invalidate_no_measure(); + invalidate_no_measure(cdata); } /** @@ -901,9 +853,9 @@ clear_shadow() { */ INLINE void TextNode:: set_bin(const std::string &bin) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_bin(bin); - invalidate_no_measure(); + invalidate_no_measure(cdata); } /** @@ -912,9 +864,9 @@ set_bin(const std::string &bin) { */ INLINE void TextNode:: clear_bin() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_bin(); - invalidate_no_measure(); + invalidate_no_measure(cdata); } /** @@ -930,8 +882,8 @@ clear_bin() { */ INLINE int TextNode:: set_draw_order(int draw_order) { - MutexHolder holder(_lock); - invalidate_no_measure(); + CDWriter cdata(_cycler, true); + invalidate_no_measure(cdata); return TextProperties::set_draw_order(draw_order); } @@ -940,9 +892,9 @@ set_draw_order(int draw_order) { */ INLINE void TextNode:: clear_draw_order() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_draw_order(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -951,9 +903,9 @@ clear_draw_order() { */ INLINE void TextNode:: set_tab_width(PN_stdfloat tab_width) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_tab_width(tab_width); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -961,9 +913,9 @@ set_tab_width(PN_stdfloat tab_width) { */ INLINE void TextNode:: clear_tab_width() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_tab_width(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -973,9 +925,9 @@ clear_tab_width() { */ INLINE void TextNode:: set_glyph_scale(PN_stdfloat glyph_scale) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_glyph_scale(glyph_scale); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -983,9 +935,9 @@ set_glyph_scale(PN_stdfloat glyph_scale) { */ INLINE void TextNode:: clear_glyph_scale() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_glyph_scale(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -995,9 +947,9 @@ clear_glyph_scale() { */ INLINE void TextNode:: set_glyph_shift(PN_stdfloat glyph_shift) { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::set_glyph_shift(glyph_shift); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -1005,9 +957,9 @@ set_glyph_shift(PN_stdfloat glyph_shift) { */ INLINE void TextNode:: clear_glyph_shift() { - MutexHolder holder(_lock); + CDWriter cdata(_cycler, true); TextProperties::clear_glyph_shift(); - invalidate_with_measure(); + invalidate_with_measure(cdata); } /** @@ -1040,9 +992,14 @@ calc_width(const std::string &line) const { */ INLINE std::wstring TextNode:: get_wordwrapped_wtext() const { - MutexHolder holder(_lock); - check_measure(); - return _wordwrapped_wtext; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return cdataw->_wordwrapped_wtext; + } else { + return cdata->_wordwrapped_wtext; + } } /** @@ -1051,9 +1008,14 @@ get_wordwrapped_wtext() const { */ INLINE PN_stdfloat TextNode:: get_left() const { - MutexHolder holder(_lock); - check_measure(); - return _text_ul[0]; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return cdataw->_text_ul[0]; + } else { + return cdata->_text_ul[0]; + } } /** @@ -1062,9 +1024,14 @@ get_left() const { */ INLINE PN_stdfloat TextNode:: get_right() const { - MutexHolder holder(_lock); - check_measure(); - return _text_lr[0]; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return cdataw->_text_lr[0]; + } else { + return cdata->_text_lr[0]; + } } /** @@ -1073,9 +1040,14 @@ get_right() const { */ INLINE PN_stdfloat TextNode:: get_bottom() const { - MutexHolder holder(_lock); - check_measure(); - return _text_lr[1]; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return cdataw->_text_lr[1]; + } else { + return cdata->_text_lr[1]; + } } /** @@ -1084,9 +1056,14 @@ get_bottom() const { */ INLINE PN_stdfloat TextNode:: get_top() const { - MutexHolder holder(_lock); - check_measure(); - return _text_ul[1]; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return cdataw->_text_ul[1]; + } else { + return cdata->_text_ul[1]; + } } /** @@ -1094,9 +1071,14 @@ get_top() const { */ INLINE PN_stdfloat TextNode:: get_height() const { - MutexHolder holder(_lock); - check_measure(); - return _text_ul[1] - _text_lr[1]; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return cdataw->_text_ul[1] - cdataw->_text_lr[1]; + } else { + return cdata->_text_ul[1] - cdata->_text_lr[1]; + } } /** @@ -1104,9 +1086,14 @@ get_height() const { */ INLINE PN_stdfloat TextNode:: get_width() const { - MutexHolder holder(_lock); - check_measure(); - return _text_lr[0] - _text_ul[0]; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return cdataw->_text_lr[0] - cdataw->_text_ul[0]; + } else { + return cdata->_text_lr[0] - cdata->_text_ul[0]; + } } /** @@ -1115,9 +1102,14 @@ get_width() const { */ INLINE LPoint3 TextNode:: get_upper_left_3d() const { - MutexHolder holder(_lock); - check_measure(); - return _ul3d; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return cdataw->_ul3d; + } else { + return cdata->_ul3d; + } } /** @@ -1126,9 +1118,14 @@ get_upper_left_3d() const { */ INLINE LPoint3 TextNode:: get_lower_right_3d() const { - MutexHolder holder(_lock); - check_measure(); - return _lr3d; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return cdataw->_lr3d; + } else { + return cdata->_lr3d; + } } /** @@ -1137,9 +1134,14 @@ get_lower_right_3d() const { */ INLINE int TextNode:: get_num_rows() const { - MutexHolder holder(_lock); - check_measure(); - return _num_rows; + CDLockedReader cdata(_cycler); + if (do_needs_measure(cdata)) { + CDWriter cdataw(((TextNode *)this)->_cycler, cdata, false); + ((TextNode *)this)->do_measure(cdataw); + return cdataw->_num_rows; + } else { + return cdata->_num_rows; + } } /** @@ -1149,8 +1151,10 @@ get_num_rows() const { */ PT(PandaNode) TextNode:: generate() { - MutexHolder holder(_lock); - return do_generate(); + // Propagate the computed values upstream if the upstream stages have no + // changes to the text. + CDWriter cdata(_cycler, false); + return do_generate(cdata); } /** @@ -1160,8 +1164,13 @@ generate() { */ INLINE void TextNode:: update() { - MutexHolder holder(_lock); - check_rebuild(); + CDLockedReader cdata(_cycler); + if (do_needs_rebuild(cdata)) { + // Propagate the generated text upstream if the upstream stages have no + // changes to the text. + CDWriter cdataw(_cycler, cdata, false); + ((TextNode *)this)->do_rebuild(cdataw); + } } /** @@ -1172,9 +1181,11 @@ update() { */ INLINE void TextNode:: force_update() { - MutexHolder holder(_lock); + // Propagate the generated text upstream if the upstream stages have no + // changes to the text. + CDWriter cdata(_cycler, false); mark_internal_bounds_stale(); - do_rebuild(); + do_rebuild(cdata); } /** @@ -1184,8 +1195,8 @@ force_update() { * changes). */ INLINE void TextNode:: -invalidate_no_measure() { - _flags |= F_needs_rebuild; +invalidate_no_measure(CData *cdata) { + cdata->_flags |= F_needs_rebuild; } /** @@ -1195,29 +1206,23 @@ invalidate_no_measure() { * changes). */ INLINE void TextNode:: -invalidate_with_measure() { - _flags |= (F_needs_rebuild | F_needs_measure); +invalidate_with_measure(CData *cdata) { + cdata->_flags |= (F_needs_rebuild | F_needs_measure); mark_internal_bounds_stale(); } /** - * Called internally to call do_rebuild() if necessary (that is, if the - * internal geometry has changed recently). + * Returns true if do_rebuild() needs to be called. */ -INLINE void TextNode:: -check_rebuild() const { - if ((_flags & F_needs_rebuild) != 0) { - ((TextNode *)this)->do_rebuild(); - } +INLINE bool TextNode:: +do_needs_rebuild(const CData *cdata) const { + return ((cdata->_flags & F_needs_rebuild) != 0); } /** - * Called internally to call do_measure() if necessary; this will remeasure - * the text without necessarily rebuilding it. + * Returns true if do_measure() needs to be called. */ -INLINE void TextNode:: -check_measure() const { - if ((_flags & F_needs_measure) != 0) { - ((TextNode *)this)->do_measure(); - } +INLINE bool TextNode:: +do_needs_measure(const CData *cdata) const { + return ((cdata->_flags & F_needs_measure) != 0); } diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index 4a77acd6d3..5050caf624 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -62,36 +62,9 @@ TextNode:: TextNode(const string &name) : PandaNode(name) { 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) { 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 ©) : 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), TextEncoder(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() { } +/** + * 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 * character is not known. This may be a wide character (greater than 255). @@ -292,14 +306,15 @@ output(std::ostream &out) const { void TextNode:: write(std::ostream &out, int indent_level) const { PandaNode::write(out, indent_level); - MutexHolder holder(_lock); + + CDReader cdata(_cycler); TextProperties::write(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) - << "in coordinate system " << _coordinate_system << "\n"; + << "in coordinate system " << cdata->_coordinate_system << "\n"; 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:: 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:: apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, 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(); + Thread *current_thread = Thread::get_current_thread(); + OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) { + CDStageWriter cdata(_cycler, pipeline_stage, current_thread); + + if ((attrib_types & SceneGraphReducer::TT_transform) != 0) { + const LMatrix4 &mat = attribs._transform->get_mat(); + cdata->_transform *= mat; + + 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_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); - - _frame_color.componentwise_mult(s); - _card_color.componentwise_mult(s); - - invalidate_no_measure(); + 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); - // 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); + 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 ((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. 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); - 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]); + 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]); } gbv->around(vertices, vertices + 8); @@ -542,21 +576,19 @@ r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, * text instead. */ 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 * bounding boxes properly without actually assembling it. */ void TextNode:: -do_measure() { +do_measure(CData *cdata) { // We no longer make this a special case. - do_rebuild(); + do_rebuild(cdata); } /** @@ -565,14 +597,12 @@ do_measure() { * represent it. */ PT(PandaNode) TextNode:: -do_generate() { - nassertr(_lock.debug_is_locked(), nullptr); - +do_generate(CData *cdata) { PStatTimer timer(_text_generate_pcollector); if (text_cat.is_debug()) { text_cat.debug() << "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, @@ -584,18 +614,18 @@ do_generate() { // row, that moves the row into the right place horizontally and vertically, // 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. - string name = get_text(); + string name = cdata->_text; size_t newline = name.find('\n'); if (newline != string::npos) { name = name.substr(0, newline); } PT(PandaNode) root = new PandaNode(name); - if (!has_text()) { + if (cdata->_wtext.empty()) { return root; } @@ -607,34 +637,32 @@ do_generate() { // 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. 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); root->set_transform(transform); - std::wstring wtext = get_wtext(); - // Assemble the text. TextAssembler assembler(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) { // No overflow. - _flags &= ~F_has_overflow; + cdata->_flags &= ~F_has_overflow; } else { // Overflow. - _flags |= F_has_overflow; + cdata->_flags |= F_has_overflow; } 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. PT(PandaNode) text = new PandaNode("text"); @@ -645,43 +673,45 @@ do_generate() { // the user. const LVector2 &ul = assembler.get_ul(); 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. - _flags &= ~F_needs_measure; + cdata->_flags &= ~F_needs_measure; // Now flatten our hierarchy to get rid of the transforms we put in, // applying them to the vertices. NodePath root_np(root); - if (_flatten_flags & FF_strong) { + if (cdata->_flatten_flags & FF_strong) { root_np.flatten_strong(); - } else if (_flatten_flags & FF_medium) { + } + else if (cdata->_flatten_flags & FF_medium) { root_np.flatten_medium(); - } else if (_flatten_flags & FF_light) { + } + else if (cdata->_flatten_flags & FF_light) { root_np.flatten_light(); } // Now deal with the decorations. - if (_flags & F_has_card) { + if (cdata->_flags & F_has_card) { 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 { - card_root = make_card(); + card_root = do_make_card(cdata); } 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)); } - 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()) { @@ -697,17 +727,17 @@ do_generate() { card_root->add_child(root); root = card_root; - if (_flags & F_card_decal) { + if (cdata->_flags & F_card_decal) { 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); 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)); } @@ -728,38 +758,46 @@ do_generate() { */ PT(PandaNode) TextNode:: 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. */ 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"); - 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); PT(GeomVertexData) vdata = new GeomVertexData - ("text", GeomVertexFormat::get_v3(), _usage_hint); + ("text", GeomVertexFormat::get_v3(), cdata->_usage_hint); vdata->unclean_set_num_rows(4); 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, top); - PT(GeomLinestrips) frame = new GeomLinestrips(_usage_hint); + PT(GeomLinestrips) frame = new GeomLinestrips(cdata->_usage_hint); frame->add_consecutive_vertices(0, 4); frame->add_vertex(0); frame->close_primitive(); @@ -777,8 +815,8 @@ make_frame() { geom->add_primitive(frame); 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); PT(Geom) geom2 = new Geom(vdata); geom2->add_primitive(corners); @@ -792,26 +830,25 @@ make_frame() { * Creates a card behind the text. */ 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"); - 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 - ("text", GeomVertexFormat::get_v3t2(), _usage_hint); + ("text", GeomVertexFormat::get_v3t2(), cdata->_usage_hint); vdata->unclean_set_num_rows(4); GeomVertexWriter vertex(vdata, InternalName::get_vertex()); GeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); @@ -826,7 +863,7 @@ make_card() { texcoord.set_data2(1.0f, 1.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->close_primitive(); @@ -844,83 +881,88 @@ make_card() { * what have you. */ 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"); - 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 - ("text", GeomVertexFormat::get_v3t2(), _usage_hint); + ("text", GeomVertexFormat::get_v3t2(), cdata->_usage_hint); vdata->unclean_set_num_rows(16); GeomVertexWriter vertex(vdata, InternalName::get_vertex()); GeomVertexWriter texcoord(vdata, InternalName::get_texcoord()); // verts 1,2,3,4 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 - 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 - _card_border_size); + vertex.set_data3(right, 0.02, top - border_size); // 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 + _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 - 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); 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 - _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(_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 - PT(GeomTristrips) card = new GeomTristrips(_usage_hint); + PT(GeomTristrips) card = new GeomTristrips(cdata->_usage_hint); card->reserve_num_vertices(24); // tristrip #1 @@ -970,3 +1012,69 @@ count_geoms(PandaNode *node) { 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); +} diff --git a/panda/src/text/textNode.h b/panda/src/text/textNode.h index 02e1cb51c7..3ace43895e 100644 --- a/panda/src/text/textNode.h +++ b/panda/src/text/textNode.h @@ -24,8 +24,12 @@ #include "pandaNode.h" #include "luse.h" #include "geom.h" -#include "pmutex.h" -#include "mutexHolder.h" +#include "cycleData.h" +#include "cycleDataLockedReader.h" +#include "cycleDataReader.h" +#include "cycleDataWriter.h" +#include "cycleDataStageReader.h" +#include "cycleDataStageWriter.h" /** * The primary interface to this module. This class does basic text assembly; @@ -99,7 +103,7 @@ PUBLISHED: INLINE bool has_frame() const; INLINE bool is_frame_as_margin() const; INLINE LVecBase4 get_frame_as_set() const; - INLINE LVecBase4 get_frame_actual() const; + LVecBase4 get_frame_actual() const; INLINE void set_frame_line_width(PN_stdfloat line_width); INLINE PN_stdfloat get_frame_line_width() const; @@ -116,7 +120,7 @@ PUBLISHED: INLINE bool get_card_decal() const; INLINE bool is_card_as_margin() const; INLINE LVecBase4 get_card_as_set() const; - INLINE LVecBase4 get_card_actual() const; + LVecBase4 get_card_actual() const; INLINE LVecBase4 get_card_transformed() const; INLINE void set_transform(const LMatrix4 &transform); @@ -295,30 +299,25 @@ public: Thread *current_thread); private: - INLINE void invalidate_no_measure(); - INLINE void invalidate_with_measure(); - INLINE void check_rebuild() const; - INLINE void check_measure() const; + class CData; - void do_rebuild(); - void do_measure(); + INLINE void invalidate_no_measure(CData *cdata); + INLINE void invalidate_with_measure(CData *cdata); + INLINE bool do_needs_rebuild(const CData *cdata) const; + INLINE bool do_needs_measure(const CData *cdata) const; - PT(PandaNode) do_generate(); + void do_rebuild(CData *cdata); + void do_measure(CData *cdata); + + PT(PandaNode) do_generate(CData *cdata); PT(PandaNode) do_get_internal_geom() const; - PT(PandaNode) make_frame(); - PT(PandaNode) make_card(); - PT(PandaNode) make_card_with_border(); + PT(PandaNode) do_make_frame(const CData *cdata); + PT(PandaNode) do_make_card(const CData *cdata); + PT(PandaNode) do_make_card_with_border(const CData *cdata); static int count_geoms(PandaNode *node); - Mutex _lock; - PT(PandaNode) _internal_geom; - - PT(Texture) _card_texture; - LColor _frame_color; - LColor _card_color; - enum Flags { F_has_frame = 0x0001, F_frame_as_margin = 0x0002, @@ -334,26 +333,54 @@ private: F_card_decal = 0x0800, }; - int _flags; - int _max_rows; - GeomEnums::UsageHint _usage_hint; - int _flatten_flags; - PN_stdfloat _frame_width; - PN_stdfloat _card_border_size; - PN_stdfloat _card_border_uv_portion; + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA_TEXT CData : public CycleData { + public: + CData(); + CData(const CData ©); + virtual CycleData *make_copy() const; + virtual TypeHandle get_parent_type() const { + return TextNode::get_class_type(); + } - LVector2 _frame_ul, _frame_lr; - LVector2 _card_ul, _card_lr; + // We copy these here because they aren't pipeline-cycled on TextEncoder. + std::string _text; + std::wstring _wtext; - LMatrix4 _transform; - CoordinateSystem _coordinate_system; + PT(PandaNode) _internal_geom; - LPoint3 _ul3d, _lr3d; + PT(Texture) _card_texture; + LColor _frame_color; + LColor _card_color; - // Returned from TextAssembler: - LVector2 _text_ul, _text_lr; - int _num_rows; - std::wstring _wordwrapped_wtext; + int _flags; + int _max_rows; + GeomEnums::UsageHint _usage_hint; + int _flatten_flags; + PN_stdfloat _frame_width; + PN_stdfloat _card_border_size; + PN_stdfloat _card_border_uv_portion; + + LVector2 _frame_ul, _frame_lr; + LVector2 _card_ul, _card_lr; + + LMatrix4 _transform; + CoordinateSystem _coordinate_system; + + LPoint3 _ul3d, _lr3d; + + // Returned from TextAssembler: + LVector2 _text_ul, _text_lr; + int _num_rows; + std::wstring _wordwrapped_wtext; + }; + + PipelineCycler _cycler; + typedef CycleDataLockedReader CDLockedReader; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + typedef CycleDataStageReader CDStageReader; + typedef CycleDataStageWriter CDStageWriter; static PStatCollector _text_generate_pcollector;