Skip to content

Commit

Permalink
Added support for left- and -right versions of modifier keys.
Browse files Browse the repository at this point in the history
Adds the ability to use Left/Right Shift, Control, Alt and Meta as key bindings.
These keys being used as modifiers (e.g. Shift+Ins, Ctrl+T) is unchanged, and either left or right will work.

References used:
https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
  • Loading branch information
EricEzaM committed Dec 8, 2020
1 parent 44e136a commit 1158b7e
Show file tree
Hide file tree
Showing 37 changed files with 241 additions and 205 deletions.
13 changes: 9 additions & 4 deletions core/core_constants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,6 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(KEY_DOWN);
BIND_CORE_ENUM_CONSTANT(KEY_PAGEUP);
BIND_CORE_ENUM_CONSTANT(KEY_PAGEDOWN);
BIND_CORE_ENUM_CONSTANT(KEY_SHIFT);
BIND_CORE_ENUM_CONSTANT(KEY_CONTROL);
BIND_CORE_ENUM_CONSTANT(KEY_META);
BIND_CORE_ENUM_CONSTANT(KEY_ALT);
BIND_CORE_ENUM_CONSTANT(KEY_CAPSLOCK);
BIND_CORE_ENUM_CONSTANT(KEY_NUMLOCK);
BIND_CORE_ENUM_CONSTANT(KEY_SCROLLLOCK);
Expand Down Expand Up @@ -244,6 +240,15 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHE);
BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHF);

BIND_CORE_ENUM_CONSTANT(KEY_LEFT_ALT);
BIND_CORE_ENUM_CONSTANT(KEY_RIGHT_ALT);
BIND_CORE_ENUM_CONSTANT(KEY_LEFT_SHIFT);
BIND_CORE_ENUM_CONSTANT(KEY_RIGHT_SHIFT);
BIND_CORE_ENUM_CONSTANT(KEY_LEFT_CONTROL);
BIND_CORE_ENUM_CONSTANT(KEY_RIGHT_CONTROL);
BIND_CORE_ENUM_CONSTANT(KEY_LEFT_META);
BIND_CORE_ENUM_CONSTANT(KEY_RIGHT_META);

BIND_CORE_ENUM_CONSTANT(KEY_UNKNOWN);
BIND_CORE_ENUM_CONSTANT(KEY_SPACE);
BIND_CORE_ENUM_CONSTANT(KEY_EXCLAM);
Expand Down
17 changes: 17 additions & 0 deletions core/input/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/input/default_controller_mappings.h"
#include "core/input/input_map.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"

#ifdef TOOLS_ENABLED
Expand Down Expand Up @@ -88,6 +89,7 @@ Input::MouseMode Input::get_mouse_mode() const {
}

void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_modifier_pressed", "keycode_mask"), &Input::is_modifier_pressed);
ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed);
ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &Input::is_mouse_button_pressed);
ClassDB::bind_method(D_METHOD("is_joy_button_pressed", "device", "button"), &Input::is_joy_button_pressed);
Expand Down Expand Up @@ -215,6 +217,21 @@ Input::SpeedTrack::SpeedTrack() {
reset();
}

bool Input::is_modifier_pressed(int p_modifier_mask) const {
switch (p_modifier_mask) {
case KEY_MASK_SHIFT:
return is_key_pressed(KEY_LEFT_SHIFT) || is_key_pressed(KEY_RIGHT_SHIFT);
case KEY_MASK_ALT:
return is_key_pressed(KEY_LEFT_ALT) || is_key_pressed(KEY_RIGHT_ALT);
case KEY_MASK_CONTROL:
return is_key_pressed(KEY_LEFT_CONTROL) || is_key_pressed(KEY_RIGHT_CONTROL);
case KEY_MASK_META:
return is_key_pressed(KEY_LEFT_META) || is_key_pressed(KEY_RIGHT_META);
default:
return false;
}
}

