diff --git a/export_presets.cfg b/export_presets.cfg index 7a494dc..b2feecf 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -51,6 +51,65 @@ ssh_remote_deploy/extra_args_scp="" ssh_remote_deploy/run_script="#!/usr/bin/env bash\nexport DISPLAY=:0\nunzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"\n\"{temp_dir}/{exe_name}\" {cmd_args}" ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash\nkill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")\nrm -rf \"{temp_dir}\"" +[preset.2] + +name="Android" +platform="Android" +runnable=true +advanced_options=false +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="builds/*,playtest/*,scripts/*" +export_path="builds/android/NETfishing-debug.apk" +patches=PackedStringArray() +encryption_include_filters="" +encryption_exclude_filters="" +seed=0 +encrypt_pck=false +encrypt_directory=false +script_export_mode=2 + +[preset.2.options] + +custom_template/debug="" +custom_template/release="" +gradle_build/use_gradle_build=false +gradle_build/export_format=0 +gradle_build/min_sdk="" +gradle_build/target_sdk="" +architectures/armeabi-v7a=false +architectures/arm64-v8a=true +architectures/x86=false +architectures/x86_64=false +version/code=30600 +version/name="0.3.6-prealpha" +package/unique_name="io.makearmy.netfishing" +package/name="NETfishing" +package/signed=true +package/app_category=0 +package/retain_data_on_uninstall=false +package/exclude_from_recents=false +package/show_in_android_tv=false +package/show_in_app_library=true +package/show_as_launcher_app=true +launcher_icons/main_192x192="res://icon.svg" +graphics/opengl_debug=false +screen/immersive_mode=true +screen/edge_to_edge=false +screen/support_small=false +screen/support_normal=true +screen/support_large=true +screen/support_xlarge=true +user_data_backup/allow=false +gesture/swipe_to_dismiss=false +permissions/internet=true +permissions/access_network_state=true +permissions/custom_permissions=PackedStringArray() +texture_format/s3tc_bptc=false +texture_format/etc2_astc=true + [preset.1] name="Linux Desktop" diff --git a/main/main.gd b/main/main.gd index cda5c8f..8b14388 100644 --- a/main/main.gd +++ b/main/main.gd @@ -922,7 +922,10 @@ func _on_peer_identity_observed(_peer_id: int, status: String) -> void: func _input(event: InputEvent) -> void: if ( - not event.is_action_pressed("ui_cancel") + not ( + event.is_action_pressed("ui_cancel") + or event.is_action_pressed("open_system_menu") + ) or (event is InputEventKey and event.echo) ): return diff --git a/player/player.gd b/player/player.gd index 8933247..08c4217 100644 --- a/player/player.gd +++ b/player/player.gd @@ -373,18 +373,28 @@ func _unhandled_input(event: InputEvent) -> void: get_viewport().set_input_as_handled() return - if ( + var mouse_zoom_in: bool = ( event is InputEventMouseButton and event.shift_pressed and event.is_action_pressed("camera_zoom_in") - ): - _set_target_zoom(_target_zoom - zoom_step) - get_viewport().set_input_as_handled() - elif ( + ) + var controller_zoom_in: bool = ( + event is InputEventJoypadButton + and event.is_action_pressed("camera_zoom_in") + ) + var mouse_zoom_out: bool = ( event is InputEventMouseButton and event.shift_pressed and event.is_action_pressed("camera_zoom_out") - ): + ) + var controller_zoom_out: bool = ( + event is InputEventJoypadButton + and event.is_action_pressed("camera_zoom_out") + ) + if mouse_zoom_in or controller_zoom_in: + _set_target_zoom(_target_zoom - zoom_step) + get_viewport().set_input_as_handled() + elif mouse_zoom_out or controller_zoom_out: _set_target_zoom(_target_zoom + zoom_step) get_viewport().set_input_as_handled() diff --git a/project.godot b/project.godot index 6f47b5c..8c1b4ce 100644 --- a/project.godot +++ b/project.godot @@ -19,6 +19,11 @@ config/icon="res://icon.svg" [display] window/stretch/aspect="expand" +window/handheld/orientation=0 + +[input_devices] + +pointing/emulate_mouse_from_touch=true [gui] @@ -53,11 +58,13 @@ move_right={ sprint={ "deadzone": 0.2, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":7,"pressure":0.0,"pressed":false,"script":null) ] } jump={ "deadzone": 0.2, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null) ] } sneak={ @@ -73,11 +80,13 @@ slow_walk={ interact={ "deadzone": 0.2, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":2,"pressure":0.0,"pressed":false,"script":null) ] } fish_primary={ "deadzone": 0.2, "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":32,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":5,"axis_value":1.0,"script":null) ] } camera_drag={ @@ -88,11 +97,13 @@ camera_drag={ camera_zoom_in={ "deadzone": 0.2, "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":32,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":4,"canceled":false,"pressed":false,"double_click":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":10,"pressure":0.0,"pressed":false,"script":null) ] } camera_zoom_out={ "deadzone": 0.2, "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":32,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":5,"canceled":false,"pressed":false,"double_click":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":9,"pressure":0.0,"pressed":false,"script":null) ] } hotbar_1={ @@ -140,14 +151,31 @@ hotbar_9={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":57,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } +hotbar_previous={ +"deadzone": 0.2, +"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) +] +} +hotbar_next={ +"deadzone": 0.2, +"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null) +] +} open_backpack={ "deadzone": 0.2, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":4,"pressure":0.0,"pressed":false,"script":null) +] +} +open_system_menu={ +"deadzone": 0.2, +"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":6,"pressure":0.0,"pressed":false,"script":null) ] } open_emotes={ "deadzone": 0.2, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":16,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null) ] } open_tacklebox={ diff --git a/scripts/build_android_debug.sh b/scripts/build_android_debug.sh new file mode 100755 index 0000000..8f856f8 --- /dev/null +++ b/scripts/build_android_debug.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -euo pipefail + +readonly SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +readonly PROJECT_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)" +readonly OUTPUT_PATH="${PROJECT_ROOT}/builds/android/NETfishing-debug.apk" +readonly GODOT_BIN="${GODOT_BIN:-godot}" + +mkdir -p -- "$(dirname -- "${OUTPUT_PATH}")" + +"${GODOT_BIN}" \ + --headless \ + --path "${PROJECT_ROOT}" \ + --export-debug "Android" \ + "${OUTPUT_PATH}" + +test -s "${OUTPUT_PATH}" +sha256sum "${OUTPUT_PATH}" diff --git a/tests/android_readiness_validation.gd b/tests/android_readiness_validation.gd new file mode 100644 index 0000000..5a03dc5 --- /dev/null +++ b/tests/android_readiness_validation.gd @@ -0,0 +1,53 @@ +extends SceneTree + + +func _init() -> void: + assert( + ProjectSettings.get_setting("display/window/handheld/orientation", -1) == 0 + ) + assert( + ProjectSettings.get_setting( + "input_devices/pointing/emulate_mouse_from_touch", false + ) + ) + assert(_has_joypad_motion(&"move_forward", JOY_AXIS_LEFT_Y, -1.0)) + assert(_has_joypad_motion(&"move_backward", JOY_AXIS_LEFT_Y, 1.0)) + assert(_has_joypad_motion(&"move_left", JOY_AXIS_LEFT_X, -1.0)) + assert(_has_joypad_motion(&"move_right", JOY_AXIS_LEFT_X, 1.0)) + assert(_has_joypad_button(&"jump", JOY_BUTTON_A)) + assert(_has_joypad_button(&"interact", JOY_BUTTON_X)) + assert(_has_joypad_motion(&"fish_primary", JOY_AXIS_TRIGGER_RIGHT, 1.0)) + assert(_has_joypad_button(&"sprint", JOY_BUTTON_LEFT_STICK)) + assert(_has_joypad_button(&"camera_zoom_out", JOY_BUTTON_LEFT_SHOULDER)) + assert(_has_joypad_button(&"camera_zoom_in", JOY_BUTTON_RIGHT_SHOULDER)) + assert(_has_joypad_button(&"hotbar_previous", JOY_BUTTON_DPAD_LEFT)) + assert(_has_joypad_button(&"hotbar_next", JOY_BUTTON_DPAD_RIGHT)) + assert(_has_joypad_button(&"open_backpack", JOY_BUTTON_BACK)) + assert(_has_joypad_button(&"open_system_menu", JOY_BUTTON_START)) + assert(_has_joypad_button(&"open_emotes", JOY_BUTTON_DPAD_UP)) + print("android readiness validation passed") + quit() + + +func _has_joypad_button(action: StringName, button_index: JoyButton) -> bool: + for event: InputEvent in InputMap.action_get_events(action): + var button_event: InputEventJoypadButton = event as InputEventJoypadButton + if button_event != null and button_event.button_index == button_index: + return true + return false + + +func _has_joypad_motion( + action: StringName, + axis: JoyAxis, + direction: float, +) -> bool: + for event: InputEvent in InputMap.action_get_events(action): + var motion_event: InputEventJoypadMotion = event as InputEventJoypadMotion + if ( + motion_event != null + and motion_event.axis == axis + and is_equal_approx(motion_event.axis_value, direction) + ): + return true + return false diff --git a/tests/android_readiness_validation.gd.uid b/tests/android_readiness_validation.gd.uid new file mode 100644 index 0000000..f499a0b --- /dev/null +++ b/tests/android_readiness_validation.gd.uid @@ -0,0 +1 @@ +uid://cbqyx4mntux7l diff --git a/ui/emote_radial_menu.gd b/ui/emote_radial_menu.gd index 4d869e0..3ff0622 100644 --- a/ui/emote_radial_menu.gd +++ b/ui/emote_radial_menu.gd @@ -34,12 +34,12 @@ func _ready() -> void: func handle_input(event: InputEvent, can_open: bool) -> bool: + if not event.is_action("open_emotes"): + return false var key_event: InputEventKey = event as InputEventKey - if key_event == null or key_event.echo: + if key_event != null and key_event.echo: return false - if key_event.physical_keycode != KEY_C: - return false - if key_event.pressed: + if event.is_pressed(): if _is_open or not can_open: return _is_open open_menu() diff --git a/ui/hotbar.gd b/ui/hotbar.gd index 6466c34..fa10df0 100644 --- a/ui/hotbar.gd +++ b/ui/hotbar.gd @@ -193,6 +193,14 @@ func _unhandled_input(event: InputEvent) -> void: or not _fishing_spot.can_change_hotbar_selection() ): return + if event.is_action_pressed("hotbar_previous"): + _hotbar.cycle_selection(-1) + get_viewport().set_input_as_handled() + return + if event.is_action_pressed("hotbar_next"): + _hotbar.cycle_selection(1) + get_viewport().set_input_as_handled() + return if event is InputEventKey and event.pressed and not event.echo: for index: int in range(PlayerHotbarType.SLOT_COUNT): if event.is_action_pressed("hotbar_%d" % (index + 1)):