Panda3D

eggNameUniquifier.cxx

00001 // Filename: eggNameUniquifier.cxx
00002 // Created by:  drose (09Nov00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "eggNameUniquifier.h"
00016 #include "eggNode.h"
00017 #include "eggGroupNode.h"
00018 #include "config_egg.h"
00019 #include "dcast.h"
00020 
00021 #include "pnotify.h"
00022 
00023 TypeHandle EggNameUniquifier::_type_handle;
00024 
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: EggNameUniquifier::Constructor
00028 //       Access: Public
00029 //  Description:
00030 ////////////////////////////////////////////////////////////////////
00031 EggNameUniquifier::
00032 EggNameUniquifier() {
00033   _index = 0;
00034 }
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: EggNameUniquifier::Destructor
00038 //       Access: Public
00039 //  Description:
00040 ////////////////////////////////////////////////////////////////////
00041 EggNameUniquifier::
00042 ~EggNameUniquifier() {
00043 }
00044 
00045 ////////////////////////////////////////////////////////////////////
00046 //     Function: EggNameUniquifier::clear
00047 //       Access: Public
00048 //  Description: Empties the table of used named and prepares the
00049 //               Uniquifier for a new tree.
00050 ////////////////////////////////////////////////////////////////////
00051 void EggNameUniquifier::
00052 clear() {
00053   _categories.clear();
00054   _index = 0;
00055 }
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: EggNameUniquifier::uniquify
00059 //       Access: Public
00060 //  Description: Begins the traversal from the indicated node.
00061 ////////////////////////////////////////////////////////////////////
00062 void EggNameUniquifier::
00063 uniquify(EggNode *node) {
00064   string category = get_category(node);
00065   if (egg_cat.is_debug()) {
00066     egg_cat.debug()
00067       << "Uniquifying " << node->get_name() << ", category = " << category
00068       << "\n";
00069   }
00070 
00071   if (!category.empty()) {
00072     string name = filter_name(node);
00073 
00074     UsedNames &names = _categories[category];
00075     bool inserted = false;
00076     if (!name.empty()) {
00077       inserted = names.insert(UsedNames::value_type(name, node)).second;
00078     }
00079 
00080     while (!inserted) {
00081       _index++;
00082       name = generate_name(node, category, _index);
00083       inserted = names.insert(UsedNames::value_type(name, node)).second;
00084     }
00085 
00086     if (egg_cat.is_debug()) {
00087       egg_cat.debug()
00088         << "Uniquifying " << node->get_name() << " to "
00089         << name << "\n";
00090     }
00091 
00092     node->set_name(name);
00093   }
00094 
00095   if (node->is_of_type(EggGroupNode::get_class_type())) {
00096     EggGroupNode *group;
00097     DCAST_INTO_V(group, node);
00098 
00099     EggGroupNode::iterator ci;
00100     for (ci = group->begin(); ci != group->end(); ++ci) {
00101       EggNode *child = (*ci);
00102       nassertv(child != (EggNode *)NULL);
00103       uniquify(child);
00104     }
00105   }
00106 }
00107 
00108 ////////////////////////////////////////////////////////////////////
00109 //     Function: EggNameUniquifier::get_node
00110 //       Access: Public
00111 //  Description: Returns the node associated with the given category
00112 //               and name, or NULL if the name has not been used.
00113 ////////////////////////////////////////////////////////////////////
00114 EggNode *EggNameUniquifier::
00115 get_node(const string &category, const string &name) const {
00116   Categories::const_iterator ci;
00117   ci = _categories.find(category);
00118   if (ci == _categories.end()) {
00119     return (EggNode *)NULL;
00120   }
00121 
00122   const UsedNames &names = (*ci).second;
00123   UsedNames::const_iterator ni;
00124   ni = names.find(name);
00125   if (ni == names.end()) {
00126     return (EggNode *)NULL;
00127   }
00128 
00129   return (*ni).second;
00130 }
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //     Function: EggNameUniquifier::has_name
00134 //       Access: Public
00135 //  Description: Returns true if the name has been used for the
00136 //               indicated category already, false otherwise.
00137 ////////////////////////////////////////////////////////////////////
00138 bool EggNameUniquifier::
00139 has_name(const string &category, const string &name) const {
00140   Categories::const_iterator ci;
00141   ci = _categories.find(category);
00142   if (ci == _categories.end()) {
00143     return false;
00144   }
00145 
00146   const UsedNames &names = (*ci).second;
00147   UsedNames::const_iterator ni;
00148   ni = names.find(name);
00149   if (ni == names.end()) {
00150     return false;
00151   }
00152 
00153   return true;
00154 }
00155 
00156 ////////////////////////////////////////////////////////////////////
00157 //     Function: EggNameUniquifier::add_name
00158 //       Access: Public
00159 //  Description: Adds the name to the indicated category.  This name
00160 //               will not be used for any other egg node within this
00161 //               category.  Returns true if the name was added, or
00162 //               false if it was already in use for the category.
00163 ////////////////////////////////////////////////////////////////////
00164 bool EggNameUniquifier::
00165 add_name(const string &category, const string &name, EggNode *node) {
00166   UsedNames &names = _categories[category];
00167   bool inserted = names.insert(UsedNames::value_type(name, node)).second;
00168   return inserted;
00169 }
00170 
00171 ////////////////////////////////////////////////////////////////////
00172 //     Function: EggNameUniquifier::filter_name
00173 //       Access: Public, Virtual
00174 //  Description: Returns the name of the given node, or at least the
00175 //               name it should be.  This provides a hook to adjust
00176 //               the name before attempting to uniquify it, if
00177 //               desired, for instance to remove invalid characters.
00178 ////////////////////////////////////////////////////////////////////
00179 string EggNameUniquifier::
00180 filter_name(EggNode *node) {
00181   return node->get_name();
00182 }
00183 
00184 ////////////////////////////////////////////////////////////////////
00185 //     Function: EggNameUniquifier::generate_name
00186 //       Access: Public, Virtual
00187 //  Description: Generates a new name for the given node when its
00188 //               existing name clashes with some other node.  This
00189 //               function will be called repeatedly, if necessary,
00190 //               until it returns a name that actually is unique.
00191 //
00192 //               The category is the string returned by
00193 //               get_category(), and index is a uniquely-generated
00194 //               number that may be useful for synthesizing the name.
00195 ////////////////////////////////////////////////////////////////////
00196 string EggNameUniquifier::
00197 generate_name(EggNode *node, const string &category, int index) {
00198   string name = filter_name(node);
00199 
00200   ostringstream str;
00201   if (name.empty()) {
00202     str << category << index;
00203   } else {
00204     str << name << "." << category << index;
00205   }
00206   return str.str();
00207 }
 All Classes Functions Variables Enumerations