mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00

libRocket calls some keys "OEM" which map to ASCII characters in non-predictable places. Since Panda3D is providing these values to libRocket from well-known sources, it seems a lesser evil to use the default US English mappings rather than losing the events entirely.
359 lines
13 KiB
C++
359 lines
13 KiB
C++
// Filename: rocketInputHandler.cxx
|
|
// Created by: rdb (20Dec11)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 "rocketInputHandler.h"
|
|
#include "buttonEventList.h"
|
|
#include "dataGraphTraverser.h"
|
|
#include "linmath_events.h"
|
|
#include "rocketRenderInterface.h"
|
|
#include "keyboardButton.h"
|
|
#include "mouseButton.h"
|
|
|
|
#include <Rocket/Core/Input.h>
|
|
|
|
using namespace Rocket::Core::Input;
|
|
|
|
TypeHandle RocketInputHandler::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: RocketInputHandler::Constructor
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
RocketInputHandler::
|
|
RocketInputHandler(const string &name) :
|
|
DataNode(name),
|
|
_modifiers(0),
|
|
_wheel_delta(0)
|
|
{
|
|
_pixel_xy_input = define_input("pixel_xy", EventStoreVec2::get_class_type());
|
|
_button_events_input = define_input("button_events", ButtonEventList::get_class_type());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: RocketInputHandler::Destructor
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
RocketInputHandler::
|
|
~RocketInputHandler() {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: RocketInputHandler::get_rocket_key
|
|
// Access: Published
|
|
// Description: Returns the libRocket KeyIdentifier for the given
|
|
// ButtonHandle, or KI_UNKNOWN (0) if it wasn't known.
|
|
////////////////////////////////////////////////////////////////////
|
|
int RocketInputHandler::
|
|
get_rocket_key(const ButtonHandle handle) {
|
|
static pmap<int, int> keymap;
|
|
pmap<int, int>::const_iterator it;
|
|
|
|
if (keymap.size() > 0) {
|
|
it = keymap.find(handle.get_index());
|
|
|
|
if (it == keymap.end()) {
|
|
return 0;
|
|
} else {
|
|
return it->second;
|
|
}
|
|
}
|
|
|
|
keymap[KeyboardButton::space().get_index()] = KI_SPACE;
|
|
keymap[KeyboardButton::backspace().get_index()] = KI_BACK;
|
|
keymap[KeyboardButton::tab().get_index()] = KI_TAB;
|
|
keymap[KeyboardButton::enter().get_index()] = KI_RETURN;
|
|
keymap[KeyboardButton::escape().get_index()] = KI_ESCAPE;
|
|
keymap[KeyboardButton::end().get_index()] = KI_END;
|
|
keymap[KeyboardButton::home().get_index()] = KI_HOME;
|
|
keymap[KeyboardButton::left().get_index()] = KI_LEFT;
|
|
keymap[KeyboardButton::up().get_index()] = KI_UP;
|
|
keymap[KeyboardButton::right().get_index()] = KI_RIGHT;
|
|
keymap[KeyboardButton::down().get_index()] = KI_DOWN;
|
|
keymap[KeyboardButton::insert().get_index()] = KI_INSERT;
|
|
keymap[KeyboardButton::del().get_index()] = KI_DELETE;
|
|
keymap[KeyboardButton::caps_lock().get_index()] = KI_CAPITAL;
|
|
keymap[KeyboardButton::f1().get_index()] = KI_F1;
|
|
keymap[KeyboardButton::f10().get_index()] = KI_F10;
|
|
keymap[KeyboardButton::f11().get_index()] = KI_F11;
|
|
keymap[KeyboardButton::f12().get_index()] = KI_F12;
|
|
keymap[KeyboardButton::f13().get_index()] = KI_F13;
|
|
keymap[KeyboardButton::f14().get_index()] = KI_F14;
|
|
keymap[KeyboardButton::f15().get_index()] = KI_F15;
|
|
keymap[KeyboardButton::f16().get_index()] = KI_F16;
|
|
keymap[KeyboardButton::f2().get_index()] = KI_F2;
|
|
keymap[KeyboardButton::f3().get_index()] = KI_F3;
|
|
keymap[KeyboardButton::f4().get_index()] = KI_F4;
|
|
keymap[KeyboardButton::f5().get_index()] = KI_F5;
|
|
keymap[KeyboardButton::f6().get_index()] = KI_F6;
|
|
keymap[KeyboardButton::f7().get_index()] = KI_F7;
|
|
keymap[KeyboardButton::f8().get_index()] = KI_F8;
|
|
keymap[KeyboardButton::f9().get_index()] = KI_F9;
|
|
keymap[KeyboardButton::help().get_index()] = KI_HELP;
|
|
keymap[KeyboardButton::lcontrol().get_index()] = KI_LCONTROL;
|
|
keymap[KeyboardButton::lshift().get_index()] = KI_LSHIFT;
|
|
keymap[KeyboardButton::num_lock().get_index()] = KI_NUMLOCK;
|
|
keymap[KeyboardButton::page_down().get_index()] = KI_NEXT;
|
|
keymap[KeyboardButton::page_up().get_index()] = KI_PRIOR;
|
|
keymap[KeyboardButton::pause().get_index()] = KI_PAUSE;
|
|
keymap[KeyboardButton::print_screen().get_index()] = KI_SNAPSHOT;
|
|
keymap[KeyboardButton::rcontrol().get_index()] = KI_RCONTROL;
|
|
keymap[KeyboardButton::rshift().get_index()] = KI_RSHIFT;
|
|
keymap[KeyboardButton::scroll_lock().get_index()] = KI_SCROLL;
|
|
|
|
// these "OEM" keys have standard mappings in Panda3D
|
|
keymap[KeyboardButton::ascii_key(';').get_index()] = KI_OEM_1;
|
|
keymap[KeyboardButton::ascii_key('=').get_index()] = KI_OEM_PLUS;
|
|
keymap[KeyboardButton::ascii_key(',').get_index()] = KI_OEM_COMMA;
|
|
keymap[KeyboardButton::ascii_key('-').get_index()] = KI_OEM_MINUS;
|
|
keymap[KeyboardButton::ascii_key('.').get_index()] = KI_OEM_PERIOD;
|
|
keymap[KeyboardButton::ascii_key('/').get_index()] = KI_OEM_2;
|
|
keymap[KeyboardButton::ascii_key('`').get_index()] = KI_OEM_3;
|
|
keymap[KeyboardButton::ascii_key('[').get_index()] = KI_OEM_4;
|
|
keymap[KeyboardButton::ascii_key('\\').get_index()] = KI_OEM_5;
|
|
keymap[KeyboardButton::ascii_key(']').get_index()] = KI_OEM_6;
|
|
|
|
// comment says this may either be "<>" or "\|", but "\" (unshifted) is handled already,
|
|
// and "<" is only available "shifted" on 101-keyboards, so assume it's this one...
|
|
keymap[KeyboardButton::ascii_key('<').get_index()] = KI_OEM_102;
|
|
|
|
for (char c = 'a'; c <= 'z'; ++c) {
|
|
keymap[KeyboardButton::ascii_key(c).get_index()] = (c - 'a') + KI_A;
|
|
}
|
|
for (char c = '0'; c <= '9'; ++c) {
|
|
keymap[KeyboardButton::ascii_key(c).get_index()] = (c - '0') + KI_0;
|
|
}
|
|
|
|
it = keymap.find(handle.get_index());
|
|
if (it != keymap.end()) {
|
|
return it->second;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: RocketInputHandler::do_transmit_data
|
|
// Access: Protected, Virtual
|
|
// Description: The virtual implementation of transmit_data(). This
|
|
// function receives an array of input parameters and
|
|
// should generate an array of output parameters. The
|
|
// input parameters may be accessed with the index
|
|
// numbers returned by the define_input() calls that
|
|
// were made earlier (presumably in the constructor);
|
|
// likewise, the output parameters should be set with
|
|
// the index numbers returned by the define_output()
|
|
// calls.
|
|
////////////////////////////////////////////////////////////////////
|
|
void RocketInputHandler::
|
|
do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input,
|
|
DataNodeTransmit &output) {
|
|
Thread *current_thread = trav->get_current_thread();
|
|
MutexHolder holder(_lock);
|
|
|
|
if (input.has_data(_pixel_xy_input)) {
|
|
// The mouse is within the window. Get the current mouse position.
|
|
const EventStoreVec2 *pixel_xy;
|
|
DCAST_INTO_V(pixel_xy, input.get_data(_pixel_xy_input).get_ptr());
|
|
LVecBase2 p = pixel_xy->get_value();
|
|
|
|
// Determine if mouse moved from last position
|
|
if (p != _mouse_xy) {
|
|
_mouse_xy_changed = true;
|
|
_mouse_xy = p;
|
|
}
|
|
}
|
|
|
|
ButtonEventList new_button_events;
|
|
|
|
// Look for new button events.
|
|
if (input.has_data(_button_events_input)) {
|
|
const ButtonEventList *this_button_events;
|
|
DCAST_INTO_V(this_button_events, input.get_data(_button_events_input).get_ptr());
|
|
int num_events = this_button_events->get_num_events();
|
|
for (int i = 0; i < num_events; i++) {
|
|
const ButtonEvent &be = this_button_events->get_event(i);
|
|
|
|
int rocket_key = KI_UNKNOWN;
|
|
|
|
switch (be._type) {
|
|
case ButtonEvent::T_down:
|
|
if (be._button == KeyboardButton::control()) {
|
|
_modifiers |= KM_CTRL;
|
|
} else if (be._button == KeyboardButton::shift()) {
|
|
_modifiers |= KM_SHIFT;
|
|
} else if (be._button == KeyboardButton::alt()) {
|
|
_modifiers |= KM_ALT;
|
|
} else if (be._button == KeyboardButton::meta()) {
|
|
_modifiers |= KM_META;
|
|
|
|
} else if (be._button == KeyboardButton::enter()) {
|
|
_text_input.push_back('\n');
|
|
|
|
} else if (be._button == MouseButton::wheel_up()) {
|
|
_wheel_delta -= 1;
|
|
} else if (be._button == MouseButton::wheel_down()) {
|
|
_wheel_delta += 1;
|
|
|
|
} else if (be._button == MouseButton::one()) {
|
|
_mouse_buttons[0] = true;
|
|
} else if (be._button == MouseButton::two()) {
|
|
_mouse_buttons[1] = true;
|
|
} else if (be._button == MouseButton::three()) {
|
|
_mouse_buttons[2] = true;
|
|
} else if (be._button == MouseButton::four()) {
|
|
_mouse_buttons[3] = true;
|
|
} else if (be._button == MouseButton::five()) {
|
|
_mouse_buttons[4] = true;
|
|
}
|
|
|
|
rocket_key = get_rocket_key(be._button);
|
|
if (rocket_key != KI_UNKNOWN) {
|
|
_keys[rocket_key] = true;
|
|
}
|
|
break;
|
|
|
|
case ButtonEvent::T_repeat:
|
|
if (be._button == KeyboardButton::enter()) {
|
|
_text_input.push_back('\n');
|
|
}
|
|
|
|
rocket_key = get_rocket_key(be._button);
|
|
if (rocket_key != KI_UNKNOWN) {
|
|
_repeated_keys.push_back(rocket_key);
|
|
}
|
|
break;
|
|
|
|
case ButtonEvent::T_up:
|
|
if (be._button == KeyboardButton::control()) {
|
|
_modifiers &= ~KM_CTRL;
|
|
} else if (be._button == KeyboardButton::shift()) {
|
|
_modifiers &= ~KM_SHIFT;
|
|
} else if (be._button == KeyboardButton::alt()) {
|
|
_modifiers &= ~KM_ALT;
|
|
} else if (be._button == KeyboardButton::meta()) {
|
|
_modifiers &= ~KM_META;
|
|
|
|
} else if (be._button == MouseButton::one()) {
|
|
_mouse_buttons[0] = false;
|
|
} else if (be._button == MouseButton::two()) {
|
|
_mouse_buttons[1] = false;
|
|
} else if (be._button == MouseButton::three()) {
|
|
_mouse_buttons[2] = false;
|
|
} else if (be._button == MouseButton::four()) {
|
|
_mouse_buttons[3] = false;
|
|
} else if (be._button == MouseButton::five()) {
|
|
_mouse_buttons[4] = false;
|
|
}
|
|
|
|
rocket_key = get_rocket_key(be._button);
|
|
if (rocket_key != KI_UNKNOWN) {
|
|
_keys[rocket_key] = false;
|
|
}
|
|
break;
|
|
|
|
case ButtonEvent::T_keystroke:
|
|
// Ignore control characters; otherwise, they actually get added to strings in the UI.
|
|
if (be._keycode > 0x1F && (be._keycode < 0x7F || be._keycode > 0x9F)) {
|
|
_text_input.push_back(be._keycode);
|
|
}
|
|
break;
|
|
|
|
case ButtonEvent::T_resume_down:
|
|
break;
|
|
|
|
case ButtonEvent::T_move:
|
|
break;
|
|
|
|
case ButtonEvent::T_candidate:
|
|
break;
|
|
|
|
case ButtonEvent::T_raw_down:
|
|
break;
|
|
|
|
case ButtonEvent::T_raw_up:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: RocketInputHandler::update_context
|
|
// Access: Public
|
|
// Description: Updates the libRocket context with the changes
|
|
// that we have gathered in do_transmit_data.
|
|
// Also calls Update() on the context.
|
|
////////////////////////////////////////////////////////////////////
|
|
void RocketInputHandler::
|
|
update_context(Rocket::Core::Context *context, int xoffs, int yoffs) {
|
|
MutexHolder holder(_lock);
|
|
|
|
if (_mouse_xy_changed) {
|
|
_mouse_xy_changed = false;
|
|
|
|
context->ProcessMouseMove(_mouse_xy.get_x() - xoffs,
|
|
_mouse_xy.get_y() - yoffs, _modifiers);
|
|
}
|
|
|
|
if (_mouse_buttons.size() > 0) {
|
|
ButtonActivityMap::const_iterator it;
|
|
for (it = _mouse_buttons.begin(); it != _mouse_buttons.end(); ++it) {
|
|
if (it->second) {
|
|
context->ProcessMouseButtonDown(it->first, _modifiers);
|
|
} else {
|
|
context->ProcessMouseButtonUp(it->first, _modifiers);
|
|
}
|
|
}
|
|
_mouse_buttons.clear();
|
|
}
|
|
|
|
if (_wheel_delta != 0) {
|
|
context->ProcessMouseWheel(_wheel_delta, _modifiers);
|
|
_wheel_delta = 0;
|
|
}
|
|
|
|
if (_keys.size() > 0) {
|
|
ButtonActivityMap::const_iterator it;
|
|
for (it = _keys.begin(); it != _keys.end(); ++it) {
|
|
if (it->second) {
|
|
context->ProcessKeyDown((KeyIdentifier) it->first, _modifiers);
|
|
} else {
|
|
context->ProcessKeyUp((KeyIdentifier) it->first, _modifiers);
|
|
}
|
|
}
|
|
_keys.clear();
|
|
}
|
|
|
|
if (_repeated_keys.size() > 0) {
|
|
pvector<int>::const_iterator it;
|
|
|
|
for (it = _repeated_keys.begin(); it != _repeated_keys.end(); ++it) {
|
|
context->ProcessKeyUp((KeyIdentifier) *it, _modifiers);
|
|
context->ProcessKeyDown((KeyIdentifier) *it, _modifiers);
|
|
}
|
|
_repeated_keys.clear();
|
|
}
|
|
|
|
if (_text_input.size() > 0) {
|
|
pvector<short>::const_iterator it;
|
|
for (it = _text_input.begin(); it != _text_input.end(); ++it) {
|
|
context->ProcessTextInput(*it);
|
|
}
|
|
_text_input.clear();
|
|
}
|
|
|
|
context->Update();
|
|
}
|