Panda3D
|
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 }