make namings more clear

This commit is contained in:
Teatov 2025-08-04 04:48:14 +10:00
parent 2bc77aa297
commit d791ec24b3
19 changed files with 261 additions and 247 deletions

View File

@ -55,6 +55,9 @@ _center_label = NodePath("Labels/CenterLabel")
_press_light = NodePath("Effects/PressLight")
_adjacency_light = NodePath("Effects/AdjacencyLight")
_sfx_player = NodePath("SFXPlayer")
_light_fade_duration = null
_starting_pop_offset = null
_rotation_damping = null
_press_sfx = SubResource("AudioStreamRandomizer_agrko")
_release_sfx = SubResource("AudioStreamRandomizer_ch32x")

View File

@ -23,6 +23,7 @@ _keys_holder = NodePath("Keys")
_sfx_player = NodePath("SFXPlayer")
_rect_mesh = NodePath("RectMesh")
_key_scene = ExtResource("2_hylia")
_anim_time_scale = null
_layout_swap_sfx = SubResource("AudioStreamRandomizer_hylia")
[node name="Keys" type="Node3D" parent="."]

View File

@ -12,7 +12,7 @@ func _ready() -> void:
_set_layout_swap_label(_keyboard.prompt_page)
_input_label.text = "awaiting input..."
_typing_label.text = ""
_keyboard.key_press_changed.connect(_on_keyboard_key_press_changed)
_keyboard.key_input_event_emitted.connect(_on_keyboard_key_input_event_emitted)
_keyboard.prompt_page_turned.connect(_on_keyboard_prompt_page_turned)
LayoutConfig.layout_swapped.connect(_set_layout_label)
@ -82,7 +82,9 @@ func _erase_typing_label() -> void:
_typing_label.text = _typing_label.text.substr(0, _typing_label.text.length() - 1)
func _on_keyboard_key_press_changed(game_key: GameKey, event: InputEventKey) -> void:
func _on_keyboard_key_input_event_emitted(
game_key: GameKey, event: InputEventKey
) -> void:
if not event.is_pressed():
return

View File