bool Input::is_key_pressed(int p_keycode) const {
_THREAD_SAFE_METHOD_
return keys_pressed.has(p_keycode);
Expand Down
1 change: 1 addition & 0 deletions core/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ class Input : public Object {

static Input *get_singleton();

bool is_modifier_pressed(int p_modifier_mask) const;
bool is_key_pressed(int p_keycode) const;
bool is_mouse_button_pressed(int p_button) const;
bool is_joy_button_pressed(int p_device, int p_button) const;
Expand Down
23 changes: 19 additions & 4 deletions core/input/input_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,16 +198,16 @@ String InputEventWithModifiers::as_text() const {
Vector<String> mod_names;

if (get_control()) {
mod_names.push_back(find_keycode_name(KEY_CONTROL));
mod_names.push_back(find_keycode_name(KEY_MASK_CONTROL));
}
if (get_shift()) {
mod_names.push_back(find_keycode_name(KEY_SHIFT));
mod_names.push_back(find_keycode_name(KEY_MASK_SHIFT));
}
if (get_alt()) {
mod_names.push_back(find_keycode_name(KEY_ALT));
mod_names.push_back(find_keycode_name(KEY_MASK_ALT));
}
if (get_metakey()) {
mod_names.push_back(find_keycode_name(KEY_META));
mod_names.push_back(find_keycode_name(KEY_MASK_META));
}

if (!mod_names.empty()) {
Expand Down Expand Up @@ -312,6 +312,21 @@ bool InputEventKey::is_echo() const {
return echo;
}

bool InputEventKey::is_keycode_modifier(int p_modifier_mask) const {
switch (p_modifier_mask) {
case KEY_MASK_SHIFT:
return keycode == KEY_LEFT_SHIFT || keycode == KEY_RIGHT_SHIFT;
case KEY_MASK_ALT:
return keycode == KEY_LEFT_ALT || keycode == KEY_RIGHT_ALT;
case KEY_MASK_CONTROL:
return keycode == KEY_LEFT_CONTROL || keycode == KEY_RIGHT_CONTROL;
case KEY_MASK_META:
return keycode == KEY_LEFT_META || keycode == KEY_RIGHT_META;
default:
return false;
}
}

uint32_t InputEventKey::get_keycode_with_modifiers() const {
uint32_t sc = keycode;
if (get_control()) {
Expand Down
2 changes: 2 additions & 0 deletions core/input/input_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ class InputEventKey : public InputEventWithModifiers {
void set_echo(bool p_enable);
virtual bool is_echo() const override;

bool is_keycode_modifier(int p_modifier_mask) const;

uint32_t get_keycode_with_modifiers() const;
uint32_t get_physical_keycode_with_modifiers() const;

Expand Down
36 changes: 23 additions & 13 deletions core/os/keyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,13 @@ static const _KeyCodeText _keycodes[] = {
{KEY_DOWN ,"Down"},
{KEY_PAGEUP ,"PageUp"},
{KEY_PAGEDOWN ,"PageDown"},
{KEY_SHIFT ,"Shift"},
{KEY_CONTROL ,"Control"},
#ifdef OSX_ENABLED
{KEY_META ,"Command"},
#ifdef APPLE_STYLE_KEYS
{KEY_LEFT_META ,"Left Command"},
{KEY_RIGHT_META ,"Right Command"},
#else
{KEY_META ,"Meta"},
{KEY_LEFT_META ,"Left Meta"},
{KEY_RIGHT_META ,"Right Meta"},
#endif
{KEY_ALT ,"Alt"},
{KEY_CAPSLOCK ,"CapsLock"},
{KEY_NUMLOCK ,"NumLock"},
{KEY_SCROLLLOCK ,"ScrollLock"},
Expand Down Expand Up @@ -158,6 +157,13 @@ static const _KeyCodeText _keycodes[] = {
{KEY_LAUNCHE ,"LaunchE"},
{KEY_LAUNCHF ,"LaunchF"},

{KEY_LEFT_SHIFT ,"Left Shift"},
{KEY_RIGHT_SHIFT ,"Right Shift"},
{KEY_LEFT_CONTROL ,"Left Control"},
{KEY_RIGHT_CONTROL ,"Right Control"},
{KEY_LEFT_ALT ,"Left Alt"},
{KEY_RIGHT_ALT ,"Right Alt"},

{KEY_UNKNOWN ,"Unknown"},

{KEY_SPACE ,"Space"},
Expand Down Expand Up @@ -322,10 +328,6 @@ bool keycode_has_unicode(uint32_t p_keycode) {
case KEY_DOWN:
case KEY_PAGEUP:
case KEY_PAGEDOWN:
case KEY_SHIFT:
case KEY_CONTROL:
case KEY_META:
case KEY_ALT:
case KEY_CAPSLOCK:
case KEY_NUMLOCK:
case KEY_SCROLLLOCK:
Expand Down Expand Up @@ -393,6 +395,14 @@ bool keycode_has_unicode(uint32_t p_keycode) {
case KEY_LAUNCHD:
case KEY_LAUNCHE:
case KEY_LAUNCHF:
case KEY_LEFT_SHIFT:
case KEY_RIGHT_SHIFT:
case KEY_LEFT_CONTROL:
case KEY_RIGHT_CONTROL:
case KEY_LEFT_ALT:
case KEY_RIGHT_ALT:
case KEY_LEFT_META:
case KEY_RIGHT_META:
return false;
}

Expand All @@ -402,19 +412,19 @@ bool keycode_has_unicode(uint32_t p_keycode) {
String keycode_get_string(uint32_t p_code) {
String codestr;
if (p_code & KEY_MASK_SHIFT) {
codestr += find_keycode_name(KEY_SHIFT);
codestr += find_keycode_name(KEY_MASK_SHIFT);
codestr += "+";
}
if (p_code & KEY_MASK_ALT) {
codestr += find_keycode_name(KEY_ALT);
codestr += find_keycode_name(KEY_MASK_ALT);
codestr += "+";
}
if (p_code & KEY_MASK_CONTROL) {
codestr += find_keycode_name(KEY_MASK_CONTROL);
codestr += "+";
}
if (p_code & KEY_MASK_META) {
codestr += find_keycode_name(KEY_META);
codestr += find_keycode_name(KEY_MASK_META);
codestr += "+";
}

Expand Down
13 changes: 9 additions & 4 deletions core/os/keyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,6 @@ enum KeyList {
KEY_DOWN = SPKEY | 0x12,
KEY_PAGEUP = SPKEY | 0x13,
KEY_PAGEDOWN = SPKEY | 0x14,
KEY_SHIFT = SPKEY | 0x15,
KEY_CONTROL = SPKEY | 0x16,
KEY_META = SPKEY | 0x17,
KEY_ALT = SPKEY | 0x18,
KEY_CAPSLOCK = SPKEY | 0x19,
KEY_NUMLOCK = SPKEY | 0x1A,
KEY_SCROLLLOCK = SPKEY | 0x1B,
Expand Down Expand Up @@ -154,6 +150,15 @@ enum KeyList {
KEY_LAUNCHE = SPKEY | 0x66,
KEY_LAUNCHF = SPKEY | 0x67,

KEY_LEFT_SHIFT = SPKEY | 0x68,
KEY_RIGHT_SHIFT = SPKEY | 0x69,
KEY_LEFT_CONTROL = SPKEY | 0x6A,
KEY_RIGHT_CONTROL = SPKEY | 0x6B,
KEY_LEFT_ALT = SPKEY | 0x6C,
KEY_RIGHT_ALT = SPKEY | 0x6D,
KEY_LEFT_META = SPKEY | 0x6E,
KEY_RIGHT_META = SPKEY | 0x6F,

KEY_UNKNOWN = SPKEY | 0xFFFFFF,

/* PRINTABLE LATIN 1 CODES */
Expand Down
2 changes: 1 addition & 1 deletion editor/animation_track_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3966,7 +3966,7 @@ bool AnimationTrackEditor::is_selection_active() const {
}

bool AnimationTrackEditor::is_snap_enabled() const {
return snap->is_pressed() ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
return snap->is_pressed() ^ Input::get_singleton()->is_modifier_pressed(KEY_MASK_COMMAND);
}

void AnimationTrackEditor::_update_tracks() {
Expand Down
4 changes: 2 additions & 2 deletions editor/code_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ void FindReplaceBar::_search_text_changed(const String &p_text) {
}

void FindReplaceBar::_search_text_entered(const String &p_text) {
if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
if (Input::get_singleton()->is_modifier_pressed(KEY_MASK_SHIFT)) {
search_prev();
} else {
search_next();
Expand All @@ -547,7 +547,7 @@ void FindReplaceBar::_replace_text_entered(const String &p_text) {
if (selection_only->is_pressed() && text_editor->is_selection_active()) {
_replace_all();
_hide_bar();
} else if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
} else if (Input::get_singleton()->is_modifier_pressed(KEY_MASK_SHIFT)) {
_replace();
search_prev();
} else {
Expand Down
4 changes: 2 additions & 2 deletions editor/editor_audio_buses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ void EditorAudioBus::_volume_changed(float p_normalized) {

const float p_db = this->_normalized_volume_to_scaled_db(p_normalized);

if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
if (Input::get_singleton()->is_modifier_pressed(KEY_MASK_COMMAND)) {
// Snap the value when holding Ctrl for easier editing.
// To do so, it needs to be converted back to normalized volume (as the slider uses that unit).
slider->set_value(_scaled_db_to_normalized_volume(Math::round(p_db)));
Expand Down Expand Up @@ -372,7 +372,7 @@ float EditorAudioBus::_scaled_db_to_normalized_volume(float db) {

void EditorAudioBus::_show_value(float slider_value) {
float db;
if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
if (Input::get_singleton()->is_modifier_pressed(KEY_MASK_COMMAND)) {
// Display the correct (snapped) value when holding Ctrl
db = Math::round(_normalized_volume_to_scaled_db(slider_value));
} else {
Expand Down
2 changes: 1 addition & 1 deletion editor/editor_help.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1973,7 +1973,7 @@ void FindBar::_search_text_changed(const String &p_text) {
}

void FindBar::_search_text_entered(const String &p_text) {
if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
if (Input::get_singleton()->is_modifier_pressed(KEY_MASK_SHIFT)) {
search_prev();
} else {
search_next();
Expand Down
2 changes: 1 addition & 1 deletion editor/export_template_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ void ExportTemplateManager::_http_download_templates_completed(int p_status, int
}

void ExportTemplateManager::_begin_template_download(const String &p_url) {
if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
if (Input::get_singleton()->is_modifier_pressed(KEY_MASK_SHIFT)) {
OS::get_singleton()->shell_open(p_url);
return;
}
Expand Down
2 changes: 1 addition & 1 deletion editor/filesystem_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2185,7 +2185,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
}
if (!to_move.empty()) {
if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
if (Input::get_singleton()->is_modifier_pressed(KEY_MASK_COMMAND)) {
for (int i = 0; i < to_move.size(); i++) {
String new_path;
String new_path_base;
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/animation_player_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ double AnimationPlayerEditor::_get_editor_step() const {
ERR_FAIL_COND_V(!anim.is_valid(), 0.0);

// Use more precise snapping when holding Shift
return Input::get_singleton()->is_key_pressed(KEY_SHIFT) ? anim->get_step() * 0.25 : anim->get_step();
return Input::get_singleton()->is_modifier_pressed(KEY_MASK_SHIFT) ? anim->get_step() * 0.25 : anim->get_step();
}

return 0.0;
Expand Down
20 changes: 11 additions & 9 deletions editor/plugins/canvas_item_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
snap_target[0] = SNAP_TARGET_NONE;
snap_target[1] = SNAP_TARGET_NONE;

bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL);
bool is_snap_active = smart_snap_active ^ Input::get_singleton()->is_modifier_pressed(KEY_MASK_COMMAND);

// Smart snap using the canvas position
Vector2 output = p_target;
Expand Down Expand Up @@ -460,7 +460,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
}

float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
if (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) && snap_rotation_step != 0) {
if (((smart_snap_active || snap_rotation) ^ Input::get_singleton()->is_modifier_pressed(KEY_MASK_COMMAND)) && snap_rotation_step != 0) {
if (snap_relative) {
return Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset + (p_start - (int)(p_start / snap_rotation_step) * snap_rotation_step);
} else {
Expand All @@ -479,7 +479,9 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
}

if (k.is_valid()) {
if (k->get_keycode() == KEY_CONTROL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT) {
if (k->is_keycode_modifier(KEY_MASK_COMMAND) ||
k->is_keycode_modifier(KEY_MASK_ALT) ||
k->is_keycode_modifier(KEY_MASK_SHIFT)) {
viewport->update();
}

Expand Down Expand Up @@ -2023,7 +2025,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) {
Transform2D simple_xform = (viewport->get_transform() * unscaled_transform).affine_inverse() * transform;

bool uniform = m->get_shift();
bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
bool is_ctrl = Input::get_singleton()->is_modifier_pressed(KEY_MASK_COMMAND);

Point2 drag_from_local = simple_xform.xform(drag_from);
Point2 drag_to_local = simple_xform.xform(drag_to);
Expand Down Expand Up @@ -3502,8 +3504,8 @@ void CanvasItemEditor::_draw_selection() {
}

// Draw the move handles
bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
bool is_ctrl = Input::get_singleton()->is_modifier_pressed(KEY_MASK_COMMAND);
bool is_alt = Input::get_singleton()->is_modifier_pressed(KEY_MASK_ALT);
if (tool == TOOL_MOVE && show_transformation_gizmos) {
if (_is_node_movable(canvas_item)) {
Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized();
Expand Down Expand Up @@ -3539,7 +3541,7 @@ void CanvasItemEditor::_draw_selection() {
Transform2D simple_xform = viewport->get_transform() * unscaled_transform;

Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE);
bool uniform = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
bool uniform = Input::get_singleton()->is_modifier_pressed(KEY_MASK_SHIFT);
Point2 offset = (simple_xform.affine_inverse().xform(drag_to) - simple_xform.affine_inverse().xform(drag_from)) * zoom;

if (drag_type == DRAG_SCALE_X) {
Expand Down Expand Up @@ -6491,8 +6493,8 @@ bool CanvasItemEditorViewport::_only_packed_scenes_selected() const {
}

void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p_data) {
bool is_shift = Input::get_singleton()->is_key_pressed(KEY_SHIFT);
bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT);
bool is_shift = Input::get_singleton()->is_modifier_pressed(KEY_MASK_SHIFT);
bool is_alt = Input::get_singleton()->is_modifier_pressed(KEY_MASK_ALT);

selected_files.clear();
Dictionary d = p_data;
Expand Down
2 changes: 1 addition & 1 deletion editor/plugins/collision_polygon_3d_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con

Vector2 cpoint(spoint.x, spoint.y);

if (snap_ignore && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
if (snap_ignore && !Input::get_singleton()->is_modifier_pressed(KEY_MASK_COMMAND)) {
snap_ignore = false;
}

Expand Down
Loading

0 comments on commit 1158b7e

Please sign in to comment.