diff --git a/panda/src/char/characterJoint.cxx b/panda/src/char/characterJoint.cxx index aec495ac24..a084b7d655 100644 --- a/panda/src/char/characterJoint.cxx +++ b/panda/src/char/characterJoint.cxx @@ -160,6 +160,30 @@ update_internals(PartGroup *parent, bool self_changed, bool parent_changed) { } } + if (net_changed && !_net_transform_nodes.empty()) { + CPT(TransformState) t = TransformState::make_mat(_net_transform); + + NodeList::iterator ai; + ai = _net_transform_nodes.begin(); + while (ai != _net_transform_nodes.end()) { + PandaNode *node = *ai; + node->set_transform(t); + ++ai; + } + } + + if (self_changed && !_local_transform_nodes.empty()) { + CPT(TransformState) t = TransformState::make_mat(_value); + + NodeList::iterator ai; + ai = _local_transform_nodes.begin(); + while (ai != _local_transform_nodes.end()) { + PandaNode *node = *ai; + node->set_transform(t); + ++ai; + } + } + return self_changed || net_changed; } @@ -203,18 +227,6 @@ has_net_transform(NodeRelation *arc) const { return (_net_transform_arcs.count(arc) > 0); } -//////////////////////////////////////////////////////////////////// -// Function: CharacterJoint::clear_net_transforms -// Access: Public -// Description: Removes all arcs from the list of arcs that will be -// updated each frame with the joint's net transform -// from the root. -//////////////////////////////////////////////////////////////////// -void CharacterJoint:: -clear_net_transforms() { - _net_transform_arcs.clear(); -} - //////////////////////////////////////////////////////////////////// // Function: CharacterJoint::add_local_transform // Access: Public @@ -255,16 +267,110 @@ has_local_transform(NodeRelation *arc) const { return (_local_transform_arcs.count(arc) > 0); } +//////////////////////////////////////////////////////////////////// +// Function: CharacterJoint::add_net_transform +// Access: Public +// Description: Adds the indicated node to the list of nodes that will +// be updated each frame with the joint's net transform +// from the root. Returns true if the node is +// successfully added, false if it had already been +// added. +//////////////////////////////////////////////////////////////////// +bool CharacterJoint:: +add_net_transform(PandaNode *node) { + return _net_transform_nodes.insert(node).second; +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJoint::remove_net_transform +// Access: Public +// Description: Removes the indicated node from the list of nodes that +// will be updated each frame with the joint's net +// transform from the root. Returns true if the node is +// successfully removed, false if it was not on the +// list. +//////////////////////////////////////////////////////////////////// +bool CharacterJoint:: +remove_net_transform(PandaNode *node) { + return (_net_transform_nodes.erase(node) > 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJoint::has_net_transform +// Access: Public +// Description: Returns true if the node is on the list of nodes that +// will be updated each frame with the joint's net +// transform from the root, false otherwise. +//////////////////////////////////////////////////////////////////// +bool CharacterJoint:: +has_net_transform(PandaNode *node) const { + return (_net_transform_nodes.count(node) > 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJoint::clear_net_transforms +// Access: Public +// Description: Removes all nodes from the list of nodes that will be +// updated each frame with the joint's net transform +// from the root. +//////////////////////////////////////////////////////////////////// +void CharacterJoint:: +clear_net_transforms() { + _net_transform_arcs.clear(); + _net_transform_nodes.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJoint::add_local_transform +// Access: Public +// Description: Adds the indicated node to the list of nodes that will +// be updated each frame with the joint's local +// transform from its parent. Returns true if the node +// is successfully added, false if it had already been +// added. +//////////////////////////////////////////////////////////////////// +bool CharacterJoint:: +add_local_transform(PandaNode *node) { + return _local_transform_nodes.insert(node).second; +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJoint::remove_local_transform +// Access: Public +// Description: Removes the indicated node from the list of nodes that +// will be updated each frame with the joint's local +// transform from its parent. Returns true if the node +// is successfully removed, false if it was not on the +// list. +//////////////////////////////////////////////////////////////////// +bool CharacterJoint:: +remove_local_transform(PandaNode *node) { + return (_local_transform_nodes.erase(node) > 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: CharacterJoint::has_local_transform +// Access: Public +// Description: Returns true if the node is on the list of nodes that +// will be updated each frame with the joint's local +// transform from its parent, false otherwise. +//////////////////////////////////////////////////////////////////// +bool CharacterJoint:: +has_local_transform(PandaNode *node) const { + return (_local_transform_nodes.count(node) > 0); +} + //////////////////////////////////////////////////////////////////// // Function: CharacterJoint::clear_local_transforms // Access: Public -// Description: Removes all arcs from the list of arcs that will be +// Description: Removes all nodes from the list of nodes that will be // updated each frame with the joint's local transform // from its parent. //////////////////////////////////////////////////////////////////// void CharacterJoint:: clear_local_transforms() { _local_transform_arcs.clear(); + _local_transform_nodes.clear(); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/char/characterJoint.h b/panda/src/char/characterJoint.h index 569b4f5406..d115435a3c 100644 --- a/panda/src/char/characterJoint.h +++ b/panda/src/char/characterJoint.h @@ -50,11 +50,19 @@ PUBLISHED: bool add_net_transform(NodeRelation *arc); bool remove_net_transform(NodeRelation *arc); bool has_net_transform(NodeRelation *arc) const; - void clear_net_transforms(); bool add_local_transform(NodeRelation *arc); bool remove_local_transform(NodeRelation *arc); bool has_local_transform(NodeRelation *arc) const; + + bool add_net_transform(PandaNode *node); + bool remove_net_transform(PandaNode *node); + bool has_net_transform(PandaNode *node) const; + void clear_net_transforms(); + + bool add_local_transform(PandaNode *node); + bool remove_local_transform(PandaNode *node); + bool has_local_transform(PandaNode *node) const; void clear_local_transforms(); private: @@ -62,6 +70,10 @@ private: ArcList _net_transform_arcs; ArcList _local_transform_arcs; + typedef pset< PT(PandaNode) > NodeList; + NodeList _net_transform_nodes; + NodeList _local_transform_nodes; + public: static void register_with_read_factory(void); virtual void write_datagram(BamWriter* manager, Datagram &me); diff --git a/panda/src/collide/qpcollisionNode.cxx b/panda/src/collide/qpcollisionNode.cxx index 39e8fdb58e..185447f366 100644 --- a/panda/src/collide/qpcollisionNode.cxx +++ b/panda/src/collide/qpcollisionNode.cxx @@ -39,6 +39,8 @@ qpCollisionNode(const string &name) : _into_collide_mask(CollideMask::all_on()), _collide_geom(false) { + // CollisionNodes are hidden by default. + set_draw_mask(DrawMask::all_off()); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/linmath/lmatrix4_src.cxx b/panda/src/linmath/lmatrix4_src.cxx index 93036bcf03..bb09dbbbbb 100644 --- a/panda/src/linmath/lmatrix4_src.cxx +++ b/panda/src/linmath/lmatrix4_src.cxx @@ -129,8 +129,17 @@ convert_mat(CoordinateSystem from, CoordinateSystem to) { //////////////////////////////////////////////////////////////////// int FLOATNAME(LMatrix4):: compare_to(const FLOATNAME(LMatrix4) &other, FLOATTYPE threshold) const { - for (int i = 0; i < 16; i++) { - if (!IS_THRESHOLD_EQUAL(_m.data[i], other._m.data[i], threshold)) { + FLOATTYPE scale = 1.0f / threshold; + + // We compare values in reverse order, since the last row of the + // matrix is most likely to be different between different matrices. + for (int i = 15; i >= 0; i--) { + // We scale both elements into the same range and truncate, rather + // than comparing the absolute values of their differences with + // IS_THRESHOLD_EQUAL. This prevents a slippery-slope effect + // where a == b and b == c but a != c. + if (cfloor(_m.data[i] * scale + 0.5) != + cfloor(other._m.data[i] * scale + 0.5)) { return (_m.data[i] < other._m.data[i]) ? -1 : 1; } } diff --git a/panda/src/pgraph/fogAttrib.cxx b/panda/src/pgraph/fogAttrib.cxx index f4b54b5b07..9929cc64f7 100644 --- a/panda/src/pgraph/fogAttrib.cxx +++ b/panda/src/pgraph/fogAttrib.cxx @@ -98,7 +98,14 @@ int FogAttrib:: compare_to_impl(const RenderAttrib *other) const { const FogAttrib *ta; DCAST_INTO_R(ta, other, 0); - return (int)(_fog - ta->_fog); + + // Comparing pointers by subtraction is problematic. Instead of + // doing this, we'll just depend on the built-in != and < operators + // for comparing pointers. + if (_fog != ta->_fog) { + return _fog < ta->_fog ? -1 : 1; + } + return 0; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/materialAttrib.cxx b/panda/src/pgraph/materialAttrib.cxx index 583135606d..916ac3b0ae 100644 --- a/panda/src/pgraph/materialAttrib.cxx +++ b/panda/src/pgraph/materialAttrib.cxx @@ -98,7 +98,14 @@ int MaterialAttrib:: compare_to_impl(const RenderAttrib *other) const { const MaterialAttrib *ta; DCAST_INTO_R(ta, other, 0); - return (int)(_material - ta->_material); + + // Comparing pointers by subtraction is problematic. Instead of + // doing this, we'll just depend on the built-in != and < operators + // for comparing pointers. + if (_material != ta->_material) { + return _material < ta->_material ? -1 : 1; + } + return 0; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index 12abc38636..7781b39864 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -398,6 +398,7 @@ PandaNode(const PandaNode ©) : cdata->_state = copy_cdata->_state; cdata->_effects = copy_cdata->_effects; cdata->_transform = copy_cdata->_transform; + cdata->_draw_mask = copy_cdata->_draw_mask; } //////////////////////////////////////////////////////////////////// @@ -1261,12 +1262,6 @@ children_changed() { //////////////////////////////////////////////////////////////////// PT(PandaNode) PandaNode:: r_copy_subgraph(PandaNode::InstanceMap &inst_map) const { - if (!safe_to_flatten()) { - // If this kind of node cannot be copied, quietly return the same - // pointer, making an instance instead of a copy. - return (PandaNode *)this; - } - PT(PandaNode) copy = make_copy(); nassertr(copy != (PandaNode *)NULL, NULL); if (copy->get_type() != get_type()) { diff --git a/panda/src/pgraph/qpcullTraverser.cxx b/panda/src/pgraph/qpcullTraverser.cxx index eda8ff418c..9aa511cca4 100644 --- a/panda/src/pgraph/qpcullTraverser.cxx +++ b/panda/src/pgraph/qpcullTraverser.cxx @@ -131,19 +131,21 @@ traverse_below(PandaNode *node, const CullTraverserData &data) { } } - // Now visit all the node's children. - PandaNode::Children cr = node->get_children(); - int num_children = cr.get_num_children(); + // Now visit all the node's children. We cannot use the + // node->get_children() interface, because that will keep a read + // pointer open, and we might end up changing this node during the + // traversal. + int num_children = node->get_num_children(); if (node->has_selective_visibility()) { int i = node->get_first_visible_child(); while (i < num_children) { - traverse(cr.get_child(i), data); + traverse(node->get_child(i), data); i = node->get_next_visible_child(i); } } else { for (int i = 0; i < num_children; i++) { - traverse(cr.get_child(i), data); + traverse(node->get_child(i), data); } } } diff --git a/panda/src/pgraph/qpsceneGraphReducer.cxx b/panda/src/pgraph/qpsceneGraphReducer.cxx index aa5cd8f842..54bd9c7f21 100644 --- a/panda/src/pgraph/qpsceneGraphReducer.cxx +++ b/panda/src/pgraph/qpsceneGraphReducer.cxx @@ -713,7 +713,7 @@ do_flatten_siblings(PandaNode *parent_node, PandaNode *child1, << "Collapsing " << *child1 << " and " << *child2 << "\n"; } - PT(PandaNode) new_child = collapse_nodes(child1, child2, true); + PT(PandaNode) new_child = collapse_nodes(child2, child1, true); if (new_child == (PandaNode *)NULL) { if (pgraph_cat.is_debug()) { pgraph_cat.debug() @@ -722,7 +722,7 @@ do_flatten_siblings(PandaNode *parent_node, PandaNode *child1, return NULL; } - choose_name(new_child, child1, child2); + choose_name(new_child, child2, child1); if (new_child == child1) { new_child->steal_children(child2); diff --git a/panda/src/pgraph/renderAttrib.cxx b/panda/src/pgraph/renderAttrib.cxx index 20782a9fa3..76dbd6609f 100644 --- a/panda/src/pgraph/renderAttrib.cxx +++ b/panda/src/pgraph/renderAttrib.cxx @@ -20,7 +20,7 @@ #include "bamReader.h" #include "indent.h" -RenderAttrib::Attribs RenderAttrib::_attribs; +RenderAttrib::Attribs *RenderAttrib::_attribs = NULL; TypeHandle RenderAttrib::_type_handle; //////////////////////////////////////////////////////////////////// @@ -30,7 +30,15 @@ TypeHandle RenderAttrib::_type_handle; //////////////////////////////////////////////////////////////////// RenderAttrib:: RenderAttrib() { - _saved_entry = _attribs.end(); + if (_attribs == (Attribs *)NULL) { + // Make sure the global _attribs map is allocated. This only has + // to be done once. We could make this map static, but then we + // run into problems if anyone creates a RenderState object at + // static init time; it also seems to cause problems when the + // Panda shared library is unloaded at application exit time. + _attribs = new Attribs; + } + _saved_entry = _attribs->end(); } //////////////////////////////////////////////////////////////////// @@ -61,9 +69,23 @@ operator = (const RenderAttrib &) { //////////////////////////////////////////////////////////////////// RenderAttrib:: ~RenderAttrib() { - if (_saved_entry != _attribs.end()) { - _attribs.erase(_saved_entry); - _saved_entry = _attribs.end(); + if (_saved_entry != _attribs->end()) { + // We cannot make this assertion, because the RenderAttrib has + // already partially destructed--this means we cannot look up the + // object in the map. In fact, the map is temporarily invalid + // until we finish destructing, since we screwed up the ordering + // when we changed the return value of get_type(). + // nassertv(_attribs->find(this) == _saved_entry); + + // Note: this isn't thread-safe, because once the derived class + // destructor exits and before this destructor completes, the map + // is invalid, and other threads may inadvertently attempt to read + // the invalid map. To make it thread-safe, we need to move this + // functionality to a separate method, that is to be called from + // *each* derived class's destructor (and then we can put the + // above assert back in). + _attribs->erase(_saved_entry); + _saved_entry = _attribs->end(); } } @@ -120,13 +142,13 @@ return_new(RenderAttrib *attrib) { // This should be a newly allocated pointer, not one that was used // for anything else. - nassertr(attrib->_saved_entry == _attribs.end(), attrib); + nassertr(attrib->_saved_entry == _attribs->end(), attrib); // Save the attrib in a local PointerTo so that it will be freed at // the end of this function if no one else uses it. CPT(RenderAttrib) pt_attrib = attrib; - pair result = _attribs.insert(attrib); + pair result = _attribs->insert(attrib); if (result.second) { // The attribute was inserted; save the iterator and return the // input attribute. diff --git a/panda/src/pgraph/renderAttrib.h b/panda/src/pgraph/renderAttrib.h index 953ee982b9..cb348a2712 100644 --- a/panda/src/pgraph/renderAttrib.h +++ b/panda/src/pgraph/renderAttrib.h @@ -85,7 +85,7 @@ protected: private: typedef pset > Attribs; - static Attribs _attribs; + static Attribs *_attribs; Attribs::iterator _saved_entry; diff --git a/panda/src/pgraph/renderEffect.cxx b/panda/src/pgraph/renderEffect.cxx index 5c103d24cf..acb865cddb 100644 --- a/panda/src/pgraph/renderEffect.cxx +++ b/panda/src/pgraph/renderEffect.cxx @@ -62,6 +62,7 @@ operator = (const RenderEffect &) { RenderEffect:: ~RenderEffect() { if (_saved_entry != _effects.end()) { + nassertv(_effects.find(this) == _saved_entry); _effects.erase(_saved_entry); _saved_entry = _effects.end(); } @@ -153,6 +154,7 @@ return_new(RenderEffect *effect) { // The effect was inserted; save the iterator and return the // input effect. effect->_saved_entry = result.first; + effect->ref(); // **** TEMPORARY HACK return pt_effect; } diff --git a/panda/src/pgraph/renderState.I b/panda/src/pgraph/renderState.I index 01c684bf62..7b3b1df85a 100644 --- a/panda/src/pgraph/renderState.I +++ b/panda/src/pgraph/renderState.I @@ -113,7 +113,7 @@ compare_to(const Attribute &other) const { return _type.get_index() - other._type.get_index(); } if (_attrib != other._attrib) { - return _attrib - other._attrib; + return _attrib < other._attrib ? -1 : 1; } return _override - other._override; } diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index 973759ae0e..43dffd9520 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -27,10 +27,11 @@ #include "indent.h" #include "compareTo.h" -RenderState::States RenderState::_states; +RenderState::States *RenderState::_states = NULL; CPT(RenderState) RenderState::_empty_state; TypeHandle RenderState::_type_handle; + //////////////////////////////////////////////////////////////////// // Function: RenderState::Constructor // Access: Protected @@ -40,7 +41,15 @@ TypeHandle RenderState::_type_handle; //////////////////////////////////////////////////////////////////// RenderState:: RenderState() { - _saved_entry = _states.end(); + if (_states == (States *)NULL) { + // Make sure the global _states map is allocated. This only has + // to be done once. We could make this map static, but then we + // run into problems if anyone creates a RenderState object at + // static init time; it also seems to cause problems when the + // Panda shared library is unloaded at application exit time. + _states = new States; + } + _saved_entry = _states->end(); _self_compose = (RenderState *)NULL; _flags = 0; } @@ -73,10 +82,10 @@ operator = (const RenderState &) { //////////////////////////////////////////////////////////////////// RenderState:: ~RenderState() { - // Remove the deleted RenderState object from the global pool. - if (_saved_entry != _states.end()) { - _states.erase(_saved_entry); - _saved_entry = _states.end(); + if (_saved_entry != _states->end()) { + nassertv(_states->find(this) == _saved_entry); + _states->erase(_saved_entry); + _saved_entry = _states->end(); } // Now make sure we clean up all other floating pointers to the @@ -725,20 +734,21 @@ return_new(RenderState *state) { // This should be a newly allocated pointer, not one that was used // for anything else. - nassertr(state->_saved_entry == _states.end(), state); + nassertr(state->_saved_entry == _states->end(), state); // Save the state in a local PointerTo so that it will be freed at // the end of this function if no one else uses it. CPT(RenderState) pt_state = state; - pair result = _states.insert(state); + pair result = _states->insert(state); + if (result.second) { // The state was inserted; save the iterator and return the // input state. state->_saved_entry = result.first; return pt_state; } - + // The state was not inserted; there must be an equivalent one // already in the set. Return that one. return *(result.first); @@ -976,8 +986,8 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) { // Now make sure the array is properly sorted. (It won't // necessarily preserve its correct sort after being read from bam, - // because the sort is based on TypeHandle indices, which can change - // from session to session.) + // because the sort is based on TypeHandle indices and raw pointers, + // both of which can change from session to session.) _attributes.sort(); return pi; diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index b98ea75a84..53b1ed1266 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -106,7 +106,7 @@ private: private: typedef pset > States; - static States _states; + static States *_states; static CPT(RenderState) _empty_state; // This iterator records the entry corresponding to this RenderState diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index f41cc0f25e..8beb4f51cb 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -98,7 +98,14 @@ int TextureAttrib:: compare_to_impl(const RenderAttrib *other) const { const TextureAttrib *ta; DCAST_INTO_R(ta, other, 0); - return (int)(_texture - ta->_texture); + + // Comparing pointers by subtraction is problematic. Instead of + // doing this, we'll just depend on the built-in != and < operators + // for comparing pointers. + if (_texture != ta->_texture) { + return _texture < ta->_texture ? -1 : 1; + } + return 0; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/transformState.cxx b/panda/src/pgraph/transformState.cxx index 67836d1d43..3be3db9587 100644 --- a/panda/src/pgraph/transformState.cxx +++ b/panda/src/pgraph/transformState.cxx @@ -24,7 +24,7 @@ #include "indent.h" #include "compareTo.h" -TransformState::States TransformState::_states; +TransformState::States *TransformState::_states = NULL; CPT(TransformState) TransformState::_identity_state; TypeHandle TransformState::_type_handle; @@ -37,7 +37,15 @@ TypeHandle TransformState::_type_handle; //////////////////////////////////////////////////////////////////// TransformState:: TransformState() { - _saved_entry = _states.end(); + if (_states == (States *)NULL) { + // Make sure the global _states map is allocated. This only has + // to be done once. We could make this map static, but then we + // run into problems if anyone creates a RenderState object at + // static init time; it also seems to cause problems when the + // Panda shared library is unloaded at application exit time. + _states = new States; + } + _saved_entry = _states->end(); _self_compose = (TransformState *)NULL; _flags = F_is_identity | F_singular_known; _inv_mat = (LMatrix4f *)NULL; @@ -77,9 +85,10 @@ TransformState:: } // Remove the deleted TransformState object from the global pool. - if (_saved_entry != _states.end()) { - _states.erase(_saved_entry); - _saved_entry = _states.end(); + if (_saved_entry != _states->end()) { + nassertv(_states->find(this) == _saved_entry); + _states->erase(_saved_entry); + _saved_entry = _states->end(); } // Now make sure we clean up all other floating pointers to the @@ -540,13 +549,13 @@ return_new(TransformState *state) { // This should be a newly allocated pointer, not one that was used // for anything else. - nassertr(state->_saved_entry == _states.end(), state); + nassertr(state->_saved_entry == _states->end(), state); // Save the state in a local PointerTo so that it will be freed at // the end of this function if no one else uses it. CPT(TransformState) pt_state = state; - pair result = _states.insert(state); + pair result = _states->insert(state); if (result.second) { // The state was inserted; save the iterator and return the // input state. diff --git a/panda/src/pgraph/transformState.h b/panda/src/pgraph/transformState.h index 09a18fde58..9a74f07673 100644 --- a/panda/src/pgraph/transformState.h +++ b/panda/src/pgraph/transformState.h @@ -109,7 +109,7 @@ private: private: typedef pset > States; - static States _states; + static States *_states; static CPT(TransformState) _identity_state; // This iterator records the entry corresponding to this TransformState diff --git a/panda/src/pgui/qppgTop.cxx b/panda/src/pgui/qppgTop.cxx index 7316f91384..7444df7161 100644 --- a/panda/src/pgui/qppgTop.cxx +++ b/panda/src/pgui/qppgTop.cxx @@ -20,6 +20,7 @@ #include "pgItem.h" #include "pgMouseWatcherGroup.h" #include "pgCullTraverser.h" +#include "cullBinAttrib.h" #include "omniBoundingVolume.h" @@ -40,6 +41,14 @@ qpPGTop(const string &name) : // culling. set_bound(OmniBoundingVolume()); set_final(true); + + // Also, screw state sorting. By default, everything under PGTop + // will be unsorted: rendered in scene graph order. This is closer + // to what the user wants anyway in a 2-d scene graph. + + // This override of 1000 should really be a system constant + // somewhere. + set_attrib(CullBinAttrib::make("unsorted", 0), 1000); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/text/config_text.cxx b/panda/src/text/config_text.cxx index 7169551c43..7a6fa3eeee 100644 --- a/panda/src/text/config_text.cxx +++ b/panda/src/text/config_text.cxx @@ -81,10 +81,13 @@ init_libtext() { string text_encoding = config_text.GetString("text-encoding", "iso8859"); if (text_encoding == "iso8859") { TextNode::_default_encoding = TextNode::E_iso8859; + qpTextNode::_default_encoding = qpTextNode::E_iso8859; } else if (text_encoding == "utf8") { TextNode::_default_encoding = TextNode::E_utf8; + qpTextNode::_default_encoding = qpTextNode::E_utf8; } else if (text_encoding == "unicode") { TextNode::_default_encoding = TextNode::E_unicode; + qpTextNode::_default_encoding = qpTextNode::E_unicode; } else { text_cat.error() << "Invalid text-encoding: " << text_encoding << "\n";