@ -27,9 +27,9 @@ class_name GameKey extends Node3D
@export_group("Animation")
@export var _pos_sod_fzr: Vector3 = Vector3(5, 0.15, 0)
@export var _light_fade_time: float = 0.25
@export var _star_pop_offset: Vector3 = Vector3(0, -2.5, 0)
@export var _rotation_damp: float = 10
@export var _light_fade_duration: float = 0.25
@export var _starting_pop_offset: Vector3 = Vector3(0, -2.5, 0)
@export var _rotation_damping: float = 10
@export_subgroup("Idle")
@export var _idle_amplitude: float = 0.4
@ -45,15 +45,15 @@ class_name GameKey extends Node3D
var props: KeyProps
var player_transform: Transform3D
var player_pos_marker_transform: Transform3D
var _keyboard: GameKeyboard
var _is_pressed: bool
var _light_timer: float
var _init_position: Vector3
var _default_position: Vector3
var _default_rotation: Vector3
var _init_pos: Vector3
var _default_pos: Vector3
var _default_rot: Vector3
var _pos_sod: SecondOrderDynamics
@onready var _polyphonic: AudioStreamPlaybackPolyphonic
@ -66,22 +66,22 @@ var _pos_sod: SecondOrderDynamics
static func instantiate_with_props(
_props: KeyProps,
init_pos: Vector3,
default_angle: float,
angle: float,
keyboard: GameKeyboard,
scene: PackedScene
) -> GameKey:
var node := scene.instantiate() as GameKey
node._keyboard = keyboard
node.load_props(_props, init_pos, default_angle)
var game_key := scene.instantiate() as GameKey
game_key._keyboard = keyboard
game_key.load_props(_props, init_pos, angle)
if _props.keycode != KEY_NONE:
node.name += " " + OS.get_keycode_string(_props.keycode)
game_key.name += " " + OS.get_keycode_string(_props.keycode)
if _props.location != KEY_LOCATION_UNSPECIFIED:
node.name += (
game_key.name += (
" " + ("Left" if _props.location == KEY_LOCATION_LEFT else "Right")
)
return node
return game_key
#endregion
@ -89,13 +89,13 @@ static func instantiate_with_props(
#region builtins
func _ready() -> void:
if not _keyboard or not props:
return
_adjacency_light.visible = false
_keyboard.layout_size_changed.connect(_on_keyboard_layout_size_changed)
_keyboard.keys_requested.connect(_on_keyboard_keys_requested)
_keyboard.is_configuring_changed.connect(_on_keyboard_is_configuring_changed)
_keyboard.player_key_changed.connect(_on_keyboard_player_key_changed)
_keyboard.layout_changed.connect(_on_keyboard_layout_changed)
_keyboard.keys_queried.connect(_on_keyboard_keys_queried)
_keyboard.configuring_changed.connect(_on_keyboard_configuring_changed)
_keyboard.player_current_key_changed.connect(
_on_keyboard_player_current_key_changed
)
_keyboard.player_finished_move.connect(_on_keyboard_player_finished_move)
_set_labels()
@ -121,13 +121,13 @@ func _unhandled_input(event: InputEvent) -> void:
if event is not InputEventKey:
return
var event_key := event as InputEventKey
if (
event_key.physical_keycode != props.keycode
or event_key.echo
or (event_key.physical_keycode == KEY_NONE or props.keycode == KEY_NONE)
or event_key.physical_keycode == KEY_NONE
or props.keycode == KEY_NONE
or (
event_key.location != KEY_LOCATION_UNSPECIFIED
and props.location != KEY_LOCATION_UNSPECIFIED
@ -136,7 +136,8 @@ func _unhandled_input(event: InputEvent) -> void:
):
return
_set_pressing_from_event(event_key)
_set_pressing(event_key.is_pressed())
_keyboard.emit_key_input_event_emitted(self, event_key)
if _keyboard.is_configuring and event_key.is_pressed():
var new_char_type: String
@ -167,9 +168,9 @@ func _exit_tree() -> void:
#region public
func load_props(_props: KeyProps, init_pos: Vector3, default_angle: float) -> void:
_init_position = init_pos
_default_rotation.y = default_angle
func load_props(_props: KeyProps, init_pos: Vector3, angle: float) -> void:
_init_pos = init_pos
_default_rot.y = angle
if props:
_props.chars_from_dict(props.chars_to_dict())
@ -182,7 +183,7 @@ func load_props(_props: KeyProps, init_pos: Vector3, default_angle: float) -> vo
func get_default_transform() -> Transform3D:
return Transform3D(Quaternion.from_euler(_default_rotation), _default_position)
return Transform3D(Quaternion.from_euler(_default_rot), _default_pos)
func is_adjacent(to: GameKey) -> bool:
@ -196,28 +197,21 @@ func is_adjacent(to: GameKey) -> bool:
#region pressing
func _set_pressing_from_event(event: InputEventKey) -> void:
_set_pressing(event.is_pressed())
_keyboard.emit_key_press(self, event)
func _set_pressing(is_pressed: bool) -> void:
if _is_pressed == is_pressed:
return
_is_pressed = is_pressed
_set_keyboard_pressed_position(_is_pressed)
if _is_pressed:
_play_sfx(_press_sfx)
else:
_play_sfx(_release_sfx)
_keyboard.emit_key_pressed(self)
_play_sfx(_press_sfx if _is_pressed else _release_sfx)
func _set_keyboard_pressed_position(pressed: bool) -> void:
_keyboard.pressed_positions[_default_position] = pressed
_keyboard.pressed_positions[_default_pos] = pressed
func _erase_keyboard_pressed_position() -> void:
_keyboard.pressed_positions.erase(_default_position)
_keyboard.pressed_positions.erase(_default_pos)
#endregion
@ -241,7 +235,7 @@ func _set_labels(chars_dict: Dictionary[String, String] = {}) -> void:
func _set_labels_text(chars_dict: Dictionary[String, String]) -> void:
if Engine.is_editor_hint() or props.keycode == KEY_SPACE or not props.is_unicode():
if Engine.is_editor_hint() or not props.is_unicode():
_center_label.text = OS.get_keycode_string(props.keycode)
return
@ -322,24 +316,24 @@ func _set_bones_from_rect(rect: Rect2, skeleton: Skeleton3D) -> void:
#region animation
func _reset_animations() -> void:
_pos_sod = SecondOrderDynamics.new(
_pos_sod_fzr, _default_position + _star_pop_offset
_pos_sod_fzr, _default_pos + _starting_pop_offset
)
func _animate(delta: float) -> void:
position = _pos_sod.process(delta, _animate_position())
rotation = lerp(rotation, _default_rotation, delta * _rotation_damp)
rotation = lerp(rotation, _default_rot, delta * _rotation_damping)
func _animate_position() -> Vector3:
var new_position := _default_position
var new_position := _default_pos
new_position.y += (
sin(
(
_keyboard.anim_time
+ (_default_position.x / _keyboard.key_size) * _idle_frequency.x
+ (_default_position.z / _keyboard.key_size) * _idle_frequency.y
+ (_default_pos.x / _keyboard.key_size) * _idle_frequency.x
+ (_default_pos.z / _keyboard.key_size) * _idle_frequency.y
)
)
* _idle_amplitude
@ -351,7 +345,7 @@ func _animate_position() -> Vector3:
return new_position
func _shake(force: float) -> void:
func _anim_shake(force: float) -> void:
_pos_sod.y = (
_pos_sod.y
+ (
@ -365,11 +359,11 @@ func _shake(force: float) -> void:
)
func _push(force: Vector3) -> void:
func _anim_push(force: Vector3) -> void:
_pos_sod.y = (_pos_sod.y + force * _keyboard.key_size)
func _push_radial(force: float) -> void:
func _anim_push_radial(force: float) -> void:
_pos_sod.y = (Vector3(
_pos_sod.y.x * (force + 1), _pos_sod.y.y, _pos_sod.y.z * (force + 1)
))
@ -377,14 +371,14 @@ func _push_radial(force: float) -> void:
func _animate_light(delta: float) -> void:
if _is_pressed:
_light_timer = _light_fade_time
_light_timer = _light_fade_duration
if _light_timer <= 0:
_press_light.visible = false
return
_press_light.visible = true
_press_light.light_energy = (_light_timer / _light_fade_time) * _light_energy
_press_light.light_energy = (_light_timer / _light_fade_duration) * _light_energy
_light_timer -= delta
@ -400,41 +394,41 @@ func _play_sfx(stream: AudioStream) -> void:
#region event handlers
func _on_keyboard_layout_size_changed(rect: Rect2) -> void:
func _on_keyboard_layout_changed(rect: Rect2) -> void:
_erase_keyboard_pressed_position()
var center := rect.get_center()
_default_position = _init_position
_default_position.x -= center.x
_default_position.z -= center.y
_default_pos = _init_pos
_default_pos.x -= center.x
_default_pos.z -= center.y
_set_keyboard_pressed_position(_is_pressed)
if Engine.is_editor_hint():
position = _default_position
position = _default_pos
return
if not _pos_sod:
_reset_animations()
func _on_keyboard_keys_requested(query_func: Callable) -> void:
func _on_keyboard_keys_queried(query_func: Callable) -> void:
if query_func.call(self):
_keyboard.key_query_respond(self)
func _on_keyboard_is_configuring_changed(value: bool) -> void:
if value:
_push_radial(0.2)
func _on_keyboard_configuring_changed(is_configuring: bool) -> void:
if is_configuring:
_anim_push_radial(0.2)
else:
_shake(0.2)
_push_radial(-0.05)
_anim_shake(0.2)
_anim_push_radial(-0.05)
func _on_keyboard_player_key_changed(game_key: GameKey) -> void:
func _on_keyboard_player_current_key_changed(game_key: GameKey) -> void:
_adjacency_light.visible = is_adjacent(game_key)
func _on_keyboard_player_finished_move(game_key: GameKey) -> void:
if game_key == self:
_push(Vector3.DOWN * _hop_land_offset)
_anim_push(Vector3.DOWN * _hop_land_offset)
#endregion

View File

@ -2,18 +2,19 @@
class_name GameKeyboard extends Node3D
#region variables
signal key_press_changed(game_key: GameKey, event: InputEventKey)
signal layout_size_changed(rect: Rect2)
signal key_pressed(game_key: GameKey)
signal key_input_event_emitted(game_key: GameKey, event: InputEventKey)
signal layout_changed(rect: Rect2)
signal prompt_page_turned(page: int)
signal keys_requested(query_func: Callable)
signal is_configuring_changed(value: bool)
signal player_key_changed(game_key: GameKey)
signal keys_queried(query_func: Callable)
signal configuring_changed(is_configuring: bool)
signal player_current_key_changed(game_key: GameKey)
signal player_finished_move(game_key: GameKey)
@export_tool_button("Generate keys")
var generate_editor_keys_btn := _generate_editor_keys
@export_tool_button("Delete keys") var delete_editor_keys_btn := _delete_editor_keys
@export_tool_button("Request keys") var query_keys_btn := _query_keys
@export_tool_button("Request keys") var query_keys_btn := _query_editor_keys
@export_group("References")
@export var _keys_holder: Node3D
@ -21,13 +22,13 @@ var generate_editor_keys_btn := _generate_editor_keys
@export var _rect_mesh: MeshInstance3D
@export var _key_scene: PackedScene
@export_group("Key params")
@export_group("Key parameters")
@export var key_size: float = 1
@export var key_gap: float = 0.1
@export_group("Animation")
@export var _rot_sod_fzr: Vector3 = Vector3(3, 0.1, 2)
@export var _time_scale: float = 0.5
@export var _anim_time_scale: float = 0.5
@export var _pressing_lean_deg := Vector2(0.15, 0.7)
@export_group("SFX")
@ -51,7 +52,7 @@ var _queried_keys_limit: int = 0
@onready var _pressing_lean_rad := Vector2(
deg_to_rad(_pressing_lean_deg.x), deg_to_rad(_pressing_lean_deg.y)
)
@onready var _default_rotation: Vector3 = _keys_holder.rotation
@onready var _default_rot: Vector3 = _keys_holder.rotation
@onready var _polyphonic: AudioStreamPlaybackPolyphonic
#endregion
@ -64,7 +65,7 @@ func _ready() -> void:
return
_polyphonic = _sfx_player.get_stream_playback()
prompt_pages_total = ceili(LayoutConfig.layouts.size() / 9.0)
_generate_keys()
_generate_game_keys()
_reset_animations()
@ -83,7 +84,7 @@ func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("toggle_configuring"):
is_configuring = not is_configuring
print("now configuring: %s" % is_configuring)
is_configuring_changed.emit(is_configuring)
configuring_changed.emit(is_configuring)
return
if event is not InputEventKey:
@ -91,24 +92,20 @@ func _unhandled_input(event: InputEvent) -> void:
var event_key := event as InputEventKey
if event_key.echo:
if event_key.echo or not event_key.is_pressed():
return
if (
event_key.is_pressed()
and is_configuring
is_configuring
and event_key.physical_keycode >= KEY_KP_0
and event_key.physical_keycode <= KEY_KP_9
):
_swap_layout(event_key.physical_keycode)
_change_layout(event_key.physical_keycode)
return
var keycode := event_key.get_physical_keycode_with_modifiers()
if (
event_key.is_pressed()
and (keycode == KEY_SHIFT | KEY_MASK_ALT or keycode == KEY_ALT | KEY_MASK_SHIFT)
):
if keycode == KEY_SHIFT | KEY_MASK_ALT or keycode == KEY_ALT | KEY_MASK_SHIFT:
alt_visual_layout = not alt_visual_layout
print("changed visual layout! " + str(alt_visual_layout))
@ -117,18 +114,6 @@ func _unhandled_input(event: InputEvent) -> void:
#region public
func emit_key_press(game_key: GameKey, event: InputEventKey) -> void:
key_press_changed.emit(game_key, event)
func emit_player_key_change(game_key: GameKey) -> void:
player_key_changed.emit(game_key)
func emit_player_finished_move(game_key: GameKey) -> void:
player_finished_move.emit(game_key)
func query_key_by_keycode(keycode: Key) -> GameKey:
var found_key: GameKey
var result := query_keys(
@ -143,13 +128,13 @@ func query_keys(query_func: Callable, limit: int = 0) -> Array[GameKey]:
_queried_keys = []
_queried_keys_limit = limit
keys_requested.emit(query_func)
keys_queried.emit(query_func)
var queried_keys := _queried_keys
_queried_keys = []
_queried_keys_limit = 0
queried_keys.sort_custom(KeyHelper.sort_func)
queried_keys.sort_custom(KeyHelper.game_key_sort)
return queried_keys
@ -158,16 +143,32 @@ func key_query_respond(game_key: GameKey) -> void:
_queried_keys.append(game_key)
func emit_key_pressed(game_key: GameKey) -> void:
key_pressed.emit(game_key)
func emit_key_input_event_emitted(game_key: GameKey, event: InputEventKey) -> void:
key_input_event_emitted.emit(game_key, event)
func emit_player_current_key_changed(game_key: GameKey) -> void:
player_current_key_changed.emit(game_key)
func emit_player_finished_move(game_key: GameKey) -> void:
player_finished_move.emit(game_key)
#endregion
#region key generation
func _generate_keys() -> void:
func _generate_game_keys() -> void:
print("generating keys...")
_iterate_keys(_generate_key, LayoutConfig.layout_rows)
_iterate_key_props_rows(_generate_game_key, LayoutConfig.layout_key_props_rows)
func _generate_key(
func _generate_game_key(
key_props: KeyProps,
key_pos: Vector3,
angle: float,
@ -179,27 +180,27 @@ func _generate_key(
_keys_holder.add_child(game_key, true)
func _iterate_keys(
func _iterate_key_props_rows(
iter_func: Callable,
layout_rows: Array[Array],
key_props_rows: Array[Array],
current_keys: Dictionary[Vector2i, Array] = {}
) -> void:
_gap_to_size_ratio = key_gap / key_size
for row: Array[KeyProps] in layout_rows:
_set_row_key_scales_with_gaps(row)
for key_props_row: Array[KeyProps] in key_props_rows:
_set_row_key_scales_with_gaps(key_props_row)
var rect := KeyHelper.iterate_keys(
iter_func, layout_rows, key_size, key_gap, current_keys
var rect := KeyHelper.iterate_key_props_rows(
iter_func, key_props_rows, key_size, key_gap, current_keys
)
layout_size_changed.emit(rect)
layout_changed.emit(rect)
_rect_mesh.scale = Vector3(rect.size.x, 1, rect.size.y)
_rect_mesh.position.x = rect.position.x + rect.size.x / 2 - rect.get_center().x
_rect_mesh.position.z = rect.position.x + rect.size.y / 2 - rect.get_center().y
func _set_row_key_scales_with_gaps(row: Array[KeyProps]) -> void:
for key_props in row:
func _set_row_key_scales_with_gaps(key_props_row: Array[KeyProps]) -> void:
for key_props in key_props_row:
key_props.width = _get_scale_with_gaps(key_props.width)
key_props.height = _get_scale_with_gaps(key_props.height)
key_props.x = _get_scale_with_gaps(key_props.x) + _gap_to_size_ratio
@ -222,52 +223,33 @@ func _get_scale_with_gaps(key_scale: float) -> float:
return key_scale + _gap_to_size_ratio * (key_scale - 1)
func _generate_editor_keys() -> void:
_delete_editor_keys()
_iterate_keys(_generate_key, LayoutANSI.new().get_key_props_rows())
func _delete_editor_keys() -> void:
pressed_positions = {}
var nodes := _keys_holder.get_children()
if not nodes:
return
print("deleting keys...")
for node in nodes:
node.queue_free()
func _query_keys() -> void:
print(query_key_by_keycode(KEY_SHIFT))
#endregion
#region layout swapping
func _swap_layout(kp_key: Key) -> void:
func _change_layout(kp_key: Key) -> void:
if kp_key == KEY_KP_0:
prompt_page = wrapi(prompt_page + 1, 0, prompt_pages_total)
prompt_page_turned.emit(prompt_page)
return
var index := kp_key - KEY_KP_1 + prompt_page * 9
if index < 0 or index >= LayoutConfig.layouts.size():
var layout_idx := kp_key - KEY_KP_1 + prompt_page * 9
if layout_idx < 0 or layout_idx >= LayoutConfig.layouts.size():
return
var new_layout := (
(LayoutConfig.layouts.values() as Array[AbstractLayout])[index].get_name()
var new_layout_name := (
(LayoutConfig.layouts.values() as Array[AbstractLayout])[layout_idx].get_name()
)
if new_layout == LayoutConfig.current_layout.get_name():
if new_layout_name == LayoutConfig.current_layout.get_name():
return
LayoutConfig.swap_layout(new_layout)
_regenerate_keys(LayoutConfig.layout_rows)
LayoutConfig.change_layout(new_layout_name)
_regenerate_keys(LayoutConfig.layout_key_props_rows)
_play_sfx(_layout_swap_sfx)
func _regenerate_keys(layout_rows: Array[Array]) -> void:
func _regenerate_keys(key_props_rows: Array[Array]) -> void:
print("REgenerating keys...")
var current_keys: Dictionary[Vector2i, Array]
@ -282,7 +264,7 @@ func _regenerate_keys(layout_rows: Array[Array]) -> void:
else:
current_keys[dict_key] = [game_key] as Array[GameKey]
_iterate_keys(_regenerate_key, layout_rows, current_keys)
_iterate_key_props_rows(_regenerate_key, key_props_rows, current_keys)
for game_keys: Array[GameKey] in current_keys.values():
for game_key in game_keys:
@ -312,9 +294,9 @@ func _regenerate_key(
if game_keys.size() == 0:
current_keys.erase(dict_key)
else:
var props_dict := LayoutConfig.get_key_config_dict(key_props.keycode)
if props_dict and props_dict is Dictionary:
key_props.chars_from_dict(props_dict)
var chars_dict := LayoutConfig.get_key_config_dict(key_props.keycode)
if chars_dict and chars_dict is Dictionary:
key_props.chars_from_dict(chars_dict)
var game_key := GameKey.instantiate_with_props(
key_props, key_pos, angle, self, _key_scene
@ -328,16 +310,16 @@ func _regenerate_key(
#region animation
func _reset_animations() -> void:
anim_time = 0
_rot_sod = SecondOrderDynamics.new(_rot_sod_fzr, _default_rotation)
_rot_sod = SecondOrderDynamics.new(_rot_sod_fzr, _default_rot)
func _animate(delta: float) -> void:
anim_time += delta * _time_scale
anim_time += delta * _anim_time_scale
_keys_holder.rotation = _rot_sod.process(delta, _animate_rotation())
func _animate_rotation() -> Vector3:
var new_rotation := _default_rotation
var new_rotation := _default_rot
for pos: Vector3 in pressed_positions.keys():
var pos_pressed := pressed_positions[pos]
if not pos_pressed:
@ -359,9 +341,32 @@ func _play_sfx(stream: AudioStream) -> void:
#endregion
#region input prompt
#region prompt
func _set_prompt_pages() -> void:
prompt_page = 0
prompt_pages_total = ceili(LayoutConfig.layouts.size() / 9.0)
#endregion
#region editor
func _generate_editor_keys() -> void:
_delete_editor_keys()
_iterate_key_props_rows(_generate_game_key, LayoutANSI.new().get_key_props_rows())
func _delete_editor_keys() -> void:
pressed_positions = {}
var nodes := _keys_holder.get_children()
if not nodes:
return
print("deleting keys...")
for node in nodes:
node.queue_free()
func _query_editor_keys() -> void:
print(query_key_by_keycode(KEY_SHIFT))
#endregion

View File

@ -10,7 +10,7 @@ const SECTION_KEYS := "keys"
const PARAM_NAME := "name"
var current_layout: AbstractLayout
var layout_rows: Array[Array]
var layout_key_props_rows: Array[Array]
var layouts: Dictionary[String, AbstractLayout] = {
LayoutANSI.name: LayoutANSI.new(),
@ -44,7 +44,7 @@ func get_key_config_dict(keycode: Key) -> Dictionary:
return _config.get_value(SECTION_KEYS, param_key, {}) as Dictionary
func swap_layout(layout_name: String) -> void:
func change_layout(layout_name: String) -> void:
if layouts.has(layout_name):
_set_layout(layouts[layout_name])
layout_swapped.emit(current_layout)
@ -60,7 +60,7 @@ func _set_defaults() -> void:
func _set_layout(layout: AbstractLayout) -> void:
print("SETTING LAYOUT: '%s'" % layout.get_name())
current_layout = layout
layout_rows = current_layout.get_key_props_rows()
layout_key_props_rows = current_layout.get_key_props_rows()
func _load_config() -> Error:
@ -70,13 +70,13 @@ func _load_config() -> Error:
if err:
push_error("failed to load layout config file: '%s'" % error_string(err))
print()
return FAILED
return err
var layout_name := ""
if _config.has_section_key(SECTION_INFO, PARAM_NAME):
var config_name: Variant = _config.get_value(SECTION_INFO, PARAM_NAME, "")
if config_name is String:
layout_name = config_name as String
var config_layout_name: Variant = _config.get_value(SECTION_INFO, PARAM_NAME)
if config_layout_name is String:
layout_name = config_layout_name as String
else:
push_error("layout config is missing '%s/%s'" % [SECTION_INFO, PARAM_NAME])
@ -86,19 +86,19 @@ func _load_config() -> Error:
push_error("layout '%s' not found" % layout_name)
_set_defaults()
for row: Array[KeyProps] in layout_rows:
for key_props in row:
var param_key := str(key_props.keycode)
for key_props_row: Array[KeyProps] in layout_key_props_rows:
for key_props in key_props_row:
var keycode := str(key_props.keycode)
if (
not key_props.is_unicode()
or not _config.has_section_key(SECTION_KEYS, param_key)
or not _config.has_section_key(SECTION_KEYS, keycode)
):
continue
var dictionary: Variant = _config.get_value(SECTION_KEYS, param_key)
if dictionary is not Dictionary[String,String]:
var chars_dict: Variant = _config.get_value(SECTION_KEYS, keycode)
if chars_dict is not Dictionary[String,String]:
continue
key_props.chars_from_dict(dictionary as Dictionary[String,String])
key_props.chars_from_dict(chars_dict as Dictionary[String,String])
print("layout config loaded!\n")
@ -108,8 +108,8 @@ func _load_config() -> Error:
func _save_config() -> Error:
_config.set_value(SECTION_INFO, PARAM_NAME, current_layout.get_name())
for row: Array[KeyProps] in layout_rows:
for key_props in row:
for key_props_row: Array[KeyProps] in layout_key_props_rows:
for key_props in key_props_row:
if not key_props.is_unicode():
continue
@ -141,7 +141,7 @@ func _load_custom_layouts(path: String) -> void:
if file_err:
push_error(
(
"error copying file '%s': %s"
"error creating file '%s': %s"
% [CUSTOM_LAYOUTS_README, error_string(file_err)]
)
)
@ -153,12 +153,13 @@ func _load_custom_layouts(path: String) -> void:
print()
return
var files := dir.get_files()
var file_names := dir.get_files()
if files:
print("loading custom layouts..\n")
if not file_names:
return
for file_name in files:
print("loading custom layouts..\n")
for file_name in file_names:
if file_name.get_extension().to_lower() != "json":
continue
var layout := LayoutCustom.new(path.path_join(file_name))
@ -171,5 +172,4 @@ func _load_custom_layouts(path: String) -> void:
% [layout.get_name()]
)
)
print()
layouts[layout.get_name()] = layout

View File

@ -51,7 +51,7 @@ const ADJACENCY_MAP: Dictionary[Key, Array] = {
}
static func sort_func(a: GameKey, b: GameKey) -> bool:
static func game_key_sort(a: GameKey, b: GameKey) -> bool:
var a_pos := a.get_default_transform().origin
var b_pos := b.get_default_transform().origin
if a_pos.y == b_pos.y:
@ -66,24 +66,32 @@ static func get_rotated_key_pos(
return (key_pos - pivot_pos).rotated(Vector3.UP, angle) + pivot_pos
static func iterate_keys(
static func iterate_key_props_rows(
iter_func: Callable,
layout_rows: Array[Array],
key_props_rows: Array[Array],
key_size: float = 1,
key_gap: float = 0,
current_keys: Dictionary[Vector2i, Array] = {}
) -> Rect2:
var pos: Vector2 = Vector2.ZERO
var key_pos: Vector2 = Vector2.ZERO
var pivot := Vector2.ZERO
var angle: float = 0
var rect: Rect2 = Rect2(0, 0, 0, 0)
for row: Array[KeyProps] in layout_rows:
var result := _iterate_row(
iter_func, row, pos, pivot, angle, rect, key_size, key_gap, current_keys
for key_props_row: Array[KeyProps] in key_props_rows:
var result := _iterate_key_props_row(
iter_func,
key_props_row,
key_pos,
pivot,
angle,
rect,
key_size,
key_gap,
current_keys
)
pos = result[0]
pos.y += 1 + key_gap
key_pos = result[0]
key_pos.y += 1 + key_gap
pivot = result[1]
angle = result[2]
rect = result[3]
@ -91,10 +99,10 @@ static func iterate_keys(
return rect
static func _iterate_row(
static func _iterate_key_props_row(
iter_func: Callable,
row: Array[KeyProps],
pos: Vector2,
key_props_row: Array[KeyProps],
key_pos: Vector2,
pivot: Vector2,
angle: float,
rect: Rect2,
@ -102,9 +110,9 @@ static func _iterate_row(
key_gap: float,
current_keys: Dictionary[Vector2i, Array]
) -> Array[Variant]:
pos.x = pivot.x
key_pos.x = pivot.x
for key_props in row:
for key_props in key_props_row:
if key_props.has_angle():
angle = -deg_to_rad(key_props.angle)
if key_props.has_pivot_x():
@ -112,29 +120,31 @@ static func _iterate_row(
if key_props.has_pivot_y():
pivot.y = key_props.pivot_y
if key_props.has_pivot_x() or key_props.has_pivot_y():
pos = pivot
key_pos = pivot
var key_pos := Vector3(pos.x + key_size / 2, 0, pos.y + key_size / 2)
key_pos.x += (
var game_key_pos := Vector3(
key_pos.x + key_size / 2, 0, key_pos.y + key_size / 2
)
game_key_pos.x += (
(key_size * key_props.width - key_size) / 2 + key_size * key_props.x
)
key_pos.z += key_props.y * key_size
game_key_pos.z += key_props.y * key_size
key_pos = KeyHelper.get_rotated_key_pos(key_pos, pivot, angle)
game_key_pos = KeyHelper.get_rotated_key_pos(game_key_pos, pivot, angle)
iter_func.call(key_props, key_pos, angle, current_keys)
iter_func.call(key_props, game_key_pos, angle, current_keys)
if pos.x < rect.position.x:
rect.position.x = pos.x
if pos.y < rect.position.y:
rect.position.y = pos.y
if key_pos.x < rect.position.x:
rect.position.x = key_pos.x
if key_pos.y < rect.position.y:
rect.position.y = key_pos.y
pos.x += key_props.width * key_size + key_props.x * key_size + key_gap
pos.y += key_props.y * key_size
key_pos.x += key_props.width * key_size + key_props.x * key_size + key_gap
key_pos.y += key_props.y * key_size
if pos.x - key_gap > rect.end.x:
rect.end.x = pos.x - key_gap
if pos.y + key_size * key_props.height > rect.end.y:
rect.end.y = pos.y + key_size * key_props.height
if key_pos.x - key_gap > rect.end.x:
rect.end.x = key_pos.x - key_gap
if key_pos.y + key_size * key_props.height > rect.end.y:
rect.end.y = key_pos.y + key_size * key_props.height
return [pos, pivot, angle, rect]
return [key_pos, pivot, angle, rect]

View File

@ -47,7 +47,7 @@ var alt_shift_char: String
func is_unicode() -> bool:
return OS.is_keycode_unicode(keycode)
return keycode != KEY_SPACE and OS.is_keycode_unicode(keycode)
func is_player_pos_key() -> bool:

View File

@ -5,13 +5,13 @@ func get_name() -> String:
return ""
func get_rows() -> Array[Array]:
func get_key_dict_rows() -> Array[Array]:
return []
func get_key_props_rows() -> Array[Array]:
var rows: Array[Array] = []
for dict_row: Array[Dictionary] in get_rows():
for dict_row: Array[Dictionary] in get_key_dict_rows():
var row: Array[KeyProps] = []
for props_dict: Dictionary in dict_row:
row.append(KeyProps.new().props_from_dict(props_dict))

View File

@ -1,4 +1,4 @@
class_name CommonRows
class_name CommonKeys
static func big_enter_iso() -> Dictionary:

View File

@ -7,17 +7,17 @@ func get_name() -> String:
return name
func get_rows() -> Array[Array]:
func get_key_dict_rows() -> Array[Array]:
return [
CommonRows.number_row() + [{KeyProps.KEY: KEY_BACKSPACE, KeyProps.W: 2}],
CommonKeys.number_row() + [{KeyProps.KEY: KEY_BACKSPACE, KeyProps.W: 2}],
(
[{KeyProps.KEY: KEY_TAB, KeyProps.W: 1.5}]
+ CommonRows.letters_row_1()
+ [CommonRows.big_enter_iso()]
+ CommonKeys.letters_row_1()
+ [CommonKeys.big_enter_iso()]
),
(
[{KeyProps.KEY: KEY_CAPSLOCK, KeyProps.W: 1.75}]
+ CommonRows.letters_row_2()
+ CommonKeys.letters_row_2()
+ [{KeyProps.KEY: KEY_BACKSLASH}]
),
(
@ -29,7 +29,7 @@ func get_rows() -> Array[Array]:
},
{KeyProps.KEY: KEY_SECTION},
]
+ CommonRows.letters_row_3()
+ CommonKeys.letters_row_3()
+ [
{KeyProps.KEY: KEY_NONE},
{
@ -39,5 +39,5 @@ func get_rows() -> Array[Array]:
}
]
),
CommonRows.bottom_row()
CommonKeys.bottom_row()
]

View File

@ -7,17 +7,17 @@ func get_name() -> String:
return name
func get_rows() -> Array[Array]:
func get_key_dict_rows() -> Array[Array]:
return [
CommonRows.number_row() + [{KeyProps.KEY: KEY_BACKSPACE, KeyProps.W: 2}],
CommonKeys.number_row() + [{KeyProps.KEY: KEY_BACKSPACE, KeyProps.W: 2}],
(
[{KeyProps.KEY: KEY_TAB, KeyProps.W: 1.5}]
+ CommonRows.letters_row_1()
+ CommonKeys.letters_row_1()
+ [{KeyProps.KEY: KEY_BACKSLASH, KeyProps.W: 1.5}]
),
(
[{KeyProps.KEY: KEY_CAPSLOCK, KeyProps.W: 1.75}]
+ CommonRows.letters_row_2()
+ CommonKeys.letters_row_2()
+ [{KeyProps.KEY: KEY_ENTER, KeyProps.W: 2.25}]
),
(
@ -28,7 +28,7 @@ func get_rows() -> Array[Array]:
KeyProps.LOC: KEY_LOCATION_LEFT
}
]
+ CommonRows.letters_row_3()
+ CommonKeys.letters_row_3()
+ [
{
KeyProps.KEY: KEY_SHIFT,
@ -37,5 +37,5 @@ func get_rows() -> Array[Array]:
}
]
),
CommonRows.bottom_row()
CommonKeys.bottom_row()
]

View File

@ -7,18 +7,18 @@ func get_name() -> String:
return name
func get_rows() -> Array[Array]:
func get_key_dict_rows() -> Array[Array]:
return [
(
CommonRows.number_row()
CommonKeys.number_row()
+ [{KeyProps.KEY: KEY_BACKSLASH}, {KeyProps.KEY: KEY_BACKSPACE}]
),
(
[{KeyProps.KEY: KEY_TAB, KeyProps.W: 1.5}]
+ CommonRows.letters_row_1()
+ [CommonRows.big_enter_ansi()]
+ CommonKeys.letters_row_1()
+ [CommonKeys.big_enter_ansi()]
),
[{KeyProps.KEY: KEY_CAPSLOCK, KeyProps.W: 1.75}] + CommonRows.letters_row_2(),
[{KeyProps.KEY: KEY_CAPSLOCK, KeyProps.W: 1.75}] + CommonKeys.letters_row_2(),
(
[
{
@ -27,7 +27,7 @@ func get_rows() -> Array[Array]:
KeyProps.LOC: KEY_LOCATION_LEFT
}
]
+ CommonRows.letters_row_3()
+ CommonKeys.letters_row_3()
+ [
{
KeyProps.KEY: KEY_SHIFT,
@ -36,5 +36,5 @@ func get_rows() -> Array[Array]:
}
]
),
CommonRows.bottom_row()
CommonKeys.bottom_row()
]

View File

@ -35,7 +35,7 @@ func get_name() -> String:
return _name
func get_rows() -> Array[Array]:
func get_key_dict_rows() -> Array[Array]:
return _rows

View File

@ -7,17 +7,17 @@ func get_name() -> String:
return name
func get_rows() -> Array[Array]:
func get_key_dict_rows() -> Array[Array]:
return [
CommonRows.number_row() + [{KeyProps.KEY: KEY_BACKSPACE, KeyProps.W: 2}],
CommonKeys.number_row() + [{KeyProps.KEY: KEY_BACKSPACE, KeyProps.W: 2}],
(
[{KeyProps.KEY: KEY_TAB, KeyProps.W: 1.5}]
+ CommonRows.letters_row_1()
+ [CommonRows.big_enter_iso()]
+ CommonKeys.letters_row_1()
+ [CommonKeys.big_enter_iso()]
),
(
[{KeyProps.KEY: KEY_CAPSLOCK, KeyProps.W: 1.75}]
+ CommonRows.letters_row_2()
+ CommonKeys.letters_row_2()
+ [{KeyProps.KEY: KEY_BACKSLASH}]
),
(
@ -29,7 +29,7 @@ func get_rows() -> Array[Array]:
},
{KeyProps.KEY: KEY_SECTION},
]
+ CommonRows.letters_row_3()
+ CommonKeys.letters_row_3()
+ [
{
KeyProps.KEY: KEY_SHIFT,
@ -38,5 +38,5 @@ func get_rows() -> Array[Array]:
}
]
),
CommonRows.bottom_row()
CommonKeys.bottom_row()
]

View File

@ -7,20 +7,20 @@ func get_name() -> String:
return name
func get_rows() -> Array[Array]:
func get_key_dict_rows() -> Array[Array]:
return [
(
CommonRows.number_row()
CommonKeys.number_row()
+ [{KeyProps.KEY: KEY_NONE}, {KeyProps.KEY: KEY_BACKSPACE}]
),
(
[{KeyProps.KEY: KEY_TAB, KeyProps.W: 1.5}]
+ CommonRows.letters_row_1()
+ [CommonRows.big_enter_iso()]
+ CommonKeys.letters_row_1()
+ [CommonKeys.big_enter_iso()]
),
(
[{KeyProps.KEY: KEY_CAPSLOCK, KeyProps.W: 1.75}]
+ CommonRows.letters_row_2()
+ CommonKeys.letters_row_2()
+ [{KeyProps.KEY: KEY_BACKSLASH}]
),
(
@ -31,7 +31,7 @@ func get_rows() -> Array[Array]:
KeyProps.LOC: KEY_LOCATION_LEFT
}
]
+ CommonRows.letters_row_3()
+ CommonKeys.letters_row_3()
+ [
{KeyProps.KEY: KEY_NONE},
{

View File

@ -7,7 +7,7 @@ func get_name() -> String:
return name
func get_rows() -> Array[Array]:
func get_key_dict_rows() -> Array[Array]:
return [
[{KeyProps.KEY: KEY_Q}, {KeyProps.KEY: KEY_W}],
[{KeyProps.KEY: KEY_A}, {KeyProps.KEY: KEY_S}],

View File

@ -5,6 +5,7 @@ class_name Player extends Node3D
@export var _keyboard: GameKeyboard
@export_group("Animation")
@export_subgroup("Moving")
@export var _move_duration: float = 0.1
@export var _move_hop_height: float = 1
@ -22,11 +23,11 @@ var _prev_pos: Vector3
#region builtins
func _ready() -> void:
_keyboard.key_press_changed.connect(_on_keyboard_key_press_changed)
_keyboard.key_pressed.connect(_on_keyboard_key_pressed)
_current_key = _keyboard.query_key_by_keycode(_starting_keycode)
if _current_key:
global_transform = _current_key.player_pos_marker.global_transform
_keyboard.emit_player_key_change(_current_key)
_keyboard.emit_player_current_key_changed(_current_key)
func _process(delta: float) -> void:
@ -42,7 +43,7 @@ func _move(game_key: GameKey) -> void:
var look_target := game_key.player_pos_marker.transform * game_key.transform
look_target.origin.y = look_from.origin.y
var looking := look_from.looking_at(look_target.origin, Vector3.UP, true)
_rotation = (looking.basis.get_rotation_quaternion())
_rotation = looking.basis.get_rotation_quaternion()
_prev_pos = _current_key.player_pos_marker.global_position
_move_timer = _move_duration
@ -51,7 +52,7 @@ func _move(game_key: GameKey) -> void:
_is_moving = true
_current_key = game_key
_keyboard.emit_player_key_change(game_key)
_keyboard.emit_player_current_key_changed(game_key)
#endregion
@ -83,13 +84,11 @@ func _animate_position() -> Vector3:
func _animate_rotation() -> Vector3:
var rotation_translate := (
var rot_translate := (
_current_key.get_default_transform().inverse()
* _current_key.player_pos_marker.global_transform
)
return (
(_rotation * (rotation_translate.basis.get_rotation_quaternion())).get_euler()
)
return _rotation * (rot_translate.basis.get_rotation_quaternion()).get_euler()
func _finish_move(_interrupted: bool) -> void:
@ -100,8 +99,8 @@ func _finish_move(_interrupted: bool) -> void:
#region event handlers
func _on_keyboard_key_press_changed(game_key: GameKey, event: InputEventKey) -> void:
if event.is_pressed() and _current_key and _current_key.is_adjacent(game_key):
func _on_keyboard_key_pressed(game_key: GameKey) -> void:
if _current_key and _current_key.is_adjacent(game_key):
_move(game_key)
#endregion