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  */
57 get_rocket_key(const ButtonHandle handle) {
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 }
MutexHolder
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:25
MouseButton::one
static ButtonHandle one()
Returns the ButtonHandle associated with the first mouse button.
Definition: mouseButton.cxx:43
ButtonEvent
Records a button event of some kind.
Definition: buttonEvent.h:46
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
rocketInputHandler.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DataGraphTraverser
This object supervises the traversal of the data graph and the moving of data from one DataNode to it...
Definition: dataGraphTraverser.h:32
pmap< int, int >
mouseButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ButtonHandle
A ButtonHandle represents a single button from any device, including keyboard buttons and mouse butto...
Definition: buttonHandle.h:26
RocketInputHandler::get_rocket_key
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.
Definition: rocketInputHandler.cxx:57
DataNodeTransmit::has_data
bool has_data(int index) const
Returns true if the indicated parameter has been stored, false otherwise.
Definition: dataNodeTransmit.I:64
RocketInputHandler::update_context
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.
Definition: rocketInputHandler.cxx:290
ButtonEventList::get_num_events
int get_num_events() const
Returns the number of events in the list.
Definition: buttonEventList.I:50
keyboardButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
KeyboardButton::ascii_key
static ButtonHandle ascii_key(char ascii_equivalent)
Returns the ButtonHandle associated with the particular ASCII character, if there is one,...
Definition: keyboardButton.cxx:24
ButtonEventList::get_event
const ButtonEvent & get_event(int n) const
Returns the nth event in the list.
Definition: buttonEventList.I:60
EventParameter::get_ptr
TypedWritableReferenceCount * get_ptr() const
Retrieves a pointer to the actual value stored in the parameter.
Definition: eventParameter.I:219
dataGraphTraverser.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
ParamValue
A handy class object for storing simple values (like integers or strings) passed along with an Event ...
Definition: paramValue.h:103
MouseButton::five
static ButtonHandle five()
Returns the ButtonHandle associated with the fifth mouse button.
Definition: mouseButton.cxx:75
ButtonEventList
Records a set of button events that happened recently.
Definition: buttonEventList.h:33
buttonEventList.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
MouseButton::four
static ButtonHandle four()
Returns the ButtonHandle associated with the fourth mouse button.
Definition: mouseButton.cxx:67
DataNode
The fundamental type of node for the data graph.
Definition: dataNode.h:52
linmath_events.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DataNodeTransmit
Encapsulates the data generated from (or sent into) any particular DataNode.
Definition: dataNodeTransmit.h:32
rocketRenderInterface.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
MouseButton::wheel_up
static ButtonHandle wheel_up()
Returns the ButtonHandle generated when the mouse wheel is rolled one notch upwards.
Definition: mouseButton.cxx:84
MouseButton::wheel_down
static ButtonHandle wheel_down()
Returns the ButtonHandle generated when the mouse wheel is rolled one notch downwards.
Definition: mouseButton.cxx:93
MouseButton::two
static ButtonHandle two()
Returns the ButtonHandle associated with the second mouse button.
Definition: mouseButton.cxx:51
MouseButton::three
static ButtonHandle three()
Returns the ButtonHandle associated with the third mouse button.
Definition: mouseButton.cxx:59
ButtonHandle::get_index
get_index
Returns the integer index associated with this ButtonHandle.
Definition: buttonHandle.h:60
ParamValue::get_value
get_value
Retrieves the value stored in the parameter.
Definition: paramValue.h:115
DataNodeTransmit::get_data
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...
Definition: dataNodeTransmit.I:52