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