Panda3D
 All Classes Functions Variables Enumerations
attribNodeRegistry.cxx
1 // Filename: attribNodeRegistry.cxx
2 // Created by: drose (07Jul07)
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 "attribNodeRegistry.h"
16 #include "lightMutexHolder.h"
17 
18 AttribNodeRegistry * TVOLATILE AttribNodeRegistry::_global_ptr;
19 
20 ////////////////////////////////////////////////////////////////////
21 // Function: AttribNodeRegistry::Constructor
22 // Access: Protected
23 // Description:
24 ////////////////////////////////////////////////////////////////////
25 AttribNodeRegistry::
26 AttribNodeRegistry() {
27 }
28 
29 ////////////////////////////////////////////////////////////////////
30 // Function: AttribNodeRegistry::add_node
31 // Access: Published
32 // Description: Adds the indicated NodePath to the registry. The
33 // name and type of the node are noted at the time of
34 // this call; if the name changes later, it will not
35 // update the registry index.
36 //
37 // The NodePath must reference some kind of an attribute
38 // node, such as a LightNode or a PlaneNode. When bam
39 // files that reference an attribute node of the same
40 // type and the same name are loaded, they will quietly
41 // be redirected to reference this NodePath.
42 //
43 // If there is already a node matching the indicated
44 // name and type, it will be replaced.
45 ////////////////////////////////////////////////////////////////////
47 add_node(const NodePath &attrib_node) {
48  nassertv(!attrib_node.is_empty());
49  LightMutexHolder holder(_lock);
50 
51  pair<Entries::iterator, bool> result = _entries.insert(Entry(attrib_node));
52  if (!result.second) {
53  // Replace an existing node.
54  (*result.first)._node = attrib_node;
55  }
56 }
57 
58 ////////////////////////////////////////////////////////////////////
59 // Function: AttribNodeRegistry::remove_node
60 // Access: Published
61 // Description: Removes the indicated NodePath from the registry.
62 // The name of the node must not have changed since the
63 // matching call to add_node(), or it will not be
64 // successfully removed.
65 //
66 // Returns true if the NodePath is found and removed,
67 // false if it is not found (for instance, because the
68 // name has changed).
69 ////////////////////////////////////////////////////////////////////
71 remove_node(const NodePath &attrib_node) {
72  nassertr(!attrib_node.is_empty(), false);
73  LightMutexHolder holder(_lock);
74  Entries::iterator ei = _entries.find(Entry(attrib_node));
75  if (ei != _entries.end()) {
76  _entries.erase(ei);
77  return true;
78  }
79  return false;
80 }
81 
82 ////////////////////////////////////////////////////////////////////
83 // Function: AttribNodeRegistry::lookup_node
84 // Access: Published
85 // Description: Looks up the indicated NodePath in the registry. If
86 // there is a node already in the registry with the
87 // matching name and type, returns that NodePath
88 // instead; otherwise, returns the original NodePath.
89 ////////////////////////////////////////////////////////////////////
91 lookup_node(const NodePath &orig_node) const {
92  nassertr(!orig_node.is_empty(), orig_node);
93 
94  LightMutexHolder holder(_lock);
95  Entries::const_iterator ei = _entries.find(Entry(orig_node));
96  if (ei != _entries.end()) {
97  return (*ei)._node;
98  }
99  return orig_node;
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function: AttribNodeRegistry::get_num_nodes
104 // Access: Published
105 // Description: Returns the total number of nodes in the registry.
106 ////////////////////////////////////////////////////////////////////
108 get_num_nodes() const {
109  LightMutexHolder holder(_lock);
110  return _entries.size();
111 }
112 
113 ////////////////////////////////////////////////////////////////////
114 // Function: AttribNodeRegistry::get_node
115 // Access: Published
116 // Description: Returns the nth NodePath recorded in the registry.
117 ////////////////////////////////////////////////////////////////////
119 get_node(int n) const {
120  LightMutexHolder holder(_lock);
121  nassertr(n >= 0 && n < (int)_entries.size(), NodePath());
122  return _entries[n]._node;
123 }
124 
125 ////////////////////////////////////////////////////////////////////
126 // Function: AttribNodeRegistry::get_node_type
127 // Access: Published
128 // Description: Returns the type of the nth node, as recorded in the
129 // registry.
130 ////////////////////////////////////////////////////////////////////
132 get_node_type(int n) const {
133  LightMutexHolder holder(_lock);
134  nassertr(n >= 0 && n < (int)_entries.size(), TypeHandle::none());
135  return _entries[n]._type;
136 }
137 
138 ////////////////////////////////////////////////////////////////////
139 // Function: AttribNodeRegistry::get_node_name
140 // Access: Published
141 // Description: Returns the name of the nth node, as recorded in the
142 // registry. This will be the node name as it was at
143 // the time the node was recorded; if the node has
144 // changed names since then, this will still return the
145 // original name.
146 ////////////////////////////////////////////////////////////////////
148 get_node_name(int n) const {
149  LightMutexHolder holder(_lock);
150  nassertr(n >= 0 && n < (int)_entries.size(), string());
151  return _entries[n]._name;
152 }
153 
154 ////////////////////////////////////////////////////////////////////
155 // Function: AttribNodeRegistry::find_node
156 // Access: Published
157 // Description: Returns the index number of the indicated NodePath in
158 // the registry (assuming its name hasn't changed since
159 // it was recorded in the registry), or -1 if the
160 // NodePath cannot be found (for instance, because its
161 // name has changed).
162 ////////////////////////////////////////////////////////////////////
164 find_node(const NodePath &attrib_node) const {
165  nassertr(!attrib_node.is_empty(), -1);
166  LightMutexHolder holder(_lock);
167  Entries::const_iterator ei = _entries.find(Entry(attrib_node));
168  if (ei != _entries.end()) {
169  return ei - _entries.begin();
170  }
171  return -1;
172 }
173 
174 ////////////////////////////////////////////////////////////////////
175 // Function: AttribNodeRegistry::find_node
176 // Access: Published
177 // Description: Returns the index number of the node with the
178 // indicated type and name in the registry, or -1 if
179 // there is no such node in the registry.
180 ////////////////////////////////////////////////////////////////////
182 find_node(TypeHandle type, const string &name) const {
183  LightMutexHolder holder(_lock);
184  Entries::const_iterator ei = _entries.find(Entry(type, name));
185  if (ei != _entries.end()) {
186  return ei - _entries.begin();
187  }
188  return -1;
189 }
190 
191 ////////////////////////////////////////////////////////////////////
192 // Function: AttribNodeRegistry::remove_node
193 // Access: Published
194 // Description: Removes the nth node from the registry.
195 ////////////////////////////////////////////////////////////////////
197 remove_node(int n) {
198  LightMutexHolder holder(_lock);
199  nassertv(n >= 0 && n < (int)_entries.size());
200  _entries.erase(_entries.begin() + n);
201 }
202 
203 ////////////////////////////////////////////////////////////////////
204 // Function: AttribNodeRegistry::clear
205 // Access: Published
206 // Description: Removes all nodes from the registry.
207 ////////////////////////////////////////////////////////////////////
209 clear() {
210  LightMutexHolder holder(_lock);
211  _entries.clear();
212 }
213 
214 ////////////////////////////////////////////////////////////////////
215 // Function: AttribNodeRegistry::output
216 // Access: Published
217 // Description:
218 ////////////////////////////////////////////////////////////////////
219 void AttribNodeRegistry::
220 output(ostream &out) const {
221  LightMutexHolder holder(_lock);
222 
223  typedef pmap<TypeHandle, int> Counts;
224  Counts counts;
225 
226  Entries::const_iterator ei;
227  for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
228  TypeHandle type = (*ei)._type;
229  Counts::iterator ci = counts.insert(Counts::value_type(type, 0)).first;
230  ++((*ci).second);
231  }
232 
233  out << _entries.size() << " entries";
234 
235  if (!counts.empty()) {
236  Counts::iterator ci = counts.begin();
237  out << " (" << (*ci).first << ":" << (*ci).second;
238  ++ci;
239  while (ci != counts.end()) {
240  out << ", " << (*ci).first << ":" << (*ci).second;
241  ++ci;
242  }
243  out << ")";
244  }
245 }
246 
247 ////////////////////////////////////////////////////////////////////
248 // Function: AttribNodeRegistry::write
249 // Access: Published
250 // Description:
251 ////////////////////////////////////////////////////////////////////
252 void AttribNodeRegistry::
253 write(ostream &out) const {
254  LightMutexHolder holder(_lock);
255 
256  Entries::const_iterator ei;
257  for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
258  const Entry &entry = (*ei);
259  out << entry._type << ", \"" << entry._name << "\": " << entry._node
260  << "\n";
261  }
262 }
263 
264 ////////////////////////////////////////////////////////////////////
265 // Function: AttribNodeRegistry::make_global_ptr
266 // Access: Private, Static
267 // Description:
268 ////////////////////////////////////////////////////////////////////
269 void AttribNodeRegistry::
270 make_global_ptr() {
273  ((void * TVOLATILE &)_global_ptr, (void *)NULL, (void *)ptr);
274  if (result != NULL) {
275  // Someone else got there first.
276  delete ptr;
277  }
278  assert(_global_ptr != (AttribNodeRegistry *)NULL);
279 }
NodePath get_node(int n) const
Returns the nth NodePath recorded in the registry.
This is our own Panda specialization on the default STL map.
Definition: pmap.h:52
NodePath lookup_node(const NodePath &orig_node) const
Looks up the indicated NodePath in the registry.
static TypeHandle none()
Returns a special zero-valued TypeHandle that is used to indicate no type.
Definition: typeHandle.I:274
void clear()
Removes all elements from the ordered vector.
This global object records NodePaths that are referenced by scene graph attribs, such as ClipPlaneAtt...
bool remove_node(const NodePath &attrib_node)
Removes the indicated NodePath from the registry.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
string get_node_name(int n) const
Returns the name of the nth node, as recorded in the registry.
Similar to MutexHolder, but for a light mutex.
void add_node(const NodePath &attrib_node)
Adds the indicated NodePath to the registry.
int find_node(const NodePath &attrib_node) const
Returns the index number of the indicated NodePath in the registry (assuming its name hasn&#39;t changed ...
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:236
size_type_0 size() const
Returns the number of elements in the ordered vector.
TypeHandle get_node_type(int n) const
Returns the type of the nth node, as recorded in the registry.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165
void clear()
Removes all nodes from the registry.
static Pointer compare_and_exchange_ptr(Pointer &mem, Pointer old_value, Pointer new_value)
Atomic compare and exchange.
int get_num_nodes() const
Returns the total number of nodes in the registry.