open_toontown_panda3d/panda/src/pgraph/attribNodeRegistry.cxx

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);
}