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