mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 18:31:55 -04:00
text: add thread safety to TextNode
This does not 100% cover all the base class TextProperties, however, so you still need to be careful not to access those from two threads at once.
This commit is contained in:
parent
5457d76b94
commit
1e084e0b2b
@ -33,6 +33,7 @@ get_line_height() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_max_rows(int max_rows) {
|
set_max_rows(int max_rows) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_max_rows = max_rows;
|
_max_rows = max_rows;
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -43,6 +44,7 @@ set_max_rows(int max_rows) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_max_rows() {
|
clear_max_rows() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_max_rows = 0;
|
_max_rows = 0;
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -53,6 +55,7 @@ clear_max_rows() {
|
|||||||
*/
|
*/
|
||||||
INLINE bool TextNode::
|
INLINE bool TextNode::
|
||||||
has_max_rows() const {
|
has_max_rows() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _max_rows > 0;
|
return _max_rows > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +65,7 @@ has_max_rows() const {
|
|||||||
*/
|
*/
|
||||||
INLINE int TextNode::
|
INLINE int TextNode::
|
||||||
get_max_rows() const {
|
get_max_rows() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _max_rows;
|
return _max_rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +75,7 @@ get_max_rows() const {
|
|||||||
*/
|
*/
|
||||||
INLINE bool TextNode::
|
INLINE bool TextNode::
|
||||||
has_overflow() const {
|
has_overflow() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return (_flags & F_has_overflow) != 0;
|
return (_flags & F_has_overflow) != 0;
|
||||||
}
|
}
|
||||||
@ -88,6 +93,7 @@ set_frame_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_frame_color(const LColor &frame_color) {
|
set_frame_color(const LColor &frame_color) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
if (_frame_color != frame_color) {
|
if (_frame_color != frame_color) {
|
||||||
_frame_color = frame_color;
|
_frame_color = frame_color;
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
@ -99,6 +105,7 @@ set_frame_color(const LColor &frame_color) {
|
|||||||
*/
|
*/
|
||||||
INLINE LColor TextNode::
|
INLINE LColor TextNode::
|
||||||
get_frame_color() const {
|
get_frame_color() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _frame_color;
|
return _frame_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +114,8 @@ get_frame_color() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_card_border(PN_stdfloat size, PN_stdfloat uv_portion) {
|
set_card_border(PN_stdfloat size, PN_stdfloat uv_portion) {
|
||||||
if (!has_card_border() || _card_border_size != size || _card_border_uv_portion != 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;
|
_flags |= F_has_card_border;
|
||||||
_card_border_size = size;
|
_card_border_size = size;
|
||||||
_card_border_uv_portion = uv_portion;
|
_card_border_uv_portion = uv_portion;
|
||||||
@ -120,7 +128,8 @@ set_card_border(PN_stdfloat size, PN_stdfloat uv_portion) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_card_border() {
|
clear_card_border() {
|
||||||
if (has_card_border()) {
|
MutexHolder holder(_lock);
|
||||||
|
if (_flags & F_has_card_border) {
|
||||||
_flags &= ~F_has_card_border;
|
_flags &= ~F_has_card_border;
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -131,6 +140,7 @@ clear_card_border() {
|
|||||||
*/
|
*/
|
||||||
INLINE PN_stdfloat TextNode::
|
INLINE PN_stdfloat TextNode::
|
||||||
get_card_border_size() const {
|
get_card_border_size() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _card_border_size;
|
return _card_border_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +149,7 @@ get_card_border_size() const {
|
|||||||
*/
|
*/
|
||||||
INLINE PN_stdfloat TextNode::
|
INLINE PN_stdfloat TextNode::
|
||||||
get_card_border_uv_portion() const {
|
get_card_border_uv_portion() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _card_border_uv_portion;
|
return _card_border_uv_portion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,6 +158,7 @@ get_card_border_uv_portion() const {
|
|||||||
*/
|
*/
|
||||||
INLINE bool TextNode::
|
INLINE bool TextNode::
|
||||||
has_card_border() const {
|
has_card_border() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return (_flags & F_has_card_border) != 0;
|
return (_flags & F_has_card_border) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,6 +175,7 @@ set_card_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_card_color(const LColor &card_color) {
|
set_card_color(const LColor &card_color) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
if (_card_color != card_color) {
|
if (_card_color != card_color) {
|
||||||
_card_color = card_color;
|
_card_color = card_color;
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
@ -174,6 +187,7 @@ set_card_color(const LColor &card_color) {
|
|||||||
*/
|
*/
|
||||||
INLINE LColor TextNode::
|
INLINE LColor TextNode::
|
||||||
get_card_color() const {
|
get_card_color() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _card_color;
|
return _card_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +199,8 @@ set_card_texture(Texture *card_texture) {
|
|||||||
if (card_texture == nullptr) {
|
if (card_texture == nullptr) {
|
||||||
clear_card_texture();
|
clear_card_texture();
|
||||||
} else {
|
} else {
|
||||||
if (!has_card_texture() || _card_texture != card_texture) {
|
MutexHolder holder(_lock);
|
||||||
|
if ((_flags & F_has_card_texture) == 0 || _card_texture != card_texture) {
|
||||||
_flags |= F_has_card_texture;
|
_flags |= F_has_card_texture;
|
||||||
_card_texture = card_texture;
|
_card_texture = card_texture;
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
@ -198,7 +213,8 @@ set_card_texture(Texture *card_texture) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_card_texture() {
|
clear_card_texture() {
|
||||||
if (has_card_texture()) {
|
MutexHolder holder(_lock);
|
||||||
|
if (_flags & F_has_card_texture) {
|
||||||
_flags &= ~F_has_card_texture;
|
_flags &= ~F_has_card_texture;
|
||||||
_card_texture = nullptr;
|
_card_texture = nullptr;
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
@ -210,6 +226,7 @@ clear_card_texture() {
|
|||||||
*/
|
*/
|
||||||
INLINE bool TextNode::
|
INLINE bool TextNode::
|
||||||
has_card_texture() const {
|
has_card_texture() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return (_flags & F_has_card_texture) != 0;
|
return (_flags & F_has_card_texture) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,6 +235,7 @@ has_card_texture() const {
|
|||||||
*/
|
*/
|
||||||
INLINE Texture *TextNode::
|
INLINE Texture *TextNode::
|
||||||
get_card_texture() const {
|
get_card_texture() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _card_texture;
|
return _card_texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +247,7 @@ get_card_texture() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_frame_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
|
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);
|
_flags |= (F_has_frame | F_frame_as_margin);
|
||||||
_frame_ul.set(left, top);
|
_frame_ul.set(left, top);
|
||||||
_frame_lr.set(right, bottom);
|
_frame_lr.set(right, bottom);
|
||||||
@ -243,6 +262,7 @@ set_frame_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_frame_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
|
set_frame_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_flags |= F_has_frame;
|
_flags |= F_has_frame;
|
||||||
_flags &= ~F_frame_as_margin;
|
_flags &= ~F_frame_as_margin;
|
||||||
_frame_ul.set(left, top);
|
_frame_ul.set(left, top);
|
||||||
@ -255,6 +275,7 @@ set_frame_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_std
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_frame() {
|
clear_frame() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_flags &= ~F_has_frame;
|
_flags &= ~F_has_frame;
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -264,6 +285,7 @@ clear_frame() {
|
|||||||
*/
|
*/
|
||||||
INLINE bool TextNode::
|
INLINE bool TextNode::
|
||||||
has_frame() const {
|
has_frame() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return (_flags & F_has_frame) != 0;
|
return (_flags & F_has_frame) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +298,8 @@ has_frame() const {
|
|||||||
*/
|
*/
|
||||||
INLINE bool TextNode::
|
INLINE bool TextNode::
|
||||||
is_frame_as_margin() const {
|
is_frame_as_margin() const {
|
||||||
nassertr(has_frame(), false);
|
MutexHolder holder(_lock);
|
||||||
|
nassertr((_flags & F_has_frame) != 0, false);
|
||||||
return (_flags & F_frame_as_margin) != 0;
|
return (_flags & F_frame_as_margin) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +311,8 @@ is_frame_as_margin() const {
|
|||||||
*/
|
*/
|
||||||
INLINE LVecBase4 TextNode::
|
INLINE LVecBase4 TextNode::
|
||||||
get_frame_as_set() const {
|
get_frame_as_set() const {
|
||||||
nassertr(has_frame(), LVecBase4(0.0, 0.0, 0.0, 0.0));
|
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]);
|
return LVecBase4(_frame_ul[0], _frame_lr[0], _frame_lr[1], _frame_ul[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,18 +327,20 @@ get_frame_as_set() const {
|
|||||||
*/
|
*/
|
||||||
INLINE LVecBase4 TextNode::
|
INLINE LVecBase4 TextNode::
|
||||||
get_frame_actual() const {
|
get_frame_actual() const {
|
||||||
if (!has_frame()) {
|
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();
|
check_measure();
|
||||||
return LVecBase4(_text_ul[0], _text_lr[0], _text_lr[1], _text_ul[1]);
|
return LVecBase4(_text_ul[0], _text_lr[0], _text_lr[1], _text_ul[1]);
|
||||||
|
|
||||||
} else if (is_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 get_frame_as_set();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,6 +349,7 @@ get_frame_actual() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_frame_line_width(PN_stdfloat frame_width) {
|
set_frame_line_width(PN_stdfloat frame_width) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_frame_width = frame_width;
|
_frame_width = frame_width;
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -332,6 +359,7 @@ set_frame_line_width(PN_stdfloat frame_width) {
|
|||||||
*/
|
*/
|
||||||
INLINE PN_stdfloat TextNode::
|
INLINE PN_stdfloat TextNode::
|
||||||
get_frame_line_width() const {
|
get_frame_line_width() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _frame_width;
|
return _frame_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,6 +370,7 @@ get_frame_line_width() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_frame_corners(bool corners) {
|
set_frame_corners(bool corners) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
if (corners) {
|
if (corners) {
|
||||||
_flags |= F_frame_corners;
|
_flags |= F_frame_corners;
|
||||||
} else {
|
} else {
|
||||||
@ -355,6 +384,7 @@ set_frame_corners(bool corners) {
|
|||||||
*/
|
*/
|
||||||
INLINE bool TextNode::
|
INLINE bool TextNode::
|
||||||
get_frame_corners() const {
|
get_frame_corners() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return (_flags & F_frame_corners) != 0;
|
return (_flags & F_frame_corners) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,6 +396,7 @@ get_frame_corners() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_card_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
|
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);
|
_flags |= (F_has_card | F_card_as_margin);
|
||||||
_card_ul.set(left, top);
|
_card_ul.set(left, top);
|
||||||
_card_lr.set(right, bottom);
|
_card_lr.set(right, bottom);
|
||||||
@ -380,6 +411,7 @@ set_card_as_margin(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_s
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_card_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
|
set_card_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_flags |= F_has_card;
|
_flags |= F_has_card;
|
||||||
_flags &= ~F_card_as_margin;
|
_flags &= ~F_card_as_margin;
|
||||||
_card_ul.set(left, top);
|
_card_ul.set(left, top);
|
||||||
@ -394,6 +426,7 @@ set_card_actual(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdf
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_card_decal(bool card_decal) {
|
set_card_decal(bool card_decal) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
if (card_decal) {
|
if (card_decal) {
|
||||||
_flags |= F_card_decal;
|
_flags |= F_card_decal;
|
||||||
} else {
|
} else {
|
||||||
@ -407,6 +440,7 @@ set_card_decal(bool card_decal) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_card() {
|
clear_card() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_flags &= ~F_has_card;
|
_flags &= ~F_has_card;
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -416,6 +450,7 @@ clear_card() {
|
|||||||
*/
|
*/
|
||||||
INLINE bool TextNode::
|
INLINE bool TextNode::
|
||||||
has_card() const {
|
has_card() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return (_flags & F_has_card) != 0;
|
return (_flags & F_has_card) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,6 +459,7 @@ has_card() const {
|
|||||||
*/
|
*/
|
||||||
INLINE bool TextNode::
|
INLINE bool TextNode::
|
||||||
get_card_decal() const {
|
get_card_decal() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return (_flags & F_card_decal) != 0;
|
return (_flags & F_card_decal) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,7 +472,8 @@ get_card_decal() const {
|
|||||||
*/
|
*/
|
||||||
INLINE bool TextNode::
|
INLINE bool TextNode::
|
||||||
is_card_as_margin() const {
|
is_card_as_margin() const {
|
||||||
nassertr(has_card(), false);
|
MutexHolder holder(_lock);
|
||||||
|
nassertr((_flags & F_has_card) != 0, false);
|
||||||
return (_flags & F_card_as_margin) != 0;
|
return (_flags & F_card_as_margin) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,7 +485,8 @@ is_card_as_margin() const {
|
|||||||
*/
|
*/
|
||||||
INLINE LVecBase4 TextNode::
|
INLINE LVecBase4 TextNode::
|
||||||
get_card_as_set() const {
|
get_card_as_set() const {
|
||||||
nassertr(has_card(), LVecBase4(0.0, 0.0, 0.0, 0.0));
|
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]);
|
return LVecBase4(_card_ul[0], _card_lr[0], _card_lr[1], _card_ul[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,18 +501,20 @@ get_card_as_set() const {
|
|||||||
*/
|
*/
|
||||||
INLINE LVecBase4 TextNode::
|
INLINE LVecBase4 TextNode::
|
||||||
get_card_actual() const {
|
get_card_actual() const {
|
||||||
if (!has_card()) {
|
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();
|
check_measure();
|
||||||
return LVecBase4(_text_ul[0], _text_lr[0], _text_lr[1], _text_ul[1]);
|
return LVecBase4(_text_ul[0], _text_lr[0], _text_lr[1], _text_ul[1]);
|
||||||
|
|
||||||
} else if (is_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 get_card_as_set();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,6 +527,8 @@ get_card_actual() const {
|
|||||||
INLINE LVecBase4 TextNode::
|
INLINE LVecBase4 TextNode::
|
||||||
get_card_transformed() const {
|
get_card_transformed() const {
|
||||||
LVecBase4 card = get_card_actual();
|
LVecBase4 card = get_card_actual();
|
||||||
|
|
||||||
|
MutexHolder holder(_lock);
|
||||||
LPoint3 ul = LPoint3(card[0], 0.0, card[3]) * _transform;
|
LPoint3 ul = LPoint3(card[0], 0.0, card[3]) * _transform;
|
||||||
LPoint3 lr = LPoint3(card[1], 0.0, card[2]) * _transform;
|
LPoint3 lr = LPoint3(card[1], 0.0, card[2]) * _transform;
|
||||||
|
|
||||||
@ -498,6 +540,7 @@ get_card_transformed() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_transform(const LMatrix4 &transform) {
|
set_transform(const LMatrix4 &transform) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_transform = transform;
|
_transform = transform;
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -507,6 +550,7 @@ set_transform(const LMatrix4 &transform) {
|
|||||||
*/
|
*/
|
||||||
INLINE LMatrix4 TextNode::
|
INLINE LMatrix4 TextNode::
|
||||||
get_transform() const {
|
get_transform() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _transform;
|
return _transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,6 +559,7 @@ get_transform() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_coordinate_system(CoordinateSystem coordinate_system) {
|
set_coordinate_system(CoordinateSystem coordinate_system) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_coordinate_system = coordinate_system;
|
_coordinate_system = coordinate_system;
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -524,6 +569,7 @@ set_coordinate_system(CoordinateSystem coordinate_system) {
|
|||||||
*/
|
*/
|
||||||
INLINE CoordinateSystem TextNode::
|
INLINE CoordinateSystem TextNode::
|
||||||
get_coordinate_system() const {
|
get_coordinate_system() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _coordinate_system;
|
return _coordinate_system;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,6 +581,7 @@ get_coordinate_system() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_usage_hint(Geom::UsageHint usage_hint) {
|
set_usage_hint(Geom::UsageHint usage_hint) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_usage_hint = usage_hint;
|
_usage_hint = usage_hint;
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -545,6 +592,7 @@ set_usage_hint(Geom::UsageHint usage_hint) {
|
|||||||
*/
|
*/
|
||||||
INLINE Geom::UsageHint TextNode::
|
INLINE Geom::UsageHint TextNode::
|
||||||
get_usage_hint() const {
|
get_usage_hint() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _usage_hint;
|
return _usage_hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,6 +633,7 @@ get_usage_hint() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_flatten_flags(int flatten_flags) {
|
set_flatten_flags(int flatten_flags) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
_flatten_flags = flatten_flags;
|
_flatten_flags = flatten_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,6 +642,7 @@ set_flatten_flags(int flatten_flags) {
|
|||||||
*/
|
*/
|
||||||
INLINE int TextNode::
|
INLINE int TextNode::
|
||||||
get_flatten_flags() const {
|
get_flatten_flags() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
return _flatten_flags;
|
return _flatten_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -602,6 +652,7 @@ get_flatten_flags() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_font(TextFont *font) {
|
set_font(TextFont *font) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_font(font);
|
TextProperties::set_font(font);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -611,6 +662,7 @@ set_font(TextFont *font) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_font() {
|
clear_font() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_font();
|
TextProperties::clear_font();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -631,6 +683,7 @@ clear_font() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_small_caps(bool small_caps) {
|
set_small_caps(bool small_caps) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_small_caps(small_caps);
|
TextProperties::set_small_caps(small_caps);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -640,6 +693,7 @@ set_small_caps(bool small_caps) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_small_caps() {
|
clear_small_caps() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_small_caps();
|
TextProperties::clear_small_caps();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -651,6 +705,7 @@ clear_small_caps() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_small_caps_scale(PN_stdfloat small_caps_scale) {
|
set_small_caps_scale(PN_stdfloat small_caps_scale) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_small_caps_scale(small_caps_scale);
|
TextProperties::set_small_caps_scale(small_caps_scale);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -660,6 +715,7 @@ set_small_caps_scale(PN_stdfloat small_caps_scale) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_small_caps_scale() {
|
clear_small_caps_scale() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_small_caps_scale();
|
TextProperties::clear_small_caps_scale();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -669,6 +725,7 @@ clear_small_caps_scale() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_slant(PN_stdfloat slant) {
|
set_slant(PN_stdfloat slant) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_slant(slant);
|
TextProperties::set_slant(slant);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -678,6 +735,7 @@ set_slant(PN_stdfloat slant) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_slant() {
|
clear_slant() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_slant();
|
TextProperties::clear_slant();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -687,6 +745,7 @@ clear_slant() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_align(TextNode::Alignment align_type) {
|
set_align(TextNode::Alignment align_type) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_align(align_type);
|
TextProperties::set_align(align_type);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -696,6 +755,7 @@ set_align(TextNode::Alignment align_type) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_align() {
|
clear_align() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_align();
|
TextProperties::clear_align();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -706,6 +766,7 @@ clear_align() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_indent(PN_stdfloat indent) {
|
set_indent(PN_stdfloat indent) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_indent(indent);
|
TextProperties::set_indent(indent);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -715,6 +776,7 @@ set_indent(PN_stdfloat indent) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_indent() {
|
clear_indent() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_indent();
|
TextProperties::clear_indent();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -725,6 +787,7 @@ clear_indent() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_wordwrap(PN_stdfloat wordwrap) {
|
set_wordwrap(PN_stdfloat wordwrap) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_wordwrap(wordwrap);
|
TextProperties::set_wordwrap(wordwrap);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -735,6 +798,7 @@ set_wordwrap(PN_stdfloat wordwrap) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_wordwrap() {
|
clear_wordwrap() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_wordwrap();
|
TextProperties::clear_wordwrap();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -744,6 +808,7 @@ clear_wordwrap() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_text_color(const LColor &text_color) {
|
set_text_color(const LColor &text_color) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_text_color(text_color);
|
TextProperties::set_text_color(text_color);
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -762,6 +827,7 @@ set_text_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_text_color() {
|
clear_text_color() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_text_color();
|
TextProperties::clear_text_color();
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -779,6 +845,7 @@ set_shadow_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b, PN_stdfloat a) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_shadow_color(const LColor &shadow_color) {
|
set_shadow_color(const LColor &shadow_color) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_shadow_color(shadow_color);
|
TextProperties::set_shadow_color(shadow_color);
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -788,6 +855,7 @@ set_shadow_color(const LColor &shadow_color) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_shadow_color() {
|
clear_shadow_color() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_shadow_color();
|
TextProperties::clear_shadow_color();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -807,6 +875,7 @@ set_shadow(PN_stdfloat xoffset, PN_stdfloat yoffset) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_shadow(const LVecBase2 &shadow_offset) {
|
set_shadow(const LVecBase2 &shadow_offset) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_shadow(shadow_offset);
|
TextProperties::set_shadow(shadow_offset);
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -816,6 +885,7 @@ set_shadow(const LVecBase2 &shadow_offset) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_shadow() {
|
clear_shadow() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_shadow();
|
TextProperties::clear_shadow();
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -831,6 +901,7 @@ clear_shadow() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_bin(const std::string &bin) {
|
set_bin(const std::string &bin) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_bin(bin);
|
TextProperties::set_bin(bin);
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -841,6 +912,7 @@ set_bin(const std::string &bin) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_bin() {
|
clear_bin() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_bin();
|
TextProperties::clear_bin();
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
}
|
}
|
||||||
@ -858,6 +930,7 @@ clear_bin() {
|
|||||||
*/
|
*/
|
||||||
INLINE int TextNode::
|
INLINE int TextNode::
|
||||||
set_draw_order(int draw_order) {
|
set_draw_order(int draw_order) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
invalidate_no_measure();
|
invalidate_no_measure();
|
||||||
return TextProperties::set_draw_order(draw_order);
|
return TextProperties::set_draw_order(draw_order);
|
||||||
}
|
}
|
||||||
@ -867,6 +940,7 @@ set_draw_order(int draw_order) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_draw_order() {
|
clear_draw_order() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_draw_order();
|
TextProperties::clear_draw_order();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -877,6 +951,7 @@ clear_draw_order() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_tab_width(PN_stdfloat tab_width) {
|
set_tab_width(PN_stdfloat tab_width) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_tab_width(tab_width);
|
TextProperties::set_tab_width(tab_width);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -886,6 +961,7 @@ set_tab_width(PN_stdfloat tab_width) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_tab_width() {
|
clear_tab_width() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_tab_width();
|
TextProperties::clear_tab_width();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -897,6 +973,7 @@ clear_tab_width() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_glyph_scale(PN_stdfloat glyph_scale) {
|
set_glyph_scale(PN_stdfloat glyph_scale) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_glyph_scale(glyph_scale);
|
TextProperties::set_glyph_scale(glyph_scale);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -906,6 +983,7 @@ set_glyph_scale(PN_stdfloat glyph_scale) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_glyph_scale() {
|
clear_glyph_scale() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_glyph_scale();
|
TextProperties::clear_glyph_scale();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -917,6 +995,7 @@ clear_glyph_scale() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_glyph_shift(PN_stdfloat glyph_shift) {
|
set_glyph_shift(PN_stdfloat glyph_shift) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::set_glyph_shift(glyph_shift);
|
TextProperties::set_glyph_shift(glyph_shift);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -926,6 +1005,7 @@ set_glyph_shift(PN_stdfloat glyph_shift) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_glyph_shift() {
|
clear_glyph_shift() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextProperties::clear_glyph_shift();
|
TextProperties::clear_glyph_shift();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -936,6 +1016,7 @@ clear_glyph_shift() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_text(const std::string &text) {
|
set_text(const std::string &text) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextEncoder::set_text(text);
|
TextEncoder::set_text(text);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -948,6 +1029,7 @@ set_text(const std::string &text) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_text(const std::string &text, TextNode::Encoding encoding) {
|
set_text(const std::string &text, TextNode::Encoding encoding) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextEncoder::set_text(text, encoding);
|
TextEncoder::set_text(text, encoding);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -957,6 +1039,7 @@ set_text(const std::string &text, TextNode::Encoding encoding) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
clear_text() {
|
clear_text() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextEncoder::clear_text();
|
TextEncoder::clear_text();
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -966,6 +1049,7 @@ clear_text() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
append_text(const std::string &text) {
|
append_text(const std::string &text) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextEncoder::append_text(text);
|
TextEncoder::append_text(text);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -976,6 +1060,7 @@ append_text(const std::string &text) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
append_unicode_char(wchar_t character) {
|
append_unicode_char(wchar_t character) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextEncoder::append_unicode_char(character);
|
TextEncoder::append_unicode_char(character);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -1008,6 +1093,7 @@ calc_width(const std::string &line) const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
set_wtext(const std::wstring &wtext) {
|
set_wtext(const std::wstring &wtext) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextEncoder::set_wtext(wtext);
|
TextEncoder::set_wtext(wtext);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -1017,6 +1103,7 @@ set_wtext(const std::wstring &wtext) {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
append_wtext(const std::wstring &wtext) {
|
append_wtext(const std::wstring &wtext) {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
TextEncoder::append_wtext(wtext);
|
TextEncoder::append_wtext(wtext);
|
||||||
invalidate_with_measure();
|
invalidate_with_measure();
|
||||||
}
|
}
|
||||||
@ -1030,6 +1117,7 @@ append_wtext(const std::wstring &wtext) {
|
|||||||
*/
|
*/
|
||||||
INLINE std::wstring TextNode::
|
INLINE std::wstring TextNode::
|
||||||
get_wordwrapped_wtext() const {
|
get_wordwrapped_wtext() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return _wordwrapped_wtext;
|
return _wordwrapped_wtext;
|
||||||
}
|
}
|
||||||
@ -1040,6 +1128,7 @@ get_wordwrapped_wtext() const {
|
|||||||
*/
|
*/
|
||||||
INLINE PN_stdfloat TextNode::
|
INLINE PN_stdfloat TextNode::
|
||||||
get_left() const {
|
get_left() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return _text_ul[0];
|
return _text_ul[0];
|
||||||
}
|
}
|
||||||
@ -1050,6 +1139,7 @@ get_left() const {
|
|||||||
*/
|
*/
|
||||||
INLINE PN_stdfloat TextNode::
|
INLINE PN_stdfloat TextNode::
|
||||||
get_right() const {
|
get_right() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return _text_lr[0];
|
return _text_lr[0];
|
||||||
}
|
}
|
||||||
@ -1060,6 +1150,7 @@ get_right() const {
|
|||||||
*/
|
*/
|
||||||
INLINE PN_stdfloat TextNode::
|
INLINE PN_stdfloat TextNode::
|
||||||
get_bottom() const {
|
get_bottom() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return _text_lr[1];
|
return _text_lr[1];
|
||||||
}
|
}
|
||||||
@ -1070,6 +1161,7 @@ get_bottom() const {
|
|||||||
*/
|
*/
|
||||||
INLINE PN_stdfloat TextNode::
|
INLINE PN_stdfloat TextNode::
|
||||||
get_top() const {
|
get_top() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return _text_ul[1];
|
return _text_ul[1];
|
||||||
}
|
}
|
||||||
@ -1079,6 +1171,7 @@ get_top() const {
|
|||||||
*/
|
*/
|
||||||
INLINE PN_stdfloat TextNode::
|
INLINE PN_stdfloat TextNode::
|
||||||
get_height() const {
|
get_height() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return _text_ul[1] - _text_lr[1];
|
return _text_ul[1] - _text_lr[1];
|
||||||
}
|
}
|
||||||
@ -1088,6 +1181,7 @@ get_height() const {
|
|||||||
*/
|
*/
|
||||||
INLINE PN_stdfloat TextNode::
|
INLINE PN_stdfloat TextNode::
|
||||||
get_width() const {
|
get_width() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return _text_lr[0] - _text_ul[0];
|
return _text_lr[0] - _text_ul[0];
|
||||||
}
|
}
|
||||||
@ -1098,6 +1192,7 @@ get_width() const {
|
|||||||
*/
|
*/
|
||||||
INLINE LPoint3 TextNode::
|
INLINE LPoint3 TextNode::
|
||||||
get_upper_left_3d() const {
|
get_upper_left_3d() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return _ul3d;
|
return _ul3d;
|
||||||
}
|
}
|
||||||
@ -1108,6 +1203,7 @@ get_upper_left_3d() const {
|
|||||||
*/
|
*/
|
||||||
INLINE LPoint3 TextNode::
|
INLINE LPoint3 TextNode::
|
||||||
get_lower_right_3d() const {
|
get_lower_right_3d() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return _lr3d;
|
return _lr3d;
|
||||||
}
|
}
|
||||||
@ -1118,10 +1214,22 @@ get_lower_right_3d() const {
|
|||||||
*/
|
*/
|
||||||
INLINE int TextNode::
|
INLINE int TextNode::
|
||||||
get_num_rows() const {
|
get_num_rows() const {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_measure();
|
check_measure();
|
||||||
return _num_rows;
|
return _num_rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the text, according to the parameters indicated within the
|
||||||
|
* TextNode, and returns a Node that may be parented within the tree to
|
||||||
|
* represent it.
|
||||||
|
*/
|
||||||
|
PT(PandaNode) TextNode::
|
||||||
|
generate() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
|
return do_generate();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can be called after the TextNode has been fully configured, to force the
|
* Can be called after the TextNode has been fully configured, to force the
|
||||||
* node to recompute its text immediately, rather than waiting for it to be
|
* node to recompute its text immediately, rather than waiting for it to be
|
||||||
@ -1129,6 +1237,7 @@ get_num_rows() const {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
update() {
|
update() {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
check_rebuild();
|
check_rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1140,8 +1249,9 @@ update() {
|
|||||||
*/
|
*/
|
||||||
INLINE void TextNode::
|
INLINE void TextNode::
|
||||||
force_update() {
|
force_update() {
|
||||||
invalidate_with_measure();
|
MutexHolder holder(_lock);
|
||||||
check_rebuild();
|
mark_internal_bounds_stale();
|
||||||
|
do_rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,7 +74,7 @@ TextNode(const string &name) : PandaNode(name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (text_small_caps) {
|
if (text_small_caps) {
|
||||||
set_small_caps(true);
|
TextProperties::set_small_caps(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
_frame_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
@ -277,10 +277,10 @@ void TextNode::
|
|||||||
output(std::ostream &out) const {
|
output(std::ostream &out) const {
|
||||||
PandaNode::output(out);
|
PandaNode::output(out);
|
||||||
|
|
||||||
check_rebuild();
|
PT(PandaNode) internal_geom = do_get_internal_geom();
|
||||||
int geom_count = 0;
|
int geom_count = 0;
|
||||||
if (_internal_geom != nullptr) {
|
if (internal_geom != nullptr) {
|
||||||
geom_count = count_geoms(_internal_geom);
|
geom_count = count_geoms(internal_geom);
|
||||||
}
|
}
|
||||||
|
|
||||||
out << " (" << geom_count << " geoms)";
|
out << " (" << geom_count << " geoms)";
|
||||||
@ -291,6 +291,7 @@ 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 {
|
||||||
|
MutexHolder holder(_lock);
|
||||||
PandaNode::write(out, indent_level);
|
PandaNode::write(out, indent_level);
|
||||||
TextProperties::write(out, indent_level + 2);
|
TextProperties::write(out, indent_level + 2);
|
||||||
indent(out, indent_level + 2)
|
indent(out, indent_level + 2)
|
||||||
@ -301,13 +302,263 @@ write(std::ostream &out, int indent_level) const {
|
|||||||
<< "text is " << get_text() << "\n";
|
<< "text is " << get_text() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the actual node that is used internally to render the text, if the
|
||||||
|
* TextNode is parented within the scene graph.
|
||||||
|
*
|
||||||
|
* In general, you should not call this method. Call generate() instead if
|
||||||
|
* you want to get a handle to geometry that represents the text. This method
|
||||||
|
* is provided as a debugging aid only.
|
||||||
|
*/
|
||||||
|
PT(PandaNode) TextNode::
|
||||||
|
get_internal_geom() const {
|
||||||
|
// Output a nuisance warning to discourage the naive from calling this
|
||||||
|
// method accidentally.
|
||||||
|
text_cat.info()
|
||||||
|
<< "TextNode::get_internal_geom() called.\n";
|
||||||
|
return do_get_internal_geom();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the union of all attributes from SceneGraphReducer::AttribTypes
|
||||||
|
* that may not safely be applied to the vertices of this node. If this is
|
||||||
|
* nonzero, these attributes must be dropped at this node as a state change.
|
||||||
|
*
|
||||||
|
* This is a generalization of safe_to_transform().
|
||||||
|
*/
|
||||||
|
int TextNode::
|
||||||
|
get_unsafe_to_apply_attribs() const {
|
||||||
|
// We have no way to apply these kinds of attributes to our TextNode, so
|
||||||
|
// insist they get dropped into the PandaNode's basic state.
|
||||||
|
return
|
||||||
|
SceneGraphReducer::TT_tex_matrix |
|
||||||
|
SceneGraphReducer::TT_other;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies whatever attributes are specified in the AccumulatedAttribs object
|
||||||
|
* (and by the attrib_types bitmask) to the vertices on this node, if
|
||||||
|
* appropriate. If this node uses geom arrays like a GeomNode, the supplied
|
||||||
|
* GeomTransformer may be used to unify shared arrays across multiple
|
||||||
|
* different nodes.
|
||||||
|
*
|
||||||
|
* This is a generalization of xform().
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used to support NodePath::calc_tight_bounds(). It is not intended
|
||||||
|
* to be called directly, and it has nothing to do with the normal Panda
|
||||||
|
* bounding-volume computation.
|
||||||
|
*
|
||||||
|
* If the node contains any geometry, this updates min_point and max_point to
|
||||||
|
* enclose its bounding box. found_any is to be set true if the node has any
|
||||||
|
* geometry at all, or left alone if it has none. This method may be called
|
||||||
|
* over several nodes, so it may enter with min_point, max_point, and
|
||||||
|
* found_any already set.
|
||||||
|
*/
|
||||||
|
CPT(TransformState) TextNode::
|
||||||
|
calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
|
||||||
|
const TransformState *transform, Thread *current_thread) const {
|
||||||
|
CPT(TransformState) next_transform =
|
||||||
|
PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
|
||||||
|
current_thread);
|
||||||
|
|
||||||
|
PT(PandaNode) geom = do_get_internal_geom();
|
||||||
|
if (geom != nullptr) {
|
||||||
|
geom->calc_tight_bounds(min_point, max_point,
|
||||||
|
found_any, next_transform, current_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
return next_transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function will be called during the cull traversal to perform any
|
||||||
|
* additional operations that should be performed at cull time. This may
|
||||||
|
* include additional manipulation of render state or additional
|
||||||
|
* visible/invisible decisions, or any other arbitrary operation.
|
||||||
|
*
|
||||||
|
* Note that this function will *not* be called unless set_cull_callback() is
|
||||||
|
* called in the constructor of the derived class. It is necessary to call
|
||||||
|
* set_cull_callback() to indicated that we require cull_callback() to be
|
||||||
|
* called.
|
||||||
|
*
|
||||||
|
* By the time this function is called, the node has already passed the
|
||||||
|
* bounding-volume test for the viewing frustum, and the node's transform and
|
||||||
|
* state have already been applied to the indicated CullTraverserData object.
|
||||||
|
*
|
||||||
|
* The return value is true if this node should be visible, or false if it
|
||||||
|
* should be culled.
|
||||||
|
*/
|
||||||
|
bool TextNode::
|
||||||
|
cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
||||||
|
|
||||||
|
PT(PandaNode) internal_geom = do_get_internal_geom();
|
||||||
|
if (internal_geom != nullptr) {
|
||||||
|
// Render the text with this node.
|
||||||
|
CullTraverserData next_data(data, internal_geom);
|
||||||
|
trav->traverse(next_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now continue to render everything else below this node.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there is some value to visiting this particular node during
|
||||||
|
* the cull traversal for any camera, false otherwise. This will be used to
|
||||||
|
* optimize the result of get_net_draw_show_mask(), so that any subtrees that
|
||||||
|
* contain only nodes for which is_renderable() is false need not be visited.
|
||||||
|
*/
|
||||||
|
bool TextNode::
|
||||||
|
is_renderable() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when needed to recompute the node's _internal_bound object. Nodes
|
||||||
|
* that contain anything of substance should redefine this to do the right
|
||||||
|
* thing.
|
||||||
|
*/
|
||||||
|
void TextNode::
|
||||||
|
compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
|
||||||
|
int &internal_vertices,
|
||||||
|
int pipeline_stage,
|
||||||
|
Thread *current_thread) const {
|
||||||
|
// First, get ourselves a fresh, empty bounding volume.
|
||||||
|
PT(BoundingVolume) bound = new BoundingSphere;
|
||||||
|
|
||||||
|
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
|
||||||
|
|
||||||
|
// Now enclose the bounding box around the text. We can do this without
|
||||||
|
// actually generating the text, if we have at least measured it.
|
||||||
|
LPoint3 vertices[8];
|
||||||
|
{
|
||||||
|
MutexHolder holder(_lock);
|
||||||
|
check_measure();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
internal_bounds = bound;
|
||||||
|
internal_vertices = 0; // TODO: estimate this better.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The recursive implementation of prepare_scene(). Don't call this directly;
|
||||||
|
* call PandaNode::prepare_scene() or NodePath::prepare_scene() instead.
|
||||||
|
*/
|
||||||
|
void TextNode::
|
||||||
|
r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
|
||||||
|
GeomTransformer &transformer, Thread *current_thread) {
|
||||||
|
|
||||||
|
PT(PandaNode) child = do_get_internal_geom();
|
||||||
|
if (child != nullptr) {
|
||||||
|
CPT(RenderState) child_state = node_state->compose(child->get_state());
|
||||||
|
child->r_prepare_scene(gsg, child_state, transformer, current_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes any existing children of the TextNode, and adds the newly generated
|
||||||
|
* text instead.
|
||||||
|
*/
|
||||||
|
void TextNode::
|
||||||
|
do_rebuild() {
|
||||||
|
nassertv(_lock.debug_is_locked());
|
||||||
|
_flags &= ~(F_needs_rebuild | F_needs_measure);
|
||||||
|
_internal_geom = do_generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {
|
||||||
|
// We no longer make this a special case.
|
||||||
|
do_rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the text, according to the parameters indicated within the
|
* Generates the text, according to the parameters indicated within the
|
||||||
* TextNode, and returns a Node that may be parented within the tree to
|
* TextNode, and returns a Node that may be parented within the tree to
|
||||||
* represent it.
|
* represent it.
|
||||||
*/
|
*/
|
||||||
PT(PandaNode) TextNode::
|
PT(PandaNode) TextNode::
|
||||||
generate() {
|
do_generate() {
|
||||||
|
nassertr(_lock.debug_is_locked(), nullptr);
|
||||||
|
|
||||||
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()
|
||||||
@ -408,20 +659,20 @@ generate() {
|
|||||||
|
|
||||||
// Now deal with the decorations.
|
// Now deal with the decorations.
|
||||||
|
|
||||||
if (has_card()) {
|
if (_flags & F_has_card) {
|
||||||
PT(PandaNode) card_root;
|
PT(PandaNode) card_root;
|
||||||
if (has_card_border()) {
|
if (_flags & F_has_card_border) {
|
||||||
card_root = make_card_with_border();
|
card_root = make_card_with_border();
|
||||||
} else {
|
} else {
|
||||||
card_root = make_card();
|
card_root = make_card();
|
||||||
}
|
}
|
||||||
card_root->set_transform(transform);
|
card_root->set_transform(transform);
|
||||||
card_root->set_attrib(ColorAttrib::make_flat(get_card_color()));
|
card_root->set_attrib(ColorAttrib::make_flat(_card_color));
|
||||||
if (get_card_color()[3] != 1.0f) {
|
if (_card_color[3] != 1.0f) {
|
||||||
card_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
card_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
||||||
}
|
}
|
||||||
if (has_card_texture()) {
|
if (_flags & F_has_card_texture) {
|
||||||
card_root->set_attrib(TextureAttrib::make(get_card_texture()));
|
card_root->set_attrib(TextureAttrib::make(_card_texture));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_bin()) {
|
if (has_bin()) {
|
||||||
@ -437,17 +688,17 @@ generate() {
|
|||||||
card_root->add_child(root);
|
card_root->add_child(root);
|
||||||
root = card_root;
|
root = card_root;
|
||||||
|
|
||||||
if (get_card_decal()) {
|
if (_flags & F_card_decal) {
|
||||||
card_root->set_effect(DecalEffect::make());
|
card_root->set_effect(DecalEffect::make());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_frame()) {
|
if (_flags & F_has_frame) {
|
||||||
PT(PandaNode) frame_root = make_frame();
|
PT(PandaNode) frame_root = make_frame();
|
||||||
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(get_frame_color()));
|
frame_root->set_attrib(ColorAttrib::make_flat(_frame_color));
|
||||||
if (get_frame_color()[3] != 1.0f) {
|
if (_frame_color[3] != 1.0f) {
|
||||||
frame_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
frame_root->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,271 +716,35 @@ generate() {
|
|||||||
/**
|
/**
|
||||||
* Returns the actual node that is used internally to render the text, if the
|
* Returns the actual node that is used internally to render the text, if the
|
||||||
* TextNode is parented within the scene graph.
|
* TextNode is parented within the scene graph.
|
||||||
*
|
|
||||||
* In general, you should not call this method. Call generate() instead if
|
|
||||||
* you want to get a handle to geometry that represents the text. This method
|
|
||||||
* is provided as a debugging aid only.
|
|
||||||
*/
|
*/
|
||||||
PandaNode *TextNode::
|
PT(PandaNode) TextNode::
|
||||||
get_internal_geom() const {
|
do_get_internal_geom() const {
|
||||||
// Output a nuisance warning to discourage the naive from calling this
|
MutexHolder holder(_lock);
|
||||||
// method accidentally.
|
|
||||||
text_cat.info()
|
|
||||||
<< "TextNode::get_internal_geom() called.\n";
|
|
||||||
check_rebuild();
|
check_rebuild();
|
||||||
return _internal_geom;
|
return _internal_geom;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the union of all attributes from SceneGraphReducer::AttribTypes
|
|
||||||
* that may not safely be applied to the vertices of this node. If this is
|
|
||||||
* nonzero, these attributes must be dropped at this node as a state change.
|
|
||||||
*
|
|
||||||
* This is a generalization of safe_to_transform().
|
|
||||||
*/
|
|
||||||
int TextNode::
|
|
||||||
get_unsafe_to_apply_attribs() const {
|
|
||||||
// We have no way to apply these kinds of attributes to our TextNode, so
|
|
||||||
// insist they get dropped into the PandaNode's basic state.
|
|
||||||
return
|
|
||||||
SceneGraphReducer::TT_tex_matrix |
|
|
||||||
SceneGraphReducer::TT_other;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies whatever attributes are specified in the AccumulatedAttribs object
|
|
||||||
* (and by the attrib_types bitmask) to the vertices on this node, if
|
|
||||||
* appropriate. If this node uses geom arrays like a GeomNode, the supplied
|
|
||||||
* GeomTransformer may be used to unify shared arrays across multiple
|
|
||||||
* different nodes.
|
|
||||||
*
|
|
||||||
* This is a generalization of xform().
|
|
||||||
*/
|
|
||||||
void TextNode::
|
|
||||||
apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
|
||||||
GeomTransformer &transformer) {
|
|
||||||
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();
|
|
||||||
set_text_color(c);
|
|
||||||
set_frame_color(c);
|
|
||||||
set_card_color(c);
|
|
||||||
set_shadow_color(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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[0] *= s[0];
|
|
||||||
tc[1] *= s[1];
|
|
||||||
tc[2] *= s[2];
|
|
||||||
tc[3] *= s[3];
|
|
||||||
set_text_color(tc);
|
|
||||||
LVecBase4 sc = get_shadow_color();
|
|
||||||
sc[0] *= s[0];
|
|
||||||
sc[1] *= s[1];
|
|
||||||
sc[2] *= s[2];
|
|
||||||
sc[3] *= s[3];
|
|
||||||
set_shadow_color(sc);
|
|
||||||
LVecBase4 fc = get_frame_color();
|
|
||||||
fc[0] *= s[0];
|
|
||||||
fc[1] *= s[1];
|
|
||||||
fc[2] *= s[2];
|
|
||||||
fc[3] *= s[3];
|
|
||||||
set_frame_color(fc);
|
|
||||||
LVecBase4 cc = get_card_color();
|
|
||||||
cc[0] *= s[0];
|
|
||||||
cc[1] *= s[1];
|
|
||||||
cc[2] *= s[2];
|
|
||||||
cc[3] *= s[3];
|
|
||||||
set_card_color(cc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is used to support NodePath::calc_tight_bounds(). It is not intended
|
|
||||||
* to be called directly, and it has nothing to do with the normal Panda
|
|
||||||
* bounding-volume computation.
|
|
||||||
*
|
|
||||||
* If the node contains any geometry, this updates min_point and max_point to
|
|
||||||
* enclose its bounding box. found_any is to be set true if the node has any
|
|
||||||
* geometry at all, or left alone if it has none. This method may be called
|
|
||||||
* over several nodes, so it may enter with min_point, max_point, and
|
|
||||||
* found_any already set.
|
|
||||||
*/
|
|
||||||
CPT(TransformState) TextNode::
|
|
||||||
calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
|
|
||||||
const TransformState *transform, Thread *current_thread) const {
|
|
||||||
CPT(TransformState) next_transform =
|
|
||||||
PandaNode::calc_tight_bounds(min_point, max_point, found_any, transform,
|
|
||||||
current_thread);
|
|
||||||
|
|
||||||
check_rebuild();
|
|
||||||
|
|
||||||
if (_internal_geom != nullptr) {
|
|
||||||
_internal_geom->calc_tight_bounds(min_point, max_point,
|
|
||||||
found_any, next_transform, current_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
return next_transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function will be called during the cull traversal to perform any
|
|
||||||
* additional operations that should be performed at cull time. This may
|
|
||||||
* include additional manipulation of render state or additional
|
|
||||||
* visible/invisible decisions, or any other arbitrary operation.
|
|
||||||
*
|
|
||||||
* Note that this function will *not* be called unless set_cull_callback() is
|
|
||||||
* called in the constructor of the derived class. It is necessary to call
|
|
||||||
* set_cull_callback() to indicated that we require cull_callback() to be
|
|
||||||
* called.
|
|
||||||
*
|
|
||||||
* By the time this function is called, the node has already passed the
|
|
||||||
* bounding-volume test for the viewing frustum, and the node's transform and
|
|
||||||
* state have already been applied to the indicated CullTraverserData object.
|
|
||||||
*
|
|
||||||
* The return value is true if this node should be visible, or false if it
|
|
||||||
* should be culled.
|
|
||||||
*/
|
|
||||||
bool TextNode::
|
|
||||||
cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
|
||||||
check_rebuild();
|
|
||||||
if (_internal_geom != nullptr) {
|
|
||||||
// Render the text with this node.
|
|
||||||
CullTraverserData next_data(data, _internal_geom);
|
|
||||||
trav->traverse(next_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now continue to render everything else below this node.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if there is some value to visiting this particular node during
|
|
||||||
* the cull traversal for any camera, false otherwise. This will be used to
|
|
||||||
* optimize the result of get_net_draw_show_mask(), so that any subtrees that
|
|
||||||
* contain only nodes for which is_renderable() is false need not be visited.
|
|
||||||
*/
|
|
||||||
bool TextNode::
|
|
||||||
is_renderable() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when needed to recompute the node's _internal_bound object. Nodes
|
|
||||||
* that contain anything of substance should redefine this to do the right
|
|
||||||
* thing.
|
|
||||||
*/
|
|
||||||
void TextNode::
|
|
||||||
compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
|
|
||||||
int &internal_vertices,
|
|
||||||
int pipeline_stage,
|
|
||||||
Thread *current_thread) const {
|
|
||||||
// First, get ourselves a fresh, empty bounding volume.
|
|
||||||
PT(BoundingVolume) bound = new BoundingSphere;
|
|
||||||
|
|
||||||
GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
|
|
||||||
|
|
||||||
// Now enclose the bounding box around the text. We can do this without
|
|
||||||
// actually generating the text, if we have at least measured it.
|
|
||||||
check_measure();
|
|
||||||
|
|
||||||
LPoint3 vertices[8];
|
|
||||||
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);
|
|
||||||
|
|
||||||
internal_bounds = bound;
|
|
||||||
internal_vertices = 0; // TODO: estimate this better.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The recursive implementation of prepare_scene(). Don't call this directly;
|
|
||||||
* call PandaNode::prepare_scene() or NodePath::prepare_scene() instead.
|
|
||||||
*/
|
|
||||||
void TextNode::
|
|
||||||
r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
|
|
||||||
GeomTransformer &transformer, Thread *current_thread) {
|
|
||||||
check_rebuild();
|
|
||||||
|
|
||||||
PandaNode *child = _internal_geom;
|
|
||||||
if (child != nullptr) {
|
|
||||||
CPT(RenderState) child_state = node_state->compose(child->get_state());
|
|
||||||
child->r_prepare_scene(gsg, child_state, transformer, current_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes any existing children of the TextNode, and adds the newly generated
|
|
||||||
* text instead.
|
|
||||||
*/
|
|
||||||
void TextNode::
|
|
||||||
do_rebuild() {
|
|
||||||
_flags &= ~(F_needs_rebuild | F_needs_measure);
|
|
||||||
_internal_geom = generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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() {
|
|
||||||
// We no longer make this a special case.
|
|
||||||
do_rebuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a frame around the text.
|
* Creates a frame around the text.
|
||||||
*/
|
*/
|
||||||
PT(PandaNode) TextNode::
|
PT(PandaNode) TextNode::
|
||||||
make_frame() {
|
make_frame() {
|
||||||
|
nassertr(_lock.debug_is_locked(), nullptr);
|
||||||
|
nassertr((_flags & F_needs_measure) == 0, nullptr);
|
||||||
|
|
||||||
PT(GeomNode) frame_node = new GeomNode("frame");
|
PT(GeomNode) frame_node = new GeomNode("frame");
|
||||||
|
|
||||||
LVector4 dimensions = get_frame_actual();
|
PN_stdfloat left = _frame_ul[0];
|
||||||
PN_stdfloat left = dimensions[0];
|
PN_stdfloat right = _frame_lr[0];
|
||||||
PN_stdfloat right = dimensions[1];
|
PN_stdfloat bottom = _frame_lr[1];
|
||||||
PN_stdfloat bottom = dimensions[2];
|
PN_stdfloat top = _frame_ul[1];
|
||||||
PN_stdfloat top = dimensions[3];
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, _frame_width);
|
CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, _frame_width);
|
||||||
CPT(RenderState) state = RenderState::make(thick);
|
CPT(RenderState) state = RenderState::make(thick);
|
||||||
@ -753,8 +768,8 @@ make_frame() {
|
|||||||
geom->add_primitive(frame);
|
geom->add_primitive(frame);
|
||||||
frame_node->add_geom(geom, state);
|
frame_node->add_geom(geom, state);
|
||||||
|
|
||||||
if (get_frame_corners()) {
|
if (_flags & F_frame_corners) {
|
||||||
PT(GeomPoints) corners = new GeomPoints(get_usage_hint());
|
PT(GeomPoints) corners = new GeomPoints(_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);
|
||||||
@ -769,13 +784,22 @@ make_frame() {
|
|||||||
*/
|
*/
|
||||||
PT(PandaNode) TextNode::
|
PT(PandaNode) TextNode::
|
||||||
make_card() {
|
make_card() {
|
||||||
|
nassertr(_lock.debug_is_locked(), nullptr);
|
||||||
|
nassertr((_flags & F_needs_measure) == 0, nullptr);
|
||||||
|
|
||||||
PT(GeomNode) card_node = new GeomNode("card");
|
PT(GeomNode) card_node = new GeomNode("card");
|
||||||
|
|
||||||
LVector4 dimensions = get_card_actual();
|
PN_stdfloat left = _card_ul[0];
|
||||||
PN_stdfloat left = dimensions[0];
|
PN_stdfloat right = _card_lr[0];
|
||||||
PN_stdfloat right = dimensions[1];
|
PN_stdfloat bottom = _card_lr[1];
|
||||||
PN_stdfloat bottom = dimensions[2];
|
PN_stdfloat top = _card_ul[1];
|
||||||
PN_stdfloat top = dimensions[3];
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
PT(GeomVertexData) vdata = new GeomVertexData
|
PT(GeomVertexData) vdata = new GeomVertexData
|
||||||
("text", GeomVertexFormat::get_v3t2(), _usage_hint);
|
("text", GeomVertexFormat::get_v3t2(), _usage_hint);
|
||||||
@ -793,7 +817,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(get_usage_hint());
|
PT(GeomTristrips) card = new GeomTristrips(_usage_hint);
|
||||||
card->add_consecutive_vertices(0, 4);
|
card->add_consecutive_vertices(0, 4);
|
||||||
card->close_primitive();
|
card->close_primitive();
|
||||||
|
|
||||||
@ -812,13 +836,22 @@ make_card() {
|
|||||||
*/
|
*/
|
||||||
PT(PandaNode) TextNode::
|
PT(PandaNode) TextNode::
|
||||||
make_card_with_border() {
|
make_card_with_border() {
|
||||||
|
nassertr(_lock.debug_is_locked(), nullptr);
|
||||||
|
nassertr((_flags & F_needs_measure) == 0, nullptr);
|
||||||
|
|
||||||
PT(GeomNode) card_node = new GeomNode("card");
|
PT(GeomNode) card_node = new GeomNode("card");
|
||||||
|
|
||||||
LVector4 dimensions = get_card_actual();
|
PN_stdfloat left = _card_ul[0];
|
||||||
PN_stdfloat left = dimensions[0];
|
PN_stdfloat right = _card_lr[0];
|
||||||
PN_stdfloat right = dimensions[1];
|
PN_stdfloat bottom = _card_lr[1];
|
||||||
PN_stdfloat bottom = dimensions[2];
|
PN_stdfloat top = _card_ul[1];
|
||||||
PN_stdfloat top = dimensions[3];
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we now create three tri-strips instead of one with vertices arranged as
|
* we now create three tri-strips instead of one with vertices arranged as
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include "pandaNode.h"
|
#include "pandaNode.h"
|
||||||
#include "luse.h"
|
#include "luse.h"
|
||||||
#include "geom.h"
|
#include "geom.h"
|
||||||
|
#include "pmutex.h"
|
||||||
|
#include "mutexHolder.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The primary interface to this module. This class does basic text assembly;
|
* The primary interface to this module. This class does basic text assembly;
|
||||||
@ -225,11 +227,11 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE int get_num_rows() const;
|
INLINE int get_num_rows() const;
|
||||||
|
|
||||||
PT(PandaNode) generate();
|
INLINE PT(PandaNode) generate();
|
||||||
INLINE void update();
|
INLINE void update();
|
||||||
INLINE void force_update();
|
INLINE void force_update();
|
||||||
|
|
||||||
PandaNode *get_internal_geom() const;
|
PT(PandaNode) get_internal_geom() const;
|
||||||
|
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
MAKE_PROPERTY(max_rows, get_max_rows, set_max_rows);
|
MAKE_PROPERTY(max_rows, get_max_rows, set_max_rows);
|
||||||
@ -312,12 +314,16 @@ private:
|
|||||||
void do_rebuild();
|
void do_rebuild();
|
||||||
void do_measure();
|
void do_measure();
|
||||||
|
|
||||||
|
PT(PandaNode) do_generate();
|
||||||
|
PT(PandaNode) do_get_internal_geom() const;
|
||||||
|
|
||||||
PT(PandaNode) make_frame();
|
PT(PandaNode) make_frame();
|
||||||
PT(PandaNode) make_card();
|
PT(PandaNode) make_card();
|
||||||
PT(PandaNode) make_card_with_border();
|
PT(PandaNode) make_card_with_border();
|
||||||
|
|
||||||
static int count_geoms(PandaNode *node);
|
static int count_geoms(PandaNode *node);
|
||||||
|
|
||||||
|
Mutex _lock;
|
||||||
PT(PandaNode) _internal_geom;
|
PT(PandaNode) _internal_geom;
|
||||||
|
|
||||||
PT(Texture) _card_texture;
|
PT(Texture) _card_texture;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user