diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index a220fc3fcb..f62eda9831 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -926,6 +926,8 @@ remove_all_children() { child_node->fix_path_lengths(cdata_child); child_node->parents_changed(); } + cdata->_down.clear(); + for (di = cdata->_stashed.begin(); di != cdata->_stashed.end(); ++di) { PT(PandaNode) child_node = (*di).get_child(); CDWriter cdata_child(child_node->_cycler); @@ -955,6 +957,7 @@ remove_all_children() { child_node->fix_path_lengths(cdata_child); child_node->parents_changed(); } + cdata->_stashed.clear(); // Mark the bounding volumes stale. force_bound_stale(); @@ -1517,9 +1520,16 @@ fix_path_lengths(const CData *cdata) { //////////////////////////////////////////////////////////////////// void PandaNode:: r_list_descendants(ostream &out, int indent_level) const { - indent(out, indent_level) << *this << "\n"; - CDReader cdata(_cycler); + indent(out, indent_level) << *this; + if (!cdata->_transform->is_identity()) { + out << " " << *cdata->_transform; + } + if (!cdata->_state->is_empty()) { + out << " " << *cdata->_state; + } + out << "\n"; + Down::const_iterator di; for (di = cdata->_down.begin(); di != cdata->_down.end(); ++di) { (*di).get_child()->r_list_descendants(out, indent_level + 2); diff --git a/panda/src/pgraph/qpnodePath.I b/panda/src/pgraph/qpnodePath.I index c3d3e9f760..69513406f2 100644 --- a/panda/src/pgraph/qpnodePath.I +++ b/panda/src/pgraph/qpnodePath.I @@ -938,7 +938,8 @@ get_distance(const qpNodePath &other) const { //////////////////////////////////////////////////////////////////// INLINE void qpNodePath:: adjust_all_priorities(int adjustment) { - nassertv(false); + nassertv(!is_empty()); + r_adjust_all_priorities(node(), adjustment); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/qpnodePath.cxx b/panda/src/pgraph/qpnodePath.cxx index 80ac1c7ef1..ac5758c2c7 100644 --- a/panda/src/pgraph/qpnodePath.cxx +++ b/panda/src/pgraph/qpnodePath.cxx @@ -2472,3 +2472,21 @@ r_find_matches(qpNodePathCollection &result, r_find_matches(result, next_level, max_matches, num_levels_remaining); } } + +//////////////////////////////////////////////////////////////////// +// Function: qpNodePath::r_adjust_all_priorities +// Access: Private +// Description: The recursive implementation of +// adjust_all_priorities(). This walks through the +// subgraph defined by the indicated node and below. +//////////////////////////////////////////////////////////////////// +void qpNodePath:: +r_adjust_all_priorities(PandaNode *node, int adjustment) { + node->set_state(node->get_state()->adjust_all_priorities(adjustment)); + + PandaNode::Children cr = node->get_children(); + int num_children = cr.get_num_children(); + for (int i = 0; i < num_children; i++) { + r_adjust_all_priorities(cr.get_child(i), adjustment); + } +} diff --git a/panda/src/pgraph/qpnodePath.h b/panda/src/pgraph/qpnodePath.h index 0ef4e0fd4d..a57d7484f7 100644 --- a/panda/src/pgraph/qpnodePath.h +++ b/panda/src/pgraph/qpnodePath.h @@ -488,6 +488,8 @@ private: const qpFindApproxLevel &level, int max_matches, int num_levels_remaining) const; + void r_adjust_all_priorities(PandaNode *node, int adjustment); + PT(qpNodePathComponent) _head; ErrorType _error_type; static int _max_search_depth; diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index 41a799c3da..19cf0a4327 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -451,7 +451,7 @@ add_attrib(const RenderAttrib *attrib, int override) const { // Access: Published // Description: Returns a new RenderState object that represents the // same as the source state, with the indicated -// RenderAttrib removed +// RenderAttrib removed. //////////////////////////////////////////////////////////////////// CPT(RenderState) RenderState:: remove_attrib(TypeHandle type) const { @@ -472,6 +472,30 @@ remove_attrib(TypeHandle type) const { return return_new(new_state); } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::remove_attrib +// Access: Published +// Description: Returns a new RenderState object that represents the +// same as the source state, with all attributes' +// override values incremented (or decremented, if +// negative) by the indicated amount. If the override +// would drop below zero, it is set to zero. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) RenderState:: +adjust_all_priorities(int adjustment) const { + RenderState *new_state = new RenderState; + new_state->_attributes.reserve(_attributes.size()); + + Attributes::const_iterator ai; + for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) { + Attribute attrib = *ai; + attrib._override = max(attrib._override + adjustment, 0); + new_state->_attributes.push_back(attrib); + } + + return return_new(new_state); +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::get_attrib // Access: Published, Virtual diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index f82feb0b24..2990ffed8d 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -81,6 +81,8 @@ PUBLISHED: CPT(RenderState) add_attrib(const RenderAttrib *attrib, int override = 0) const; CPT(RenderState) remove_attrib(TypeHandle type) const; + CPT(RenderState) adjust_all_priorities(int adjustment) const; + const RenderAttrib *get_attrib(TypeHandle type) const; void output(ostream &out) const; diff --git a/panda/src/pgraph/transformState.cxx b/panda/src/pgraph/transformState.cxx index 97a6a3f9e7..67836d1d43 100644 --- a/panda/src/pgraph/transformState.cxx +++ b/panda/src/pgraph/transformState.cxx @@ -186,7 +186,7 @@ operator < (const TransformState &other) const { if (c != 0) { return c < 0; } - c = _scale.compare_to(other._hpr); + c = _scale.compare_to(other._scale); return c < 0; } diff --git a/panda/src/text/Sources.pp b/panda/src/text/Sources.pp index 0c32d6d21b..8f6978ba64 100644 --- a/panda/src/text/Sources.pp +++ b/panda/src/text/Sources.pp @@ -6,7 +6,8 @@ #define TARGET text #define LOCAL_LIBS \ - cull putil gobj sgattrib graph sgraph linmath sgraphutil pnmimage gsgbase \ + cull putil gobj sgattrib pgraph graph sgraph linmath \ + sgraphutil pnmimage gsgbase \ mathutil #define COMBINED_SOURCES $[TARGET]_composite1.cxx @@ -21,7 +22,8 @@ stringDecoder.I stringDecoder.h \ textFont.I textFont.h \ textGlyph.I textGlyph.h \ - textNode.I textNode.h textNode.cxx + textNode.I textNode.h textNode.cxx \ + qptextNode.I qptextNode.h qptextNode.cxx #define INCLUDED_SOURCES \ config_text.cxx \ @@ -43,7 +45,8 @@ stringDecoder.I stringDecoder.h \ textFont.I textFont.h \ textGlyph.I textGlyph.h \ - textNode.I textNode.h + textNode.I textNode.h \ + qptextNode.I qptextNode.h #define IGATESCAN all diff --git a/panda/src/text/config_text.cxx b/panda/src/text/config_text.cxx index 5b9889a52c..7169551c43 100644 --- a/panda/src/text/config_text.cxx +++ b/panda/src/text/config_text.cxx @@ -20,6 +20,7 @@ #include "staticTextFont.h" #include "textFont.h" #include "textNode.h" +#include "qptextNode.h" #include "dynamicTextFont.h" #include "dynamicTextPage.h" #include "geomTextGlyph.h" @@ -68,6 +69,7 @@ init_libtext() { StaticTextFont::init_type(); TextFont::init_type(); TextNode::init_type(); + qpTextNode::init_type(); #ifdef HAVE_FREETYPE DynamicTextFont::init_type(); diff --git a/panda/src/text/dynamicTextGlyph.cxx b/panda/src/text/dynamicTextGlyph.cxx index 14dc5ea26a..21517e16b2 100644 --- a/panda/src/text/dynamicTextGlyph.cxx +++ b/panda/src/text/dynamicTextGlyph.cxx @@ -22,6 +22,9 @@ #include "dynamicTextPage.h" #include "geomTextGlyph.h" +#include "textureAttrib.h" +#include "transparencyAttrib.h" +#include "renderState.h" #include "textureTransition.h" #include "transparencyTransition.h" @@ -164,6 +167,9 @@ make_geom(int bitmap_top, int bitmap_left, _trans.set_transition(tex); _trans.set_transition(trans); + _state = RenderState::make(TextureAttrib::make(_page), + TransparencyAttrib::make(TransparencyAttrib::M_alpha)); + _advance = advance / pixels_per_unit; } diff --git a/panda/src/text/staticTextFont.cxx b/panda/src/text/staticTextFont.cxx index b7ef4c182b..770e915049 100644 --- a/panda/src/text/staticTextFont.cxx +++ b/panda/src/text/staticTextFont.cxx @@ -21,6 +21,9 @@ #include "geom.h" #include "geomPoint.h" +#include "qpgeomNode.h" +#include "renderState.h" + #include "geomNode.h" #include "namedNode.h" #include "renderRelation.h" @@ -49,6 +52,25 @@ StaticTextFont(Node *font_def) { } } +//////////////////////////////////////////////////////////////////// +// Function: StaticTextFont::Constructor +// Access: Published +// Description: The constructor expects the root node to a model +// generated via egg-mkfont, which consists of a set of +// models, one per each character in the font. +//////////////////////////////////////////////////////////////////// +StaticTextFont:: +StaticTextFont(PandaNode *font_def) { + nassertv(font_def != (PandaNode *)NULL); + _qpfont = font_def; + _glyphs.clear(); + + find_characters(font_def, RenderState::make_empty()); + _is_valid = !_glyphs.empty(); + + set_name(font_def->get_name()); +} + //////////////////////////////////////////////////////////////////// // Function: StaticTextFont::write // Access: Published, Virtual @@ -298,3 +320,116 @@ find_characters(Node *root) { } } } + +//////////////////////////////////////////////////////////////////// +// Function: StaticTextFont::find_character_gsets +// Access: Private +// Description: Given that 'root' is a PandaNode containing at least +// a polygon and a point which define the character's +// appearance and kern position, respectively, +// recursively walk the hierarchy and root and locate +// those two Geoms. +//////////////////////////////////////////////////////////////////// +void StaticTextFont:: +find_character_gsets(PandaNode *root, Geom *&ch, GeomPoint *&dot, + const RenderState *&state, const RenderState *net_state) { + CPT(RenderState) next_net_state = net_state->compose(root->get_state()); + + if (root->is_geom_node()) { + qpGeomNode *geode = DCAST(qpGeomNode, root); + + for (int i = 0; i < geode->get_num_geoms(); i++) { + dDrawable *geom = geode->get_geom(i); + if (geom->is_of_type(GeomPoint::get_class_type())) { + dot = DCAST(GeomPoint, geom); + + } else if (geom->is_of_type(Geom::get_class_type())) { + ch = DCAST(Geom, geom); + state = next_net_state->compose(geode->get_geom_state(i)); + } + } + + } else { + PandaNode::Children cr = root->get_children(); + int num_children = cr.get_num_children(); + for (int i = 0; i < num_children; i++) { + find_character_gsets(cr.get_child(i), ch, dot, state, next_net_state); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: StaticTextFont::find_characters +// Access: Private +// Description: Walk the hierarchy beginning at the indicated root +// and locate any nodes whose names are just integers. +// These are taken to be characters, and their +// definitions and kern informations are retrieved. +//////////////////////////////////////////////////////////////////// +void StaticTextFont:: +find_characters(PandaNode *root, const RenderState *net_state) { + CPT(RenderState) next_net_state = net_state->compose(root->get_state()); + string name = root->get_name(); + + bool all_digits = !name.empty(); + const char *p = name.c_str(); + while (all_digits && *p != '\0') { + // VC++ complains if we treat an int as a bool, so we have to do + // this != 0 comparison on the int isdigit() function to shut it + // up. + all_digits = (isdigit(*p) != 0); + p++; + } + + if (all_digits) { + int character = atoi(name.c_str()); + Geom *ch = NULL; + GeomPoint *dot = NULL; + const RenderState *state = NULL; + find_character_gsets(root, ch, dot, state, next_net_state); + if (dot != NULL) { + // Get the first vertex from the "dot" geoset. This will be the + // origin of the next character. + PTA_Vertexf alist; + PTA_ushort ilist; + float width; + dot->get_coords(alist, ilist); + if (ilist.empty()) { + width = alist[0][0]; + } else { + width = alist[ilist[0]][0]; + } + + _glyphs[character] = new TextGlyph(ch, state, width); + } + + } else if (name == "ds") { + // The group "ds" is a special node that indicate's the font's + // design size, or line height. + + Geom *ch = NULL; + GeomPoint *dot = NULL; + const RenderState *state = NULL; + find_character_gsets(root, ch, dot, state, next_net_state); + if (dot != NULL) { + // Get the first vertex from the "dot" geoset. This will be the + // design size indicator. + PTA_Vertexf alist; + PTA_ushort ilist; + dot->get_coords(alist, ilist); + if (ilist.empty()) { + _line_height = alist[0][2]; + } else { + _line_height = alist[ilist[0]][2]; + } + _space_advance = 0.25f * _line_height; + } + + } else { + PandaNode::Children cr = root->get_children(); + int num_children = cr.get_num_children(); + for (int i = 0; i < num_children; i++) { + find_characters(cr.get_child(i), next_net_state); + } + } +} diff --git a/panda/src/text/staticTextFont.h b/panda/src/text/staticTextFont.h index b2560fccae..464d6d48d2 100644 --- a/panda/src/text/staticTextFont.h +++ b/panda/src/text/staticTextFont.h @@ -25,6 +25,8 @@ #include "textFont.h" #include "textGlyph.h" #include "pt_Node.h" +#include "pandaNode.h" +#include "pointerTo.h" #include "pmap.h" class Node; @@ -42,6 +44,7 @@ class GeomPoint; class EXPCL_PANDA StaticTextFont : public TextFont { PUBLISHED: StaticTextFont(Node *font_def); + StaticTextFont(PandaNode *font_def); virtual void write(ostream &out, int indent_level) const; @@ -53,11 +56,17 @@ private: bool find_character_gsets(Node *root, Geom *&ch, GeomPoint *&dot, AllTransitionsWrapper &trans); void find_characters(Node *root); + void find_character_gsets(PandaNode *root, Geom *&ch, GeomPoint *&dot, + const RenderState *&state, + const RenderState *net_state); + void find_characters(PandaNode *root, + const RenderState *net_state); typedef pmap Glyphs; Glyphs _glyphs; float _font_height; PT_Node _font; + PT(PandaNode) _qpfont; public: static TypeHandle get_class_type() { diff --git a/panda/src/text/textGlyph.I b/panda/src/text/textGlyph.I index dc518da824..3e80b1c490 100644 --- a/panda/src/text/textGlyph.I +++ b/panda/src/text/textGlyph.I @@ -37,6 +37,21 @@ INLINE TextGlyph:: TextGlyph(Geom *geom, const AllTransitionsWrapper &trans, float advance) : _geom(geom), _trans(trans), _advance(advance) { + _state = RenderState::make_empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: TextGlyph::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE TextGlyph:: +TextGlyph(Geom *geom, const RenderState *state, float advance) : + _geom(geom), _state(state), _advance(advance) +{ + if (_state == (RenderState *)NULL) { + _state = RenderState::make_empty(); + } } //////////////////////////////////////////////////////////////////// @@ -48,6 +63,7 @@ INLINE TextGlyph:: TextGlyph(const TextGlyph ©) : _geom(copy._geom), _trans(copy._trans), + _state(copy._state), _advance(copy._advance) { } @@ -61,6 +77,7 @@ INLINE void TextGlyph:: operator = (const TextGlyph ©) { _geom = copy._geom; _trans = copy._trans; + _state = copy._state; _advance = copy._advance; } @@ -75,6 +92,17 @@ get_trans() const { return _trans; } +//////////////////////////////////////////////////////////////////// +// Function: TextGlyph::get_state +// Access: Public +// Description: Returns the state in which the glyph should be +// rendered. +//////////////////////////////////////////////////////////////////// +INLINE const RenderState *TextGlyph:: +get_state() const { + return _state; +} + //////////////////////////////////////////////////////////////////// // Function: TextGlyph::get_advance // Access: Public diff --git a/panda/src/text/textGlyph.h b/panda/src/text/textGlyph.h index abbd98b7ef..283b2df74d 100644 --- a/panda/src/text/textGlyph.h +++ b/panda/src/text/textGlyph.h @@ -21,6 +21,7 @@ #include "pandabase.h" #include "allTransitionsWrapper.h" +#include "renderState.h" #include "referenceCount.h" #include "geom.h" #include "pointerTo.h" @@ -37,17 +38,20 @@ class EXPCL_PANDA TextGlyph : public ReferenceCount { public: INLINE TextGlyph(); INLINE TextGlyph(Geom *geom, const AllTransitionsWrapper &trans, float advance); + INLINE TextGlyph(Geom *geom, const RenderState *state, float advance); INLINE TextGlyph(const TextGlyph ©); INLINE void operator = (const TextGlyph ©); virtual ~TextGlyph(); virtual PT(Geom) get_geom() const; INLINE const AllTransitionsWrapper &get_trans() const; + INLINE const RenderState *get_state() const; INLINE float get_advance() const; protected: PT(Geom) _geom; AllTransitionsWrapper _trans; + CPT(RenderState) _state; float _advance; }; diff --git a/panda/src/text/textNode.h b/panda/src/text/textNode.h index 4e7b1447fd..7adcc63a36 100644 --- a/panda/src/text/textNode.h +++ b/panda/src/text/textNode.h @@ -35,11 +35,9 @@ #include "allTransitionsWrapper.h" // These are deprecated. Use TextNode::Alignment instead. -BEGIN_PUBLISH #define TM_ALIGN_LEFT 1 #define TM_ALIGN_RIGHT 2 #define TM_ALIGN_CENTER 3 -END_PUBLISH class StringDecoder;