diff --git a/scenes/game_key.tscn b/scenes/game_key.tscn index 82322b0..397a066 100644 --- a/scenes/game_key.tscn +++ b/scenes/game_key.tscn @@ -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") diff --git a/scenes/game_keyboard.tscn b/scenes/game_keyboard.tscn index 39a35c7..5c76491 100644 --- a/scenes/game_keyboard.tscn +++ b/scenes/game_keyboard.tscn @@ -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="."] diff --git a/scripts/debug/debug_key_display.gd b/scripts/debug/debug_key_display.gd index 21f77fa..5f476ec 100644 --- a/scripts/debug/debug_key_display.gd +++ b/scripts/debug/debug_key_display.gd @@ -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 diff --git a/scripts/game_key.gd b/scripts/game_key.gd index e6b9540..e735f1d 100644 --- a/scripts/game_key.gd +++ b/scripts/game_key.gd @@ -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 diff --git a/scripts/game_keyboard.gd b/scripts/game_keyboard.gd index e1dc253..b9ede31 100644 --- a/scripts/game_keyboard.gd +++ b/scripts/game_keyboard.gd @@ -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 diff --git a/scripts/globals/layout_config.gd b/scripts/globals/layout_config.gd index 709c3ea..be7ac29 100644 --- a/scripts/globals/layout_config.gd +++ b/scripts/globals/layout_config.gd @@ -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 diff --git a/scripts/key_helper.gd b/scripts/key_helper.gd index 0783b5e..b1ce70c 100644 --- a/scripts/key_helper.gd +++ b/scripts/key_helper.gd @@ -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] diff --git a/scripts/key_props.gd b/scripts/key_props.gd index f64952c..a9a84fb 100644 --- a/scripts/key_props.gd +++ b/scripts/key_props.gd @@ -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: diff --git a/scripts/layouts/abstract_layout.gd b/scripts/layouts/abstract_layout.gd index d42732e..4f866e5 100644 --- a/scripts/layouts/abstract_layout.gd +++ b/scripts/layouts/abstract_layout.gd @@ -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)) diff --git a/scripts/layouts/common_rows.gd b/scripts/layouts/common_keys.gd similarity index 99% rename from scripts/layouts/common_rows.gd rename to scripts/layouts/common_keys.gd index 662f086..823fca4 100644 --- a/scripts/layouts/common_rows.gd +++ b/scripts/layouts/common_keys.gd @@ -1,4 +1,4 @@ -class_name CommonRows +class_name CommonKeys static func big_enter_iso() -> Dictionary: diff --git a/scripts/layouts/common_rows.gd.uid b/scripts/layouts/common_keys.gd.uid similarity index 100% rename from scripts/layouts/common_rows.gd.uid rename to scripts/layouts/common_keys.gd.uid diff --git a/scripts/layouts/layout_abnt.gd b/scripts/layouts/layout_abnt.gd index 7d78c39..9d7c1c6 100644 --- a/scripts/layouts/layout_abnt.gd +++ b/scripts/layouts/layout_abnt.gd @@ -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() ] diff --git a/scripts/layouts/layout_ansi.gd b/scripts/layouts/layout_ansi.gd index dc8b6a6..b3e6351 100644 --- a/scripts/layouts/layout_ansi.gd +++ b/scripts/layouts/layout_ansi.gd @@ -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() ] diff --git a/scripts/layouts/layout_ansi_variant.gd b/scripts/layouts/layout_ansi_variant.gd index 0f6abe1..dbce402 100644 --- a/scripts/layouts/layout_ansi_variant.gd +++ b/scripts/layouts/layout_ansi_variant.gd @@ -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() ] diff --git a/scripts/layouts/layout_custom.gd b/scripts/layouts/layout_custom.gd index 139ee95..25bb992 100644 --- a/scripts/layouts/layout_custom.gd +++ b/scripts/layouts/layout_custom.gd @@ -35,7 +35,7 @@ func get_name() -> String: return _name -func get_rows() -> Array[Array]: +func get_key_dict_rows() -> Array[Array]: return _rows diff --git a/scripts/layouts/layout_iso.gd b/scripts/layouts/layout_iso.gd index c1c8df3..869577d 100644 --- a/scripts/layouts/layout_iso.gd +++ b/scripts/layouts/layout_iso.gd @@ -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() ] diff --git a/scripts/layouts/layout_jis.gd b/scripts/layouts/layout_jis.gd index 516aa41..63667a8 100644 --- a/scripts/layouts/layout_jis.gd +++ b/scripts/layouts/layout_jis.gd @@ -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}, { diff --git a/scripts/layouts/layout_test.gd b/scripts/layouts/layout_test.gd index f6a0165..a97a5c3 100644 --- a/scripts/layouts/layout_test.gd +++ b/scripts/layouts/layout_test.gd @@ -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}], diff --git a/scripts/player.gd b/scripts/player.gd index 02eb945..ecf99ec 100644 --- a/scripts/player.gd +++ b/scripts/player.gd @@ -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