はじめに
Godotではボタンにショートカットを設定できますが、複数のボタンで同一のショートカットを設定すると、次のように最後に設定されたボタンが反応します。
ここでは、ペイントツールでSキーを押すと選択ツールが順番に切り替わるように、次のように同一のショートカットで複数のボタンが順番に反応することを目指します。
環境
v4.2.2.stable.official [15073afe3]
ShortcutManager
ショートカットを独自に処理するためにShortcutManager
というクラスを用意します。
class_name ShortcutManager
extends Node
signal handled(targets: Array[Variant])
var _shortcut_map = {}
func _shortcut_input(event):
var event_name = ShortcutManager._get_event_name(event)
var targets = _shortcut_map.get(event_name)
if targets == null:
return
handled.emit(targets)
get_viewport().set_input_as_handled()
func add_shortcut(shortcut: Shortcut, target: Variant):
for event_name in ShortcutManager._get_shortcut_event_names(shortcut):
if _shortcut_map.has(event_name):
_shortcut_map[event_name].append(target)
else:
_shortcut_map[event_name] = [target]
static func _get_shortcut_event_names(shortcut: Shortcut):
return shortcut.events.map(_get_event_name)
static func _get_event_name(event: InputEvent):
return StringName(str(event))
add_shortcut
メソッドでショートカットと、それに反応する対象を登録します。
クラスの使用側がショートカットに対するアクションを判別できれば、target
はなんでも構いません。
_shortcut_input
メソッドでイベントが登録されていれば、handled
シグナルを発信します。
handled
シグナルで送られるのは、トリガーとなったショートカットが紐づけられたすべてのtarget
です。
ボタンのリスト
次のようにノードを組み合わせ、
ButtonList
ノードに次のようなスクリプトをアタッチすれば、上記のGIFような動作になります。
extends VBoxContainer
@onready var buttons = [
$Button1,
$Button2,
$Button3,
$Button4,
$Button5,
$Button6,
]
var selected_button: Button = null
func _ready():
for button in buttons:
button.toggled.connect(_on_button_toggled.bind(button))
$ShortcutManager.add_shortcut(button.shortcut, button)
button.shortcut = null
$ShortcutManager.handled.connect(_on_shortcut_manager_handled)
func _on_button_toggled(toggled_on: bool, button: Button):
if toggled_on:
selected_button = button
func _on_shortcut_manager_handled(targets):
var index = targets.find(selected_button) + 1
var button = targets[index % len(targets)]
button.button_pressed = true
ここで各ボタンにはボタングループとショートカットが設定されており、Toggle Modeがオンになっています。
ShortcutManager
ノードには上記のShortcutManager
クラスのスクリプトをアタッチします。ベースノードはNode
です。
おわりに
以上でペイントツールのツールボタンのショートカットのようなものがGodotで実装できます。
GDScriptにも早くジェネリクスが導入されてほしいですね。