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