mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
allow embedded graphics in text paragraphs
This commit is contained in:
parent
42fc71791e
commit
d300c4a10c
@ -32,6 +32,20 @@ TextEncoder() {
|
|||||||
_flags = (F_got_text | F_got_wtext);
|
_flags = (F_got_text | F_got_wtext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextEncoder::Copy Constructor
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE TextEncoder::
|
||||||
|
TextEncoder(const TextEncoder ©) :
|
||||||
|
_flags(copy._flags),
|
||||||
|
_encoding(copy._encoding),
|
||||||
|
_text(copy._text),
|
||||||
|
_wtext(copy._wtext)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TextEncoder::set_encoding
|
// Function: TextEncoder::set_encoding
|
||||||
// Access: Published
|
// Access: Published
|
||||||
|
@ -47,6 +47,7 @@ PUBLISHED:
|
|||||||
};
|
};
|
||||||
|
|
||||||
INLINE TextEncoder();
|
INLINE TextEncoder();
|
||||||
|
INLINE TextEncoder(const TextEncoder ©);
|
||||||
|
|
||||||
INLINE void set_encoding(Encoding encoding);
|
INLINE void set_encoding(Encoding encoding);
|
||||||
INLINE Encoding get_encoding() const;
|
INLINE Encoding get_encoding() const;
|
||||||
|
@ -57,7 +57,8 @@ PGButton::
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
PGButton::
|
PGButton::
|
||||||
PGButton(const PGButton ©) :
|
PGButton(const PGButton ©) :
|
||||||
PGItem(copy)
|
PGItem(copy),
|
||||||
|
_click_buttons(copy._click_buttons)
|
||||||
{
|
{
|
||||||
_button_down = false;
|
_button_down = false;
|
||||||
}
|
}
|
||||||
|
@ -552,3 +552,14 @@ compare_largest(const LVecBase4f *&largest, float &largest_area,
|
|||||||
largest_area = new_area;
|
largest_area = new_area;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PGItem::StateDef::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE PGItem::StateDef::
|
||||||
|
StateDef() :
|
||||||
|
_frame_stale(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@ -100,10 +100,34 @@ PGItem(const PGItem ©) :
|
|||||||
_has_frame(copy._has_frame),
|
_has_frame(copy._has_frame),
|
||||||
_frame(copy._frame),
|
_frame(copy._frame),
|
||||||
_state(copy._state),
|
_state(copy._state),
|
||||||
_flags(copy._flags)
|
_flags(copy._flags),
|
||||||
|
_sounds(copy._sounds)
|
||||||
{
|
{
|
||||||
_notify = NULL;
|
_notify = NULL;
|
||||||
_region = new PGMouseWatcherRegion(this);
|
_region = new PGMouseWatcherRegion(this);
|
||||||
|
|
||||||
|
// We give our region the same name as the region for the PGItem
|
||||||
|
// we're copying--so that this PGItem will generate the same event
|
||||||
|
// names when the user interacts with it.
|
||||||
|
_region->set_name(copy._region->get_name());
|
||||||
|
|
||||||
|
// Make a deep copy of all of the original PGItem's StateDefs.
|
||||||
|
size_t num_state_defs = copy._state_defs.size();
|
||||||
|
_state_defs.reserve(num_state_defs);
|
||||||
|
for (size_t i = 0; i < num_state_defs; ++i) {
|
||||||
|
// We cheat and cast away the const, because the frame is just a
|
||||||
|
// cache. But we have to get the frame out of the source before we
|
||||||
|
// can safely copy it.
|
||||||
|
StateDef &old_sd = (StateDef &)(copy._state_defs[i]);
|
||||||
|
old_sd._frame.remove_node();
|
||||||
|
old_sd._frame_stale = true;
|
||||||
|
|
||||||
|
StateDef new_sd;
|
||||||
|
new_sd._root = old_sd._root.copy_to(NodePath());
|
||||||
|
new_sd._frame_style = old_sd._frame_style;
|
||||||
|
|
||||||
|
_state_defs.push_back(new_sd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -1135,9 +1159,7 @@ frame_changed() {
|
|||||||
void PGItem::
|
void PGItem::
|
||||||
slot_state_def(int state) {
|
slot_state_def(int state) {
|
||||||
while (state >= (int)_state_defs.size()) {
|
while (state >= (int)_state_defs.size()) {
|
||||||
StateDef def;
|
_state_defs.push_back(StateDef());
|
||||||
def._frame_stale = true;
|
|
||||||
_state_defs.push_back(def);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +207,7 @@ private:
|
|||||||
|
|
||||||
class StateDef {
|
class StateDef {
|
||||||
public:
|
public:
|
||||||
|
INLINE StateDef();
|
||||||
NodePath _root;
|
NodePath _root;
|
||||||
PGFrameStyle _frame_style;
|
PGFrameStyle _frame_style;
|
||||||
NodePath _frame;
|
NodePath _frame;
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
textAssembler.I textAssembler.h \
|
textAssembler.I textAssembler.h \
|
||||||
textFont.I textFont.h \
|
textFont.I textFont.h \
|
||||||
textGlyph.I textGlyph.h \
|
textGlyph.I textGlyph.h \
|
||||||
|
textGraphic.I textGraphic.h \
|
||||||
textNode.I textNode.h \
|
textNode.I textNode.h \
|
||||||
textProperties.I textProperties.h \
|
textProperties.I textProperties.h \
|
||||||
textPropertiesManager.I textPropertiesManager.h
|
textPropertiesManager.I textPropertiesManager.h
|
||||||
@ -38,6 +39,7 @@
|
|||||||
staticTextFont.cxx \
|
staticTextFont.cxx \
|
||||||
textAssembler.cxx \
|
textAssembler.cxx \
|
||||||
textFont.cxx textGlyph.cxx \
|
textFont.cxx textGlyph.cxx \
|
||||||
|
textGraphic.cxx \
|
||||||
textNode.cxx \
|
textNode.cxx \
|
||||||
textProperties.cxx \
|
textProperties.cxx \
|
||||||
textPropertiesManager.cxx
|
textPropertiesManager.cxx
|
||||||
@ -53,6 +55,7 @@
|
|||||||
textAssembler.I textAssembler.h \
|
textAssembler.I textAssembler.h \
|
||||||
textFont.I textFont.h \
|
textFont.I textFont.h \
|
||||||
textGlyph.I textGlyph.h \
|
textGlyph.I textGlyph.h \
|
||||||
|
textGraphic.I textGraphic.h \
|
||||||
textNode.I textNode.h \
|
textNode.I textNode.h \
|
||||||
textProperties.I textProperties.h \
|
textProperties.I textProperties.h \
|
||||||
textPropertiesManager.I textPropertiesManager.h
|
textPropertiesManager.I textPropertiesManager.h
|
||||||
|
@ -118,6 +118,13 @@ ConfigVariableInt text_soft_break_key
|
|||||||
"when it is used as a break point, no character is "
|
"when it is used as a break point, no character is "
|
||||||
"introduced in its place."));
|
"introduced in its place."));
|
||||||
|
|
||||||
|
ConfigVariableInt text_embed_graphic_key
|
||||||
|
("text-embed-graphic-key", 5,
|
||||||
|
PRC_DESC("This is the decimal character number that, embedded in "
|
||||||
|
"a string, is used to bracket the name of a model "
|
||||||
|
"added to the TextPropertiesManager object, to "
|
||||||
|
"embed an arbitrary graphic image within a paragraph."));
|
||||||
|
|
||||||
wstring
|
wstring
|
||||||
get_text_soft_hyphen_output() {
|
get_text_soft_hyphen_output() {
|
||||||
static wstring *text_soft_hyphen_output = NULL;
|
static wstring *text_soft_hyphen_output = NULL;
|
||||||
|
@ -45,6 +45,7 @@ extern ConfigVariableInt text_push_properties_key;
|
|||||||
extern ConfigVariableInt text_pop_properties_key;
|
extern ConfigVariableInt text_pop_properties_key;
|
||||||
extern ConfigVariableInt text_soft_hyphen_key;
|
extern ConfigVariableInt text_soft_hyphen_key;
|
||||||
extern ConfigVariableInt text_soft_break_key;
|
extern ConfigVariableInt text_soft_break_key;
|
||||||
|
extern ConfigVariableInt text_embed_graphic_key;
|
||||||
extern wstring get_text_soft_hyphen_output();
|
extern wstring get_text_soft_hyphen_output();
|
||||||
extern ConfigVariableDouble text_hyphen_ratio;
|
extern ConfigVariableDouble text_hyphen_ratio;
|
||||||
extern wstring get_text_never_break_before();
|
extern wstring get_text_never_break_before();
|
||||||
|
@ -84,7 +84,11 @@ get_num_rows() const {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
INLINE float TextAssembler::
|
INLINE float TextAssembler::
|
||||||
calc_width(const TextCharacter &tch) {
|
calc_width(const TextCharacter &tch) {
|
||||||
return calc_width(tch._character, *tch._properties);
|
if (tch._graphic != (TextGraphic *)NULL) {
|
||||||
|
return calc_width(tch._graphic, *tch._properties);
|
||||||
|
} else {
|
||||||
|
return calc_width(tch._character, *tch._properties);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -95,6 +99,20 @@ calc_width(const TextCharacter &tch) {
|
|||||||
INLINE TextAssembler::TextCharacter::
|
INLINE TextAssembler::TextCharacter::
|
||||||
TextCharacter(wchar_t character, const TextProperties *properties) :
|
TextCharacter(wchar_t character, const TextProperties *properties) :
|
||||||
_character(character),
|
_character(character),
|
||||||
|
_graphic(NULL),
|
||||||
|
_properties(properties)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextAssembler::TextCharacter::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE TextAssembler::TextCharacter::
|
||||||
|
TextCharacter(const TextGraphic *graphic, const TextProperties *properties) :
|
||||||
|
_character(0),
|
||||||
|
_graphic(graphic),
|
||||||
_properties(properties)
|
_properties(properties)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,9 @@ get_wordwrapped_wtext() const {
|
|||||||
for (ti = _wordwrapped_string.begin();
|
for (ti = _wordwrapped_string.begin();
|
||||||
ti != _wordwrapped_string.end();
|
ti != _wordwrapped_string.end();
|
||||||
++ti) {
|
++ti) {
|
||||||
wtext += (*ti)._character;
|
if ((*ti)._graphic != (TextGraphic *)NULL) {
|
||||||
|
wtext += (*ti)._character;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wtext;
|
return wtext;
|
||||||
@ -203,8 +205,13 @@ assemble_text() {
|
|||||||
// and put them under a common node.
|
// and put them under a common node.
|
||||||
PT(PandaNode) parent_node = new PandaNode("common");
|
PT(PandaNode) parent_node = new PandaNode("common");
|
||||||
|
|
||||||
PT(GeomNode) shadow_node = new GeomNode("shadow");
|
PT(PandaNode) shadow_node = new PandaNode("shadow");
|
||||||
PT(GeomNode) text_node = new GeomNode("text");
|
PT(GeomNode) shadow_geom_node = new GeomNode("shadow_geom");
|
||||||
|
shadow_node->add_child(shadow_geom_node);
|
||||||
|
|
||||||
|
PT(PandaNode) text_node = new PandaNode("text");
|
||||||
|
PT(GeomNode) text_geom_node = new GeomNode("text_geom");
|
||||||
|
text_node->add_child(text_geom_node);
|
||||||
|
|
||||||
const TextProperties *properties = NULL;
|
const TextProperties *properties = NULL;
|
||||||
CPT(RenderState) text_state;
|
CPT(RenderState) text_state;
|
||||||
@ -256,16 +263,18 @@ assemble_text() {
|
|||||||
// goes, while the place-text function just stomps on the
|
// goes, while the place-text function just stomps on the
|
||||||
// vertices.
|
// vertices.
|
||||||
if (properties->has_shadow()) {
|
if (properties->has_shadow()) {
|
||||||
placement->assign_copy_to(shadow_node, shadow_state, shadow_xform);
|
placement->assign_copy_to(shadow_geom_node, shadow_state, shadow_xform);
|
||||||
|
placement->copy_graphic_to(shadow_node, shadow_state, shadow_xform);
|
||||||
any_shadow = true;
|
any_shadow = true;
|
||||||
}
|
}
|
||||||
placement->assign_to(text_node, text_state);
|
placement->assign_to(text_geom_node, text_state);
|
||||||
|
placement->copy_graphic_to(text_node, text_state, LMatrix4f::ident_mat());
|
||||||
delete placement;
|
delete placement;
|
||||||
}
|
}
|
||||||
placed_glyphs.clear();
|
placed_glyphs.clear();
|
||||||
|
|
||||||
if (any_shadow) {
|
if (any_shadow) {
|
||||||
// The shadow_node must appear first to guarantee the correct
|
// The shadow_geom_node must appear first to guarantee the correct
|
||||||
// rendering order.
|
// rendering order.
|
||||||
parent_node->add_child(shadow_node);
|
parent_node->add_child(shadow_node);
|
||||||
}
|
}
|
||||||
@ -316,6 +325,17 @@ calc_width(wchar_t character, const TextProperties &properties) {
|
|||||||
return advance * glyph_scale;
|
return advance * glyph_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextAssembler::calc_width
|
||||||
|
// Access: Private, Static
|
||||||
|
// Description: Returns the width of a single TextGraphic image.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
float TextAssembler::
|
||||||
|
calc_width(const TextGraphic *graphic, const TextProperties &properties) {
|
||||||
|
LVecBase4f frame = graphic->get_frame();
|
||||||
|
return (frame[1] - frame[0]) * properties.get_glyph_scale();
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TextAssembler::scan_wtext
|
// Function: TextAssembler::scan_wtext
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -368,7 +388,13 @@ scan_wtext(wstring::const_iterator &si,
|
|||||||
|
|
||||||
// Define the new properties by extending the current properties.
|
// Define the new properties by extending the current properties.
|
||||||
TextProperties *new_properties = new TextProperties(*current_properties);
|
TextProperties *new_properties = new TextProperties(*current_properties);
|
||||||
new_properties->add_properties(manager->get_properties(name));
|
const TextProperties *named_props = manager->get_properties_ptr(name);
|
||||||
|
if (named_props != (TextProperties *)NULL) {
|
||||||
|
new_properties->add_properties(*named_props);
|
||||||
|
} else {
|
||||||
|
text_cat.warning()
|
||||||
|
<< "Unknown TextProperties: " << name << "\n";
|
||||||
|
}
|
||||||
_properties_list.push_back(new_properties);
|
_properties_list.push_back(new_properties);
|
||||||
|
|
||||||
// And recursively scan with the nested properties.
|
// And recursively scan with the nested properties.
|
||||||
@ -390,6 +416,45 @@ scan_wtext(wstring::const_iterator &si,
|
|||||||
++si;
|
++si;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
} else if ((*si) == text_embed_graphic_key) {
|
||||||
|
// This indicates an embedded graphic. Pull off the name of the
|
||||||
|
// TextGraphic structure, which is everything until the next
|
||||||
|
// text_embed_graphic_key.
|
||||||
|
|
||||||
|
wstring wname;
|
||||||
|
++si;
|
||||||
|
while (si != send && (*si) != text_embed_graphic_key) {
|
||||||
|
wname += (*si);
|
||||||
|
++si;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (si == send) {
|
||||||
|
// We didn't close the text_embed_graphic_key. That's an
|
||||||
|
// error.
|
||||||
|
text_cat.warning()
|
||||||
|
<< "Unclosed embed_graphic in text.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++si;
|
||||||
|
|
||||||
|
// Now we have to encode the wstring into a string, for lookup
|
||||||
|
// in the TextPropertiesManager.
|
||||||
|
string name = _encoder->encode_wtext(wname);
|
||||||
|
|
||||||
|
TextPropertiesManager *manager =
|
||||||
|
TextPropertiesManager::get_global_ptr();
|
||||||
|
|
||||||
|
// Get the graphic image.
|
||||||
|
const TextGraphic *named_graphic = manager->get_graphic_ptr(name);
|
||||||
|
if (named_graphic != (TextGraphic *)NULL) {
|
||||||
|
text_string.push_back(TextCharacter(named_graphic, current_properties));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
text_cat.warning()
|
||||||
|
<< "Unknown TextGraphic: " << name << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// A normal character. Apply it.
|
// A normal character. Apply it.
|
||||||
text_string.push_back(TextCharacter(*si, current_properties));
|
text_string.push_back(TextCharacter(*si, current_properties));
|
||||||
@ -771,6 +836,7 @@ assemble_row(TextAssembler::TextString::const_iterator &si,
|
|||||||
|
|
||||||
while (si != send) {
|
while (si != send) {
|
||||||
wchar_t character = (*si)._character;
|
wchar_t character = (*si)._character;
|
||||||
|
const TextGraphic *graphic = (*si)._graphic;
|
||||||
const TextProperties *properties = (*si)._properties;
|
const TextProperties *properties = (*si)._properties;
|
||||||
|
|
||||||
TextFont *font = properties->get_font();
|
TextFont *font = properties->get_font();
|
||||||
@ -782,7 +848,12 @@ assemble_row(TextAssembler::TextString::const_iterator &si,
|
|||||||
|
|
||||||
// And the height of the row is the maximum of all the fonts used
|
// And the height of the row is the maximum of all the fonts used
|
||||||
// within the row.
|
// within the row.
|
||||||
line_height = max(line_height, font->get_line_height());
|
if (graphic != (TextGraphic *)NULL) {
|
||||||
|
LVecBase4f frame = graphic->get_frame();
|
||||||
|
line_height = max(line_height, frame[3] - frame[2]);
|
||||||
|
} else {
|
||||||
|
line_height = max(line_height, font->get_line_height());
|
||||||
|
}
|
||||||
|
|
||||||
if (character == '\n') {
|
if (character == '\n') {
|
||||||
// The newline character marks the end of the row.
|
// The newline character marks the end of the row.
|
||||||
@ -803,6 +874,38 @@ assemble_row(TextAssembler::TextString::const_iterator &si,
|
|||||||
} else if (character == text_soft_hyphen_key) {
|
} else if (character == text_soft_hyphen_key) {
|
||||||
// And so is the 'soft-hyphen' key character.
|
// And so is the 'soft-hyphen' key character.
|
||||||
|
|
||||||
|
} else if (graphic != (TextGraphic *)NULL) {
|
||||||
|
// A special embedded graphic.
|
||||||
|
GlyphPlacement *placement = new GlyphPlacement;
|
||||||
|
row_placed_glyphs.push_back(placement);
|
||||||
|
|
||||||
|
placement->_graphic_model = graphic->get_model().node();
|
||||||
|
|
||||||
|
LVecBase4f frame = graphic->get_frame();
|
||||||
|
float glyph_scale = properties->get_glyph_scale();
|
||||||
|
|
||||||
|
float advance = (frame[1] - frame[0]);
|
||||||
|
|
||||||
|
// Now compute the matrix that will transform the glyph (or
|
||||||
|
// glyphs) into position.
|
||||||
|
LMatrix4f glyph_xform = LMatrix4f::scale_mat(glyph_scale);
|
||||||
|
|
||||||
|
glyph_xform(3, 0) += (xpos - frame[0]);
|
||||||
|
glyph_xform(3, 2) += (properties->get_glyph_shift() - frame[2]);
|
||||||
|
|
||||||
|
if (properties->has_slant()) {
|
||||||
|
LMatrix4f shear(1.0f, 0.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
|
properties->get_slant(), 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glyph_xform = shear * glyph_xform;
|
||||||
|
}
|
||||||
|
|
||||||
|
placement->_xform = glyph_xform;
|
||||||
|
placement->_properties = properties;
|
||||||
|
|
||||||
|
xpos += advance * glyph_scale;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// A printable character.
|
// A printable character.
|
||||||
bool got_glyph;
|
bool got_glyph;
|
||||||
@ -1482,5 +1585,27 @@ assign_copy_to(GeomNode *geom_node, const RenderState *state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextAssembler::GlyphPlacement::copy_graphic_to
|
||||||
|
// Access: Private
|
||||||
|
// Description: If the GlyphPlacement includes a special graphic,
|
||||||
|
// copies it to the indicated node.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TextAssembler::GlyphPlacement::
|
||||||
|
copy_graphic_to(PandaNode *node, const RenderState *state,
|
||||||
|
const LMatrix4f &extra_xform) const {
|
||||||
|
if (_graphic_model != (PandaNode *)NULL) {
|
||||||
|
LMatrix4f new_xform = _xform * extra_xform;
|
||||||
|
|
||||||
|
// We need an intermediate node to hold the transform and state.
|
||||||
|
PT(PandaNode) intermediate_node = new PandaNode("");
|
||||||
|
node->add_child(intermediate_node);
|
||||||
|
|
||||||
|
intermediate_node->set_transform(TransformState::make_mat(new_xform));
|
||||||
|
intermediate_node->set_state(state);
|
||||||
|
intermediate_node->add_child(_graphic_model->copy_subgraph());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // CPPPARSER
|
#endif // CPPPARSER
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "geom.h"
|
#include "geom.h"
|
||||||
|
|
||||||
class TextEncoder;
|
class TextEncoder;
|
||||||
|
class TextGraphic;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : TextAssembler
|
// Class : TextAssembler
|
||||||
@ -63,6 +64,7 @@ public:
|
|||||||
INLINE const LVector2f &get_lr() const;
|
INLINE const LVector2f &get_lr() const;
|
||||||
|
|
||||||
static float calc_width(wchar_t character, const TextProperties &properties);
|
static float calc_width(wchar_t character, const TextProperties &properties);
|
||||||
|
static float calc_width(const TextGraphic *graphic, const TextProperties &properties);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// These structures are built up and operated on by scan_wtext() and
|
// These structures are built up and operated on by scan_wtext() and
|
||||||
@ -74,7 +76,9 @@ private:
|
|||||||
class TextCharacter {
|
class TextCharacter {
|
||||||
public:
|
public:
|
||||||
INLINE TextCharacter(wchar_t character, const TextProperties *properties);
|
INLINE TextCharacter(wchar_t character, const TextProperties *properties);
|
||||||
|
INLINE TextCharacter(const TextGraphic *graphic, const TextProperties *properties);
|
||||||
wchar_t _character;
|
wchar_t _character;
|
||||||
|
const TextGraphic *_graphic;
|
||||||
const TextProperties *_properties;
|
const TextProperties *_properties;
|
||||||
};
|
};
|
||||||
typedef pvector<TextCharacter> TextString;
|
typedef pvector<TextCharacter> TextString;
|
||||||
@ -112,9 +116,12 @@ private:
|
|||||||
bool &found_any, Thread *current_thread) const;
|
bool &found_any, Thread *current_thread) const;
|
||||||
void assign_to(GeomNode *geom_node, const RenderState *state) const;
|
void assign_to(GeomNode *geom_node, const RenderState *state) const;
|
||||||
void assign_copy_to(GeomNode *geom_node, const RenderState *state,
|
void assign_copy_to(GeomNode *geom_node, const RenderState *state,
|
||||||
const LMatrix4f &xform) const;
|
const LMatrix4f &extra_xform) const;
|
||||||
|
void copy_graphic_to(PandaNode *node, const RenderState *state,
|
||||||
|
const LMatrix4f &extra_xform) const;
|
||||||
|
|
||||||
Pieces _pieces;
|
Pieces _pieces;
|
||||||
|
PT(PandaNode) _graphic_model;
|
||||||
LMatrix4f _xform;
|
LMatrix4f _xform;
|
||||||
const TextProperties *_properties;
|
const TextProperties *_properties;
|
||||||
};
|
};
|
||||||
|
116
panda/src/text/textGraphic.I
Normal file
116
panda/src/text/textGraphic.I
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Filename: textGraphic.I
|
||||||
|
// Created by: drose (18Aug06)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the Panda 3d
|
||||||
|
// Software license. You should have received a copy of this license
|
||||||
|
// along with this source code; you will also find a current copy of
|
||||||
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||||
|
//
|
||||||
|
// To contact the maintainers of this program write to
|
||||||
|
// panda3d-general@lists.sourceforge.net .
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextGraphic::Constructor
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE TextGraphic::
|
||||||
|
TextGraphic() {
|
||||||
|
_frame = LVecBase4f::zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextGraphic::Constructor
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE TextGraphic::
|
||||||
|
TextGraphic(const NodePath &model, const LVecBase4f &frame) :
|
||||||
|
_model(model),
|
||||||
|
_frame(frame)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextGraphic::Constructor
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE TextGraphic::
|
||||||
|
TextGraphic(const NodePath &model, float left, float right, float bottom, float top) :
|
||||||
|
_model(model),
|
||||||
|
_frame(left, right, bottom, top)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextGraphic::get_model
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the NodePath associated with the graphic,
|
||||||
|
// that renders the desired image.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE NodePath TextGraphic::
|
||||||
|
get_model() const {
|
||||||
|
return _model;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextGraphic::set_model
|
||||||
|
// Access: Published
|
||||||
|
// Description: Changes the NodePath associated with the graphic.
|
||||||
|
// This NodePath should contain geometry that will
|
||||||
|
// render the desired graphic image.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void TextGraphic::
|
||||||
|
set_model(const NodePath &model) {
|
||||||
|
_model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextGraphic::get_frame
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the frame specified for the graphic. This is
|
||||||
|
// the amount of space that will be reserved for the
|
||||||
|
// graphic when it is embedded in a text paragraph, in
|
||||||
|
// the form (left, right, bottom, top).
|
||||||
|
//
|
||||||
|
// The actual graphic, as rendered by the NodePath
|
||||||
|
// specified via set_model(), should more or less fit
|
||||||
|
// within this rectangle. It is not required to fit
|
||||||
|
// completely within it, but if it does not, it may
|
||||||
|
// visually overlap with nearby text.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE LVecBase4f TextGraphic::
|
||||||
|
get_frame() const {
|
||||||
|
return _frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextGraphic::set_frame
|
||||||
|
// Access: Published
|
||||||
|
// Description: Specifies the (left, right, bottom, top) bounding
|
||||||
|
// frame for the graphic. See get_frame().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void TextGraphic::
|
||||||
|
set_frame(const LVecBase4f &frame) {
|
||||||
|
_frame = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextGraphic::set_frame
|
||||||
|
// Access: Published
|
||||||
|
// Description: Specifies the (left, right, bottom, top) bounding
|
||||||
|
// frame for the graphic. See get_frame().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void TextGraphic::
|
||||||
|
set_frame(float left, float right, float bottom, float top) {
|
||||||
|
_frame.set(left, right, bottom, top);
|
||||||
|
}
|
19
panda/src/text/textGraphic.cxx
Normal file
19
panda/src/text/textGraphic.cxx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Filename: textGraphic.cxx
|
||||||
|
// Created by: drose (18Aug06)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the Panda 3d
|
||||||
|
// Software license. You should have received a copy of this license
|
||||||
|
// along with this source code; you will also find a current copy of
|
||||||
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||||
|
//
|
||||||
|
// To contact the maintainers of this program write to
|
||||||
|
// panda3d-general@lists.sourceforge.net .
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "textGraphic.h"
|
67
panda/src/text/textGraphic.h
Normal file
67
panda/src/text/textGraphic.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Filename: textGraphic.h
|
||||||
|
// Created by: drose (18Aug06)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the Panda 3d
|
||||||
|
// Software license. You should have received a copy of this license
|
||||||
|
// along with this source code; you will also find a current copy of
|
||||||
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||||
|
//
|
||||||
|
// To contact the maintainers of this program write to
|
||||||
|
// panda3d-general@lists.sourceforge.net .
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef TEXTGRAPHIC_H
|
||||||
|
#define TEXTGRAPHIC_H
|
||||||
|
|
||||||
|
#include "pandabase.h"
|
||||||
|
|
||||||
|
#include "config_text.h"
|
||||||
|
#include "nodePath.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Class : TextGraphic
|
||||||
|
// Description : This defines a special model that has been
|
||||||
|
// constructed for the purposes of embedding an
|
||||||
|
// arbitrary graphic image within a text paragraph.
|
||||||
|
//
|
||||||
|
// It can be any arbitrary model, though it should be
|
||||||
|
// built along the same scale as the text, and it should
|
||||||
|
// probably be at least mostly two-dimensional.
|
||||||
|
// Typically, this means it should be constructed in the
|
||||||
|
// X-Z plane, and it should have a maximum vertical (Z)
|
||||||
|
// height of 1.0.
|
||||||
|
//
|
||||||
|
// The frame specifies an arbitrary bounding volume in
|
||||||
|
// the form (left, right, bottom, top). This indicates
|
||||||
|
// the amount of space that will be reserved within the
|
||||||
|
// paragraph. The actual model is not actually required
|
||||||
|
// to fit within this rectangle, but if it does not, it
|
||||||
|
// may visually overlap with nearby text.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
class EXPCL_PANDA TextGraphic {
|
||||||
|
PUBLISHED:
|
||||||
|
INLINE TextGraphic();
|
||||||
|
INLINE TextGraphic(const NodePath &model, const LVecBase4f &frame);
|
||||||
|
INLINE TextGraphic(const NodePath &model, float left, float right, float bottom, float top);
|
||||||
|
|
||||||
|
INLINE NodePath get_model() const;
|
||||||
|
INLINE void set_model(const NodePath &model);
|
||||||
|
|
||||||
|
INLINE LVecBase4f get_frame() const;
|
||||||
|
INLINE void set_frame(const LVecBase4f &frame);
|
||||||
|
INLINE void set_frame(float left, float right, float bottom, float top);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NodePath _model;
|
||||||
|
LVecBase4f _frame;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "textGraphic.I"
|
||||||
|
|
||||||
|
#endif
|
@ -120,6 +120,50 @@ TextNode(const string &name, const TextProperties ©) :
|
|||||||
_lr3d.set(0.0f, 0.0f, 0.0f);
|
_lr3d.set(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextNode::Copy Constructor
|
||||||
|
// Access: Published
|
||||||
|
// Description: OK, this is a true copy constructor.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
TextNode::
|
||||||
|
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),
|
||||||
|
_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),
|
||||||
|
_assembler(this)
|
||||||
|
{
|
||||||
|
invalidate_with_measure();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextNode::make_copy
|
||||||
|
// Access: Protected, Virtual
|
||||||
|
// Description: Returns a newly-allocated Node that is a shallow copy
|
||||||
|
// of this one. It will be a different Node pointer,
|
||||||
|
// but its internal data may or may not be shared with
|
||||||
|
// that of the original Node.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PandaNode *TextNode::
|
||||||
|
make_copy() const {
|
||||||
|
return new TextNode(*this);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TextNode::Destructor
|
// Function: TextNode::Destructor
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -267,8 +311,7 @@ generate() {
|
|||||||
|
|
||||||
PT(PandaNode) text_root = _assembler.assemble_text();
|
PT(PandaNode) text_root = _assembler.assemble_text();
|
||||||
|
|
||||||
// Parent the text in. We create an intermediate node so we can
|
// Parent the text in.
|
||||||
// choose to reinstance the text_root as the shadow, below.
|
|
||||||
PT(PandaNode) text = new PandaNode("text");
|
PT(PandaNode) text = new PandaNode("text");
|
||||||
root->add_child(text, get_draw_order() + 2);
|
root->add_child(text, get_draw_order() + 2);
|
||||||
text->add_child(text_root);
|
text->add_child(text_root);
|
||||||
|
@ -57,6 +57,11 @@ class EXPCL_PANDA TextNode : public PandaNode, public TextEncoder, public TextPr
|
|||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
TextNode(const string &name);
|
TextNode(const string &name);
|
||||||
TextNode(const string &name, const TextProperties ©);
|
TextNode(const string &name, const TextProperties ©);
|
||||||
|
protected:
|
||||||
|
TextNode(const TextNode ©);
|
||||||
|
virtual PandaNode *make_copy() const;
|
||||||
|
|
||||||
|
PUBLISHED:
|
||||||
~TextNode();
|
~TextNode();
|
||||||
|
|
||||||
INLINE float get_line_height() const;
|
INLINE float get_line_height() const;
|
||||||
|
@ -118,6 +118,105 @@ clear_properties(const string &name) {
|
|||||||
_properties.erase(name);
|
_properties.erase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextPropertiesManager::set_graphic
|
||||||
|
// Access: Published
|
||||||
|
// Description: Defines the TextGraphic associated with the
|
||||||
|
// indicated name. When the name is subsequently
|
||||||
|
// encountered in text embedded between \5 characters in
|
||||||
|
// a TextNode string, the specified graphic will be
|
||||||
|
// embedded in the text at that point.
|
||||||
|
//
|
||||||
|
// If there was already a TextGraphic structure
|
||||||
|
// associated with this name, it is quietly replaced
|
||||||
|
// with the new definition.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TextPropertiesManager::
|
||||||
|
set_graphic(const string &name, const TextGraphic &graphic) {
|
||||||
|
_graphics[name] = graphic;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextPropertiesManager::set_graphic
|
||||||
|
// Access: Published
|
||||||
|
// Description: This flavor of set_graphic implicitly creates a frame
|
||||||
|
// for the model using the model's actual computed
|
||||||
|
// bounding volume, as derived from
|
||||||
|
// NodePath::calc_tight_bounds(). Create a TextGraphic
|
||||||
|
// object first if you want to have explicit control of
|
||||||
|
// the frame.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TextPropertiesManager::
|
||||||
|
set_graphic(const string &name, const NodePath &model) {
|
||||||
|
LPoint3f min_point, max_point;
|
||||||
|
model.calc_tight_bounds(min_point, max_point);
|
||||||
|
|
||||||
|
TextGraphic graphic(model,
|
||||||
|
min_point.dot(LVector3f::right()),
|
||||||
|
max_point.dot(LVector3f::right()),
|
||||||
|
min_point.dot(LVector3f::up()),
|
||||||
|
max_point.dot(LVector3f::up()));
|
||||||
|
|
||||||
|
_graphics[name] = graphic;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextPropertiesManager::get_graphic
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the TextGraphic associated with the
|
||||||
|
// indicated name. If there was not previously a
|
||||||
|
// TextGraphic associated with this name, a warning
|
||||||
|
// is printed and then a default TextGraphic
|
||||||
|
// structure is associated with the name, and returned.
|
||||||
|
//
|
||||||
|
// Call has_graphic() instead to check whether a
|
||||||
|
// particular name has been defined.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
TextGraphic TextPropertiesManager::
|
||||||
|
get_graphic(const string &name) {
|
||||||
|
Graphics::const_iterator pi;
|
||||||
|
pi = _graphics.find(name);
|
||||||
|
if (pi != _graphics.end()) {
|
||||||
|
return (*pi).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
text_cat.warning()
|
||||||
|
<< "Creating default TextGraphic for name '" << name << "'\n";
|
||||||
|
|
||||||
|
TextGraphic default_graphic;
|
||||||
|
_graphics[name] = default_graphic;
|
||||||
|
return default_graphic;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextPropertiesManager::has_graphic
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns true if a TextGraphic structure has been
|
||||||
|
// associated with the indicated name, false otherwise.
|
||||||
|
// Normally this means set_graphic() has been called
|
||||||
|
// with this name, but because get_graphic() will
|
||||||
|
// implicitly create a default TextGraphic structure,
|
||||||
|
// it may also mean simply that get_graphic() has
|
||||||
|
// been called with the indicated name.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool TextPropertiesManager::
|
||||||
|
has_graphic(const string &name) const {
|
||||||
|
Graphics::const_iterator pi;
|
||||||
|
pi = _graphics.find(name);
|
||||||
|
return (pi != _graphics.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextPropertiesManager::clear_graphic
|
||||||
|
// Access: Published
|
||||||
|
// Description: Removes the named TextGraphic structure from the
|
||||||
|
// manager.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TextPropertiesManager::
|
||||||
|
clear_graphic(const string &name) {
|
||||||
|
_graphics.erase(name);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TextPropertiesManager::write
|
// Function: TextPropertiesManager::write
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -146,3 +245,37 @@ get_global_ptr() {
|
|||||||
}
|
}
|
||||||
return _global_ptr;
|
return _global_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextPropertiesManager::get_properties_ptr
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns a pointer to the TextProperties with the
|
||||||
|
// indicated name, or NULL if there is no properties
|
||||||
|
// with that name.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
const TextProperties *TextPropertiesManager::
|
||||||
|
get_properties_ptr(const string &name) {
|
||||||
|
Properties::const_iterator pi;
|
||||||
|
pi = _properties.find(name);
|
||||||
|
if (pi != _properties.end()) {
|
||||||
|
return &(*pi).second;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TextPropertiesManager::get_graphic_ptr
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns a pointer to the TextGraphic with the
|
||||||
|
// indicated name, or NULL if there is no graphic
|
||||||
|
// with that name.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
const TextGraphic *TextPropertiesManager::
|
||||||
|
get_graphic_ptr(const string &name) {
|
||||||
|
Graphics::const_iterator pi;
|
||||||
|
pi = _graphics.find(name);
|
||||||
|
if (pi != _graphics.end()) {
|
||||||
|
return &(*pi).second;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "config_text.h"
|
#include "config_text.h"
|
||||||
#include "textProperties.h"
|
#include "textProperties.h"
|
||||||
|
#include "textGraphic.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : TextPropertiesManager
|
// Class : TextPropertiesManager
|
||||||
@ -44,6 +45,14 @@
|
|||||||
// the character "n" will be rendered in the "up" state,
|
// the character "n" will be rendered in the "up" state,
|
||||||
// and then " + y" will be rendered in the normal state
|
// and then " + y" will be rendered in the normal state
|
||||||
// again.
|
// again.
|
||||||
|
//
|
||||||
|
// This can also be used to define arbitrary models that
|
||||||
|
// can serve as embedded graphic images in a text
|
||||||
|
// paragraph. This works similarly; the convention is
|
||||||
|
// to create a TextGraphic that describes the graphic
|
||||||
|
// image, and then associate it here via the
|
||||||
|
// set_graphic() call. Then "\5name\5" will embed the
|
||||||
|
// named graphic.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDA TextPropertiesManager {
|
class EXPCL_PANDA TextPropertiesManager {
|
||||||
protected:
|
protected:
|
||||||
@ -56,14 +65,27 @@ PUBLISHED:
|
|||||||
bool has_properties(const string &name) const;
|
bool has_properties(const string &name) const;
|
||||||
void clear_properties(const string &name);
|
void clear_properties(const string &name);
|
||||||
|
|
||||||
|
void set_graphic(const string &name, const TextGraphic &graphic);
|
||||||
|
void set_graphic(const string &name, const NodePath &model);
|
||||||
|
TextGraphic get_graphic(const string &name);
|
||||||
|
bool has_graphic(const string &name) const;
|
||||||
|
void clear_graphic(const string &name);
|
||||||
|
|
||||||
void write(ostream &out, int indent_level = 0) const;
|
void write(ostream &out, int indent_level = 0) const;
|
||||||
|
|
||||||
static TextPropertiesManager *get_global_ptr();
|
static TextPropertiesManager *get_global_ptr();
|
||||||
|
|
||||||
|
public:
|
||||||
|
const TextProperties *get_properties_ptr(const string &name);
|
||||||
|
const TextGraphic *get_graphic_ptr(const string &name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef pmap<string, TextProperties> Properties;
|
typedef pmap<string, TextProperties> Properties;
|
||||||
Properties _properties;
|
Properties _properties;
|
||||||
|
|
||||||
|
typedef pmap<string, TextGraphic> Graphics;
|
||||||
|
Graphics _graphics;
|
||||||
|
|
||||||
static TextPropertiesManager *_global_ptr;
|
static TextPropertiesManager *_global_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "textAssembler.cxx"
|
#include "textAssembler.cxx"
|
||||||
#include "textFont.cxx"
|
#include "textFont.cxx"
|
||||||
#include "textGlyph.cxx"
|
#include "textGlyph.cxx"
|
||||||
|
#include "textGraphic.cxx"
|
||||||
#include "textNode.cxx"
|
#include "textNode.cxx"
|
||||||
#include "textProperties.cxx"
|
#include "textProperties.cxx"
|
||||||
#include "textPropertiesManager.cxx"
|
#include "textPropertiesManager.cxx"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user