170 lines
3.7 KiB
GDScript
170 lines
3.7 KiB
GDScript
class_name LayoutKLE extends AbstractLayout
|
|
|
|
const LABEL_TO_KEYCODE_MAP: Dictionary[String, Key] = {
|
|
"`": KEY_QUOTELEFT,
|
|
"-": KEY_MINUS,
|
|
"=": KEY_EQUAL,
|
|
"[": KEY_BRACKETLEFT,
|
|
"]": KEY_BRACKETRIGHT,
|
|
"\\": KEY_BACKSLASH,
|
|
";": KEY_SEMICOLON,
|
|
"'": KEY_APOSTROPHE,
|
|
",": KEY_COMMA,
|
|
".": KEY_PERIOD,
|
|
"/": KEY_SLASH,
|
|
"Esc": KEY_ESCAPE,
|
|
"Back Space": KEY_BACKSPACE,
|
|
"Caps Lock": KEY_CAPSLOCK,
|
|
"Win": KEY_META,
|
|
"PrtSc": KEY_PRINT,
|
|
"Scroll Lock": KEY_SCROLLLOCK,
|
|
"PgUp": KEY_PAGEUP,
|
|
"PgDn": KEY_PAGEDOWN,
|
|
"Num Lock": KEY_NUMLOCK,
|
|
"*": KEY_KP_MULTIPLY,
|
|
"+": KEY_KP_ADD,
|
|
"Del": KEY_KP_PERIOD,
|
|
"↑": KEY_UP,
|
|
"←": KEY_LEFT,
|
|
"↓": KEY_DOWN,
|
|
"→": KEY_RIGHT,
|
|
}
|
|
|
|
const W := "w"
|
|
const H := "h"
|
|
const X := "x"
|
|
const Y := "y"
|
|
|
|
var has_errors: bool = false
|
|
|
|
var _name: String
|
|
var _rows: Array[Array]
|
|
|
|
|
|
func _init(json_path: String) -> void:
|
|
var data := _load_json_file(json_path)
|
|
if not data:
|
|
has_errors = true
|
|
printerr("ERROR LOADING KLE LAYOUT JSON: '%s'" % json_path)
|
|
return
|
|
|
|
var layout_rows := _deserialize(data)
|
|
if not layout_rows:
|
|
has_errors = true
|
|
printerr("ERROR DESERIALIZING KLE LAYOUT: '%s'" % json_path)
|
|
return
|
|
|
|
_rows = layout_rows
|
|
|
|
|
|
func name() -> String:
|
|
return _name
|
|
|
|
|
|
func rows() -> Array[Array]:
|
|
return _rows
|
|
|
|
|
|
func _load_json_file(path: String) -> Array:
|
|
var file := FileAccess.open(path, FileAccess.READ)
|
|
if not file:
|
|
printerr("error opening file '%s': %s" % [path, FileAccess.get_open_error()])
|
|
return []
|
|
var content := file.get_as_text()
|
|
|
|
var json := JSON.new()
|
|
var err := json.parse(content)
|
|
if err != OK:
|
|
printerr(
|
|
(
|
|
"json parse error in '%s' at line %s: %s"
|
|
% [path, json.get_error_line(), json.get_error_message()]
|
|
)
|
|
)
|
|
return []
|
|
|
|
var data: Variant = json.data
|
|
if data is not Array:
|
|
return []
|
|
|
|
_name = path.get_file()
|
|
|
|
return data
|
|
|
|
|
|
func _deserialize(data: Array) -> Array[Array]:
|
|
var layout_rows: Array[Array] = []
|
|
|
|
for data_row: Variant in data:
|
|
if data_row is Array:
|
|
var layout_row := _deserialize_row(data_row as Array)
|
|
layout_rows.append(layout_row)
|
|
|
|
return layout_rows
|
|
|
|
|
|
func _deserialize_row(data_row: Array) -> Array[Dictionary]:
|
|
var layout_row: Array[Dictionary] = []
|
|
|
|
var current_key_data_dict: Dictionary = {}
|
|
for key_data: Variant in data_row:
|
|
if key_data is Dictionary:
|
|
current_key_data_dict = key_data as Dictionary
|
|
|
|
if key_data is String:
|
|
var key_dict := {
|
|
KeyProps.KEY:
|
|
_get_keycode_from_legend(key_data as String, current_key_data_dict)
|
|
}
|
|
key_dict.merge(_deserialize_key(current_key_data_dict))
|
|
layout_row.append(key_dict)
|
|
current_key_data_dict = _cleanup_key_data_dict(current_key_data_dict)
|
|
|
|
return layout_row
|
|
|
|
|
|
func _deserialize_key(data_key: Dictionary) -> Dictionary:
|
|
var key_dict: Dictionary = {}
|
|
|
|
if data_key.has(W):
|
|
key_dict[KeyProps.W] = data_key[W]
|
|
if data_key.has(H):
|
|
key_dict[KeyProps.H] = data_key[H]
|
|
if data_key.has(X):
|
|
key_dict[KeyProps.X] = data_key[X]
|
|
if data_key.has(Y):
|
|
key_dict[KeyProps.Y] = data_key[Y]
|
|
|
|
return key_dict
|
|
|
|
|
|
func _cleanup_key_data_dict(data_key: Dictionary) -> Dictionary:
|
|
data_key.erase(W)
|
|
data_key.erase(H)
|
|
data_key.erase(X)
|
|
data_key.erase(Y)
|
|
return data_key
|
|
|
|
|
|
func _get_keycode_from_legend(legend: String, data_key: Dictionary) -> Key:
|
|
if legend == "" and data_key.has(W) and data_key[W] > 1:
|
|
return KEY_SPACE
|
|
|
|
var labels := legend.split("\n")
|
|
|
|
var keycode := OS.find_keycode_from_string(labels[0])
|
|
|
|
if keycode == KEY_NONE and labels.size() == 2:
|
|
keycode = OS.find_keycode_from_string(labels[1])
|
|
|
|
if (
|
|
keycode == KEY_NONE
|
|
and LABEL_TO_KEYCODE_MAP.has(labels[1] if labels.size() == 2 else labels[0])
|
|
):
|
|
keycode = LABEL_TO_KEYCODE_MAP[labels[1] if labels.size() == 2 else labels[0]]
|
|
|
|
if keycode == KEY_NONE:
|
|
printerr("could not recognize key label '%s'" % legend)
|
|
|
|
return keycode
|