open_toontown_panda3d/panda/src/egg/eggNameUniquifier.cxx

212 lines
6.8 KiB
C++

// Filename: eggNameUniquifier.cxx
// Created by: drose (09Nov00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "eggNameUniquifier.h"
#include "eggNode.h"
#include "eggGroupNode.h"
#include "config_egg.h"
#include "dcast.h"
#include "pnotify.h"
TypeHandle EggNameUniquifier::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: EggNameUniquifier::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggNameUniquifier::
EggNameUniquifier() {
_index = 0;
}
////////////////////////////////////////////////////////////////////
// Function: EggNameUniquifier::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggNameUniquifier::
~EggNameUniquifier() {
}
////////////////////////////////////////////////////////////////////
// Function: EggNameUniquifier::clear
// Access: Public
// Description: Empties the table of used named and prepares the
// Uniquifier for a new tree.
////////////////////////////////////////////////////////////////////
void EggNameUniquifier::
clear() {
_categories.clear();
_index = 0;
}
////////////////////////////////////////////////////////////////////
// Function: EggNameUniquifier::uniquify
// Access: Public
// Description: Begins the traversal from the indicated node.
////////////////////////////////////////////////////////////////////
void EggNameUniquifier::
uniquify(EggNode *node) {
string category = get_category(node);
if (egg_cat.is_debug()) {
egg_cat.debug()
<< "Uniquifying " << node->get_name() << ", category = " << category
<< "\n";
}
if (!category.empty()) {
string name = filter_name(node);
UsedNames &names = _categories[category];
bool inserted = false;
if (!name.empty()) {
inserted = names.insert(UsedNames::value_type(name, node)).second;
}
while (!inserted) {
_index++;
name = generate_name(node, category, _index);
inserted = names.insert(UsedNames::value_type(name, node)).second;
}
if (egg_cat.is_debug()) {
egg_cat.debug()
<< "Uniquifying " << node->get_name() << " to "
<< name << "\n";
}
node->set_name(name);
}
if (node->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *group;
DCAST_INTO_V(group, node);
EggGroupNode::iterator ci;
for (ci = group->begin(); ci != group->end(); ++ci) {
EggNode *child = (*ci);
nassertv(child != (EggNode *)NULL);
uniquify(child);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggNameUniquifier::get_node
// Access: Public
// Description: Returns the node associated with the given category
// and name, or NULL if the name has not been used.
////////////////////////////////////////////////////////////////////
EggNode *EggNameUniquifier::
get_node(const string &category, const string &name) const {
Categories::const_iterator ci;
ci = _categories.find(category);
if (ci == _categories.end()) {
return (EggNode *)NULL;
}
const UsedNames &names = (*ci).second;
UsedNames::const_iterator ni;
ni = names.find(name);
if (ni == names.end()) {
return (EggNode *)NULL;
}
return (*ni).second;
}
////////////////////////////////////////////////////////////////////
// Function: EggNameUniquifier::has_name
// Access: Public
// Description: Returns true if the name has been used for the
// indicated category already, false otherwise.
////////////////////////////////////////////////////////////////////
bool EggNameUniquifier::
has_name(const string &category, const string &name) const {
Categories::const_iterator ci;
ci = _categories.find(category);
if (ci == _categories.end()) {
return false;
}
const UsedNames &names = (*ci).second;
UsedNames::const_iterator ni;
ni = names.find(name);
if (ni == names.end()) {
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggNameUniquifier::add_name
// Access: Public
// Description: Adds the name to the indicated category. This name
// will not be used for any other egg node within this
// category. Returns true if the name was added, or
// false if it was already in use for the category.
////////////////////////////////////////////////////////////////////
bool EggNameUniquifier::
add_name(const string &category, const string &name, EggNode *node) {
UsedNames &names = _categories[category];
bool inserted = names.insert(UsedNames::value_type(name, node)).second;
return inserted;
}
////////////////////////////////////////////////////////////////////
// Function: EggNameUniquifier::filter_name
// Access: Public, Virtual
// Description: Returns the name of the given node, or at least the
// name it should be. This provides a hook to adjust
// the name before attempting to uniquify it, if
// desired, for instance to remove invalid characters.
////////////////////////////////////////////////////////////////////
string EggNameUniquifier::
filter_name(EggNode *node) {
return node->get_name();
}
////////////////////////////////////////////////////////////////////
// Function: EggNameUniquifier::generate_name
// Access: Public, Virtual
// Description: Generates a new name for the given node when its
// existing name clashes with some other node. This
// function will be called repeatedly, if necessary,
// until it returns a name that actually is unique.
//
// The category is the string returned by
// get_category(), and index is a uniquely-generated
// number that may be useful for synthesizing the name.
////////////////////////////////////////////////////////////////////
string EggNameUniquifier::
generate_name(EggNode *node, const string &category, int index) {
string name = filter_name(node);
ostringstream str;
if (name.empty()) {
str << category << index;
} else {
str << name << "." << category << index;
}
return str.str();
}