open_toontown_panda3d/panda/src/putil/buttonRegistry.cxx

230 lines
7.7 KiB
C++

// Filename: buttonRegistry.cxx
// Created by: drose (01Mar00)
//
////////////////////////////////////////////////////////////////////
//
// 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 "buttonRegistry.h"
#include "config_util.h"
#include <stdio.h>
// In general, we use the util_cat->info() syntax in this file
// (instead of util_cat.info()), because much of this work is done at
// static init time, and we must use the arrow syntax to force
// initialization of the util_cat category.
ButtonRegistry *ButtonRegistry::_global_pointer = NULL;
////////////////////////////////////////////////////////////////////
// Function: ButtonRegistry::register_button
// Access: Public
// Description: Registers a new ButtonHandle with the indicated name,
// and if specified, the indicated ASCII equivalent.
// Returns true if the button was registered, or false
// it was already registered; in either case, the new
// ButtonHandle is loaded into the first parameter.
//
// If the alias is not ButtonHandle::none(), it
// indicates an alias (alternate name) for the same
// button. Each button is allowed to have one alias,
// and multiple different buttons can refer to the same
// alias. The alias should be the more general name for
// the button, for instance, shift is an alias for
// lshift, but not vice-versa.
//
// This defines a new kind of button matching the
// indicated name. The ButtonHandle can then be passed
// around to devices as a button in its own right.
////////////////////////////////////////////////////////////////////
bool ButtonRegistry::
register_button(ButtonHandle &button_handle, const string &name,
ButtonHandle alias, char ascii_equivalent) {
NameRegistry::iterator ri;
ri = _name_registry.find(name);
if (ri == _name_registry.end()) {
// The name was not already used; this is the first time this
// button has been defined.
int index = -1;
if (ascii_equivalent != '\0') {
if (_handle_registry[ascii_equivalent] == (RegistryNode *)NULL) {
index = ascii_equivalent;
} else {
util_cat->error()
<< "Attempt to register multiple buttons under ASCII equivalent "
<< ascii_equivalent << "\n";
}
}
#ifdef NOTIFY_DEBUG
// This code runs at static init time, so cannot use the
// util_cat.is_spam() syntax.
if (util_cat->is_spam()) {
util_cat->spam()
<< "Registering button " << name << "\n";
}
#endif
if (index == -1) {
// It's not an ASCII equivalent; make up a new number.
index = _handle_registry.size();
_handle_registry.push_back(NULL);
}
ButtonHandle new_handle;
new_handle._index = index;
RegistryNode *rnode = new RegistryNode(new_handle, alias, name);
_handle_registry[index] = rnode;
_name_registry[name] = rnode;
button_handle = new_handle;
return true;
}
RegistryNode *rnode = (*ri).second;
nassertr(rnode->_name == (*ri).first, false);
nassertr(rnode->_handle._index >= 0 &&
rnode->_handle._index < (int)_handle_registry.size(), false);
nassertr(_handle_registry[rnode->_handle._index] == rnode, false);
nassertr(rnode->_handle._index != 0, false);
if (button_handle != rnode->_handle) {
// Hmm, we seem to have a contradictory button registration!
util_cat->warning()
<< "Attempt to register button " << name << " more than once!\n";
button_handle = rnode->_handle;
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: ButtonRegistry::get_button
// Access: Published
// Description: Finds a ButtonHandle in the registry matching the
// indicated name. If there is no such ButtonHandle,
// registers a new one and returns it.
////////////////////////////////////////////////////////////////////
ButtonHandle ButtonRegistry::
get_button(const string &name) {
NameRegistry::const_iterator ri;
ri = _name_registry.find(name);
if (ri != _name_registry.end()) {
return (*ri).second->_handle;
}
ButtonHandle button;
register_button(button, name);
return button;
}
////////////////////////////////////////////////////////////////////
// Function: ButtonRegistry::find_ascii_button
// Access: Published
// Description: Finds a ButtonHandle in the registry matching the
// indicated ASCII equivalent character. If there is no
// such ButtonHandle, returns ButtonHandle::none().
////////////////////////////////////////////////////////////////////
ButtonHandle ButtonRegistry::
find_ascii_button(char ascii_equivalent) const {
if (_handle_registry[ascii_equivalent] == (RegistryNode *)NULL) {
return ButtonHandle::none();
}
return _handle_registry[ascii_equivalent]->_handle;
}
////////////////////////////////////////////////////////////////////
// Function: ButtonRegistry::write
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void ButtonRegistry::
write(ostream &out) const {
out << "ASCII equivalents:\n";
for (int i = 1; i < 128; i++) {
if (_handle_registry[i] != (RegistryNode *)NULL) {
char hex[12];
sprintf(hex, "%02x", (unsigned int)i);
nassertv(strlen(hex) < 12);
out << " " << hex << " " << _handle_registry[i]->_name << "\n";
}
}
out << "\nOther buttons:\n";
NameRegistry::const_iterator ri;
for (ri = _name_registry.begin(); ri != _name_registry.end(); ++ri) {
if (!(*ri).second->_handle.has_ascii_equivalent()) {
out << " " << (*ri).second->_name;
if ((*ri).second->_alias != ButtonHandle::none()) {
out << " (alias " << (*ri).second->_alias << ")";
}
out << "\n";
}
}
}
////////////////////////////////////////////////////////////////////
// Function: ButtonRegistry::Constructor
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
ButtonRegistry::
ButtonRegistry() {
// We'll start by filling up the handle_registry with 128 entries
// for ButtonHandle::none(), as well as for all the ASCII
// equivalents.
_handle_registry.reserve(128);
int i;
for (i = 0; i < 128; i++) {
_handle_registry.push_back(NULL);
}
}
////////////////////////////////////////////////////////////////////
// Function: ButtonRegistry::init_global_pointer
// Access: Private, Static
// Description: Constructs the ButtonRegistry object for the first
// time.
////////////////////////////////////////////////////////////////////
void ButtonRegistry::
init_global_pointer() {
_global_pointer = new ButtonRegistry;
}
////////////////////////////////////////////////////////////////////
// Function: ButtonRegistry::look_up
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
ButtonRegistry::RegistryNode *ButtonRegistry::
look_up(ButtonHandle handle) const {
nassertr(handle._index != 0, NULL);
if (handle._index < 0 ||
handle._index >= (int)_handle_registry.size()) {
util_cat->fatal()
<< "Invalid ButtonHandle index " << handle._index
<< "! Is memory corrupt?\n";
return (RegistryNode *)NULL;
}
return _handle_registry[handle._index];
}