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 */
45 void EggNameUniquifier::
46 clear() {
47 _categories.clear();
48 _index = 0;
49 }
50
51 /**
52 * Begins the traversal from the indicated node.
53 */
54 void EggNameUniquifier::
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 */
104 EggNode *EggNameUniquifier::
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 */
126 bool EggNameUniquifier::
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 */
149 bool EggNameUniquifier::
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::
162 filter_name(EggNode *node) {
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 }
EggGroupNode
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
EggNameUniquifier::add_name
bool add_name(const std::string &category, const std::string &name, EggNode *node=nullptr)
Adds the name to the indicated category.
Definition: eggNameUniquifier.cxx:150
EggNameUniquifier::filter_name
virtual std::string filter_name(EggNode *node)
Returns the name of the given node, or at least the name it should be.
Definition: eggNameUniquifier.cxx:162
EggNameUniquifier::get_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.
Definition: eggNameUniquifier.cxx:105
EggNameUniquifier::generate_name
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.
Definition: eggNameUniquifier.cxx:175
EggNameUniquifier::clear
void clear()
Empties the table of used named and prepares the Uniquifier for a new tree.
Definition: eggNameUniquifier.cxx:46
EggNameUniquifier::uniquify
void uniquify(EggNode *node)
Begins the traversal from the indicated node.
Definition: eggNameUniquifier.cxx:55
EggNameUniquifier::has_name
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.
Definition: eggNameUniquifier.cxx:127
EggNode
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:36
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
pmap
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
config_egg.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggGroupNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggNameUniquifier.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pnotify.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.