280 lines
10 KiB
C++
280 lines
10 KiB
C++
// Filename: attribNodeRegistry.cxx
|
|
// Created by: drose (07Jul07)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
//
|
|
// All use of this software is subject to the terms of the revised BSD
|
|
// license. You should have received a copy of this license along
|
|
// with this source code in a file named "LICENSE."
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "attribNodeRegistry.h"
|
|
#include "lightMutexHolder.h"
|
|
|
|
AttribNodeRegistry * TVOLATILE AttribNodeRegistry::_global_ptr;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::Constructor
|
|
// Access: Protected
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
AttribNodeRegistry::
|
|
AttribNodeRegistry() {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::add_node
|
|
// Access: Published
|
|
// Description: Adds the indicated NodePath to the registry. The
|
|
// name and type of the node are noted at the time of
|
|
// this call; if the name changes later, it will not
|
|
// update the registry index.
|
|
//
|
|
// The NodePath must reference some kind of an attribute
|
|
// node, such as a LightNode or a PlaneNode. When bam
|
|
// files that reference an attribute node of the same
|
|
// type and the same name are loaded, they will quietly
|
|
// be redirected to reference this NodePath.
|
|
//
|
|
// If there is already a node matching the indicated
|
|
// name and type, it will be replaced.
|
|
////////////////////////////////////////////////////////////////////
|
|
void AttribNodeRegistry::
|
|
add_node(const NodePath &attrib_node) {
|
|
nassertv(!attrib_node.is_empty());
|
|
LightMutexHolder holder(_lock);
|
|
|
|
pair<Entries::iterator, bool> result = _entries.insert(Entry(attrib_node));
|
|
if (!result.second) {
|
|
// Replace an existing node.
|
|
(*result.first)._node = attrib_node;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::remove_node
|
|
// Access: Published
|
|
// Description: Removes the indicated NodePath from the registry.
|
|
// The name of the node must not have changed since the
|
|
// matching call to add_node(), or it will not be
|
|
// successfully removed.
|
|
//
|
|
// Returns true if the NodePath is found and removed,
|
|
// false if it is not found (for instance, because the
|
|
// name has changed).
|
|
////////////////////////////////////////////////////////////////////
|
|
bool AttribNodeRegistry::
|
|
remove_node(const NodePath &attrib_node) {
|
|
nassertr(!attrib_node.is_empty(), false);
|
|
LightMutexHolder holder(_lock);
|
|
Entries::iterator ei = _entries.find(Entry(attrib_node));
|
|
if (ei != _entries.end()) {
|
|
_entries.erase(ei);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::lookup_node
|
|
// Access: Published
|
|
// Description: Looks up the indicated NodePath in the registry. If
|
|
// there is a node already in the registry with the
|
|
// matching name and type, returns that NodePath
|
|
// instead; otherwise, returns the original NodePath.
|
|
////////////////////////////////////////////////////////////////////
|
|
NodePath AttribNodeRegistry::
|
|
lookup_node(const NodePath &orig_node) const {
|
|
nassertr(!orig_node.is_empty(), orig_node);
|
|
|
|
LightMutexHolder holder(_lock);
|
|
Entries::const_iterator ei = _entries.find(Entry(orig_node));
|
|
if (ei != _entries.end()) {
|
|
return (*ei)._node;
|
|
}
|
|
return orig_node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::get_num_nodes
|
|
// Access: Published
|
|
// Description: Returns the total number of nodes in the registry.
|
|
////////////////////////////////////////////////////////////////////
|
|
int AttribNodeRegistry::
|
|
get_num_nodes() const {
|
|
LightMutexHolder holder(_lock);
|
|
return _entries.size();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::get_node
|
|
// Access: Published
|
|
// Description: Returns the nth NodePath recorded in the registry.
|
|
////////////////////////////////////////////////////////////////////
|
|
NodePath AttribNodeRegistry::
|
|
get_node(int n) const {
|
|
LightMutexHolder holder(_lock);
|
|
nassertr(n >= 0 && n < (int)_entries.size(), NodePath());
|
|
return _entries[n]._node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::get_node_type
|
|
// Access: Published
|
|
// Description: Returns the type of the nth node, as recorded in the
|
|
// registry.
|
|
////////////////////////////////////////////////////////////////////
|
|
TypeHandle AttribNodeRegistry::
|
|
get_node_type(int n) const {
|
|
LightMutexHolder holder(_lock);
|
|
nassertr(n >= 0 && n < (int)_entries.size(), TypeHandle::none());
|
|
return _entries[n]._type;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::get_node_name
|
|
// Access: Published
|
|
// Description: Returns the name of the nth node, as recorded in the
|
|
// registry. This will be the node name as it was at
|
|
// the time the node was recorded; if the node has
|
|
// changed names since then, this will still return the
|
|
// original name.
|
|
////////////////////////////////////////////////////////////////////
|
|
string AttribNodeRegistry::
|
|
get_node_name(int n) const {
|
|
LightMutexHolder holder(_lock);
|
|
nassertr(n >= 0 && n < (int)_entries.size(), string());
|
|
return _entries[n]._name;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::find_node
|
|
// Access: Published
|
|
// Description: Returns the index number of the indicated NodePath in
|
|
// the registry (assuming its name hasn't changed since
|
|
// it was recorded in the registry), or -1 if the
|
|
// NodePath cannot be found (for instance, because its
|
|
// name has changed).
|
|
////////////////////////////////////////////////////////////////////
|
|
int AttribNodeRegistry::
|
|
find_node(const NodePath &attrib_node) const {
|
|
nassertr(!attrib_node.is_empty(), -1);
|
|
LightMutexHolder holder(_lock);
|
|
Entries::const_iterator ei = _entries.find(Entry(attrib_node));
|
|
if (ei != _entries.end()) {
|
|
return ei - _entries.begin();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::find_node
|
|
// Access: Published
|
|
// Description: Returns the index number of the node with the
|
|
// indicated type and name in the registry, or -1 if
|
|
// there is no such node in the registry.
|
|
////////////////////////////////////////////////////////////////////
|
|
int AttribNodeRegistry::
|
|
find_node(TypeHandle type, const string &name) const {
|
|
LightMutexHolder holder(_lock);
|
|
Entries::const_iterator ei = _entries.find(Entry(type, name));
|
|
if (ei != _entries.end()) {
|
|
return ei - _entries.begin();
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::remove_node
|
|
// Access: Published
|
|
// Description: Removes the nth node from the registry.
|
|
////////////////////////////////////////////////////////////////////
|
|
void AttribNodeRegistry::
|
|
remove_node(int n) {
|
|
LightMutexHolder holder(_lock);
|
|
nassertv(n >= 0 && n < (int)_entries.size());
|
|
_entries.erase(_entries.begin() + n);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::clear
|
|
// Access: Published
|
|
// Description: Removes all nodes from the registry.
|
|
////////////////////////////////////////////////////////////////////
|
|
void AttribNodeRegistry::
|
|
clear() {
|
|
LightMutexHolder holder(_lock);
|
|
_entries.clear();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::output
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void AttribNodeRegistry::
|
|
output(ostream &out) const {
|
|
LightMutexHolder holder(_lock);
|
|
|
|
typedef pmap<TypeHandle, int> Counts;
|
|
Counts counts;
|
|
|
|
Entries::const_iterator ei;
|
|
for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
|
|
TypeHandle type = (*ei)._type;
|
|
Counts::iterator ci = counts.insert(Counts::value_type(type, 0)).first;
|
|
++((*ci).second);
|
|
}
|
|
|
|
out << _entries.size() << " entries";
|
|
|
|
if (!counts.empty()) {
|
|
Counts::iterator ci = counts.begin();
|
|
out << " (" << (*ci).first << ":" << (*ci).second;
|
|
++ci;
|
|
while (ci != counts.end()) {
|
|
out << ", " << (*ci).first << ":" << (*ci).second;
|
|
++ci;
|
|
}
|
|
out << ")";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::write
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void AttribNodeRegistry::
|
|
write(ostream &out) const {
|
|
LightMutexHolder holder(_lock);
|
|
|
|
Entries::const_iterator ei;
|
|
for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
|
|
const Entry &entry = (*ei);
|
|
out << entry._type << ", \"" << entry._name << "\": " << entry._node
|
|
<< "\n";
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: AttribNodeRegistry::make_global_ptr
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void AttribNodeRegistry::
|
|
make_global_ptr() {
|
|
AttribNodeRegistry *ptr = new AttribNodeRegistry;
|
|
void *result = AtomicAdjust::compare_and_exchange_ptr
|
|
((void * TVOLATILE &)_global_ptr, (void *)NULL, (void *)ptr);
|
|
if (result != NULL) {
|
|
// Someone else got there first.
|
|
delete ptr;
|
|
}
|
|
assert(_global_ptr != (AttribNodeRegistry *)NULL);
|
|
}
|