From 6750cd7ad4cf29c06fe5b893e83a040886d1b106 Mon Sep 17 00:00:00 2001 From: Alula <6276139+alula@users.noreply.github.com> Date: Fri, 23 Apr 2021 03:55:13 +0200 Subject: [PATCH] touchscreen / android improvements --- .../io/github/doukutsu_rs/MainActivity.java | 31 ++++++--- src/scene/game_scene.rs | 50 ++++++++------- src/text_script.rs | 64 +++++++++++++++++-- 3 files changed, 107 insertions(+), 38 deletions(-) diff --git a/app/app/src/main/java/io/github/doukutsu_rs/MainActivity.java b/app/app/src/main/java/io/github/doukutsu_rs/MainActivity.java index 27ecfcb..cfc4618 100644 --- a/app/app/src/main/java/io/github/doukutsu_rs/MainActivity.java +++ b/app/app/src/main/java/io/github/doukutsu_rs/MainActivity.java @@ -58,19 +58,30 @@ public class MainActivity extends NativeActivity { } private void updateCutouts() { + this.displayInsets[0] = 0; + this.displayInsets[1] = 0; + this.displayInsets[2] = 0; + this.displayInsets[3] = 0; + + WindowInsets insets = getWindow().getDecorView().getRootWindowInsets(); + + if (insets != null) { + this.displayInsets[0] = Math.max(this.displayInsets[0], insets.getStableInsetLeft()); + this.displayInsets[1] = Math.max(this.displayInsets[1], insets.getStableInsetTop()); + this.displayInsets[2] = Math.max(this.displayInsets[2], insets.getStableInsetRight()); + this.displayInsets[3] = Math.max(this.displayInsets[3], insets.getStableInsetBottom()); + } + if (SDK_INT >= Build.VERSION_CODES.P) { - WindowInsets insets = getWindow().getDecorView().getRootWindowInsets(); + android.view.DisplayCutout cutout = insets.getDisplayCutout(); - if (insets != null) { - android.view.DisplayCutout cutout = insets.getDisplayCutout(); - - if (cutout != null) { - this.displayInsets[0] = cutout.getSafeInsetLeft(); - this.displayInsets[1] = cutout.getSafeInsetTop(); - this.displayInsets[2] = cutout.getSafeInsetRight(); - this.displayInsets[3] = cutout.getSafeInsetBottom(); - } + if (cutout != null) { + this.displayInsets[0] = Math.max(this.displayInsets[0], cutout.getSafeInsetLeft()); + this.displayInsets[1] = Math.max(this.displayInsets[0], cutout.getSafeInsetTop()); + this.displayInsets[2] = Math.max(this.displayInsets[0], cutout.getSafeInsetRight()); + this.displayInsets[3] = Math.max(this.displayInsets[0], cutout.getSafeInsetBottom()); } + } } } diff --git a/src/scene/game_scene.rs b/src/scene/game_scene.rs index f03357a..de7f07e 100644 --- a/src/scene/game_scene.rs +++ b/src/scene/game_scene.rs @@ -1,3 +1,5 @@ +use std::ops::Range; + use log::info; use crate::caret::CaretType; @@ -30,9 +32,8 @@ use crate::shared_game_state::SharedGameState; use crate::stage::{BackgroundType, Stage}; use crate::text_script::{ConfirmSelection, ScriptMode, TextScriptExecutionState, TextScriptLine, TextScriptVM}; use crate::texture_set::SizedBatch; +use crate::weapon::{Weapon, WeaponType}; use crate::weapon::bullet::BulletManager; -use crate::weapon::{WeaponType, Weapon}; -use std::ops::Range; pub struct GameScene { pub tick: u32, @@ -389,8 +390,11 @@ impl GameScene { return Ok(()); } - let top_pos = if state.textscript_vm.flags.position_top() { 32.0 } else { state.canvas_size.1 as f32 - 66.0 }; - let left_pos = (state.canvas_size.0 / 2.0 - 122.0).floor(); + let (off_left, off_top, off_right, off_bottom) = crate::framework::graphics::screen_insets_scaled(ctx, state.scale); + + let center = ((state.canvas_size.0 - off_left - off_right) / 2.0).floor(); + let top_pos = if state.textscript_vm.flags.position_top() { 32.0 + off_top } else { state.canvas_size.1 as f32 - off_bottom - 66.0 }; + let left_pos = off_left + center - 122.0; { let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "TextBox")?; @@ -404,46 +408,46 @@ impl GameScene { if state.textscript_vm.item != 0 { batch.add_rect( - (state.canvas_size.0 / 2.0 - 40.0).floor(), - state.canvas_size.1 - 112.0, + center - 40.0, + state.canvas_size.1 - off_bottom - 112.0, &state.constants.textscript.get_item_top_left, ); batch.add_rect( - (state.canvas_size.0 / 2.0 - 40.0).floor(), - state.canvas_size.1 - 96.0, + center - 40.0, + state.canvas_size.1 - off_bottom - 96.0, &state.constants.textscript.get_item_bottom_left, ); batch.add_rect( - (state.canvas_size.0 / 2.0 + 32.0).floor(), - state.canvas_size.1 - 112.0, + center + 32.0, + state.canvas_size.1 - off_bottom - 112.0, &state.constants.textscript.get_item_top_right, ); batch.add_rect( - (state.canvas_size.0 / 2.0 + 32.0).floor(), - state.canvas_size.1 - 104.0, + center + 32.0, + state.canvas_size.1 - off_bottom- 104.0, &state.constants.textscript.get_item_right, ); batch.add_rect( - (state.canvas_size.0 / 2.0 + 32.0).floor(), - state.canvas_size.1 - 96.0, + center + 32.0, + state.canvas_size.1 - off_bottom - 96.0, &state.constants.textscript.get_item_right, ); batch.add_rect( - (state.canvas_size.0 / 2.0 + 32.0).floor(), - state.canvas_size.1 - 88.0, + center + 32.0, + state.canvas_size.1 - off_bottom - 88.0, &state.constants.textscript.get_item_bottom_right, ); } if let TextScriptExecutionState::WaitConfirmation(_, _, _, wait, selection) = state.textscript_vm.state { let pos_y = if wait > 14 { - state.canvas_size.1 - 96.0 - (wait as f32 - 2.0) * 4.0 + state.canvas_size.1 - off_bottom - 96.0 - (wait as f32 + 2.0) * 4.0 } else { - state.canvas_size.1 - 96.0 + state.canvas_size.1 - off_bottom - 96.0 }; batch.add_rect( - (state.canvas_size.0 / 2.0 + 56.0).floor(), + center + 56.0, pos_y, &state.constants.textscript.textbox_rect_yes_no, ); @@ -452,7 +456,7 @@ impl GameScene { let pos_x = if selection == ConfirmSelection::No { 41.0 } else { 0.0 }; batch.add_rect( - (state.canvas_size.0 / 2.0 + 51.0).floor() + pos_x, + center + 51.0 + pos_x, state.canvas_size.1 - 86.0, &state.constants.textscript.textbox_rect_cursor, ); @@ -495,7 +499,7 @@ impl GameScene { rect.bottom = rect.top + 16; let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "ArmsImage")?; - batch.add_rect((state.canvas_size.0 / 2.0 - 12.0).floor(), state.canvas_size.1 - 104.0, &rect); + batch.add_rect((center - 12.0).floor(), state.canvas_size.1 - off_bottom - 104.0, &rect); batch.draw(ctx)?; } else { let item_id = state.textscript_vm.item as u16 - 1000; @@ -506,7 +510,7 @@ impl GameScene { rect.bottom = rect.top + 16; let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "ItemImage")?; - batch.add_rect((state.canvas_size.0 / 2.0 - 20.0).floor(), state.canvas_size.1 - 104.0, &rect); + batch.add_rect((center - 20.0).floor(), state.canvas_size.1 - off_bottom - 104.0, &rect); batch.draw(ctx)?; } } @@ -1452,7 +1456,7 @@ impl Scene for GameScene { self.player2.controller.update_trigger(); state.touch_controls.control_type = - if state.control_flags.control_enabled() { TouchControlType::Controls } else { TouchControlType::Dialog }; + if state.control_flags.control_enabled() { TouchControlType::Controls } else { TouchControlType::None }; if state.settings.touch_controls { state.touch_controls.interact_icon = false; diff --git a/src/text_script.rs b/src/text_script.rs index a3e6913..6f1dc67 100644 --- a/src/text_script.rs +++ b/src/text_script.rs @@ -14,7 +14,7 @@ use num_derive::FromPrimitive; use num_traits::{clamp, FromPrimitive}; use crate::bitfield; -use crate::common::{Direction, FadeDirection, FadeState}; +use crate::common::{Direction, FadeDirection, FadeState, Rect}; use crate::encoding::{read_cur_shift_jis, read_cur_wtf8}; use crate::engine_constants::EngineConstants; use crate::entity::GameEntity; @@ -22,6 +22,7 @@ use crate::frame::UpdateTarget; use crate::framework::context::Context; use crate::framework::error::GameError::{InvalidValue, ParseError}; use crate::framework::error::GameResult; +use crate::input::touch_controls::TouchControlType; use crate::npc::NPC; use crate::player::{ControlMode, TargetPlayer}; use crate::scene::game_scene::GameScene; @@ -542,6 +543,10 @@ impl TextScriptVM { break; } + if !state.control_flags.control_enabled() { + state.touch_controls.control_type = TouchControlType::Dialog; + } + if let Some(bytecode) = state.textscript_vm.scripts.find_script(state.textscript_vm.mode, event) { let mut cursor = Cursor::new(bytecode); cursor.seek(SeekFrom::Start(ip as u64))?; @@ -565,7 +570,8 @@ impl TextScriptVM { state.textscript_vm.prev_char = chr; state.textscript_vm.line_1.push(chr); - let text_len = state.font.text_width(state.textscript_vm.line_1.iter().copied(), &state.constants); + let text_len = + state.font.text_width(state.textscript_vm.line_1.iter().copied(), &state.constants); if text_len >= 284.0 { state.textscript_vm.current_line = TextScriptLine::Line2; } @@ -574,7 +580,8 @@ impl TextScriptVM { state.textscript_vm.prev_char = chr; state.textscript_vm.line_2.push(chr); - let text_len = state.font.text_width(state.textscript_vm.line_2.iter().copied(), &state.constants); + let text_len = + state.font.text_width(state.textscript_vm.line_2.iter().copied(), &state.constants); if text_len >= 284.0 { state.textscript_vm.current_line = TextScriptLine::Line3; } @@ -583,7 +590,8 @@ impl TextScriptVM { state.textscript_vm.prev_char = chr; state.textscript_vm.line_3.push(chr); - let text_len = state.font.text_width(state.textscript_vm.line_3.iter().copied(), &state.constants); + let text_len = + state.font.text_width(state.textscript_vm.line_3.iter().copied(), &state.constants); if text_len >= 284.0 { state.textscript_vm.line_1.clear(); state.textscript_vm.line_1.append(&mut state.textscript_vm.line_2); @@ -640,6 +648,48 @@ impl TextScriptVM { break; } + let mut confirm = + game_scene.player1.controller.trigger_jump() || game_scene.player2.controller.trigger_jump(); + + if state.settings.touch_controls && !state.control_flags.control_enabled() { + state.touch_controls.control_type = TouchControlType::None; + + let (off_left, _, off_right, off_bottom) = + crate::framework::graphics::screen_insets_scaled(ctx, state.scale); + let box_x = ((state.canvas_size.0 - off_left - off_right) / 2.0) as isize + 51; + let box_y = (state.canvas_size.1 - off_bottom - 96.0) as isize; + + if state.touch_controls.consume_click_in(Rect::new_size(box_x, box_y, 40, 20)) { + match selection { + ConfirmSelection::Yes => confirm = true, + ConfirmSelection::No => { + state.sound_manager.play_sfx(1); + state.textscript_vm.state = TextScriptExecutionState::WaitConfirmation( + event, + ip, + no_event, + 0, + ConfirmSelection::Yes, + ); + } + } + } else if state.touch_controls.consume_click_in(Rect::new_size(box_x + 41, box_y, 40, 20)) { + match selection { + ConfirmSelection::Yes => { + state.sound_manager.play_sfx(1); + state.textscript_vm.state = TextScriptExecutionState::WaitConfirmation( + event, + ip, + no_event, + 0, + ConfirmSelection::No, + ); + } + ConfirmSelection::No => confirm = true, + } + } + } + if game_scene.player1.controller.trigger_left() || game_scene.player1.controller.trigger_right() || game_scene.player2.controller.trigger_left() @@ -651,7 +701,7 @@ impl TextScriptVM { break; } - if game_scene.player1.controller.trigger_jump() || game_scene.player2.controller.trigger_jump() { + if confirm { state.sound_manager.play_sfx(18); match selection { ConfirmSelection::Yes => { @@ -674,6 +724,10 @@ impl TextScriptVM { TextScriptExecutionState::WaitInput(event, ip, blink) => { state.textscript_vm.state = TextScriptExecutionState::WaitInput(event, ip, (blink + 1) % 20); + if !state.control_flags.control_enabled() { + state.touch_controls.control_type = TouchControlType::Dialog; + } + if game_scene.player1.controller.trigger_jump() || game_scene.player1.controller.trigger_shoot() || game_scene.player1.controller.skip()