diff --git a/Cargo.toml b/Cargo.toml index 593db8d..fd9b443 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,12 +56,10 @@ android = [] byteorder = "1.4" case_insensitive_hashmap = "1.0.0" chrono = { version = "0.4", default-features = false, features = ["clock", "std"] } -#cpal = "0.14" -cpal = { git = "https://github.com/doukutsu-rs/cpal", branch = "horizon" } +cpal = { git = "https://github.com/doukutsu-rs/cpal", rev = "9d269d8724102404e73a61e9def0c0cbc921b676" } directories = "3" downcast = "0.11" -#glutin = { git = "https://github.com/doukutsu-rs/glutin.git", rev = "8dd457b9adb7dbac7ade337246b6356c784272d9", optional = true, default_features = false, features = ["x11"] } -glutin = { version = "0.30", optional = true, default_features = false, features = ["x11"] } +glutin = { git = "https://github.com/doukutsu-rs/glutin.git", rev = "2dd95f042e6e090d36f577cbea125560dd99bd27", optional = true, default_features = false, features = ["x11"] } imgui = "0.8" image = { version = "0.24", default-features = false, features = ["png", "bmp"] } itertools = "0.10" @@ -86,8 +84,7 @@ strum_macros = "0.24" # remove and replace when drain_filter is in stable vec_mut_scan = "0.4" webbrowser = { version = "0.8", optional = true } -#winit = { git = "https://github.com/alula/winit.git", rev = "6acf76ff192dd8270aaa119b9f35716c03685f9f", optional = true, default_features = false, features = ["x11"] } -winit = { version = "0.27", optional = true, default_features = false, features = ["x11"] } +winit = { git = "https://github.com/doukutsu-rs/winit.git", rev = "878f206d19af01b0977277929eee5e32667453c0", optional = true, default_features = false, features = ["x11"] } xmltree = "0.10" [target.'cfg(target_os = "windows")'.dependencies] diff --git a/app/.gitignore b/app/.gitignore index bd3a20d..043795d 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -231,3 +231,4 @@ fabric.properties !/gradle/wrapper/gradle-wrapper.jar # End of https://www.toptal.com/developers/gitignore/api/androidstudio,gradle,android +app/release/ \ No newline at end of file diff --git a/app/app/build.gradle b/app/app/build.gradle index 6bdca86..b0184d5 100644 --- a/app/app/build.gradle +++ b/app/app/build.gradle @@ -4,21 +4,23 @@ plugins { } android { - compileSdkVersion 30 - buildToolsVersion "30.0.3" - ndkVersion "22.1.7171670" + namespace "io.github.doukutsu_rs" + compileSdkVersion 33 + buildToolsVersion "33.0.0" + ndkVersion "25.0.8775105" defaultConfig { applicationId "io.github.doukutsu_rs" minSdkVersion 24 - targetSdkVersion 30 - versionCode 1 - versionName "1.0" + targetSdkVersion 33 + versionCode 2 + versionName "0.100.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" ndk { abiFilters 'x86', 'arm64-v8a', 'armeabi-v7a' + stl = "c++_shared" } externalNativeBuild { @@ -61,12 +63,10 @@ android { } dependencies { - implementation 'com.android.support:support-annotations:28.0.0' - implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'com.android.support:design:28.0.0' - implementation 'com.android.support.constraint:constraint-layout:2.0.1' - implementation 'android.arch.navigation:navigation-fragment:1.0.0' - implementation 'android.arch.navigation:navigation-ui:1.0.0' + implementation 'androidx.annotation:annotation:1.5.0' + implementation 'androidx.appcompat:appcompat:1.6.0' + implementation 'com.google.android.material:material:1.8.0-rc01' + implementation 'androidx.constraintlayout:constraintlayout:2.1.1' } println("cargo target: ${project.buildDir.getAbsolutePath()}/rust-target") diff --git a/app/app/src/main/AndroidManifest.xml b/app/app/src/main/AndroidManifest.xml index 8297b6e..d5a5a13 100644 --- a/app/app/src/main/AndroidManifest.xml +++ b/app/app/src/main/AndroidManifest.xml @@ -1,15 +1,25 @@ - + - - - + @@ -19,8 +29,10 @@ - @@ -28,4 +40,4 @@ - + \ No newline at end of file diff --git a/app/app/src/main/cpp/CMakeLists.txt b/app/app/src/main/cpp/CMakeLists.txt index 8625d7b..f480dc3 100644 --- a/app/app/src/main/cpp/CMakeLists.txt +++ b/app/app/src/main/cpp/CMakeLists.txt @@ -1,8 +1,8 @@ # Sets the minimum version of CMake required to build your native library. # This ensures that a certain set of CMake features is available to # your build. - -cmake_minimum_required(VERSION 3.10) +project(doukutsu-rs) +cmake_minimum_required(VERSION 3.18) # Copy shared STL files to Android Studio output directory so they can be # packaged in the APK. @@ -21,7 +21,7 @@ cmake_minimum_required(VERSION 3.10) function(configure_shared_stl lib_path so_base) message("Configuring STL ${so_base} for ${ANDROID_ABI}") configure_file( - "${ANDROID_NDK}/sources/cxx-stl/${lib_path}/libs/${ANDROID_ABI}/lib${so_base}.so" + "${ANDROID_NDK}/toolchains/llvm/prebuilt/${ANDROID_HOST_TAG}/sysroot/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/lib${so_base}.so" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${so_base}.so" COPYONLY) endfunction() @@ -50,4 +50,4 @@ endif() # and CMake builds them for you. When you build your app, Gradle # automatically packages shared libraries with your APK. -#add_library(dummy SHARED dummy.cpp) +add_library(dummy SHARED dummy.cpp) diff --git a/app/app/src/main/java/io/github/doukutsu_rs/DoukutsuDocumentsProvider.java b/app/app/src/main/java/io/github/doukutsu_rs/DoukutsuDocumentsProvider.java index 01fe368..d06b8fc 100644 --- a/app/app/src/main/java/io/github/doukutsu_rs/DoukutsuDocumentsProvider.java +++ b/app/app/src/main/java/io/github/doukutsu_rs/DoukutsuDocumentsProvider.java @@ -3,6 +3,7 @@ package io.github.doukutsu_rs; import android.database.Cursor; import android.database.MatrixCursor; import android.database.MatrixCursor.RowBuilder; +import android.os.Build; import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; import android.provider.DocumentsContract.Document; @@ -17,6 +18,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; +import static android.os.Build.VERSION.SDK_INT; + public class DoukutsuDocumentsProvider extends DocumentsProvider { private final static String[] DEFAULT_ROOT_PROJECTION = new String[]{ @@ -187,7 +190,13 @@ public class DoukutsuDocumentsProvider extends DocumentsProvider { File newPath = new File(file.getParentFile().getAbsolutePath() + "/" + displayName); try { - Files.move(file.toPath(), newPath.toPath()); + if (SDK_INT >= Build.VERSION_CODES.O) { + Files.move(file.toPath(), newPath.toPath()); + } else { + if (!file.renameTo(newPath)) { + throw new IOException("Couldn't rename file: " + file.getAbsolutePath()); + } + } } catch (IOException e) { throw new FileNotFoundException(e.getMessage()); } @@ -205,8 +214,18 @@ public class DoukutsuDocumentsProvider extends DocumentsProvider { File[] files = file.listFiles(); if (files != null) { for (File f : files) { - if (!Files.isSymbolicLink(f.toPath())) { - deleteRecursive(f); + if (SDK_INT >= Build.VERSION_CODES.O) { + if (!Files.isSymbolicLink(f.toPath())) { + deleteRecursive(f); + } + } else { + try { + if (!f.getAbsolutePath().equals(f.getCanonicalPath())) { + deleteRecursive(f); + } + } catch (IOException e) { + e.printStackTrace(); + } } } } diff --git a/app/app/src/main/java/io/github/doukutsu_rs/DownloadActivity.java b/app/app/src/main/java/io/github/doukutsu_rs/DownloadActivity.java index 0a1c873..595cc98 100644 --- a/app/app/src/main/java/io/github/doukutsu_rs/DownloadActivity.java +++ b/app/app/src/main/java/io/github/doukutsu_rs/DownloadActivity.java @@ -2,7 +2,7 @@ package io.github.doukutsu_rs; import android.content.Intent; import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatActivity; import android.widget.ProgressBar; import android.widget.TextView; diff --git a/app/app/src/main/res/layout/activity_download.xml b/app/app/src/main/res/layout/activity_download.xml index 4f29a5f..97f1db2 100644 --- a/app/app/src/main/res/layout/activity_download.xml +++ b/app/app/src/main/res/layout/activity_download.xml @@ -1,5 +1,6 @@ - - + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 6a8063d..079dfea 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,13 +2,13 @@ buildscript { repositories { google() - jcenter() + mavenCentral() maven { url "https://plugins.gradle.org/m2/" } } dependencies { - classpath "com.android.tools.build:gradle:4.2.0" + classpath "com.android.tools.build:gradle:7.4.0" classpath "gradle.plugin.com.github.willir.rust:plugin:0.3.4" // NOTE: Do not place your application dependencies here; they belong @@ -19,7 +19,7 @@ buildscript { allprojects { repositories { google() - jcenter() + mavenCentral() } } diff --git a/app/gradle/wrapper/gradle-wrapper.properties b/app/gradle/wrapper/gradle-wrapper.properties index bb9bece..5c2f040 100644 --- a/app/gradle/wrapper/gradle-wrapper.properties +++ b/app/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Feb 17 23:16:31 CET 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/drsandroid/Cargo.toml b/drsandroid/Cargo.toml index 348588a..7b8ad81 100644 --- a/drsandroid/Cargo.toml +++ b/drsandroid/Cargo.toml @@ -4,6 +4,10 @@ description = "doukutsu-rs targeted for Android" version = "0.1.0" edition = "2021" +[profile.release] +opt-level = 3 +incremental = true + [lib] crate-type = ["cdylib"] diff --git a/drsandroid/src/lib.rs b/drsandroid/src/lib.rs index 2b0addc..095fc7a 100644 --- a/drsandroid/src/lib.rs +++ b/drsandroid/src/lib.rs @@ -3,5 +3,5 @@ pub fn android_main() { let options = doukutsu_rs::game::LaunchOptions { server_mode: false, editor: false }; - doukutsu_rs::init(options).unwrap(); + doukutsu_rs::game::init(options).unwrap(); } diff --git a/src/engine_constants/mod.rs b/src/engine_constants/mod.rs index 517c04b..5514f5c 100644 --- a/src/engine_constants/mod.rs +++ b/src/engine_constants/mod.rs @@ -308,7 +308,7 @@ impl GamepadConsts { base, Rect::new(base.left + 64, base.top, base.right + 64, base.bottom), Rect::new(base.left + 128, base.top, base.right + 128, base.bottom), - Rect::new(base.left + 192, base.top, base.right + 192, base.bottom), + Rect::new(base.left + 64, base.top + 128, base.right + 64, base.bottom + 128), ] } } diff --git a/src/framework/backend_glutin.rs b/src/framework/backend_glutin.rs index 8c7e44b..40fb991 100644 --- a/src/framework/backend_glutin.rs +++ b/src/framework/backend_glutin.rs @@ -10,7 +10,8 @@ use glutin::event_loop::{ControlFlow, EventLoop}; use glutin::window::WindowBuilder; use imgui::{DrawCmdParams, DrawData, DrawIdx, DrawVert}; -use crate::{Game, GAME_SUSPENDED}; +use crate::game::Game; +use crate::game::GAME_SUSPENDED; use crate::common::Rect; use crate::framework::backend::{Backend, BackendEventLoop, BackendRenderer, BackendTexture, SpriteBatchCommand}; use crate::framework::context::Context; @@ -112,18 +113,21 @@ fn request_android_redraw() { #[cfg(target_os = "android")] fn get_insets() -> GameResult<(f32, f32, f32, f32)> { unsafe { + use jni::objects::JObject; + use jni::JavaVM; + let vm_ptr = ndk_glue::native_activity().vm(); - let vm = unsafe { jni::JavaVM::from_raw(vm_ptr) }?; + let vm = JavaVM::from_raw(vm_ptr)?; let vm_env = vm.attach_current_thread()?; //let class = vm_env.find_class("io/github/doukutsu_rs/MainActivity")?; - let class = vm_env.new_global_ref(ndk_glue::native_activity().activity())?; + let class = vm_env.new_global_ref(JObject::from_raw(ndk_glue::native_activity().activity()))?; let field = vm_env.get_field(class.as_obj(), "displayInsets", "[I")?.to_jni().l as jni::sys::jintArray; let mut elements = [0; 4]; vm_env.get_int_array_region(field, 0, &mut elements)?; - vm_env.delete_local_ref(field.into()); + vm_env.delete_local_ref(JObject::from_raw(field)); Ok((elements[0] as f32, elements[1] as f32, elements[2] as f32, elements[3] as f32)) } diff --git a/src/framework/backend_horizon.rs b/src/framework/backend_horizon.rs index d2f7cc7..4b47ed1 100644 --- a/src/framework/backend_horizon.rs +++ b/src/framework/backend_horizon.rs @@ -293,8 +293,8 @@ pub struct HorizonEventLoop { const GAMEPAD_KEYMAP: [Button; 16] = [ Button::South, Button::East, - Button::North, Button::West, + Button::North, Button::LeftStick, Button::RightStick, Button::LeftShoulder, @@ -351,6 +351,14 @@ impl HorizonEventLoop { let button = GAMEPAD_KEYMAP[i]; let mask = 1 << i; + if i == 8 { + ctx.gamepad_context.set_axis_value(id as u32, Axis::TriggerLeft, if buttons_down & mask != 0 { 1.0 } else { 0.0 }); + continue; + } else if i == 9 { + ctx.gamepad_context.set_axis_value(id as u32, Axis::TriggerRight, if buttons_down & mask != 0 { 1.0 } else { 0.0 }); + continue; + } + if buttons_down & mask != 0 { ctx.gamepad_context.set_button(id as u32, button, true); } @@ -363,10 +371,11 @@ impl HorizonEventLoop { let analog_x = pad.sticks[0].x as f64 / 32768.0; let analog_y = -pad.sticks[0].y as f64 / 32768.0; - ctx.gamepad_context.set_axis_value(id as u32, Axis::LeftX, analog_x.clamp(0.0, 1.0)); - ctx.gamepad_context.set_axis_value(id as u32, Axis::LeftY, analog_y.clamp(0.0, 1.0)); - ctx.gamepad_context.set_axis_value(id as u32, Axis::RightX, (-analog_x).clamp(0.0, 1.0)); - ctx.gamepad_context.set_axis_value(id as u32, Axis::RightY, (-analog_y).clamp(0.0, 1.0)); + ctx.gamepad_context.set_axis_value(id as u32, Axis::LeftX, (analog_x).clamp(-1.0, 1.0)); + ctx.gamepad_context.set_axis_value(id as u32, Axis::LeftY, (analog_y).clamp(-1.0, 1.0)); + ctx.gamepad_context.set_axis_value(id as u32, Axis::RightX, (analog_x).clamp(-1.0, 1.0)); + ctx.gamepad_context.set_axis_value(id as u32, Axis::RightY, (analog_y).clamp(-1.0, 1.0)); + ctx.gamepad_context.update_axes(id as u32); } } } diff --git a/src/game/settings.rs b/src/game/settings.rs index 437ee57..044f838 100644 --- a/src/game/settings.rs +++ b/src/game/settings.rs @@ -527,12 +527,12 @@ pub fn player_default_controller_button_map() -> PlayerControllerButtonMap { down: PlayerControllerInputType::Either(Button::DPadDown, Axis::LeftY, AxisDirection::Down), prev_weapon: PlayerControllerInputType::ButtonInput(Button::LeftShoulder), next_weapon: PlayerControllerInputType::ButtonInput(Button::RightShoulder), - jump: PlayerControllerInputType::ButtonInput(Button::South), - shoot: PlayerControllerInputType::ButtonInput(Button::West), - skip: PlayerControllerInputType::AxisInput(Axis::TriggerLeft, AxisDirection::Either), + jump: PlayerControllerInputType::ButtonInput(Button::East), + shoot: PlayerControllerInputType::ButtonInput(Button::South), + skip: PlayerControllerInputType::ButtonInput(Button::West), strafe: PlayerControllerInputType::AxisInput(Axis::TriggerRight, AxisDirection::Either), - inventory: PlayerControllerInputType::ButtonInput(Button::North), - map: PlayerControllerInputType::ButtonInput(Button::East), + inventory: PlayerControllerInputType::ButtonInput(Button::West), + map: PlayerControllerInputType::ButtonInput(Button::North), menu_ok: PlayerControllerInputType::ButtonInput(Button::South), menu_back: PlayerControllerInputType::ButtonInput(Button::East), } diff --git a/src/input/touch_player_controller.rs b/src/input/touch_player_controller.rs index f86ee29..b990380 100644 --- a/src/input/touch_player_controller.rs +++ b/src/input/touch_player_controller.rs @@ -291,8 +291,7 @@ impl PlayerController for TouchPlayerController { } fn skip(&self) -> bool { - // TODO - false + self.state.inventory() } fn strafe(&self) -> bool { @@ -341,8 +340,7 @@ impl PlayerController for TouchPlayerController { } fn trigger_skip(&self) -> bool { - // TODO - false + self.trigger.inventory() } fn trigger_strafe(&self) -> bool { diff --git a/src/menu/settings_menu.rs b/src/menu/settings_menu.rs index ff3ae59..5393e91 100644 --- a/src/menu/settings_menu.rs +++ b/src/menu/settings_menu.rs @@ -48,8 +48,8 @@ impl Default for MainMenuEntry { #[derive(Debug, Clone, Copy, Eq, PartialEq)] enum GraphicsMenuEntry { - WindowMode, VSyncMode, + WindowMode, LightingEffects, WeaponLightCone, ScreenShake, @@ -63,7 +63,7 @@ enum GraphicsMenuEntry { impl Default for GraphicsMenuEntry { fn default() -> Self { - GraphicsMenuEntry::WindowMode + GraphicsMenuEntry::VSyncMode } } @@ -182,19 +182,6 @@ impl SettingsMenu { } pub fn init(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult { - #[cfg(not(target_os = "android"))] - self.graphics.push_entry( - GraphicsMenuEntry::WindowMode, - MenuEntry::Options( - state.loc.t("menus.options_menu.graphics_menu.window_mode.entry").to_owned(), - state.settings.window_mode as usize, - vec![ - state.loc.t("menus.options_menu.graphics_menu.window_mode.windowed").to_owned(), - state.loc.t("menus.options_menu.graphics_menu.window_mode.fullscreen").to_owned(), - ], - ), - ); - self.graphics.push_entry( GraphicsMenuEntry::VSyncMode, MenuEntry::DescriptiveOptions( @@ -216,6 +203,18 @@ impl SettingsMenu { ], ), ); + #[cfg(not(all(target_os = "android", target_os = "horizon")))] + self.graphics.push_entry( + GraphicsMenuEntry::WindowMode, + MenuEntry::Options( + state.loc.t("menus.options_menu.graphics_menu.window_mode.entry").to_owned(), + state.settings.window_mode as usize, + vec![ + state.loc.t("menus.options_menu.graphics_menu.window_mode.windowed").to_owned(), + state.loc.t("menus.options_menu.graphics_menu.window_mode.fullscreen").to_owned(), + ], + ), + ); self.graphics.push_entry( GraphicsMenuEntry::LightingEffects, MenuEntry::Toggle( diff --git a/src/sound/mod.rs b/src/sound/mod.rs index 8e42d8e..73a4aab 100644 --- a/src/sound/mod.rs +++ b/src/sound/mod.rs @@ -4,7 +4,6 @@ use std::str::FromStr; use std::sync::mpsc; use std::sync::mpsc::{Receiver, Sender}; -use cpal::Sample; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; #[cfg(feature = "ogg-playback")] use lewton::inside_ogg::OggStreamReader; @@ -123,9 +122,17 @@ impl SoundManager { let config = config_result.unwrap(); let res = match config.sample_format() { - cpal::SampleFormat::F32 => run::(rx, soundbank.to_owned(), device, config.into()), + cpal::SampleFormat::I8 => run::(rx, soundbank.to_owned(), device, config.into()), cpal::SampleFormat::I16 => run::(rx, soundbank.to_owned(), device, config.into()), + cpal::SampleFormat::I32 => run::(rx, soundbank.to_owned(), device, config.into()), + cpal::SampleFormat::I64 => run::(rx, soundbank.to_owned(), device, config.into()), + cpal::SampleFormat::U8 => run::(rx, soundbank.to_owned(), device, config.into()), cpal::SampleFormat::U16 => run::(rx, soundbank.to_owned(), device, config.into()), + cpal::SampleFormat::U32 => run::(rx, soundbank.to_owned(), device, config.into()), + cpal::SampleFormat::U64 => run::(rx, soundbank.to_owned(), device, config.into()), + cpal::SampleFormat::F32 => run::(rx, soundbank.to_owned(), device, config.into()), + cpal::SampleFormat::F64 => run::(rx, soundbank.to_owned(), device, config.into()), + _ => Err(AudioError("Unsupported sample format.".to_owned())), }; if let Err(res) = &res { @@ -584,7 +591,7 @@ fn run( config: cpal::StreamConfig, ) -> GameResult where - T: cpal::Sample, + T: cpal::SizedSample + cpal::FromSample, { let sample_rate = config.sample_rate.0 as f32; let channels = config.channels as usize; @@ -821,8 +828,8 @@ fn run( ) as u16 ^ 0x8000; - frame[0] = Sample::from::(&sample_l); - frame[1] = Sample::from::(&sample_r); + frame[0] = T::from_sample(sample_l); + frame[1] = T::from_sample(sample_r); } else { let sample = clamp( ((((bgm_sample_l ^ 0x8000) as i16) + ((bgm_sample_r ^ 0x8000) as i16)) as f32 * bgm_vol / 2.0) @@ -833,11 +840,12 @@ fn run( ) as u16 ^ 0x8000; - frame[0] = Sample::from::(&sample); + frame[0] = T::from_sample(sample); } } }, err_fn, + None ); if stream_result.is_err() {