Panda3D
|
00001 // Filename: attribNodeRegistry.cxx 00002 // Created by: drose (07Jul07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "attribNodeRegistry.h" 00016 #include "lightMutexHolder.h" 00017 00018 AttribNodeRegistry * TVOLATILE AttribNodeRegistry::_global_ptr; 00019 00020 //////////////////////////////////////////////////////////////////// 00021 // Function: AttribNodeRegistry::Constructor 00022 // Access: Protected 00023 // Description: 00024 //////////////////////////////////////////////////////////////////// 00025 AttribNodeRegistry:: 00026 AttribNodeRegistry() { 00027 } 00028 00029 //////////////////////////////////////////////////////////////////// 00030 // Function: AttribNodeRegistry::add_node 00031 // Access: Published 00032 // Description: Adds the indicated NodePath to the registry. The 00033 // name and type of the node are noted at the time of 00034 // this call; if the name changes later, it will not 00035 // update the registry index. 00036 // 00037 // The NodePath must reference some kind of an attribute 00038 // node, such as a LightNode or a PlaneNode. When bam 00039 // files that reference an attribute node of the same 00040 // type and the same name are loaded, they will quietly 00041 // be redirected to reference this NodePath. 00042 // 00043 // If there is already a node matching the indicated 00044 // name and type, it will be replaced. 00045 //////////////////////////////////////////////////////////////////// 00046 void AttribNodeRegistry:: 00047 add_node(const NodePath &attrib_node) { 00048 nassertv(!attrib_node.is_empty()); 00049 LightMutexHolder holder(_lock); 00050 00051 pair<Entries::iterator, bool> result = _entries.insert(Entry(attrib_node)); 00052 if (!result.second) { 00053 // Replace an existing node. 00054 (*result.first)._node = attrib_node; 00055 } 00056 } 00057 00058 //////////////////////////////////////////////////////////////////// 00059 // Function: AttribNodeRegistry::remove_node 00060 // Access: Published 00061 // Description: Removes the indicated NodePath from the registry. 00062 // The name of the node must not have changed since the 00063 // matching call to add_node(), or it will not be 00064 // successfully removed. 00065 // 00066 // Returns true if the NodePath is found and removed, 00067 // false if it is not found (for instance, because the 00068 // name has changed). 00069 //////////////////////////////////////////////////////////////////// 00070 bool AttribNodeRegistry:: 00071 remove_node(const NodePath &attrib_node) { 00072 nassertr(!attrib_node.is_empty(), false); 00073 LightMutexHolder holder(_lock); 00074 Entries::iterator ei = _entries.find(Entry(attrib_node)); 00075 if (ei != _entries.end()) { 00076 _entries.erase(ei); 00077 return true; 00078 } 00079 return false; 00080 } 00081 00082 //////////////////////////////////////////////////////////////////// 00083 // Function: AttribNodeRegistry::lookup_node 00084 // Access: Published 00085 // Description: Looks up the indicated NodePath in the registry. If 00086 // there is a node already in the registry with the 00087 // matching name and type, returns that NodePath 00088 // instead; otherwise, returns the original NodePath. 00089 //////////////////////////////////////////////////////////////////// 00090 NodePath AttribNodeRegistry:: 00091 lookup_node(const NodePath &orig_node) const { 00092 nassertr(!orig_node.is_empty(), orig_node); 00093 00094 LightMutexHolder holder(_lock); 00095 Entries::const_iterator ei = _entries.find(Entry(orig_node)); 00096 if (ei != _entries.end()) { 00097 return (*ei)._node; 00098 } 00099 return orig_node; 00100 } 00101 00102 //////////////////////////////////////////////////////////////////// 00103 // Function: AttribNodeRegistry::get_num_nodes 00104 // Access: Published 00105 // Description: Returns the total number of nodes in the registry. 00106 //////////////////////////////////////////////////////////////////// 00107 int AttribNodeRegistry:: 00108 get_num_nodes() const { 00109 LightMutexHolder holder(_lock); 00110 return _entries.size(); 00111 } 00112 00113 //////////////////////////////////////////////////////////////////// 00114 // Function: AttribNodeRegistry::get_node 00115 // Access: Published 00116 // Description: Returns the nth NodePath recorded in the registry. 00117 //////////////////////////////////////////////////////////////////// 00118 NodePath AttribNodeRegistry:: 00119 get_node(int n) const { 00120 LightMutexHolder holder(_lock); 00121 nassertr(n >= 0 && n < (int)_entries.size(), NodePath()); 00122 return _entries[n]._node; 00123 } 00124 00125 //////////////////////////////////////////////////////////////////// 00126 // Function: AttribNodeRegistry::get_node_type 00127 // Access: Published 00128 // Description: Returns the type of the nth node, as recorded in the 00129 // registry. 00130 //////////////////////////////////////////////////////////////////// 00131 TypeHandle AttribNodeRegistry:: 00132 get_node_type(int n) const { 00133 LightMutexHolder holder(_lock); 00134 nassertr(n >= 0 && n < (int)_entries.size(), TypeHandle::none()); 00135 return _entries[n]._type; 00136 } 00137 00138 //////////////////////////////////////////////////////////////////// 00139 // Function: AttribNodeRegistry::get_node_name 00140 // Access: Published 00141 // Description: Returns the name of the nth node, as recorded in the 00142 // registry. This will be the node name as it was at 00143 // the time the node was recorded; if the node has 00144 // changed names since then, this will still return the 00145 // original name. 00146 //////////////////////////////////////////////////////////////////// 00147 string AttribNodeRegistry:: 00148 get_node_name(int n) const { 00149 LightMutexHolder holder(_lock); 00150 nassertr(n >= 0 && n < (int)_entries.size(), string()); 00151 return _entries[n]._name; 00152 } 00153 00154 //////////////////////////////////////////////////////////////////// 00155 // Function: AttribNodeRegistry::find_node 00156 // Access: Published 00157 // Description: Returns the index number of the indicated NodePath in 00158 // the registry (assuming its name hasn't changed since 00159 // it was recorded in the registry), or -1 if the 00160 // NodePath cannot be found (for instance, because its 00161 // name has changed). 00162 //////////////////////////////////////////////////////////////////// 00163 int AttribNodeRegistry:: 00164 find_node(const NodePath &attrib_node) const { 00165 nassertr(!attrib_node.is_empty(), -1); 00166 LightMutexHolder holder(_lock); 00167 Entries::const_iterator ei = _entries.find(Entry(attrib_node)); 00168 if (ei != _entries.end()) { 00169 return ei - _entries.begin(); 00170 } 00171 return -1; 00172 } 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: AttribNodeRegistry::find_node 00176 // Access: Published 00177 // Description: Returns the index number of the node with the 00178 // indicated type and name in the registry, or -1 if 00179 // there is no such node in the registry. 00180 //////////////////////////////////////////////////////////////////// 00181 int AttribNodeRegistry:: 00182 find_node(TypeHandle type, const string &name) const { 00183 LightMutexHolder holder(_lock); 00184 Entries::const_iterator ei = _entries.find(Entry(type, name)); 00185 if (ei != _entries.end()) { 00186 return ei - _entries.begin(); 00187 } 00188 return -1; 00189 } 00190 00191 //////////////////////////////////////////////////////////////////// 00192 // Function: AttribNodeRegistry::remove_node 00193 // Access: Published 00194 // Description: Removes the nth node from the registry. 00195 //////////////////////////////////////////////////////////////////// 00196 void AttribNodeRegistry:: 00197 remove_node(int n) { 00198 LightMutexHolder holder(_lock); 00199 nassertv(n >= 0 && n < (int)_entries.size()); 00200 _entries.erase(_entries.begin() + n); 00201 } 00202 00203 //////////////////////////////////////////////////////////////////// 00204 // Function: AttribNodeRegistry::clear 00205 // Access: Published 00206 // Description: Removes all nodes from the registry. 00207 //////////////////////////////////////////////////////////////////// 00208 void AttribNodeRegistry:: 00209 clear() { 00210 LightMutexHolder holder(_lock); 00211 _entries.clear(); 00212 } 00213 00214 //////////////////////////////////////////////////////////////////// 00215 // Function: AttribNodeRegistry::output 00216 // Access: Published 00217 // Description: 00218 //////////////////////////////////////////////////////////////////// 00219 void AttribNodeRegistry:: 00220 output(ostream &out) const { 00221 LightMutexHolder holder(_lock); 00222 00223 typedef pmap<TypeHandle, int> Counts; 00224 Counts counts; 00225 00226 Entries::const_iterator ei; 00227 for (ei = _entries.begin(); ei != _entries.end(); ++ei) { 00228 TypeHandle type = (*ei)._type; 00229 Counts::iterator ci = counts.insert(Counts::value_type(type, 0)).first; 00230 ++((*ci).second); 00231 } 00232 00233 out << _entries.size() << " entries"; 00234 00235 if (!counts.empty()) { 00236 Counts::iterator ci = counts.begin(); 00237 out << " (" << (*ci).first << ":" << (*ci).second; 00238 ++ci; 00239 while (ci != counts.end()) { 00240 out << ", " << (*ci).first << ":" << (*ci).second; 00241 ++ci; 00242 } 00243 out << ")"; 00244 } 00245 } 00246 00247 //////////////////////////////////////////////////////////////////// 00248 // Function: AttribNodeRegistry::write 00249 // Access: Published 00250 // Description: 00251 //////////////////////////////////////////////////////////////////// 00252 void AttribNodeRegistry:: 00253 write(ostream &out) const { 00254 LightMutexHolder holder(_lock); 00255 00256 Entries::const_iterator ei; 00257 for (ei = _entries.begin(); ei != _entries.end(); ++ei) { 00258 const Entry &entry = (*ei); 00259 out << entry._type << ", \"" << entry._name << "\": " << entry._node 00260 << "\n"; 00261 } 00262 } 00263 00264 //////////////////////////////////////////////////////////////////// 00265 // Function: AttribNodeRegistry::make_global_ptr 00266 // Access: Private, Static 00267 // Description: 00268 //////////////////////////////////////////////////////////////////// 00269 void AttribNodeRegistry:: 00270 make_global_ptr() { 00271 AttribNodeRegistry *ptr = new AttribNodeRegistry; 00272 void *result = AtomicAdjust::compare_and_exchange_ptr 00273 ((void * TVOLATILE &)_global_ptr, (void *)NULL, (void *)ptr); 00274 if (result != NULL) { 00275 // Someone else got there first. 00276 delete ptr; 00277 } 00278 assert(_global_ptr != (AttribNodeRegistry *)NULL); 00279 }