Panda3D
 All Classes Functions Variables Enumerations
eggNameUniquifier.cxx
1 // Filename: eggNameUniquifier.cxx
2 // Created by: drose (09Nov00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "eggNameUniquifier.h"
16 #include "eggNode.h"
17 #include "eggGroupNode.h"
18 #include "config_egg.h"
19 #include "dcast.h"
20 
21 #include "pnotify.h"
22 
23 TypeHandle EggNameUniquifier::_type_handle;
24 
25 
26 ////////////////////////////////////////////////////////////////////
27 // Function: EggNameUniquifier::Constructor
28 // Access: Public
29 // Description:
30 ////////////////////////////////////////////////////////////////////
31 EggNameUniquifier::
32 EggNameUniquifier() {
33  _index = 0;
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: EggNameUniquifier::Destructor
38 // Access: Public
39 // Description:
40 ////////////////////////////////////////////////////////////////////
41 EggNameUniquifier::
42 ~EggNameUniquifier() {
43 }
44 
45 ////////////////////////////////////////////////////////////////////
46 // Function: EggNameUniquifier::clear
47 // Access: Public
48 // Description: Empties the table of used named and prepares the
49 // Uniquifier for a new tree.
50 ////////////////////////////////////////////////////////////////////
52 clear() {
53  _categories.clear();
54  _index = 0;
55 }
56 
57 ////////////////////////////////////////////////////////////////////
58 // Function: EggNameUniquifier::uniquify
59 // Access: Public
60 // Description: Begins the traversal from the indicated node.
61 ////////////////////////////////////////////////////////////////////
63 uniquify(EggNode *node) {
64  string category = get_category(node);
65  if (egg_cat.is_debug()) {
66  egg_cat.debug()
67  << "Uniquifying " << node->get_name() << ", category = " << category
68  << "\n";
69  }
70 
71  if (!category.empty()) {
72  string name = filter_name(node);
73 
74  UsedNames &names = _categories[category];
75  bool inserted = false;
76  if (!name.empty()) {
77  inserted = names.insert(UsedNames::value_type(name, node)).second;
78  }
79 
80  while (!inserted) {
81  _index++;
82  name = generate_name(node, category, _index);
83  inserted = names.insert(UsedNames::value_type(name, node)).second;
84  }
85 
86  if (egg_cat.is_debug()) {
87  egg_cat.debug()
88  << "Uniquifying " << node->get_name() << " to "
89  << name << "\n";
90  }
91 
92  node->set_name(name);
93  }
94 
95  if (node->is_of_type(EggGroupNode::get_class_type())) {
96  EggGroupNode *group;
97  DCAST_INTO_V(group, node);
98 
99  EggGroupNode::iterator ci;
100  for (ci = group->begin(); ci != group->end(); ++ci) {
101  EggNode *child = (*ci);
102  nassertv(child != (EggNode *)NULL);
103  uniquify(child);
104  }
105  }
106 }
107 
108 ////////////////////////////////////////////////////////////////////
109 // Function: EggNameUniquifier::get_node
110 // Access: Public
111 // Description: Returns the node associated with the given category
112 // and name, or NULL if the name has not been used.
113 ////////////////////////////////////////////////////////////////////
115 get_node(const string &category, const string &name) const {
116  Categories::const_iterator ci;
117  ci = _categories.find(category);
118  if (ci == _categories.end()) {
119  return (EggNode *)NULL;
120  }
121 
122  const UsedNames &names = (*ci).second;
123  UsedNames::const_iterator ni;
124  ni = names.find(name);
125  if (ni == names.end()) {
126  return (EggNode *)NULL;
127  }
128 
129  return (*ni).second;
130 }
131 
132 ////////////////////////////////////////////////////////////////////
133 // Function: EggNameUniquifier::has_name
134 // Access: Public
135 // Description: Returns true if the name has been used for the
136 // indicated category already, false otherwise.
137 ////////////////////////////////////////////////////////////////////
139 has_name(const string &category, const string &name) const {
140  Categories::const_iterator ci;
141  ci = _categories.find(category);
142  if (ci == _categories.end()) {
143  return false;
144  }
145 
146  const UsedNames &names = (*ci).second;
147  UsedNames::const_iterator ni;
148  ni = names.find(name);
149  if (ni == names.end()) {
150  return false;
151  }
152 
153  return true;
154 }
155 
156 ////////////////////////////////////////////////////////////////////
157 // Function: EggNameUniquifier::add_name
158 // Access: Public
159 // Description: Adds the name to the indicated category. This name
160 // will not be used for any other egg node within this
161 // category. Returns true if the name was added, or
162 // false if it was already in use for the category.
163 ////////////////////////////////////////////////////////////////////
165 add_name(const string &category, const string &name, EggNode *node) {
166  UsedNames &names = _categories[category];
167  bool inserted = names.insert(UsedNames::value_type(name, node)).second;
168  return inserted;
169 }
170 
171 ////////////////////////////////////////////////////////////////////
172 // Function: EggNameUniquifier::filter_name
173 // Access: Public, Virtual
174 // Description: Returns the name of the given node, or at least the
175 // name it should be. This provides a hook to adjust
176 // the name before attempting to uniquify it, if
177 // desired, for instance to remove invalid characters.
178 ////////////////////////////////////////////////////////////////////
179 string EggNameUniquifier::
181  return node->get_name();
182 }
183 
184 ////////////////////////////////////////////////////////////////////
185 // Function: EggNameUniquifier::generate_name
186 // Access: Public, Virtual
187 // Description: Generates a new name for the given node when its
188 // existing name clashes with some other node. This
189 // function will be called repeatedly, if necessary,
190 // until it returns a name that actually is unique.
191 //
192 // The category is the string returned by
193 // get_category(), and index is a uniquely-generated
194 // number that may be useful for synthesizing the name.
195 ////////////////////////////////////////////////////////////////////
196 string EggNameUniquifier::
197 generate_name(EggNode *node, const string &category, int index) {
198  string name = filter_name(node);
199 
200  ostringstream str;
201  if (name.empty()) {
202  str << category << index;
203  } else {
204  str << name << "." << category << index;
205  }
206  return str.str();
207 }
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:51
void clear()
Empties the table of used named and prepares the Uniquifier for a new tree.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
virtual string filter_name(EggNode *node)
Returns the name of the given node, or at least the name it should be.
EggNode * get_node(const string &category, const string &name) const
Returns the node associated with the given category and name, or NULL if the name has not been used...
void uniquify(EggNode *node)
Begins the traversal from the indicated node.
bool has_name(const string &category, const string &name) const
Returns true if the name has been used for the indicated category already, false otherwise.
virtual string generate_name(EggNode *node, const string &category, int index)
Generates a new name for the given node when its existing name clashes with some other node...
bool add_name(const string &category, const string &name, EggNode *node=NULL)
Adds the name to the indicated category.
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:38
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85