Panda3D
rocketInputHandler.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 rocketInputHandler.cxx
10  * @author rdb
11  * @date 2011-12-20
12  */
13 
14 #include "rocketInputHandler.h"
15 #include "buttonEventList.h"
16 #include "dataGraphTraverser.h"
17 #include "linmath_events.h"
18 #include "rocketRenderInterface.h"
19 #include "keyboardButton.h"
20 #include "mouseButton.h"
21 
22 #ifndef CPPPARSER
23 #include <Rocket/Core/Input.h>
24 
25 using namespace Rocket::Core::Input;
26 #endif
27 
28 TypeHandle RocketInputHandler::_type_handle;
29 
30 /**
31  *
32  */
33 RocketInputHandler::
34 RocketInputHandler(const std::string &name) :
35  DataNode(name),
36  _mouse_xy(-1),
37  _mouse_xy_changed(false),
38  _modifiers(0),
39  _wheel_delta(0)
40 {
41  _pixel_xy_input = define_input("pixel_xy", EventStoreVec2::get_class_type());
42  _button_events_input = define_input("button_events", ButtonEventList::get_class_type());
43 }
44 
45 /**
46  *
47  */
48 RocketInputHandler::
49 ~RocketInputHandler() {
50 }
51 
52 /**
53  * Returns the libRocket KeyIdentifier for the given ButtonHandle, or
54  * KI_UNKNOWN (0) if it wasn't known.
55  */
58  static pmap<int, int> keymap;
60 
61  if (keymap.size() > 0) {
62  it = keymap.find(handle.get_index());
63 
64  if (it == keymap.end()) {
65  return 0;
66  } else {
67  return it->second;
68  }
69  }
70 
71  keymap[KeyboardButton::space().get_index()] = KI_SPACE;
72  keymap[KeyboardButton::backspace().get_index()] = KI_BACK;
73  keymap[KeyboardButton::tab().get_index()] = KI_TAB;
74  keymap[KeyboardButton::enter().get_index()] = KI_RETURN;
75  keymap[KeyboardButton::escape().get_index()] = KI_ESCAPE;
76  keymap[KeyboardButton::end().get_index()] = KI_END;
77  keymap[KeyboardButton::home().get_index()] = KI_HOME;
78  keymap[KeyboardButton::left().get_index()] = KI_LEFT;
79  keymap[KeyboardButton::up().get_index()] = KI_UP;
80  keymap[KeyboardButton::right().get_index()] = KI_RIGHT;
81  keymap[KeyboardButton::down().get_index()] = KI_DOWN;
82  keymap[KeyboardButton::insert().get_index()] = KI_INSERT;
83  keymap[KeyboardButton::del().get_index()] = KI_DELETE;
84  keymap[KeyboardButton::caps_lock().get_index()] = KI_CAPITAL;
85  keymap[KeyboardButton::f1().get_index()] = KI_F1;
86  keymap[KeyboardButton::f10().get_index()] = KI_F10;
87  keymap[KeyboardButton::f11().get_index()] = KI_F11;
88  keymap[KeyboardButton::f12().get_index()] = KI_F12;
89  keymap[KeyboardButton::f13().get_index()] = KI_F13;
90  keymap[KeyboardButton::f14().get_index()] = KI_F14;
91  keymap[KeyboardButton::f15().get_index()] = KI_F15;
92  keymap[KeyboardButton::f16().get_index()] = KI_F16;
93  keymap[KeyboardButton::f2().get_index()] = KI_F2;
94  keymap[KeyboardButton::f3().get_index()] = KI_F3;
95  keymap[KeyboardButton::f4().get_index()] = KI_F4;
96  keymap[KeyboardButton::f5().get_index()] = KI_F5;
97  keymap[KeyboardButton::f6().get_index()] = KI_F6;
98  keymap[KeyboardButton::f7().get_index()] = KI_F7;
99  keymap[KeyboardButton::f8().get_index()] = KI_F8;
100  keymap[KeyboardButton::f9().get_index()] = KI_F9;
101  keymap[KeyboardButton::help().get_index()] = KI_HELP;
102  keymap[KeyboardButton::lcontrol().get_index()] = KI_LCONTROL;
103  keymap[KeyboardButton::lshift().get_index()] = KI_LSHIFT;
104  keymap[KeyboardButton::num_lock().get_index()] = KI_NUMLOCK;
105  keymap[KeyboardButton::page_down().get_index()] = KI_NEXT;
106  keymap[KeyboardButton::page_up().get_index()] = KI_PRIOR;
107  keymap[KeyboardButton::pause().get_index()] = KI_PAUSE;
108  keymap[KeyboardButton::print_screen().get_index()] = KI_SNAPSHOT;
109  keymap[KeyboardButton::rcontrol().get_index()] = KI_RCONTROL;
110  keymap[KeyboardButton::rshift().get_index()] = KI_RSHIFT;
111  keymap[KeyboardButton::scroll_lock().get_index()] = KI_SCROLL;
112 
113  // these "OEM" keys have standard mappings in Panda3D
114  keymap[KeyboardButton::ascii_key(';').get_index()] = KI_OEM_1;
115  keymap[KeyboardButton::ascii_key('=').get_index()] = KI_OEM_PLUS;
116  keymap[KeyboardButton::ascii_key(',').get_index()] = KI_OEM_COMMA;
117  keymap[KeyboardButton::ascii_key('-').get_index()] = KI_OEM_MINUS;
118  keymap[KeyboardButton::ascii_key('.').get_index()] = KI_OEM_PERIOD;
119  keymap[KeyboardButton::ascii_key('/').get_index()] = KI_OEM_2;
120  keymap[KeyboardButton::ascii_key('`').get_index()] = KI_OEM_3;
121  keymap[KeyboardButton::ascii_key('[').get_index()] = KI_OEM_4;
122  keymap[KeyboardButton::ascii_key('\\').get_index()] = KI_OEM_5;
123  keymap[KeyboardButton::ascii_key(']').get_index()] = KI_OEM_6;
124 
125  // comment says this may either be "<>" or "\|", but "\" (unshifted) is
126  // handled already, and "<" is only available "shifted" on 101-keyboards, so
127  // assume it's this one...
128  keymap[KeyboardButton::ascii_key('<').get_index()] = KI_OEM_102;
129 
130  for (char c = 'a'; c <= 'z'; ++c) {
131  keymap[KeyboardButton::ascii_key(c).get_index()] = (c - 'a') + KI_A;
132  }
133  for (char c = '0'; c <= '9'; ++c) {
134  keymap[KeyboardButton::ascii_key(c).get_index()] = (c - '0') + KI_0;
135  }
136 
137  it = keymap.find(handle.get_index());
138  if (it != keymap.end()) {
139  return it->second;
140  }
141  return 0;
142 }
143 
144 /**
145  * The virtual implementation of transmit_data(). This function receives an
146  * array of input parameters and should generate an array of output
147  * parameters. The input parameters may be accessed with the index numbers
148  * returned by the define_input() calls that were made earlier (presumably in
149  * the constructor); likewise, the output parameters should be set with the
150  * index numbers returned by the define_output() calls.
151  */
152 void RocketInputHandler::
153 do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
154  DataNodeTransmit &output) {
155  MutexHolder holder(_lock);
156 
157  if (input.has_data(_pixel_xy_input)) {
158  // The mouse is within the window. Get the current mouse position.
159  const EventStoreVec2 *pixel_xy;
160  DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_ptr());
161  LVecBase2 p = pixel_xy->get_value();
162 
163  // Determine if mouse moved from last position
164  if (p != _mouse_xy) {
165  _mouse_xy_changed = true;
166  _mouse_xy = p;
167  }
168  }
169 
170  ButtonEventList new_button_events;
171 
172  // Look for new button events.
173  if (input.has_data(_button_events_input)) {
174  const ButtonEventList *this_button_events;
175  DCAST_INTO_V(this_button_events, input.get_data(_button_events_input).get_ptr());
176  int num_events = this_button_events->get_num_events();
177  for (int i = 0; i < num_events; i++) {
178  const ButtonEvent &be = this_button_events->get_event(i);
179 
180  int rocket_key = KI_UNKNOWN;
181 
182  switch (be._type) {
183  case ButtonEvent::T_down:
184  if (be._button == KeyboardButton::control()) {
185  _modifiers |= KM_CTRL;
186  } else if (be._button == KeyboardButton::shift()) {
187  _modifiers |= KM_SHIFT;
188  } else if (be._button == KeyboardButton::alt()) {
189  _modifiers |= KM_ALT;
190  } else if (be._button == KeyboardButton::meta()) {
191  _modifiers |= KM_META;
192 
193  } else if (be._button == KeyboardButton::enter()) {
194  _text_input.push_back('\n');
195 
196  } else if (be._button == MouseButton::wheel_up()) {
197  _wheel_delta -= 1;
198  } else if (be._button == MouseButton::wheel_down()) {
199  _wheel_delta += 1;
200 
201  } else if (be._button == MouseButton::one()) {
202  _mouse_buttons[0] = true;
203  } else if (be._button == MouseButton::two()) {
204  _mouse_buttons[1] = true;
205  } else if (be._button == MouseButton::three()) {
206  _mouse_buttons[2] = true;
207  } else if (be._button == MouseButton::four()) {
208  _mouse_buttons[3] = true;
209  } else if (be._button == MouseButton::five()) {
210  _mouse_buttons[4] = true;
211  }
212 
213  rocket_key = get_rocket_key(be._button);
214  if (rocket_key != KI_UNKNOWN) {
215  _keys[rocket_key] = true;
216  }
217  break;
218 
219  case ButtonEvent::T_repeat:
220  if (be._button == KeyboardButton::enter()) {
221  _text_input.push_back('\n');
222  }
223 
224  rocket_key = get_rocket_key(be._button);
225  if (rocket_key != KI_UNKNOWN) {
226  _repeated_keys.push_back(rocket_key);
227  }
228  break;
229 
230  case ButtonEvent::T_up:
231  if (be._button == KeyboardButton::control()) {
232  _modifiers &= ~KM_CTRL;
233  } else if (be._button == KeyboardButton::shift()) {
234  _modifiers &= ~KM_SHIFT;
235  } else if (be._button == KeyboardButton::alt()) {
236  _modifiers &= ~KM_ALT;
237  } else if (be._button == KeyboardButton::meta()) {
238  _modifiers &= ~KM_META;
239 
240  } else if (be._button == MouseButton::one()) {
241  _mouse_buttons[0] = false;
242  } else if (be._button == MouseButton::two()) {
243  _mouse_buttons[1] = false;
244  } else if (be._button == MouseButton::three()) {
245  _mouse_buttons[2] = false;
246  } else if (be._button == MouseButton::four()) {
247  _mouse_buttons[3] = false;
248  } else if (be._button == MouseButton::five()) {
249  _mouse_buttons[4] = false;
250  }
251 
252  rocket_key = get_rocket_key(be._button);
253  if (rocket_key != KI_UNKNOWN) {
254  _keys[rocket_key] = false;
255  }
256  break;
257 
258  case ButtonEvent::T_keystroke:
259  // Ignore control characters; otherwise, they actually get added to
260  // strings in the UI.
261  if (be._keycode > 0x1F && (be._keycode < 0x7F || be._keycode > 0x9F)) {
262  _text_input.push_back(be._keycode);
263  }
264  break;
265 
266  case ButtonEvent::T_resume_down:
267  break;
268 
269  case ButtonEvent::T_move:
270  break;
271 
272  case ButtonEvent::T_candidate:
273  break;
274 
275  case ButtonEvent::T_raw_down:
276  break;
277 
278  case ButtonEvent::T_raw_up:
279  break;
280  }
281  }
282  }
283 }
284 
285 /**
286  * Updates the libRocket context with the changes that we have gathered in
287  * do_transmit_data. Also calls Update() on the context.
288  */
290 update_context(Rocket::Core::Context *context, int xoffs, int yoffs) {
291  MutexHolder holder(_lock);
292 
293  if (_keys.size() > 0) {
294  ButtonActivityMap::const_iterator it;
295  for (it = _keys.begin(); it != _keys.end(); ++it) {
296  if (it->second) {
297  context->ProcessKeyDown((KeyIdentifier) it->first, _modifiers);
298  } else {
299  context->ProcessKeyUp((KeyIdentifier) it->first, _modifiers);
300  }
301  }
302  _keys.clear();
303  }
304 
305  if (_repeated_keys.size() > 0) {
307 
308  for (it = _repeated_keys.begin(); it != _repeated_keys.end(); ++it) {
309  context->ProcessKeyUp((KeyIdentifier) *it, _modifiers);
310  context->ProcessKeyDown((KeyIdentifier) *it, _modifiers);
311  }
312  _repeated_keys.clear();
313  }
314 
315  if (_text_input.size() > 0) {
317  for (it = _text_input.begin(); it != _text_input.end(); ++it) {
318  context->ProcessTextInput(*it);
319  }
320  _text_input.clear();
321  }
322 
323  if (_mouse_xy_changed) {
324  _mouse_xy_changed = false;
325 
326  context->ProcessMouseMove(_mouse_xy.get_x() - xoffs,
327  _mouse_xy.get_y() - yoffs, _modifiers);
328  }
329 
330  if (_mouse_buttons.size() > 0) {
331  ButtonActivityMap::const_iterator it;
332  for (it = _mouse_buttons.begin(); it != _mouse_buttons.end(); ++it) {
333  if (it->second) {
334  context->ProcessMouseButtonDown(it->first, _modifiers);
335  } else {
336  context->ProcessMouseButtonUp(it->first, _modifiers);
337  }
338  }
339  _mouse_buttons.clear();
340  }
341 
342  if (_wheel_delta != 0) {
343  context->ProcessMouseWheel(_wheel_delta, _modifiers);
344  _wheel_delta = 0;
345  }
346 
347  context->Update();
348 }
static int get_rocket_key(const ButtonHandle handle)
Returns the libRocket KeyIdentifier for the given ButtonHandle, or KI_UNKNOWN (0) if it wasn't known.
The fundamental type of node for the data graph.
Definition: dataNode.h:52
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static ButtonHandle three()
Returns the ButtonHandle associated with the third mouse button.
Definition: mouseButton.cxx:59
static ButtonHandle two()
Returns the ButtonHandle associated with the second mouse button.
Definition: mouseButton.cxx:51
get_index
Returns the integer index associated with this ButtonHandle.
Definition: buttonHandle.h:60
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_value
Retrieves the value stored in the parameter.
Definition: paramValue.h:115
void update_context(Rocket::Core::Context *context, int xoffs, int yoffs)
Updates the libRocket context with the changes that we have gathered in do_transmit_data.
int get_num_events() const
Returns the number of events in the list.
static ButtonHandle one()
Returns the ButtonHandle associated with the first mouse button.
Definition: mouseButton.cxx:43
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:25
Records a button event of some kind.
Definition: buttonEvent.h:46
bool has_data(int index) const
Returns true if the indicated parameter has been stored, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A handy class object for storing simple values (like integers or strings) passed along with an Event ...
Definition: paramValue.h:103
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Records a set of button events that happened recently.
static ButtonHandle four()
Returns the ButtonHandle associated with the fourth mouse button.
Definition: mouseButton.cxx:67
A ButtonHandle represents a single button from any device, including keyboard buttons and mouse butto...
Definition: buttonHandle.h:26
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
static ButtonHandle wheel_down()
Returns the ButtonHandle generated when the mouse wheel is rolled one notch downwards.
Definition: mouseButton.cxx:93
static ButtonHandle five()
Returns the ButtonHandle associated with the fifth mouse button.
Definition: mouseButton.cxx:75
TypedWritableReferenceCount * get_ptr() const
Retrieves a pointer to the actual value stored in the parameter.
const EventParameter & get_data(int index) const
Extracts the data for the indicated index, if it has been stored, or the empty parameter if it has no...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const ButtonEvent & get_event(int n) const
Returns the nth event in the list.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static ButtonHandle ascii_key(char ascii_equivalent)
Returns the ButtonHandle associated with the particular ASCII character, if there is one,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static ButtonHandle wheel_up()
Returns the ButtonHandle generated when the mouse wheel is rolled one notch upwards.
Definition: mouseButton.cxx:84
Encapsulates the data generated from (or sent into) any particular DataNode.
This object supervises the traversal of the data graph and the moving of data from one DataNode to it...