Panda3D
Loading...
Searching...
No Matches
buttonRegistry.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file buttonRegistry.cxx
10 * @author drose
11 * @date 2000-03-01
12 */
13
14#include "buttonRegistry.h"
15#include "config_putil.h"
16
17#include <stdio.h>
18
19// In general, we use the util_cat->info() syntax in this file (instead of
20// util_cat.info()), because much of this work is done at static init time,
21// and we must use the arrow syntax to force initialization of the util_cat
22// category.
23
24ButtonRegistry *ButtonRegistry::_global_pointer = nullptr;
25
26
27/**
28 * Registers a new ButtonHandle with the indicated name, and if specified, the
29 * indicated ASCII equivalent. Returns true if the button was registered, or
30 * false it was already registered; in either case, the new ButtonHandle is
31 * loaded into the first parameter.
32 *
33 * If the alias is not ButtonHandle::none(), it indicates an alias (alternate
34 * name) for the same button. Each button is allowed to have one alias, and
35 * multiple different buttons can refer to the same alias. The alias should
36 * be the more general name for the button, for instance, shift is an alias
37 * for lshift, but not vice-versa.
38 *
39 * This defines a new kind of button matching the indicated name. The
40 * ButtonHandle can then be passed around to devices as a button in its own
41 * right.
42 */
44register_button(ButtonHandle &button_handle, const std::string &name,
45 ButtonHandle alias, char ascii_equivalent) {
46 NameRegistry::iterator ri;
47 ri = _name_registry.find(name);
48
49 if (ri == _name_registry.end()) {
50 // The name was not already used; this is the first time this button has
51 // been defined.
52
53 int index = -1;
54 if (ascii_equivalent != '\0') {
55 if (_handle_registry[ascii_equivalent] == nullptr) {
56 index = ascii_equivalent;
57 } else {
58 util_cat->error()
59 << "Attempt to register multiple buttons under ASCII equivalent "
60 << ascii_equivalent << "\n";
61 }
62 }
63
64#ifdef NOTIFY_DEBUG
65 // This code runs at static init time, so cannot use the
66 // util_cat.is_spam() syntax.
67 if (util_cat->is_spam()) {
68 util_cat->spam()
69 << "Registering button " << name << "\n";
70 }
71#endif
72
73 if (index == -1) {
74 // It's not an ASCII equivalent; make up a new number.
75 index = _handle_registry.size();
76 _handle_registry.push_back(nullptr);
77 }
78
79 ButtonHandle new_handle;
80 new_handle._index = index;
81
82 RegistryNode *rnode = new RegistryNode(new_handle, alias, name);
83 _handle_registry[index] = rnode;
84 _name_registry[name] = rnode;
85
86 button_handle = new_handle;
87 return true;
88 }
89
90 RegistryNode *rnode = (*ri).second;
91 nassertr(rnode->_name == (*ri).first, false);
92 nassertr(rnode->_handle._index >= 0 &&
93 rnode->_handle._index < (int)_handle_registry.size(), false);
94 nassertr(_handle_registry[rnode->_handle._index] == rnode, false);
95 nassertr(rnode->_handle._index != 0, false);
96
97 if (button_handle != rnode->_handle) {
98 // Hmm, we seem to have a contradictory button registration!
99 util_cat->warning()
100 << "Attempt to register button " << name << " more than once!\n";
101
102 button_handle = rnode->_handle;
103 }
104 return false;
105}
106
107/**
108 * Finds a ButtonHandle in the registry matching the indicated name. If there
109 * is no such ButtonHandle, registers a new one and returns it.
110 */
112get_button(const std::string &name) {
113 NameRegistry::const_iterator ri;
114 ri = _name_registry.find(name);
115
116 if (ri != _name_registry.end()) {
117 return (*ri).second->_handle;
118 }
119
120 ButtonHandle button;
121 register_button(button, name);
122 return button;
123}
124
125/**
126 * Finds a ButtonHandle in the registry matching the indicated name. If there
127 * is no such ButtonHandle, returns ButtonHandle::none().
128 */
130find_button(const std::string &name) {
131 NameRegistry::const_iterator ri;
132 ri = _name_registry.find(name);
133
134 if (ri != _name_registry.end()) {
135 return (*ri).second->_handle;
136 }
137
138 return ButtonHandle::none();
139}
140
141/**
142 * Finds a ButtonHandle in the registry matching the indicated ASCII
143 * equivalent character. If there is no such ButtonHandle, returns
144 * ButtonHandle::none().
145 */
147find_ascii_button(char ascii_equivalent) const {
148 if (_handle_registry[ascii_equivalent] == nullptr) {
149 return ButtonHandle::none();
150 }
151 return _handle_registry[ascii_equivalent]->_handle;
152}
153
154/**
155 *
156 */
157void ButtonRegistry::
158write(std::ostream &out) const {
159 out << "ASCII equivalents:\n";
160 for (int i = 1; i < 128; i++) {
161 if (_handle_registry[i] != nullptr) {
162 char hex[12];
163 sprintf(hex, "%02x", (unsigned int)i);
164 nassertv(strlen(hex) < 12);
165
166 out << " " << hex << " " << _handle_registry[i]->_name << "\n";
167 }
168 }
169
170 out << "\nOther buttons:\n";
171 NameRegistry::const_iterator ri;
172 for (ri = _name_registry.begin(); ri != _name_registry.end(); ++ri) {
173 if (!(*ri).second->_handle.has_ascii_equivalent()) {
174 out << " " << (*ri).second->_name;
175 if ((*ri).second->_alias != ButtonHandle::none()) {
176 out << " (alias " << (*ri).second->_alias << ")";
177 }
178 out << "\n";
179 }
180 }
181}
182
183
184/**
185 *
186 */
187ButtonRegistry::
188ButtonRegistry() {
189 // We'll start by filling up the handle_registry with 128 entries for
190 // ButtonHandle::none(), as well as for all the ASCII equivalents.
191
192 _handle_registry.reserve(128);
193 int i;
194 for (i = 0; i < 128; i++) {
195 _handle_registry.push_back(nullptr);
196 }
197}
198
199/**
200 * Constructs the ButtonRegistry object for the first time.
201 */
202void ButtonRegistry::
203init_global_pointer() {
204 _global_pointer = new ButtonRegistry;
205}
206
207
208/**
209 *
210 */
211ButtonRegistry::RegistryNode *ButtonRegistry::
212look_up(ButtonHandle handle) const {
213 nassertr(handle._index != 0, nullptr);
214
215 if (handle._index < 0 ||
216 handle._index >= (int)_handle_registry.size()) {
217 util_cat->fatal()
218 << "Invalid ButtonHandle index " << handle._index
219 << "! Is memory corrupt?\n";
220 return nullptr;
221 }
222
223 return _handle_registry[handle._index];
224}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A ButtonHandle represents a single button from any device, including keyboard buttons and mouse butto...
The ButtonRegistry class maintains all the assigned ButtonHandles in a given system.
ButtonHandle find_ascii_button(char ascii_equivalent) const
Finds a ButtonHandle in the registry matching the indicated ASCII equivalent character.
ButtonHandle find_button(const std::string &name)
Finds a ButtonHandle in the registry matching the indicated name.
bool register_button(ButtonHandle &button_handle, const std::string &name, ButtonHandle alias=ButtonHandle::none(), char ascii_equivalent='\0')
Registers a new ButtonHandle with the indicated name, and if specified, the indicated ASCII equivalen...
ButtonHandle get_button(const std::string &name)
Finds a ButtonHandle in the registry matching the indicated name.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.