new android port
44
Cargo.toml
|
@ -4,27 +4,8 @@ edition = "2018"
|
||||||
name = "doukutsu-rs"
|
name = "doukutsu-rs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
#[lib]
|
[lib]
|
||||||
#crate-type = ["lib", "cdylib"]
|
crate-type = ["lib", "cdylib"]
|
||||||
|
|
||||||
[package.metadata.android]
|
|
||||||
android_version = 29
|
|
||||||
target_sdk_version = 28
|
|
||||||
min_sdk_version = 26
|
|
||||||
build_targets = ["aarch64-linux-android"]
|
|
||||||
package_name = "io.github.doukutsu_rs.android"
|
|
||||||
apk_label = "doukutsu-rs"
|
|
||||||
opengles_version = [3, 1]
|
|
||||||
fullscreen = true
|
|
||||||
orientation = "sensorLandscape"
|
|
||||||
permission = [
|
|
||||||
{ name = "android.permission.READ_EXTERNAL_STORAGE" },
|
|
||||||
{ name = "android.permission.WRITE_EXTERNAL_STORAGE" }
|
|
||||||
]
|
|
||||||
application_metadatas = [
|
|
||||||
{ name = "android:hardwareAccelerated", value = "true" },
|
|
||||||
{ name = "android:requestLegacyExternalStorage", value = "true" }
|
|
||||||
]
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = 'thin'
|
lto = 'thin'
|
||||||
|
@ -43,20 +24,22 @@ opt-level = 1
|
||||||
default = ["scripting", "backend-sdl", "ogg-playback"]
|
default = ["scripting", "backend-sdl", "ogg-playback"]
|
||||||
ogg-playback = ["lewton"]
|
ogg-playback = ["lewton"]
|
||||||
backend-sdl = ["sdl2"]
|
backend-sdl = ["sdl2"]
|
||||||
backend-gfx = ["winit", "imgui-gfx-renderer", "imgui-winit-support"]
|
#backend-sokol = ["sokol"]
|
||||||
|
backend-glutin = ["winit", "glutin"]
|
||||||
scripting = ["lua-ffi"]
|
scripting = ["lua-ffi"]
|
||||||
editor = []
|
editor = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
#cpal = { path = "./3rdparty/cpal" }
|
||||||
|
#glutin = { path = "./3rdparty/glutin/glutin", optional = true }
|
||||||
bitvec = "0.20"
|
bitvec = "0.20"
|
||||||
byteorder = "1.4"
|
byteorder = "1.4"
|
||||||
case_insensitive_hashmap = "1.0.0"
|
case_insensitive_hashmap = "1.0.0"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
cpal = "0.13"
|
cpal = { git = "https://github.com/doukutsu-rs/cpal.git", rev = "e027550be0b93b7e2912c7de28a4944a7d04e070" }
|
||||||
directories = "3"
|
directories = "3"
|
||||||
|
glutin = { git = "https://github.com/doukutsu-rs/glutin.git", rev = "a34ee3c99b3c999b638ca2bae53cf96df2b94c04", optional = true }
|
||||||
imgui = "0.7.0"
|
imgui = "0.7.0"
|
||||||
imgui-gfx-renderer = { version = "0.7.0", optional = true }
|
|
||||||
imgui-winit-support = { version = "0.7.0", default-features = false, features = ["winit-24"], optional = true }
|
|
||||||
image = { version = "0.23", default-features = false, features = ["png", "bmp"] }
|
image = { version = "0.23", default-features = false, features = ["png", "bmp"] }
|
||||||
itertools = "0.10"
|
itertools = "0.10"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
@ -69,6 +52,7 @@ num-traits = "0.2.12"
|
||||||
paste = "1.0.0"
|
paste = "1.0.0"
|
||||||
pretty_env_logger = "0.4.0"
|
pretty_env_logger = "0.4.0"
|
||||||
sdl2 = { version = "0.34", optional = true, features = ["unsafe_textures", "bundled", "static-link"] }
|
sdl2 = { version = "0.34", optional = true, features = ["unsafe_textures", "bundled", "static-link"] }
|
||||||
|
#sokol = { git = "https://github.com/doukutsu-rs/sokol-rs.git", rev = "", optional = true }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_derive = "1"
|
serde_derive = "1"
|
||||||
serde_yaml = "0.8"
|
serde_yaml = "0.8"
|
||||||
|
@ -77,12 +61,16 @@ strum_macros = "0.20"
|
||||||
# remove and replace when drain_filter is in stable
|
# remove and replace when drain_filter is in stable
|
||||||
vec_mut_scan = "0.4"
|
vec_mut_scan = "0.4"
|
||||||
webbrowser = "0.5.5"
|
webbrowser = "0.5.5"
|
||||||
winit = { version = "0.24", features = ["serde"], optional = true }
|
winit = { version = "0.24", optional = true }
|
||||||
|
|
||||||
|
#[build-dependencies]
|
||||||
|
#gl_generator = { version = "0.14.0", optional = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["winuser"] }
|
winapi = { version = "0.3", features = ["winuser"] }
|
||||||
|
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
ndk = "0.3"
|
ndk = "0.2"
|
||||||
ndk-glue = "0.3"
|
ndk-glue = "0.2"
|
||||||
|
ndk-sys = "0.2"
|
||||||
jni = "0.19"
|
jni = "0.19"
|
||||||
|
|
233
app/.gitignore
vendored
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/androidstudio,gradle,android
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=androidstudio,gradle,android
|
||||||
|
|
||||||
|
### Android ###
|
||||||
|
# Built application files
|
||||||
|
*.apk
|
||||||
|
*.aar
|
||||||
|
*.ap_
|
||||||
|
*.aab
|
||||||
|
|
||||||
|
# Files for the ART/Dalvik VM
|
||||||
|
*.dex
|
||||||
|
|
||||||
|
# Java class files
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
bin/
|
||||||
|
gen/
|
||||||
|
out/
|
||||||
|
# Uncomment the following line in case you need and you don't have the release build type files in your app
|
||||||
|
# release/
|
||||||
|
|
||||||
|
# Gradle files
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Proguard folder generated by Eclipse
|
||||||
|
proguard/
|
||||||
|
|
||||||
|
# Log Files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Android Studio Navigation editor temp files
|
||||||
|
.navigation/
|
||||||
|
|
||||||
|
# Android Studio captures folder
|
||||||
|
captures/
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
*.iml
|
||||||
|
.idea/workspace.xml
|
||||||
|
.idea/tasks.xml
|
||||||
|
.idea/gradle.xml
|
||||||
|
.idea/assetWizardSettings.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
.idea/libraries
|
||||||
|
# Android Studio 3 in .gitignore file.
|
||||||
|
.idea/caches
|
||||||
|
.idea/modules.xml
|
||||||
|
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
|
||||||
|
.idea/navEditor.xml
|
||||||
|
|
||||||
|
# Keystore files
|
||||||
|
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||||
|
#*.jks
|
||||||
|
#*.keystore
|
||||||
|
|
||||||
|
# External native build folder generated in Android Studio 2.2 and later
|
||||||
|
.externalNativeBuild
|
||||||
|
.cxx/
|
||||||
|
|
||||||
|
# Google Services (e.g. APIs or Firebase)
|
||||||
|
# google-services.json
|
||||||
|
|
||||||
|
# Freeline
|
||||||
|
freeline.py
|
||||||
|
freeline/
|
||||||
|
freeline_project_description.json
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots
|
||||||
|
fastlane/test_output
|
||||||
|
fastlane/readme.md
|
||||||
|
|
||||||
|
# Version control
|
||||||
|
vcs.xml
|
||||||
|
|
||||||
|
# lint
|
||||||
|
lint/intermediates/
|
||||||
|
lint/generated/
|
||||||
|
lint/outputs/
|
||||||
|
lint/tmp/
|
||||||
|
# lint/reports/
|
||||||
|
|
||||||
|
### Android Patch ###
|
||||||
|
gen-external-apklibs
|
||||||
|
output.json
|
||||||
|
|
||||||
|
# Replacement of .externalNativeBuild directories introduced
|
||||||
|
# with Android Studio 3.5.
|
||||||
|
|
||||||
|
### Gradle ###
|
||||||
|
.gradle
|
||||||
|
|
||||||
|
# Ignore Gradle GUI config
|
||||||
|
gradle-app.setting
|
||||||
|
|
||||||
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
|
!gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Cache of project
|
||||||
|
.gradletasknamecache
|
||||||
|
|
||||||
|
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
||||||
|
# gradle/wrapper/gradle-wrapper.properties
|
||||||
|
|
||||||
|
### Gradle Patch ###
|
||||||
|
**/build/
|
||||||
|
|
||||||
|
### AndroidStudio ###
|
||||||
|
# Covers files to be ignored for android development using Android Studio.
|
||||||
|
|
||||||
|
# Built application files
|
||||||
|
|
||||||
|
# Files for the ART/Dalvik VM
|
||||||
|
|
||||||
|
# Java class files
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
|
||||||
|
# Gradle files
|
||||||
|
|
||||||
|
# Signing files
|
||||||
|
.signing/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
|
||||||
|
# Proguard folder generated by Eclipse
|
||||||
|
|
||||||
|
# Log Files
|
||||||
|
|
||||||
|
# Android Studio
|
||||||
|
/*/build/
|
||||||
|
/*/local.properties
|
||||||
|
/*/out
|
||||||
|
/*/*/build
|
||||||
|
/*/*/production
|
||||||
|
*.ipr
|
||||||
|
*~
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Keystore files
|
||||||
|
*.jks
|
||||||
|
*.keystore
|
||||||
|
|
||||||
|
# Google Services (e.g. APIs or Firebase)
|
||||||
|
# google-services.json
|
||||||
|
|
||||||
|
# Android Patch
|
||||||
|
|
||||||
|
# External native build folder generated in Android Studio 2.2 and later
|
||||||
|
|
||||||
|
# NDK
|
||||||
|
obj/
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# IntelliJ IDEA
|
||||||
|
*.iws
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# User-specific configurations
|
||||||
|
.idea/caches/
|
||||||
|
.idea/libraries/
|
||||||
|
.idea/shelf/
|
||||||
|
.idea/.name
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/copyright/profiles_settings.xml
|
||||||
|
.idea/encodings.xml
|
||||||
|
.idea/misc.xml
|
||||||
|
.idea/scopes/scope_settings.xml
|
||||||
|
.idea/vcs.xml
|
||||||
|
.idea/jsLibraryMappings.xml
|
||||||
|
.idea/datasources.xml
|
||||||
|
.idea/dataSources.ids
|
||||||
|
.idea/sqlDataSources.xml
|
||||||
|
.idea/dynamic.xml
|
||||||
|
.idea/uiDesigner.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
|
||||||
|
# OS-specific files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Legacy Eclipse project files
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.cproject
|
||||||
|
.settings/
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.war
|
||||||
|
*.ear
|
||||||
|
|
||||||
|
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/mongoSettings.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
### AndroidStudio Patch ###
|
||||||
|
|
||||||
|
!/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/androidstudio,gradle,android
|
1
app/app/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build
|
99
app/app/build.gradle
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
plugins {
|
||||||
|
id 'com.android.application'
|
||||||
|
id 'com.github.willir.rust.cargo-ndk-android'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 30
|
||||||
|
buildToolsVersion "30.0.3"
|
||||||
|
//ndkVersion "21.3.6528147"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "io.github.doukutsu_rs"
|
||||||
|
minSdkVersion 24
|
||||||
|
targetSdkVersion 30
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
ndk {
|
||||||
|
abiFilters 'x86', 'arm64-v8a'
|
||||||
|
}
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
arguments "-DANDROID_STL=c++_shared"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def documentsAuthorityValue = applicationId + ".documents"
|
||||||
|
|
||||||
|
manifestPlaceholders =
|
||||||
|
[documentsAuthority: documentsAuthorityValue]
|
||||||
|
|
||||||
|
buildConfigField "String",
|
||||||
|
"DOCUMENTS_AUTHORITY",
|
||||||
|
"\"${documentsAuthorityValue}\""
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
viewBinding true
|
||||||
|
}
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
cmake {
|
||||||
|
path "src/main/cpp/CMakeLists.txt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'com.android.support:support-annotations:28.0.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
println("cargo target: ${project.buildDir.getAbsolutePath()}/rust-target")
|
||||||
|
|
||||||
|
cargoNdk {
|
||||||
|
targets = [
|
||||||
|
"x86",
|
||||||
|
"arm64"
|
||||||
|
]
|
||||||
|
librariesNames = ["libdoukutsu_rs.so"]
|
||||||
|
//targetDirectory = "${project.buildDir.getAbsolutePath()}/rust-target"
|
||||||
|
module = "../"
|
||||||
|
extraCargoEnv = ["ANDROID_NDK_HOME": android.ndkDirectory]
|
||||||
|
extraCargoBuildArguments = ["--no-default-features", "--features", "backend-glutin ogg-playback scripting"]
|
||||||
|
verbose = true
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
buildType = "release"
|
||||||
|
}
|
||||||
|
debug {
|
||||||
|
buildType = "debug"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.whenTaskAdded { task ->
|
||||||
|
if (task.name == 'javaPreCompileDebug') {
|
||||||
|
task.dependsOn 'buildCargoNdkDebug'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.name == 'javaPreCompileRelease') {
|
||||||
|
task.dependsOn 'buildCargoNdkRelease'
|
||||||
|
}
|
||||||
|
}
|
21
app/app/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
39
app/app/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="io.github.doukutsu_rs">
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/Theme.Doukutsurs">
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name=".DoukutsuDocumentsProvider"
|
||||||
|
android:authorities="${documentsAuthority}"
|
||||||
|
android:exported="true"
|
||||||
|
android:grantUriPermissions="true"
|
||||||
|
android:permission="android.permission.MANAGE_DOCUMENTS">
|
||||||
|
<intent-filter>
|
||||||
|
<action
|
||||||
|
android:name="android.content.action.DOCUMENTS_PROVIDER"/>
|
||||||
|
</intent-filter>
|
||||||
|
</provider>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="io.github.doukutsu_rs.MainActivity"
|
||||||
|
android:label="doukutsu-rs"
|
||||||
|
android:screenOrientation="sensorLandscape"
|
||||||
|
android:launchMode="standard"
|
||||||
|
android:configChanges="orientation|keyboardHidden|screenSize">
|
||||||
|
<meta-data android:name="android.app.lib_name" android:value="doukutsu_rs" />
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
53
app/app/src/main/cpp/CMakeLists.txt
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# Copy shared STL files to Android Studio output directory so they can be
|
||||||
|
# packaged in the APK.
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# find_package(ndk-stl REQUIRED)
|
||||||
|
#
|
||||||
|
# or
|
||||||
|
#
|
||||||
|
# find_package(ndk-stl REQUIRED PATHS ".")
|
||||||
|
|
||||||
|
if(NOT ${ANDROID_STL} MATCHES "_shared")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
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"
|
||||||
|
"${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${so_base}.so"
|
||||||
|
COPYONLY)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
if("${ANDROID_STL}" STREQUAL "libstdc++")
|
||||||
|
# The default minimal system C++ runtime library.
|
||||||
|
elseif("${ANDROID_STL}" STREQUAL "gabi++_shared")
|
||||||
|
# The GAbi++ runtime (shared).
|
||||||
|
message(FATAL_ERROR "gabi++_shared was not configured by ndk-stl package")
|
||||||
|
elseif("${ANDROID_STL}" STREQUAL "stlport_shared")
|
||||||
|
# The STLport runtime (shared).
|
||||||
|
configure_shared_stl("stlport" "stlport_shared")
|
||||||
|
elseif("${ANDROID_STL}" STREQUAL "gnustl_shared")
|
||||||
|
# The GNU STL (shared).
|
||||||
|
configure_shared_stl("gnu-libstdc++/4.9" "gnustl_shared")
|
||||||
|
elseif("${ANDROID_STL}" STREQUAL "c++_shared")
|
||||||
|
# The LLVM libc++ runtime (static).
|
||||||
|
configure_shared_stl("llvm-libc++" "c++_shared")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "STL configuration ANDROID_STL=${ANDROID_STL} is not supported")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Specifies a library name, specifies whether the library is STATIC or
|
||||||
|
# SHARED, and provides relative paths to the source code. You can
|
||||||
|
# define multiple libraries by adding multiple add_library() commands,
|
||||||
|
# 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)
|
2
app/app/src/main/cpp/dummy.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
void drs_dummy_export() {
|
||||||
|
}
|
BIN
app/app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 48 KiB |
|
@ -0,0 +1,279 @@
|
||||||
|
package io.github.doukutsu_rs;
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.MatrixCursor;
|
||||||
|
import android.database.MatrixCursor.RowBuilder;
|
||||||
|
import android.os.CancellationSignal;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.provider.DocumentsContract.Document;
|
||||||
|
import android.provider.DocumentsContract.Root;
|
||||||
|
import android.provider.DocumentsProvider;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.webkit.MimeTypeMap;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
public class DoukutsuDocumentsProvider extends DocumentsProvider {
|
||||||
|
private final static String[] DEFAULT_ROOT_PROJECTION =
|
||||||
|
new String[]{
|
||||||
|
Root.COLUMN_DOCUMENT_ID,
|
||||||
|
Root.COLUMN_ROOT_ID,
|
||||||
|
Root.COLUMN_ICON,
|
||||||
|
Root.COLUMN_TITLE,
|
||||||
|
Root.COLUMN_MIME_TYPES,
|
||||||
|
Root.COLUMN_AVAILABLE_BYTES,
|
||||||
|
Root.COLUMN_FLAGS
|
||||||
|
};
|
||||||
|
|
||||||
|
private final static String[] DEFAULT_DOCUMENT_PROJECTION =
|
||||||
|
new String[]{
|
||||||
|
Document.COLUMN_DOCUMENT_ID,
|
||||||
|
Document.COLUMN_DISPLAY_NAME,
|
||||||
|
Document.COLUMN_SIZE,
|
||||||
|
Document.COLUMN_LAST_MODIFIED,
|
||||||
|
Document.COLUMN_MIME_TYPE,
|
||||||
|
Document.COLUMN_FLAGS
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
|
||||||
|
File file = getContext().getFilesDir();
|
||||||
|
String id = file.getAbsolutePath();
|
||||||
|
Log.d(DoukutsuDocumentsProvider.class.getName(), "files dir location: " + id);
|
||||||
|
|
||||||
|
MatrixCursor result = new MatrixCursor(projection != null ?
|
||||||
|
projection : DEFAULT_ROOT_PROJECTION);
|
||||||
|
|
||||||
|
RowBuilder row = result.newRow();
|
||||||
|
|
||||||
|
row.add(Root.COLUMN_DOCUMENT_ID, id);
|
||||||
|
row.add(Root.COLUMN_ROOT_ID, id);
|
||||||
|
row.add(Root.COLUMN_ICON, R.mipmap.ic_launcher);
|
||||||
|
row.add(Root.COLUMN_TITLE,
|
||||||
|
getContext().getString(R.string.document_provider_name));
|
||||||
|
row.add(Root.COLUMN_MIME_TYPES, "*/*");
|
||||||
|
row.add(Root.COLUMN_AVAILABLE_BYTES, file.getFreeSpace());
|
||||||
|
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException {
|
||||||
|
MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
|
||||||
|
|
||||||
|
Log.d("dupa", "queryDocument: " + documentId);
|
||||||
|
pushFile(result, new File(documentId));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder) throws FileNotFoundException {
|
||||||
|
MatrixCursor result = new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
|
||||||
|
|
||||||
|
File root = new File(parentDocumentId);
|
||||||
|
Log.d("dupa", "doc id:" + parentDocumentId);
|
||||||
|
|
||||||
|
if (!root.exists()) {
|
||||||
|
Log.d("dupa", "no such file");
|
||||||
|
throw new FileNotFoundException("No such file: " + root.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!root.isDirectory()) {
|
||||||
|
Log.d("dupa", "not a directory");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] files = root.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
for (File file : files) {
|
||||||
|
pushFile(result, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParcelFileDescriptor openDocument(String documentId, String mode, @Nullable CancellationSignal signal) throws FileNotFoundException {
|
||||||
|
File file = new File(documentId);
|
||||||
|
int imode = ParcelFileDescriptor.parseMode(mode);
|
||||||
|
return ParcelFileDescriptor.open(file, imode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String createDocument(String parentDocumentId, String mimeType, String displayName) throws FileNotFoundException {
|
||||||
|
File file = new File(parentDocumentId, displayName);
|
||||||
|
|
||||||
|
if (file.exists()) {
|
||||||
|
int nextId = 1;
|
||||||
|
|
||||||
|
while (file.exists()) {
|
||||||
|
// maybe let's put the id before extension?
|
||||||
|
file = new File(parentDocumentId, String.format("%s (%d)", displayName, nextId));
|
||||||
|
|
||||||
|
++nextId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (mimeType != null && mimeType.equals(Document.MIME_TYPE_DIR)) {
|
||||||
|
if (!file.mkdir()) {
|
||||||
|
throw new FileNotFoundException("Couldn't create directory: " + file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!file.createNewFile()) {
|
||||||
|
throw new FileNotFoundException("Couldn't create file: " + file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new FileNotFoundException("Couldn't create file: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return file.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteDocument(String documentId) throws FileNotFoundException {
|
||||||
|
File file = new File(documentId);
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
throw new FileNotFoundException("Couldn't find file: " + file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteRecursive(file);
|
||||||
|
// todo refresh this shit
|
||||||
|
// getContext().getContentResolver().refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDocumentType(String documentId) throws FileNotFoundException {
|
||||||
|
File file = new File(documentId);
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
throw new FileNotFoundException("Couldn't find file: " + file.getAbsolutePath());
|
||||||
|
} else if (file.isDirectory()) {
|
||||||
|
return Document.MIME_TYPE_DIR;
|
||||||
|
} else if (file.isFile()) {
|
||||||
|
return getMimeType(file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreate() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChildDocument(String parentDocumentId, String documentId) {
|
||||||
|
return documentId.startsWith(parentDocumentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String renameDocument(String documentId, String displayName) throws FileNotFoundException {
|
||||||
|
File file = new File(documentId);
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
throw new FileNotFoundException("Couldn't find file: " + file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
File newPath = new File(file.getParentFile().getAbsolutePath() + "/" + displayName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Files.move(file.toPath(), newPath.toPath());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new FileNotFoundException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPath.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeDocument(String documentId, String parentDocumentId) throws FileNotFoundException {
|
||||||
|
deleteDocument(documentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void deleteRecursive(File file) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
File[] files = file.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
for (File f : files) {
|
||||||
|
if (!Files.isSymbolicLink(f.toPath())) {
|
||||||
|
deleteRecursive(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String getMimeType(String url) {
|
||||||
|
String type = null;
|
||||||
|
String extension = MimeTypeMap.getFileExtensionFromUrl(url.toLowerCase());
|
||||||
|
|
||||||
|
if (extension != null) {
|
||||||
|
switch (extension) {
|
||||||
|
case "pbm":
|
||||||
|
type = "image/bmp";
|
||||||
|
break;
|
||||||
|
case "yml":
|
||||||
|
type = "text/x-yaml";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == null) {
|
||||||
|
type = "application/octet-stream";
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushFile(MatrixCursor result, File file) throws FileNotFoundException {
|
||||||
|
if (!file.exists()) {
|
||||||
|
throw new FileNotFoundException("Couldn't find file: " + file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
String mimeType = "application/octet-stream";
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
mimeType = Document.MIME_TYPE_DIR;
|
||||||
|
|
||||||
|
if (file.canWrite()) {
|
||||||
|
flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
|
||||||
|
}
|
||||||
|
} else if (file.isFile()) {
|
||||||
|
mimeType = getMimeType(file.getAbsolutePath());
|
||||||
|
|
||||||
|
if (file.canWrite()) {
|
||||||
|
flags |= Document.FLAG_SUPPORTS_WRITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.getParentFile().canWrite()) {
|
||||||
|
flags |= Document.FLAG_SUPPORTS_DELETE | Document.FLAG_SUPPORTS_RENAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
RowBuilder row = result.newRow();
|
||||||
|
row.add(Document.COLUMN_DOCUMENT_ID, file.getAbsolutePath());
|
||||||
|
row.add(Document.COLUMN_DISPLAY_NAME, file.getName());
|
||||||
|
row.add(Document.COLUMN_SIZE, file.length());
|
||||||
|
row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
|
||||||
|
row.add(Document.COLUMN_FLAGS, flags);
|
||||||
|
row.add(Document.COLUMN_MIME_TYPE, mimeType);
|
||||||
|
row.add(Document.COLUMN_ICON, R.mipmap.ic_launcher);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package io.github.doukutsu_rs;
|
||||||
|
|
||||||
|
import android.app.NativeActivity;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.hardware.SensorManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.OrientationEventListener;
|
||||||
|
import android.view.WindowInsets;
|
||||||
|
|
||||||
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
|
|
||||||
|
public class MainActivity extends NativeActivity {
|
||||||
|
private int[] displayInsets = new int[]{0, 0, 0, 0};
|
||||||
|
private OrientationEventListener listener;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
listener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_UI) {
|
||||||
|
@Override
|
||||||
|
public void onOrientationChanged(int orientation) {
|
||||||
|
MainActivity.this.updateCutouts();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (listener.canDetectOrientation()) {
|
||||||
|
listener.enable();
|
||||||
|
} else {
|
||||||
|
listener = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
|
||||||
|
if (listener != null) {
|
||||||
|
listener.disable();
|
||||||
|
|
||||||
|
listener = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttachedToWindow() {
|
||||||
|
super.onAttachedToWindow();
|
||||||
|
|
||||||
|
this.updateCutouts();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
|
super.onConfigurationChanged(newConfig);
|
||||||
|
|
||||||
|
this.updateCutouts();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCutouts() {
|
||||||
|
if (SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
WindowInsets insets = getWindow().getDecorView().getRootWindowInsets();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
app/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:endX="85.84757"
|
||||||
|
android:endY="92.4963"
|
||||||
|
android:startX="42.9492"
|
||||||
|
android:startY="49.59793"
|
||||||
|
android:type="linear">
|
||||||
|
<item
|
||||||
|
android:color="#44000000"
|
||||||
|
android:offset="0.0" />
|
||||||
|
<item
|
||||||
|
android:color="#00000000"
|
||||||
|
android:offset="1.0" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
</vector>
|
170
app/app/src/main/res/drawable/ic_launcher_background.xml
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path
|
||||||
|
android:fillColor="#3DDC84"
|
||||||
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M9,0L9,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,0L19,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,0L29,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,0L39,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,0L49,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,0L59,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,0L69,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,0L79,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M89,0L89,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M99,0L99,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,9L108,9"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,19L108,19"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,29L108,29"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,39L108,39"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,49L108,49"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,59L108,59"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,69L108,69"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,79L108,79"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,89L108,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,99L108,99"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,29L89,29"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,39L89,39"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,49L89,49"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,59L89,59"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,69L89,69"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,79L89,79"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,19L29,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,19L39,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,19L49,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,19L59,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,19L69,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,19L79,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
</vector>
|
5
app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
BIN
app/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
app/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
app/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
app/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
app/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
app/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
app/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
app/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 5 KiB |
BIN
app/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
app/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
app/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
app/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
app/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
app/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
app/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 16 KiB |
8
app/app/src/main/res/values-v27/themes.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<style name="Theme.Doukutsurs" parent="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen">
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode">
|
||||||
|
shortEdges
|
||||||
|
</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
10
app/app/src/main/res/values/colors.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="purple_200">#FFBB86FC</color>
|
||||||
|
<color name="purple_500">#FF6200EE</color>
|
||||||
|
<color name="purple_700">#FF3700B3</color>
|
||||||
|
<color name="teal_200">#FF03DAC5</color>
|
||||||
|
<color name="teal_700">#FF018786</color>
|
||||||
|
<color name="black">#FF000000</color>
|
||||||
|
<color name="white">#FFFFFFFF</color>
|
||||||
|
</resources>
|
4
app/app/src/main/res/values/ic_launcher_background.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#8DA5F8</color>
|
||||||
|
</resources>
|
4
app/app/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">doukutsu-rs</string>
|
||||||
|
<string name="document_provider_name">doukutsu-rs game data</string>
|
||||||
|
</resources>
|
6
app/app/src/main/res/values/themes.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.Doukutsurs" parent="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen">
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</resources>
|
28
app/build.gradle
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
maven {
|
||||||
|
url "https://plugins.gradle.org/m2/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "com.android.tools.build:gradle:4.0.2"
|
||||||
|
classpath "gradle.plugin.com.github.willir.rust:plugin:0.3.4"
|
||||||
|
|
||||||
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
// in the individual module build.gradle files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete rootProject.buildDir
|
||||||
|
}
|
17
app/gradle.properties
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# Project-wide Gradle settings.
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||||
|
# Android operating system, and which are packaged with your app"s APK
|
||||||
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||||
|
android.useAndroidX=true
|
BIN
app/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
app/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +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
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
172
app/gradlew
vendored
Executable file
|
@ -0,0 +1,172 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
84
app/gradlew.bat
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
2
app/settings.gradle
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
rootProject.name = "doukutsu-rs"
|
||||||
|
include ':app'
|
28
build.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
// #[cfg(feature = "generate-gl")]
|
||||||
|
// use gl_generator::{Api, Fallbacks, Profile, Registry};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// let dest = PathBuf::from(&env::var("OUT_DIR").unwrap());
|
||||||
|
let target = env::var("TARGET").unwrap_or_else(|e| panic!(e));
|
||||||
|
let is_android = cfg!(target_os = "android") || (cfg!(target_os = "linux") && target.contains("android")); // hack
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
//
|
||||||
|
// #[cfg(feature = "generate-gl")]
|
||||||
|
// {
|
||||||
|
// let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();
|
||||||
|
//
|
||||||
|
// Registry::new(Api::Gles2, (3, 0), Profile::Core, Fallbacks::All, [])
|
||||||
|
// .write_bindings(gl_generator::StructGenerator, &mut file)
|
||||||
|
// .unwrap();
|
||||||
|
// }
|
||||||
|
|
||||||
|
if is_android {
|
||||||
|
println!("cargo:rustc-link-lib=dylib=GLESv2");
|
||||||
|
println!("cargo:rustc-link-lib=dylib=EGL");
|
||||||
|
}
|
||||||
|
}
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#Thu Feb 18 11:02:22 CET 2021
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
172
gradlew
vendored
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
84
gradlew.bat
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
8
src/builtin/shaders/basic-110.frag.glsl
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
varying vec4 color;
|
||||||
|
varying vec4 frag_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
frag_color = color;
|
||||||
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
#version 150 core
|
|
||||||
|
|
||||||
in vec2 a_Pos;
|
|
||||||
in vec2 a_Uv;
|
|
||||||
|
|
||||||
in vec4 a_Src;
|
|
||||||
in vec4 a_TCol1;
|
|
||||||
in vec4 a_TCol2;
|
|
||||||
in vec4 a_TCol3;
|
|
||||||
in vec4 a_TCol4;
|
|
||||||
in vec4 a_Color;
|
|
||||||
|
|
||||||
layout (std140) uniform Globals {
|
|
||||||
mat4 u_MVP;
|
|
||||||
};
|
|
||||||
|
|
||||||
out vec2 v_Uv;
|
|
||||||
out vec4 v_Color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
v_Uv = a_Uv * a_Src.zw + a_Src.xy;
|
|
||||||
v_Color = a_Color;
|
|
||||||
mat4 instance_transform = mat4(a_TCol1, a_TCol2, a_TCol3, a_TCol4);
|
|
||||||
vec4 position = instance_transform * vec4(a_Pos, 0.0, 1.0);
|
|
||||||
|
|
||||||
gl_Position = u_MVP * position;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
#version 300 es
|
|
||||||
|
|
||||||
uniform mediump sampler2D t_Texture;
|
|
||||||
varying mediump vec2 v_Uv;
|
|
||||||
varying mediump vec4 v_Color;
|
|
||||||
|
|
||||||
//uniform mediump mat4 u_MVP;
|
|
||||||
|
|
||||||
mediump vec4 Target0;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_FragColor = texture2D(t_Texture, v_Uv) * v_Color;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
#version 300 es
|
|
||||||
|
|
||||||
attribute mediump vec2 a_Pos;
|
|
||||||
attribute mediump vec2 a_Uv;
|
|
||||||
attribute mediump vec4 a_VertColor;
|
|
||||||
|
|
||||||
attribute mediump vec4 a_Src;
|
|
||||||
attribute mediump vec4 a_TCol1;
|
|
||||||
attribute mediump vec4 a_TCol2;
|
|
||||||
attribute mediump vec4 a_TCol3;
|
|
||||||
attribute mediump vec4 a_TCol4;
|
|
||||||
attribute mediump vec4 a_Color;
|
|
||||||
|
|
||||||
uniform mediump mat4 u_MVP;
|
|
||||||
|
|
||||||
varying mediump vec2 v_Uv;
|
|
||||||
varying mediump vec4 v_Color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
v_Uv = a_Uv * a_Src.zw + a_Src.xy;
|
|
||||||
v_Color = a_Color * a_VertColor;
|
|
||||||
mat4 instance_transform = mat4(a_TCol1, a_TCol2, a_TCol3, a_TCol4);
|
|
||||||
vec4 position = instance_transform * vec4(a_Pos, 0.0, 1.0);
|
|
||||||
|
|
||||||
gl_Position = u_MVP * position;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
#version 300 es
|
|
||||||
|
|
||||||
in vec2 a_Pos;
|
|
||||||
in vec2 a_Uv;
|
|
||||||
|
|
||||||
in vec4 a_Src;
|
|
||||||
in vec4 a_TCol1;
|
|
||||||
in vec4 a_TCol2;
|
|
||||||
in vec4 a_TCol3;
|
|
||||||
in vec4 a_TCol4;
|
|
||||||
in vec4 a_Color;
|
|
||||||
|
|
||||||
layout (std140) uniform Globals {
|
|
||||||
mat4 u_MVP;
|
|
||||||
};
|
|
||||||
|
|
||||||
out vec2 v_Uv;
|
|
||||||
out vec4 v_Color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
v_Uv = a_Uv * a_Src.zw + a_Src.xy;
|
|
||||||
v_Color = a_Color;
|
|
||||||
mat4 instance_transform = mat4(a_TCol1, a_TCol2, a_TCol3, a_TCol4);
|
|
||||||
vec4 position = instance_transform * vec4(a_Pos, 0.0, 1.0);
|
|
||||||
|
|
||||||
gl_Position = u_MVP * position;
|
|
||||||
}
|
|
|
@ -113,10 +113,10 @@ impl BuiltinFS {
|
||||||
FSNode::File("organya-wavetable-doukutsu.bin", include_bytes!("builtin/organya-wavetable-doukutsu.bin")),
|
FSNode::File("organya-wavetable-doukutsu.bin", include_bytes!("builtin/organya-wavetable-doukutsu.bin")),
|
||||||
FSNode::File("touch.png", include_bytes!("builtin/touch.png")),
|
FSNode::File("touch.png", include_bytes!("builtin/touch.png")),
|
||||||
FSNode::Directory("shaders", vec![
|
FSNode::Directory("shaders", vec![
|
||||||
FSNode::File("basic_150.vert.glsl", include_bytes!("builtin/shaders/basic_150.vert.glsl")),
|
// FSNode::File("basic_150.vert.glsl", include_bytes!("builtin/shaders/basic_150.vert.glsl")),
|
||||||
FSNode::File("water_150.frag.glsl", include_bytes!("builtin/shaders/water_150.frag.glsl")),
|
// FSNode::File("water_150.frag.glsl", include_bytes!("builtin/shaders/water_150.frag.glsl")),
|
||||||
FSNode::File("basic_es300.vert.glsl", include_bytes!("builtin/shaders/basic_es300.vert.glsl")),
|
// FSNode::File("basic_es300.vert.glsl", include_bytes!("builtin/shaders/basic_es300.vert.glsl")),
|
||||||
FSNode::File("water_es300.frag.glsl", include_bytes!("builtin/shaders/water_es300.frag.glsl")),
|
// FSNode::File("water_es300.frag.glsl", include_bytes!("builtin/shaders/water_es300.frag.glsl")),
|
||||||
]),
|
]),
|
||||||
FSNode::Directory("lightmap", vec![
|
FSNode::Directory("lightmap", vec![
|
||||||
FSNode::File("spot.png", include_bytes!("builtin/lightmap/spot.png")),
|
FSNode::File("spot.png", include_bytes!("builtin/lightmap/spot.png")),
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::framework::context::Context;
|
|
||||||
use crate::framework::error::GameResult;
|
|
||||||
|
|
||||||
use crate::common::Rect;
|
use crate::common::Rect;
|
||||||
use crate::components::draw_common::{Alignment, draw_number};
|
use crate::components::draw_common::{draw_number, Alignment};
|
||||||
use crate::entity::GameEntity;
|
use crate::entity::GameEntity;
|
||||||
use crate::frame::Frame;
|
use crate::frame::Frame;
|
||||||
|
use crate::framework::context::Context;
|
||||||
|
use crate::framework::error::GameResult;
|
||||||
|
use crate::framework::graphics::screen_insets_scaled;
|
||||||
use crate::inventory::Inventory;
|
use crate::inventory::Inventory;
|
||||||
use crate::player::Player;
|
use crate::player::Player;
|
||||||
use crate::shared_game_state::SharedGameState;
|
use crate::shared_game_state::SharedGameState;
|
||||||
|
@ -78,11 +78,7 @@ impl GameEntity<(&Player, &mut Inventory)> for HUD {
|
||||||
self.current_level = inventory.get_current_level() as usize;
|
self.current_level = inventory.get_current_level() as usize;
|
||||||
|
|
||||||
for (a, slot) in self.weapon_types.iter_mut().enumerate() {
|
for (a, slot) in self.weapon_types.iter_mut().enumerate() {
|
||||||
*slot = if let Some(weapon) = inventory.get_weapon(a) {
|
*slot = if let Some(weapon) = inventory.get_weapon(a) { weapon.wtype as u8 } else { 0 };
|
||||||
weapon.wtype as u8
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update health bar
|
// update health bar
|
||||||
|
@ -163,13 +159,19 @@ impl GameEntity<(&Player, &mut Inventory)> for HUD {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (left, top, right, bottom) = screen_insets_scaled(ctx, state.scale);
|
||||||
|
|
||||||
// none
|
// none
|
||||||
let weap_x = self.weapon_x_pos as f32;
|
let weap_x = self.weapon_x_pos as f32;
|
||||||
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "TextBox")?;
|
let batch = state.texture_set.get_or_load_batch(ctx, &state.constants, "TextBox")?;
|
||||||
|
|
||||||
let (bar_offset, num_offset, weapon_offset) = match self.alignment {
|
let (bar_offset, num_offset, weapon_offset) = match self.alignment {
|
||||||
Alignment::Left => (0.0, 0.0, 0.0),
|
Alignment::Left => (left, left, left),
|
||||||
Alignment::Right => (state.canvas_size.0 - 112.0, state.canvas_size.0 - 48.0, state.canvas_size.0 - 40.0),
|
Alignment::Right => (
|
||||||
|
state.canvas_size.0 - 112.0 - right,
|
||||||
|
state.canvas_size.0 - 48.0 - right,
|
||||||
|
state.canvas_size.0 - 40.0 - right,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
let air_offset = if self.has_player2 {
|
let air_offset = if self.has_player2 {
|
||||||
50.0 * match self.alignment {
|
50.0 * match self.alignment {
|
||||||
|
@ -181,31 +183,24 @@ impl GameEntity<(&Player, &mut Inventory)> for HUD {
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.max_ammo == 0 {
|
if self.max_ammo == 0 {
|
||||||
batch.add_rect(bar_offset + weap_x + 48.0, 16.0,
|
batch.add_rect(bar_offset + weap_x + 48.0, 16.0 + top, &Rect::new_size(80, 48, 16, 8));
|
||||||
&Rect::new_size(80, 48, 16, 8));
|
batch.add_rect(bar_offset + weap_x + 48.0, 24.0 + top, &Rect::new_size(80, 48, 16, 8));
|
||||||
batch.add_rect(bar_offset + weap_x + 48.0, 24.0,
|
|
||||||
&Rect::new_size(80, 48, 16, 8));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// per
|
// per
|
||||||
batch.add_rect(bar_offset + weap_x + 32.0, 24.0,
|
batch.add_rect(bar_offset + weap_x + 32.0, 24.0 + top, &Rect::new_size(72, 48, 8, 8));
|
||||||
&Rect::new_size(72, 48, 8, 8));
|
|
||||||
// lv
|
// lv
|
||||||
batch.add_rect(num_offset + weap_x, 32.0,
|
batch.add_rect(num_offset + weap_x, 32.0 + top, &Rect::new_size(80, 80, 16, 8));
|
||||||
&Rect::new_size(80, 80, 16, 8));
|
|
||||||
// xp box
|
// xp box
|
||||||
batch.add_rect(bar_offset + weap_x + 24.0, 32.0,
|
batch.add_rect(bar_offset + weap_x + 24.0, 32.0 + top, &Rect::new_size(0, 72, 40, 8));
|
||||||
&Rect::new_size(0, 72, 40, 8));
|
|
||||||
|
|
||||||
if self.max_level {
|
if self.max_level {
|
||||||
batch.add_rect(bar_offset + weap_x + 24.0, 32.0,
|
batch.add_rect(bar_offset + weap_x + 24.0, 32.0 + top, &Rect::new_size(40, 72, 40, 8));
|
||||||
&Rect::new_size(40, 72, 40, 8));
|
|
||||||
} else if self.max_xp > 0 {
|
} else if self.max_xp > 0 {
|
||||||
// xp bar
|
// xp bar
|
||||||
let bar_width = (self.xp as f32 / self.max_xp as f32 * 40.0) as u16;
|
let bar_width = (self.xp as f32 / self.max_xp as f32 * 40.0) as u16;
|
||||||
|
|
||||||
batch.add_rect(bar_offset + weap_x + 24.0, 32.0,
|
batch.add_rect(bar_offset + weap_x + 24.0, 32.0 + top, &Rect::new_size(0, 80, bar_width, 8));
|
||||||
&Rect::new_size(0, 80, bar_width, 8));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.max_life != 0 {
|
if self.max_life != 0 {
|
||||||
|
@ -213,28 +208,23 @@ impl GameEntity<(&Player, &mut Inventory)> for HUD {
|
||||||
let bar_width = (self.life as f32 / self.max_life as f32 * 39.0) as u16;
|
let bar_width = (self.life as f32 / self.max_life as f32 * 39.0) as u16;
|
||||||
|
|
||||||
// heart/hp number box
|
// heart/hp number box
|
||||||
batch.add_rect(num_offset + 16.0, 40.0,
|
batch.add_rect(num_offset + 16.0, 40.0 + top, &Rect::new_size(0, 40, 24, 8));
|
||||||
&Rect::new_size(0, 40, 24, 8));
|
|
||||||
// life box
|
// life box
|
||||||
batch.add_rect(bar_offset + 40.0, 40.0,
|
batch.add_rect(bar_offset + 40.0, 40.0 + top, &Rect::new_size(24, 40, 40, 8));
|
||||||
&Rect::new_size(24, 40, 40, 8));
|
|
||||||
// yellow bar
|
// yellow bar
|
||||||
batch.add_rect(bar_offset + 40.0, 40.0,
|
batch.add_rect(bar_offset + 40.0, 40.0 + top, &Rect::new_size(0, 32, yellow_bar_width, 8));
|
||||||
&Rect::new_size(0, 32, yellow_bar_width, 8));
|
|
||||||
// life
|
// life
|
||||||
batch.add_rect(bar_offset + 40.0, 40.0,
|
batch.add_rect(bar_offset + 40.0, 40.0 + top, &Rect::new_size(0, 24, bar_width, 8));
|
||||||
&Rect::new_size(0, 24, bar_width, 8));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.air_counter > 0 {
|
if self.air_counter > 0 {
|
||||||
let rect = if self.air % 30 > 10 {
|
let rect = if self.air % 30 > 10 { Rect::new_size(112, 72, 32, 8) } else { Rect::new_size(112, 80, 32, 8) };
|
||||||
Rect::new_size(112, 72, 32, 8)
|
|
||||||
} else {
|
|
||||||
Rect::new_size(112, 80, 32, 8)
|
|
||||||
};
|
|
||||||
|
|
||||||
batch.add_rect((state.canvas_size.0 / 2.0).floor() - 40.0 + air_offset,
|
batch.add_rect(
|
||||||
(state.canvas_size.1 / 2.0).floor(), &rect);
|
left + ((state.canvas_size.0 - left - right) / 2.0).floor() - 40.0 + air_offset,
|
||||||
|
top + ((state.canvas_size.1 - top - bottom) / 2.0).floor(),
|
||||||
|
&rect,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.draw(ctx)?;
|
batch.draw(ctx)?;
|
||||||
|
@ -267,7 +257,7 @@ impl GameEntity<(&Player, &mut Inventory)> for HUD {
|
||||||
if wtype != 0 {
|
if wtype != 0 {
|
||||||
rect.left = wtype as u16 * 16;
|
rect.left = wtype as u16 * 16;
|
||||||
rect.right = rect.left + 16;
|
rect.right = rect.left + 16;
|
||||||
batch.add_rect(pos_x + weapon_offset, 16.0, &rect);
|
batch.add_rect(pos_x + weapon_offset, 16.0 + top, &rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -275,17 +265,22 @@ impl GameEntity<(&Player, &mut Inventory)> for HUD {
|
||||||
batch.draw(ctx)?;
|
batch.draw(ctx)?;
|
||||||
|
|
||||||
if self.air_counter > 0 && self.air_counter % 6 < 4 {
|
if self.air_counter > 0 && self.air_counter % 6 < 4 {
|
||||||
draw_number((state.canvas_size.0 / 2.0).floor() + 8.0 + air_offset,
|
draw_number(
|
||||||
(state.canvas_size.1 / 2.0).floor(),
|
left + ((state.canvas_size.0 - left - right) / 2.0).floor() + 8.0 + air_offset,
|
||||||
(self.air / 10) as usize, Alignment::Left, state, ctx)?;
|
top + ((state.canvas_size.1 - top - bottom) / 2.0).floor(),
|
||||||
|
(self.air / 10) as usize,
|
||||||
|
Alignment::Left,
|
||||||
|
state,
|
||||||
|
ctx,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.max_ammo != 0 {
|
if self.max_ammo != 0 {
|
||||||
draw_number(num_offset + weap_x + 64.0, 16.0, self.ammo as usize, Alignment::Right, state, ctx)?;
|
draw_number(num_offset + weap_x + 64.0, 16.0 + top, self.ammo as usize, Alignment::Right, state, ctx)?;
|
||||||
draw_number(num_offset + weap_x + 64.0, 24.0, self.max_ammo as usize, Alignment::Right, state, ctx)?;
|
draw_number(num_offset + weap_x + 64.0, 24.0 + top, self.max_ammo as usize, Alignment::Right, state, ctx)?;
|
||||||
}
|
}
|
||||||
draw_number(num_offset + weap_x + 24.0, 32.0, self.current_level, Alignment::Right, state, ctx)?;
|
draw_number(num_offset + weap_x + 24.0, 32.0 + top, self.current_level, Alignment::Right, state, ctx)?;
|
||||||
draw_number(num_offset + 40.0, 40.0, self.life_bar as usize, Alignment::Right, state, ctx)?;
|
draw_number(num_offset + 40.0, 40.0 + top, self.life_bar as usize, Alignment::Right, state, ctx)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,10 @@ pub trait BackendRenderer {
|
||||||
|
|
||||||
fn present(&mut self) -> GameResult;
|
fn present(&mut self) -> GameResult;
|
||||||
|
|
||||||
|
fn prepare_draw(&mut self, width: f32, height: f32) -> GameResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn create_texture_mutable(&mut self, width: u16, height: u16) -> GameResult<Box<dyn BackendTexture>>;
|
fn create_texture_mutable(&mut self, width: u16, height: u16) -> GameResult<Box<dyn BackendTexture>>;
|
||||||
|
|
||||||
fn create_texture(&mut self, width: u16, height: u16, data: &[u8]) -> GameResult<Box<dyn BackendTexture>>;
|
fn create_texture(&mut self, width: u16, height: u16, data: &[u8]) -> GameResult<Box<dyn BackendTexture>>;
|
||||||
|
@ -36,8 +40,6 @@ pub trait BackendRenderer {
|
||||||
fn imgui(&self) -> GameResult<&mut imgui::Context>;
|
fn imgui(&self) -> GameResult<&mut imgui::Context>;
|
||||||
|
|
||||||
fn render_imgui(&mut self, draw_data: &DrawData) -> GameResult;
|
fn render_imgui(&mut self, draw_data: &DrawData) -> GameResult;
|
||||||
|
|
||||||
fn prepare_frame(&self, ui: &imgui::Ui) -> GameResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BackendTexture {
|
pub trait BackendTexture {
|
||||||
|
@ -51,10 +53,20 @@ pub trait BackendTexture {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_backend() -> GameResult<Box<dyn Backend>> {
|
pub fn init_backend() -> GameResult<Box<dyn Backend>> {
|
||||||
#[cfg(feature = "backend_sdl")]
|
#[cfg(all(feature = "backend-glutin"))]
|
||||||
{
|
{
|
||||||
return crate::framework::backend_sdl2::SDL2Backend::new()
|
return crate::framework::backend_opengl::GlutinBackend::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "backend-sokol")]
|
||||||
|
{
|
||||||
|
return crate::framework::backend_sokol::SokolBackend::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "backend-sdl")]
|
||||||
|
{
|
||||||
|
return crate::framework::backend_sdl2::SDL2Backend::new();
|
||||||
|
}
|
||||||
|
|
||||||
log::warn!("No backend compiled in, using null backend instead.");
|
log::warn!("No backend compiled in, using null backend instead.");
|
||||||
crate::framework::backend_null::NullBackend::new()
|
crate::framework::backend_null::NullBackend::new()
|
||||||
|
|
|
@ -29,6 +29,9 @@ impl BackendEventLoop for NullEventLoop {
|
||||||
fn run(&mut self, game: &mut Game, ctx: &mut Context) {
|
fn run(&mut self, game: &mut Game, ctx: &mut Context) {
|
||||||
let state_ref = unsafe { &mut *game.state.get() };
|
let state_ref = unsafe { &mut *game.state.get() };
|
||||||
|
|
||||||
|
ctx.screen_size = (640.0, 480.0);
|
||||||
|
state_ref.handle_resize(ctx).unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
game.update(ctx).unwrap();
|
game.update(ctx).unwrap();
|
||||||
if state_ref.shutdown {
|
if state_ref.shutdown {
|
||||||
|
@ -118,8 +121,4 @@ impl BackendRenderer for NullRenderer {
|
||||||
fn render_imgui(&mut self, draw_data: &DrawData) -> GameResult {
|
fn render_imgui(&mut self, draw_data: &DrawData) -> GameResult {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_frame<'ui>(&self, ui: &Ui<'ui>) -> GameResult {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
1121
src/framework/backend_opengl.rs
Normal file
|
@ -564,14 +564,8 @@ impl BackendRenderer for SDL2Renderer {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_frame<'ui>(&self, _ui: &Ui<'ui>) -> GameResult {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SDL2Renderer {}
|
|
||||||
|
|
||||||
struct SDL2Texture {
|
struct SDL2Texture {
|
||||||
refs: Rc<RefCell<SDL2Context>>,
|
refs: Rc<RefCell<SDL2Context>>,
|
||||||
texture: Option<Texture>,
|
texture: Option<Texture>,
|
||||||
|
|
358
src/framework/backend_sokol.rs
Normal file
|
@ -0,0 +1,358 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::mem;
|
||||||
|
use std::ops::DerefMut;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use imgui::{DrawData, Ui};
|
||||||
|
use ndk::input_queue::InputQueue;
|
||||||
|
use sokol::app::{SApp, SAppDesc, SAppEvent, SAppEventType, SAppKeycode};
|
||||||
|
use sokol::gfx::{sg_isvalid, sg_query_backend, sg_shutdown};
|
||||||
|
|
||||||
|
use crate::common::{Color, Rect};
|
||||||
|
use crate::framework::backend::{Backend, BackendEventLoop, BackendRenderer, BackendTexture, SpriteBatchCommand};
|
||||||
|
use crate::framework::context::Context;
|
||||||
|
use crate::framework::error::GameResult;
|
||||||
|
use crate::framework::graphics::BlendMode;
|
||||||
|
use crate::framework::keyboard::ScanCode;
|
||||||
|
use crate::Game;
|
||||||
|
|
||||||
|
pub struct SokolBackend;
|
||||||
|
|
||||||
|
impl SokolBackend {
|
||||||
|
pub fn new() -> GameResult<Box<dyn Backend>> {
|
||||||
|
Ok(Box::new(SokolBackend))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backend for SokolBackend {
|
||||||
|
fn create_event_loop(&self) -> GameResult<Box<dyn BackendEventLoop>> {
|
||||||
|
Ok(Box::new(SokolEventLoop))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SokolEventLoop;
|
||||||
|
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
extern "C" {
|
||||||
|
fn sapp_android_on_create(
|
||||||
|
activity: *mut ndk_sys::ANativeActivity,
|
||||||
|
window: *mut ndk_sys::ANativeWindow,
|
||||||
|
input_queue: *mut ndk_sys::AInputQueue,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BackendEventLoop for SokolEventLoop {
|
||||||
|
fn run(&mut self, game: &mut Game, ctx: &mut Context) {
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
unsafe {
|
||||||
|
let activity = ndk_glue::native_activity().ptr().as_ptr();
|
||||||
|
let window = match ndk_glue::native_window().as_ref() {
|
||||||
|
None => std::ptr::null_mut(),
|
||||||
|
Some(p) => p.ptr().as_ptr(),
|
||||||
|
};
|
||||||
|
let input_queue = match ndk_glue::input_queue().as_ref() {
|
||||||
|
None => std::ptr::null_mut(),
|
||||||
|
Some(p) => p.ptr().as_ptr(),
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("activity = {:?} window = {:?} input_queue = {:?}", activity, window, input_queue);
|
||||||
|
|
||||||
|
sapp_android_on_create(activity, window, input_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Callbacks<'a, 'b> {
|
||||||
|
ctx: &'a mut Context,
|
||||||
|
game: &'b mut Game,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'a, 'b> SApp for Callbacks<'a, 'b> {
|
||||||
|
fn sapp_init(&mut self) {
|
||||||
|
let state_ref = unsafe { &mut *self.game.state.get() };
|
||||||
|
|
||||||
|
self.ctx.screen_size = (640.0, 480.0);
|
||||||
|
state_ref.handle_resize(self.ctx).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sapp_frame(&mut self) {
|
||||||
|
let state_ref = unsafe { &mut *self.game.state.get() };
|
||||||
|
|
||||||
|
self.game.update(self.ctx).unwrap();
|
||||||
|
|
||||||
|
// todo: not really supported on iOS/consoles
|
||||||
|
if state_ref.shutdown {
|
||||||
|
log::info!("Shutting down...");
|
||||||
|
std::process::exit(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if state_ref.next_scene.is_some() {
|
||||||
|
mem::swap(&mut self.game.scene, &mut state_ref.next_scene);
|
||||||
|
state_ref.next_scene = None;
|
||||||
|
self.game.scene.as_mut().unwrap().init(state_ref, self.ctx).unwrap();
|
||||||
|
self.game.loops = 0;
|
||||||
|
state_ref.frame_time = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.game.draw(self.ctx).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sapp_cleanup(&mut self) {
|
||||||
|
if sg_isvalid() {
|
||||||
|
sg_shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sapp_event(&mut self, event: SAppEvent) {
|
||||||
|
let state_ref = unsafe { &mut *self.game.state.get() };
|
||||||
|
println!("event: {:?}", event.event_type);
|
||||||
|
|
||||||
|
match event.event_type {
|
||||||
|
SAppEventType::Invalid => {}
|
||||||
|
SAppEventType::KeyDown => {
|
||||||
|
if let Some(drs_scan) = conv_scancode(event.key_code) {
|
||||||
|
state_ref.process_debug_keys(drs_scan);
|
||||||
|
self.ctx.keyboard_context.set_key(drs_scan, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAppEventType::KeyUp => {
|
||||||
|
if let Some(drs_scan) = conv_scancode(event.key_code) {
|
||||||
|
self.ctx.keyboard_context.set_key(drs_scan, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAppEventType::Char => {}
|
||||||
|
SAppEventType::MouseDown => {}
|
||||||
|
SAppEventType::MouseUp => {}
|
||||||
|
SAppEventType::MouseScroll => {}
|
||||||
|
SAppEventType::MouseMove => {}
|
||||||
|
SAppEventType::MouseEnter => {}
|
||||||
|
SAppEventType::MouseLeave => {}
|
||||||
|
SAppEventType::TouchesBegan => {}
|
||||||
|
SAppEventType::TouchesMoved => {}
|
||||||
|
SAppEventType::TouchesEnded => {}
|
||||||
|
SAppEventType::TouchesCancelled => {}
|
||||||
|
SAppEventType::Resized => {}
|
||||||
|
SAppEventType::Iconified => {}
|
||||||
|
SAppEventType::Restored => {}
|
||||||
|
SAppEventType::Suspended => {}
|
||||||
|
SAppEventType::Resumed => {}
|
||||||
|
SAppEventType::UpdateCursor => {}
|
||||||
|
SAppEventType::QuitRequested => {
|
||||||
|
state_ref.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sokol::app::sapp_run(
|
||||||
|
Callbacks { ctx: unsafe { std::mem::transmute(ctx) }, game: unsafe { std::mem::transmute(game) } },
|
||||||
|
SAppDesc {
|
||||||
|
width: 640,
|
||||||
|
height: 480,
|
||||||
|
window_title: "doukutsu-rs".to_string(),
|
||||||
|
ios_keyboard_resizes_canvas: false,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
std::thread::sleep(Duration::from_millis(10))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_renderer(&self) -> GameResult<Box<dyn BackendRenderer>> {
|
||||||
|
let mut imgui = imgui::Context::create();
|
||||||
|
imgui.io_mut().display_size = [640.0, 480.0];
|
||||||
|
imgui.fonts().build_alpha8_texture();
|
||||||
|
|
||||||
|
log::info!("Using Sokol backend: {:?}", sg_query_backend());
|
||||||
|
|
||||||
|
Ok(Box::new(SokolRenderer(RefCell::new(imgui))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NullTexture(u16, u16);
|
||||||
|
|
||||||
|
impl BackendTexture for NullTexture {
|
||||||
|
fn dimensions(&self) -> (u16, u16) {
|
||||||
|
(self.0, self.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&mut self, command: SpriteBatchCommand) {}
|
||||||
|
|
||||||
|
fn clear(&mut self) {}
|
||||||
|
|
||||||
|
fn draw(&mut self) -> GameResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SokolRenderer(RefCell<imgui::Context>);
|
||||||
|
|
||||||
|
impl BackendRenderer for SokolRenderer {
|
||||||
|
fn clear(&mut self, color: Color) {}
|
||||||
|
|
||||||
|
fn present(&mut self) -> GameResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_texture_mutable(&mut self, width: u16, height: u16) -> GameResult<Box<dyn BackendTexture>> {
|
||||||
|
Ok(Box::new(NullTexture(width, height)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_texture(&mut self, width: u16, height: u16, data: &[u8]) -> GameResult<Box<dyn BackendTexture>> {
|
||||||
|
Ok(Box::new(NullTexture(width, height)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_blend_mode(&mut self, blend: BlendMode) -> GameResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_render_target(&mut self, texture: Option<&Box<dyn BackendTexture>>) -> GameResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_rect(&mut self, rect: Rect<isize>, color: Color) -> GameResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_outline_rect(&mut self, rect: Rect<isize>, line_width: usize, color: Color) -> GameResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn imgui(&self) -> GameResult<&mut imgui::Context> {
|
||||||
|
unsafe { Ok(&mut *self.0.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_imgui(&mut self, draw_data: &DrawData) -> GameResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_frame<'ui>(&self, ui: &Ui<'ui>) -> GameResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn conv_scancode(code: SAppKeycode) -> Option<ScanCode> {
|
||||||
|
match code {
|
||||||
|
SAppKeycode::KeySpace => Some(ScanCode::Space),
|
||||||
|
SAppKeycode::KeyApostrophe => Some(ScanCode::Apostrophe),
|
||||||
|
SAppKeycode::KeyComma => Some(ScanCode::Comma),
|
||||||
|
SAppKeycode::KeyMinus => Some(ScanCode::Minus),
|
||||||
|
SAppKeycode::KeyPeriod => Some(ScanCode::Period),
|
||||||
|
SAppKeycode::KeySlash => Some(ScanCode::Slash),
|
||||||
|
SAppKeycode::Key0 => Some(ScanCode::Key0),
|
||||||
|
SAppKeycode::Key1 => Some(ScanCode::Key1),
|
||||||
|
SAppKeycode::Key2 => Some(ScanCode::Key2),
|
||||||
|
SAppKeycode::Key3 => Some(ScanCode::Key3),
|
||||||
|
SAppKeycode::Key4 => Some(ScanCode::Key4),
|
||||||
|
SAppKeycode::Key5 => Some(ScanCode::Key5),
|
||||||
|
SAppKeycode::Key6 => Some(ScanCode::Key6),
|
||||||
|
SAppKeycode::Key7 => Some(ScanCode::Key7),
|
||||||
|
SAppKeycode::Key8 => Some(ScanCode::Key8),
|
||||||
|
SAppKeycode::Key9 => Some(ScanCode::Key9),
|
||||||
|
SAppKeycode::KeySemicolon => Some(ScanCode::Semicolon),
|
||||||
|
SAppKeycode::KeyEqual => Some(ScanCode::Equals),
|
||||||
|
SAppKeycode::KeyA => Some(ScanCode::A),
|
||||||
|
SAppKeycode::KeyB => Some(ScanCode::B),
|
||||||
|
SAppKeycode::KeyC => Some(ScanCode::C),
|
||||||
|
SAppKeycode::KeyD => Some(ScanCode::D),
|
||||||
|
SAppKeycode::KeyE => Some(ScanCode::E),
|
||||||
|
SAppKeycode::KeyF => Some(ScanCode::F),
|
||||||
|
SAppKeycode::KeyG => Some(ScanCode::G),
|
||||||
|
SAppKeycode::KeyH => Some(ScanCode::H),
|
||||||
|
SAppKeycode::KeyI => Some(ScanCode::I),
|
||||||
|
SAppKeycode::KeyJ => Some(ScanCode::J),
|
||||||
|
SAppKeycode::KeyK => Some(ScanCode::K),
|
||||||
|
SAppKeycode::KeyL => Some(ScanCode::L),
|
||||||
|
SAppKeycode::KeyM => Some(ScanCode::M),
|
||||||
|
SAppKeycode::KeyN => Some(ScanCode::N),
|
||||||
|
SAppKeycode::KeyO => Some(ScanCode::O),
|
||||||
|
SAppKeycode::KeyP => Some(ScanCode::P),
|
||||||
|
SAppKeycode::KeyQ => Some(ScanCode::Q),
|
||||||
|
SAppKeycode::KeyR => Some(ScanCode::R),
|
||||||
|
SAppKeycode::KeyS => Some(ScanCode::S),
|
||||||
|
SAppKeycode::KeyT => Some(ScanCode::T),
|
||||||
|
SAppKeycode::KeyU => Some(ScanCode::U),
|
||||||
|
SAppKeycode::KeyV => Some(ScanCode::V),
|
||||||
|
SAppKeycode::KeyW => Some(ScanCode::W),
|
||||||
|
SAppKeycode::KeyX => Some(ScanCode::X),
|
||||||
|
SAppKeycode::KeyY => Some(ScanCode::Y),
|
||||||
|
SAppKeycode::KeyZ => Some(ScanCode::Z),
|
||||||
|
SAppKeycode::KeyLeftBracket => Some(ScanCode::LBracket),
|
||||||
|
SAppKeycode::KeyBackslash => Some(ScanCode::Backslash),
|
||||||
|
SAppKeycode::KeyRightBracket => Some(ScanCode::RBracket),
|
||||||
|
SAppKeycode::KeyGraveAccent => Some(ScanCode::Grave),
|
||||||
|
SAppKeycode::KeyWorld1 => Some(ScanCode::AbntC1),
|
||||||
|
SAppKeycode::KeyWorld2 => Some(ScanCode::AbntC2),
|
||||||
|
SAppKeycode::KeyEscape => Some(ScanCode::Escape),
|
||||||
|
SAppKeycode::KeyEnter => Some(ScanCode::Return),
|
||||||
|
SAppKeycode::KeyTab => Some(ScanCode::Tab),
|
||||||
|
SAppKeycode::KeyBackspace => Some(ScanCode::Backspace),
|
||||||
|
SAppKeycode::KeyInsert => Some(ScanCode::Insert),
|
||||||
|
SAppKeycode::KeyDelete => Some(ScanCode::Delete),
|
||||||
|
SAppKeycode::KeyRight => Some(ScanCode::Right),
|
||||||
|
SAppKeycode::KeyLeft => Some(ScanCode::Left),
|
||||||
|
SAppKeycode::KeyDown => Some(ScanCode::Down),
|
||||||
|
SAppKeycode::KeyUp => Some(ScanCode::Up),
|
||||||
|
SAppKeycode::KeyPageUp => Some(ScanCode::PageUp),
|
||||||
|
SAppKeycode::KeyPageDown => Some(ScanCode::PageDown),
|
||||||
|
SAppKeycode::KeyHome => Some(ScanCode::Home),
|
||||||
|
SAppKeycode::KeyEnd => Some(ScanCode::End),
|
||||||
|
SAppKeycode::KeyCapsLock => Some(ScanCode::Capslock),
|
||||||
|
SAppKeycode::KeyScrollLock => Some(ScanCode::Scrolllock),
|
||||||
|
SAppKeycode::KeyNumLock => Some(ScanCode::Numlock),
|
||||||
|
SAppKeycode::KeyPrintScreen => Some(ScanCode::Sysrq),
|
||||||
|
SAppKeycode::KeyPause => Some(ScanCode::Pause),
|
||||||
|
SAppKeycode::KeyF1 => Some(ScanCode::F1),
|
||||||
|
SAppKeycode::KeyF2 => Some(ScanCode::F2),
|
||||||
|
SAppKeycode::KeyF3 => Some(ScanCode::F3),
|
||||||
|
SAppKeycode::KeyF4 => Some(ScanCode::F4),
|
||||||
|
SAppKeycode::KeyF5 => Some(ScanCode::F5),
|
||||||
|
SAppKeycode::KeyF6 => Some(ScanCode::F6),
|
||||||
|
SAppKeycode::KeyF7 => Some(ScanCode::F7),
|
||||||
|
SAppKeycode::KeyF8 => Some(ScanCode::F8),
|
||||||
|
SAppKeycode::KeyF9 => Some(ScanCode::F9),
|
||||||
|
SAppKeycode::KeyF10 => Some(ScanCode::F10),
|
||||||
|
SAppKeycode::KeyF11 => Some(ScanCode::F11),
|
||||||
|
SAppKeycode::KeyF12 => Some(ScanCode::F12),
|
||||||
|
SAppKeycode::KeyF13 => Some(ScanCode::F13),
|
||||||
|
SAppKeycode::KeyF14 => Some(ScanCode::F14),
|
||||||
|
SAppKeycode::KeyF15 => Some(ScanCode::F15),
|
||||||
|
SAppKeycode::KeyF16 => Some(ScanCode::F16),
|
||||||
|
SAppKeycode::KeyF17 => Some(ScanCode::F17),
|
||||||
|
SAppKeycode::KeyF18 => Some(ScanCode::F18),
|
||||||
|
SAppKeycode::KeyF19 => Some(ScanCode::F19),
|
||||||
|
SAppKeycode::KeyF20 => Some(ScanCode::F20),
|
||||||
|
SAppKeycode::KeyF21 => Some(ScanCode::F21),
|
||||||
|
SAppKeycode::KeyF22 => Some(ScanCode::F22),
|
||||||
|
SAppKeycode::KeyF23 => Some(ScanCode::F23),
|
||||||
|
SAppKeycode::KeyF24 => Some(ScanCode::F24),
|
||||||
|
SAppKeycode::KeyKP0 => Some(ScanCode::Numpad0),
|
||||||
|
SAppKeycode::KeyKP1 => Some(ScanCode::Numpad1),
|
||||||
|
SAppKeycode::KeyKP2 => Some(ScanCode::Numpad2),
|
||||||
|
SAppKeycode::KeyKP3 => Some(ScanCode::Numpad3),
|
||||||
|
SAppKeycode::KeyKP4 => Some(ScanCode::Numpad4),
|
||||||
|
SAppKeycode::KeyKP5 => Some(ScanCode::Numpad5),
|
||||||
|
SAppKeycode::KeyKP6 => Some(ScanCode::Numpad6),
|
||||||
|
SAppKeycode::KeyKP7 => Some(ScanCode::Numpad7),
|
||||||
|
SAppKeycode::KeyKP8 => Some(ScanCode::Numpad8),
|
||||||
|
SAppKeycode::KeyKP9 => Some(ScanCode::Numpad9),
|
||||||
|
SAppKeycode::KeyKPDecimal => Some(ScanCode::NumpadDecimal),
|
||||||
|
SAppKeycode::KeyKPDivide => Some(ScanCode::NumpadDivide),
|
||||||
|
SAppKeycode::KeyKPMultiply => Some(ScanCode::NumpadMultiply),
|
||||||
|
SAppKeycode::KeyKPSubtract => Some(ScanCode::NumpadSubtract),
|
||||||
|
SAppKeycode::KeyKPAdd => Some(ScanCode::NumpadAdd),
|
||||||
|
SAppKeycode::KeyKPEnter => Some(ScanCode::NumpadEnter),
|
||||||
|
SAppKeycode::KeyKPEqual => Some(ScanCode::NumpadEquals),
|
||||||
|
SAppKeycode::KeyLeftShift => Some(ScanCode::LShift),
|
||||||
|
SAppKeycode::KeyLeftControl => Some(ScanCode::LControl),
|
||||||
|
SAppKeycode::KeyLeftAlt => Some(ScanCode::LAlt),
|
||||||
|
SAppKeycode::KeyLeftSuper => Some(ScanCode::LWin),
|
||||||
|
SAppKeycode::KeyRightShift => Some(ScanCode::RShift),
|
||||||
|
SAppKeycode::KeyRightControl => Some(ScanCode::RControl),
|
||||||
|
SAppKeycode::KeyRightAlt => Some(ScanCode::RAlt),
|
||||||
|
SAppKeycode::KeyRightSuper => Some(ScanCode::RWin),
|
||||||
|
SAppKeycode::KeyMenu => Some(ScanCode::Menu),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,15 @@
|
||||||
use crate::framework::backend::{init_backend, BackendRenderer};
|
use crate::framework::backend::{init_backend, BackendRenderer};
|
||||||
use crate::framework::error::GameResult;
|
use crate::framework::error::GameResult;
|
||||||
use crate::framework::filesystem::Filesystem;
|
use crate::framework::filesystem::Filesystem;
|
||||||
use crate::Game;
|
|
||||||
use crate::framework::keyboard::KeyboardContext;
|
use crate::framework::keyboard::KeyboardContext;
|
||||||
|
use crate::Game;
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub(crate) filesystem: Filesystem,
|
pub(crate) filesystem: Filesystem,
|
||||||
pub(crate) renderer: Option<Box<dyn BackendRenderer>>,
|
pub(crate) renderer: Option<Box<dyn BackendRenderer>>,
|
||||||
pub(crate) keyboard_context: KeyboardContext,
|
pub(crate) keyboard_context: KeyboardContext,
|
||||||
pub(crate) screen_size: (f32, f32),
|
pub(crate) screen_size: (f32, f32),
|
||||||
|
pub(crate) screen_insets: (f32, f32, f32, f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
|
@ -18,6 +19,7 @@ impl Context {
|
||||||
renderer: None,
|
renderer: None,
|
||||||
keyboard_context: KeyboardContext::new(),
|
keyboard_context: KeyboardContext::new(),
|
||||||
screen_size: (320.0, 240.0),
|
screen_size: (320.0, 240.0),
|
||||||
|
screen_insets: (0.0, 0.0, 0.0, 0.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1965
src/framework/gl.rs
Normal file
|
@ -60,6 +60,14 @@ pub fn screen_size(ctx: &mut Context) -> (f32, f32) {
|
||||||
ctx.screen_size
|
ctx.screen_size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn screen_insets(ctx: &mut Context) -> (f32, f32, f32, f32) {
|
||||||
|
ctx.screen_insets
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn screen_insets_scaled(ctx: &mut Context, scale: f32) -> (f32, f32, f32, f32) {
|
||||||
|
(ctx.screen_insets.0 / scale, ctx.screen_insets.1 / scale, ctx.screen_insets.2 / scale, ctx.screen_insets.3 / scale)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_render_target(ctx: &mut Context, texture: Option<&Box<dyn BackendTexture>>) -> GameResult {
|
pub fn set_render_target(ctx: &mut Context, texture: Option<&Box<dyn BackendTexture>>) -> GameResult {
|
||||||
if let Some(renderer) = ctx.renderer.as_mut() {
|
if let Some(renderer) = ctx.renderer.as_mut() {
|
||||||
return renderer.set_render_target(texture);
|
return renderer.set_render_target(texture);
|
||||||
|
@ -108,9 +116,9 @@ pub fn render_imgui(ctx: &mut Context, draw_data: &imgui::DrawData) -> GameResul
|
||||||
Err(GameError::RenderError("Rendering backend hasn't been initialized yet.".to_string()))
|
Err(GameError::RenderError("Rendering backend hasn't been initialized yet.".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn imgui_prepare_frame(ctx: &Context, ui: &imgui::Ui) -> GameResult {
|
pub fn prepare_draw(ctx: &mut Context) -> GameResult {
|
||||||
if let Some(renderer) = ctx.renderer.as_ref() {
|
if let Some(renderer) = ctx.renderer.as_mut() {
|
||||||
return renderer.prepare_frame(ui);
|
return renderer.prepare_draw(ctx.screen_size.0, ctx.screen_size.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(GameError::RenderError("Rendering backend hasn't been initialized yet.".to_string()))
|
Err(GameError::RenderError("Rendering backend hasn't been initialized yet.".to_string()))
|
||||||
|
|
|
@ -165,6 +165,7 @@ pub enum ScanCode {
|
||||||
Mail,
|
Mail,
|
||||||
MediaSelect,
|
MediaSelect,
|
||||||
MediaStop,
|
MediaStop,
|
||||||
|
Menu,
|
||||||
Minus,
|
Minus,
|
||||||
Mute,
|
Mute,
|
||||||
MyComputer,
|
MyComputer,
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
pub mod backend;
|
pub mod backend;
|
||||||
#[cfg(feature = "backend_sdl2")]
|
|
||||||
pub mod backend_sdl2;
|
|
||||||
pub mod backend_null;
|
pub mod backend_null;
|
||||||
|
#[cfg(feature = "backend-glutin")]
|
||||||
|
pub mod backend_opengl;
|
||||||
|
#[cfg(feature = "backend-glutin")]
|
||||||
|
mod gl;
|
||||||
|
#[cfg(feature = "backend-sdl")]
|
||||||
|
pub mod backend_sdl2;
|
||||||
|
#[cfg(feature = "backend-sokol")]
|
||||||
|
pub mod backend_sokol;
|
||||||
pub mod context;
|
pub mod context;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod filesystem;
|
pub mod filesystem;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::framework::context::Context;
|
|
||||||
use crate::framework::error::GameResult;
|
|
||||||
|
|
||||||
use crate::common::Rect;
|
use crate::common::Rect;
|
||||||
use crate::engine_constants::EngineConstants;
|
use crate::engine_constants::EngineConstants;
|
||||||
|
use crate::framework::context::Context;
|
||||||
|
use crate::framework::error::GameResult;
|
||||||
|
use crate::framework::graphics::screen_insets_scaled;
|
||||||
use crate::texture_set::TextureSet;
|
use crate::texture_set::TextureSet;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
@ -14,67 +14,38 @@ pub enum TouchControlType {
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct TouchPoint {
|
pub struct TouchPoint {
|
||||||
id: u64,
|
pub id: u64,
|
||||||
touch_id: u64,
|
pub touch_id: u64,
|
||||||
position: (f64, f64),
|
pub position: (f64, f64),
|
||||||
last_position: (f64, f64),
|
pub last_position: (f64, f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TouchControls {
|
pub struct TouchControls {
|
||||||
pub control_type: TouchControlType,
|
pub control_type: TouchControlType,
|
||||||
pub points: Vec<TouchPoint>,
|
pub points: Vec<TouchPoint>,
|
||||||
pub interact_icon: bool,
|
pub interact_icon: bool,
|
||||||
touch_id_counter: u64,
|
pub touch_id_counter: u64,
|
||||||
clicks: Vec<TouchPoint>,
|
pub clicks: Vec<TouchPoint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TouchControls {
|
impl TouchControls {
|
||||||
pub fn new() -> TouchControls {
|
pub fn new() -> TouchControls {
|
||||||
TouchControls {
|
TouchControls {
|
||||||
control_type: TouchControlType::None,
|
control_type: TouchControlType::None,
|
||||||
touch_id_counter: 0,
|
|
||||||
interact_icon: false,
|
|
||||||
points: Vec::with_capacity(8),
|
points: Vec::with_capacity(8),
|
||||||
|
interact_icon: false,
|
||||||
|
touch_id_counter: 0,
|
||||||
clicks: Vec::with_capacity(8),
|
clicks: Vec::with_capacity(8),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
pub fn process_winit_event(&mut self, scale: f32, touch: winit::event::Touch) {
|
|
||||||
match touch.phase {
|
|
||||||
TouchPhase::Started | TouchPhase::Moved => {
|
|
||||||
if let Some(point) = self.points.iter_mut().find(|p| p.id == touch.id) {
|
|
||||||
point.last_position = point.position;
|
|
||||||
point.position = (touch.location.x / scale as f64, touch.location.y / scale as f64);
|
|
||||||
} else {
|
|
||||||
self.touch_id_counter = self.touch_id_counter.wrapping_add(1);
|
|
||||||
|
|
||||||
let point = TouchPoint {
|
|
||||||
id: touch.id,
|
|
||||||
touch_id: self.touch_id_counter,
|
|
||||||
position: (touch.location.x / scale as f64, touch.location.y / scale as f64),
|
|
||||||
last_position: (0.0, 0.0),
|
|
||||||
};
|
|
||||||
self.points.push(point);
|
|
||||||
|
|
||||||
if touch.phase == TouchPhase::Started {
|
|
||||||
self.clicks.push(point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TouchPhase::Ended | TouchPhase::Cancelled => {
|
|
||||||
self.points.retain(|p| p.id != touch.id);
|
|
||||||
self.clicks.retain(|p| p.id != touch.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
pub fn point_in(&self, bounds: Rect) -> Option<u64> {
|
pub fn point_in(&self, bounds: Rect) -> Option<u64> {
|
||||||
for point in self.points.iter() {
|
for point in self.points.iter() {
|
||||||
if (point.position.0 as isize) > bounds.left
|
if (point.position.0 as isize) > bounds.left
|
||||||
&& (point.position.0 as isize) < bounds.right
|
&& (point.position.0 as isize) < bounds.right
|
||||||
&& (point.position.1 as isize) > bounds.top
|
&& (point.position.1 as isize) > bounds.top
|
||||||
&& (point.position.1 as isize) < bounds.bottom {
|
&& (point.position.1 as isize) < bounds.bottom
|
||||||
|
{
|
||||||
return Some(point.touch_id);
|
return Some(point.touch_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +60,8 @@ impl TouchControls {
|
||||||
if (point.position.0 as isize) > bounds.left
|
if (point.position.0 as isize) > bounds.left
|
||||||
&& (point.position.0 as isize) < bounds.right
|
&& (point.position.0 as isize) < bounds.right
|
||||||
&& (point.position.1 as isize) > bounds.top
|
&& (point.position.1 as isize) > bounds.top
|
||||||
&& (point.position.1 as isize) < bounds.bottom {
|
&& (point.position.1 as isize) < bounds.bottom
|
||||||
|
{
|
||||||
point.touch_id = 0;
|
point.touch_id = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -99,11 +71,20 @@ impl TouchControls {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&self, canvas_size: (f32, f32), constants: &EngineConstants, texture_set: &mut TextureSet, ctx: &mut Context) -> GameResult {
|
pub fn draw(
|
||||||
|
&self,
|
||||||
|
canvas_size: (f32, f32),
|
||||||
|
scale: f32,
|
||||||
|
constants: &EngineConstants,
|
||||||
|
texture_set: &mut TextureSet,
|
||||||
|
ctx: &mut Context,
|
||||||
|
) -> GameResult {
|
||||||
if self.control_type == TouchControlType::Controls {
|
if self.control_type == TouchControlType::Controls {
|
||||||
let batch = texture_set.get_or_load_batch(ctx, constants, "builtin/touch")?;
|
let batch = texture_set.get_or_load_batch(ctx, constants, "builtin/touch")?;
|
||||||
let color = (255, 255, 255, 160);
|
let color = (255, 255, 255, 160);
|
||||||
|
|
||||||
|
let (left, _, right, bottom) = screen_insets_scaled(ctx, scale);
|
||||||
|
|
||||||
for x in 0..3 {
|
for x in 0..3 {
|
||||||
for y in 0..3 {
|
for y in 0..3 {
|
||||||
let mut icon_x = x;
|
let mut icon_x = x;
|
||||||
|
@ -113,21 +94,28 @@ impl TouchControls {
|
||||||
icon_x = 3;
|
icon_x = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.add_rect_tinted(4.0 + 48.0 * x as f32 + 8.0,
|
batch.add_rect_tinted(
|
||||||
(canvas_size.1 - 4.0 - 48.0 * 3.0) + 48.0 * y as f32 + 8.0,
|
4.0 + 48.0 * x as f32 + 8.0 + left,
|
||||||
color,
|
(canvas_size.1 - 4.0 - 48.0 * 3.0) + 48.0 * y as f32 + 8.0 - bottom,
|
||||||
&Rect::new_size(icon_x * 32, icon_y * 32, 32, 32));
|
color,
|
||||||
|
&Rect::new_size(icon_x * 32, icon_y * 32, 32, 32),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
batch.add_rect_tinted(
|
||||||
|
canvas_size.0 - (4.0 + 48.0) + 8.0 - right,
|
||||||
|
canvas_size.1 - (4.0 + 48.0) + 8.0 - bottom,
|
||||||
|
color,
|
||||||
|
&Rect::new_size(3 * 32, 32, 32, 32),
|
||||||
|
);
|
||||||
|
|
||||||
batch.add_rect_tinted(canvas_size.0 - (4.0 + 48.0) + 8.0, canvas_size.1 - (4.0 + 48.0) + 8.0,
|
batch.add_rect_tinted(
|
||||||
color,
|
canvas_size.0 - (4.0 + 48.0) + 8.0 - right,
|
||||||
&Rect::new_size(3 * 32, 32, 32, 32));
|
canvas_size.1 - (4.0 + 48.0) * 2.0 + 8.0 - bottom,
|
||||||
|
color,
|
||||||
batch.add_rect_tinted(canvas_size.0 - (4.0 + 48.0) + 8.0, canvas_size.1 - (4.0 + 48.0) * 2.0 + 8.0,
|
&Rect::new_size(3 * 32, 0, 32, 32),
|
||||||
color,
|
);
|
||||||
&Rect::new_size(3 * 32, 0, 32, 32));
|
|
||||||
|
|
||||||
batch.draw(ctx)?;
|
batch.draw(ctx)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use crate::framework::context::Context;
|
|
||||||
use crate::framework::error::GameResult;
|
|
||||||
|
|
||||||
|
|
||||||
use crate::bitfield;
|
use crate::bitfield;
|
||||||
use crate::common::Rect;
|
use crate::common::Rect;
|
||||||
|
use crate::framework::context::Context;
|
||||||
|
use crate::framework::error::GameResult;
|
||||||
|
use crate::framework::graphics::screen_insets_scaled;
|
||||||
use crate::input::player_controller::PlayerController;
|
use crate::input::player_controller::PlayerController;
|
||||||
use crate::input::touch_controls::TouchControlType;
|
use crate::input::touch_controls::TouchControlType;
|
||||||
use crate::shared_game_state::SharedGameState;
|
use crate::shared_game_state::SharedGameState;
|
||||||
|
@ -37,21 +36,21 @@ bitfield! {
|
||||||
|
|
||||||
impl TouchPlayerController {
|
impl TouchPlayerController {
|
||||||
pub fn new() -> TouchPlayerController {
|
pub fn new() -> TouchPlayerController {
|
||||||
TouchPlayerController {
|
TouchPlayerController { state: KeyState(0), old_state: KeyState(0), trigger: KeyState(0), prev_touch_len: 0 }
|
||||||
state: KeyState(0),
|
|
||||||
old_state: KeyState(0),
|
|
||||||
trigger: KeyState(0),
|
|
||||||
prev_touch_len: 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlayerController for TouchPlayerController {
|
impl PlayerController for TouchPlayerController {
|
||||||
fn update(&mut self, state: &mut SharedGameState, _ctx: &mut Context) -> GameResult {
|
fn update(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||||
match state.touch_controls.control_type {
|
match state.touch_controls.control_type {
|
||||||
TouchControlType::None => {}
|
TouchControlType::None => {}
|
||||||
TouchControlType::Dialog => {
|
TouchControlType::Dialog => {
|
||||||
self.state.set_jump(state.touch_controls.point_in(Rect::new_size(0, 0, state.canvas_size.0 as isize, state.canvas_size.1 as isize)).is_some());
|
self.state.set_jump(
|
||||||
|
state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(0, 0, state.canvas_size.0 as isize, state.canvas_size.1 as isize))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
if state.touch_controls.points.len() > 1 && self.prev_touch_len != state.touch_controls.points.len() {
|
if state.touch_controls.points.len() > 1 && self.prev_touch_len != state.touch_controls.points.len() {
|
||||||
self.prev_touch_len = state.touch_controls.points.len();
|
self.prev_touch_len = state.touch_controls.points.len();
|
||||||
|
@ -59,37 +58,152 @@ impl PlayerController for TouchPlayerController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TouchControlType::Controls => {
|
TouchControlType::Controls => {
|
||||||
|
let (left, _, right, bottom) = screen_insets_scaled(ctx, state.scale);
|
||||||
|
|
||||||
|
let left = 4 + left as isize;
|
||||||
|
let bottom = 4 + bottom as isize;
|
||||||
|
let right = 4 + right as isize;
|
||||||
|
|
||||||
self.state.0 = 0;
|
self.state.0 = 0;
|
||||||
// left
|
// left
|
||||||
self.state.set_left(self.state.left() || state.touch_controls.point_in(Rect::new_size(4, state.canvas_size.1 as isize - 4 - 48 * 2, 48, 48)).is_some());
|
self.state.set_left(
|
||||||
|
self.state.left()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(left, state.canvas_size.1 as isize - bottom - 48 * 2, 48, 48))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
// up
|
// up
|
||||||
self.state.set_up(self.state.up() || state.touch_controls.point_in(Rect::new_size(48 + 4, state.canvas_size.1 as isize - 4 - 48 * 3, 48, 48)).is_some());
|
self.state.set_up(
|
||||||
|
self.state.up()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(48 + left, state.canvas_size.1 as isize - bottom - 48 * 3, 48, 48))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
// right
|
// right
|
||||||
self.state.set_right(self.state.right() || state.touch_controls.point_in(Rect::new_size(4 + 48 * 2, state.canvas_size.1 as isize - 4 - 48 * 2, 48, 48)).is_some());
|
self.state.set_right(
|
||||||
|
self.state.right()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(
|
||||||
|
48 * 2 + left,
|
||||||
|
state.canvas_size.1 as isize - bottom - 48 * 2,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
// down
|
// down
|
||||||
self.state.set_down(self.state.down() || state.touch_controls.point_in(Rect::new_size(48 + 4, state.canvas_size.1 as isize - 4 - 48, 48, 48)).is_some());
|
self.state.set_down(
|
||||||
|
self.state.down()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(48 + left, state.canvas_size.1 as isize - bottom - 48, 48, 48))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
// left+up
|
// left+up
|
||||||
self.state.set_left(self.state.left() || state.touch_controls.point_in(Rect::new_size(4, state.canvas_size.1 as isize - 4 - 48 * 3, 48, 48)).is_some());
|
self.state.set_left(
|
||||||
self.state.set_up(self.state.up() || state.touch_controls.point_in(Rect::new_size(4, state.canvas_size.1 as isize - 4 - 48 * 3, 48, 48)).is_some());
|
self.state.left()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(left, state.canvas_size.1 as isize - bottom - 48 * 3, 48, 48))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
self.state.set_up(
|
||||||
|
self.state.up()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(left, state.canvas_size.1 as isize - bottom - 48 * 3, 48, 48))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
// right+up
|
// right+up
|
||||||
self.state.set_right(self.state.right() || state.touch_controls.point_in(Rect::new_size(4 + 48 * 2, state.canvas_size.1 as isize - 4 - 48 * 3, 48, 48)).is_some());
|
self.state.set_right(
|
||||||
self.state.set_up(self.state.up() || state.touch_controls.point_in(Rect::new_size(4 + 48 * 2, state.canvas_size.1 as isize - 4 - 48 * 3, 48, 48)).is_some());
|
self.state.right()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(
|
||||||
|
48 * 2 + left,
|
||||||
|
state.canvas_size.1 as isize - bottom - 48 * 3,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
self.state.set_up(
|
||||||
|
self.state.up()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(
|
||||||
|
48 * 2 + left,
|
||||||
|
state.canvas_size.1 as isize - bottom - 48 * 3,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
// left+down
|
// left+down
|
||||||
self.state.set_left(self.state.left() || state.touch_controls.point_in(Rect::new_size(4, state.canvas_size.1 as isize - 48 - 4, 48, 48)).is_some());
|
self.state.set_left(
|
||||||
self.state.set_down(self.state.down() || state.touch_controls.point_in(Rect::new_size(4, state.canvas_size.1 as isize - 48 - 4, 48, 48)).is_some());
|
self.state.left()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(left, state.canvas_size.1 as isize - 48 - bottom, 48, 48))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
self.state.set_down(
|
||||||
|
self.state.down()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(left, state.canvas_size.1 as isize - 48 - bottom, 48, 48))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
// right+down
|
// right+down
|
||||||
self.state.set_right(self.state.right() || state.touch_controls.point_in(Rect::new_size(4 + 48 * 2, state.canvas_size.1 as isize - 48 - 4, 48, 48)).is_some());
|
self.state.set_right(
|
||||||
self.state.set_down(self.state.down() || state.touch_controls.point_in(Rect::new_size(4 + 48 * 2, state.canvas_size.1 as isize - 48 - 4, 48, 48)).is_some());
|
self.state.right()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(48 * 2 + left, state.canvas_size.1 as isize - 48 - bottom, 48, 48))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
self.state.set_down(
|
||||||
|
self.state.down()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(48 * 2 + left, state.canvas_size.1 as isize - 48 - bottom, 48, 48))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
|
||||||
self.state.set_jump(self.state.jump() || state.touch_controls.point_in(Rect::new_size(state.canvas_size.0 as isize - 48 - 4, state.canvas_size.1 as isize - 48 - 4, 48, 48)).is_some());
|
self.state.set_jump(
|
||||||
self.state.set_shoot(self.state.shoot() || state.touch_controls.point_in(Rect::new_size(state.canvas_size.0 as isize - 48 - 4, state.canvas_size.1 as isize - (48 - 4) * 2, 48, 48)).is_some());
|
self.state.jump()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(
|
||||||
|
state.canvas_size.0 as isize - 48 - right,
|
||||||
|
state.canvas_size.1 as isize - (48 + 4) - bottom,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
|
self.state.set_shoot(
|
||||||
|
self.state.shoot()
|
||||||
|
|| state
|
||||||
|
.touch_controls
|
||||||
|
.point_in(Rect::new_size(
|
||||||
|
state.canvas_size.0 as isize - 48 - right,
|
||||||
|
state.canvas_size.1 as isize - (48 + 4) * 2 - bottom,
|
||||||
|
48,
|
||||||
|
48,
|
||||||
|
))
|
||||||
|
.is_some(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
190
src/lib.rs
|
@ -10,9 +10,11 @@ extern crate strum_macros;
|
||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Mutex;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use log::*;
|
use log::*;
|
||||||
use pretty_env_logger::env_logger::Env;
|
use pretty_env_logger::env_logger::Env;
|
||||||
|
|
||||||
|
@ -65,6 +67,10 @@ mod text_script;
|
||||||
mod texture_set;
|
mod texture_set;
|
||||||
mod weapon;
|
mod weapon;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref GAME_SUSPENDED: Mutex<bool> = Mutex::new(false);
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Game {
|
pub struct Game {
|
||||||
scene: Option<Box<dyn Scene>>,
|
scene: Option<Box<dyn Scene>>,
|
||||||
state: UnsafeCell<SharedGameState>,
|
state: UnsafeCell<SharedGameState>,
|
||||||
|
@ -98,14 +104,12 @@ impl Game {
|
||||||
TimingMode::_50Hz | TimingMode::_60Hz => {
|
TimingMode::_50Hz | TimingMode::_60Hz => {
|
||||||
let last_tick = self.next_tick;
|
let last_tick = self.next_tick;
|
||||||
|
|
||||||
while self.start_time.elapsed().as_nanos() >= self.next_tick && self.loops < 10
|
while self.start_time.elapsed().as_nanos() >= self.next_tick && self.loops < 10 {
|
||||||
{
|
|
||||||
if (state_ref.settings.speed - 1.0).abs() < 0.01 {
|
if (state_ref.settings.speed - 1.0).abs() < 0.01 {
|
||||||
self.next_tick += state_ref.timing_mode.get_delta() as u128;
|
self.next_tick += state_ref.timing_mode.get_delta() as u128;
|
||||||
} else {
|
} else {
|
||||||
self.next_tick += (state_ref.timing_mode.get_delta() as f64
|
self.next_tick +=
|
||||||
/ state_ref.settings.speed)
|
(state_ref.timing_mode.get_delta() as f64 / state_ref.settings.speed) as u128;
|
||||||
as u128;
|
|
||||||
}
|
}
|
||||||
self.loops += 1;
|
self.loops += 1;
|
||||||
}
|
}
|
||||||
|
@ -114,8 +118,7 @@ impl Game {
|
||||||
log::warn!("Frame skip is way too high, a long system lag occurred?");
|
log::warn!("Frame skip is way too high, a long system lag occurred?");
|
||||||
self.last_tick = self.start_time.elapsed().as_nanos();
|
self.last_tick = self.start_time.elapsed().as_nanos();
|
||||||
self.next_tick = self.last_tick
|
self.next_tick = self.last_tick
|
||||||
+ (state_ref.timing_mode.get_delta() as f64 / state_ref.settings.speed)
|
+ (state_ref.timing_mode.get_delta() as f64 / state_ref.settings.speed) as u128;
|
||||||
as u128;
|
|
||||||
self.loops = 0;
|
self.loops = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,152 +144,59 @@ impl Game {
|
||||||
|
|
||||||
if state_ref.timing_mode != TimingMode::FrameSynchronized {
|
if state_ref.timing_mode != TimingMode::FrameSynchronized {
|
||||||
let mut elapsed = self.start_time.elapsed().as_nanos();
|
let mut elapsed = self.start_time.elapsed().as_nanos();
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
{
|
// Even with the non-monotonic Instant mitigation at the start of the event loop, there's still a chance of it not working.
|
||||||
// Even with the non-monotonic Instant mitigation at the start of the event loop, there's still a chance of it not working.
|
// This check here should trigger if that happens and makes sure there's no panic from an underflow.
|
||||||
// This check here should trigger if that happens and makes sure there's no panic from an underflow.
|
if elapsed < self.last_tick {
|
||||||
if elapsed < self.last_tick {
|
elapsed = self.last_tick;
|
||||||
elapsed = self.last_tick;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let n1 = (elapsed - self.last_tick) as f64;
|
let n1 = (elapsed - self.last_tick) as f64;
|
||||||
let n2 = (self.next_tick - self.last_tick) as f64;
|
let n2 = (self.next_tick - self.last_tick) as f64;
|
||||||
state_ref.frame_time = if state_ref.settings.motion_interpolation {
|
state_ref.frame_time = if state_ref.settings.motion_interpolation { n1 / n2 } else { 1.0 };
|
||||||
n1 / n2
|
|
||||||
} else {
|
|
||||||
1.0
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
G_MAG = if state_ref.settings.subpixel_coords {
|
G_MAG = if state_ref.settings.subpixel_coords { state_ref.scale } else { 1.0 };
|
||||||
state_ref.scale
|
|
||||||
} else {
|
|
||||||
1.0
|
|
||||||
};
|
|
||||||
I_MAG = state_ref.scale;
|
I_MAG = state_ref.scale;
|
||||||
}
|
}
|
||||||
self.loops = 0;
|
self.loops = 0;
|
||||||
|
|
||||||
|
graphics::prepare_draw(ctx)?;
|
||||||
graphics::clear(ctx, [0.0, 0.0, 0.0, 1.0].into());
|
graphics::clear(ctx, [0.0, 0.0, 0.0, 1.0].into());
|
||||||
/*graphics::set_projection(ctx, DrawParam::new()
|
|
||||||
.scale(Vec2::new(state_ref.scale, state_ref.scale))
|
|
||||||
.to_matrix());*/
|
|
||||||
|
|
||||||
if let Some(scene) = self.scene.as_mut() {
|
if let Some(scene) = self.scene.as_mut() {
|
||||||
scene.draw(state_ref, ctx)?;
|
scene.draw(state_ref, ctx)?;
|
||||||
if state_ref.settings.touch_controls {
|
if state_ref.settings.touch_controls {
|
||||||
state_ref.touch_controls.draw(
|
state_ref.touch_controls.draw(
|
||||||
state_ref.canvas_size,
|
state_ref.canvas_size,
|
||||||
|
state_ref.scale,
|
||||||
&state_ref.constants,
|
&state_ref.constants,
|
||||||
&mut state_ref.texture_set,
|
&mut state_ref.texture_set,
|
||||||
ctx,
|
ctx,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
//graphics::set_projection(ctx, self.def_matrix);
|
|
||||||
self.ui.draw(state_ref, ctx, scene)?;
|
self.ui.draw(state_ref, ctx, scene)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics::present(ctx)?;
|
graphics::present(ctx)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
fn request_perms() -> GameResult {
|
#[cfg_attr(target_os = "android", ndk_glue::main())]
|
||||||
use jni::objects::JObject;
|
|
||||||
use jni::objects::JValue;
|
|
||||||
|
|
||||||
let native_activity = ndk_glue::native_activity();
|
|
||||||
let vm_ptr = native_activity.vm();
|
|
||||||
let vm = unsafe { jni::JavaVM::from_raw(vm_ptr) }?;
|
|
||||||
let vm_env = vm.attach_current_thread()?;
|
|
||||||
|
|
||||||
fn perm_name<'a, 'b, 'c>(
|
|
||||||
vm_env: &'b jni::AttachGuard<'a>,
|
|
||||||
name: &'c str,
|
|
||||||
) -> GameResult<jni::objects::JValue<'a>> {
|
|
||||||
let class = vm_env.find_class("android/Manifest$permission")?;
|
|
||||||
Ok(vm_env.get_static_field(class, name.to_owned(), "Ljava/lang/String;")?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_permission(
|
|
||||||
vm_env: &jni::AttachGuard,
|
|
||||||
activity: &jni::sys::jobject,
|
|
||||||
name: &str,
|
|
||||||
) -> GameResult<bool> {
|
|
||||||
let perm_granted = {
|
|
||||||
let class = vm_env.find_class("android/content/pm/PackageManager")?;
|
|
||||||
vm_env
|
|
||||||
.get_static_field(class, "PERMISSION_GRANTED", "I")?
|
|
||||||
.i()?
|
|
||||||
};
|
|
||||||
|
|
||||||
let perm = perm_name(vm_env, name)?;
|
|
||||||
let activity_obj = JObject::from(*activity);
|
|
||||||
let result = vm_env
|
|
||||||
.call_method(
|
|
||||||
activity_obj,
|
|
||||||
"checkSelfPermission",
|
|
||||||
"(Ljava/lang/String;)I",
|
|
||||||
&[perm],
|
|
||||||
)?
|
|
||||||
.i()?;
|
|
||||||
Ok(result == perm_granted)
|
|
||||||
}
|
|
||||||
|
|
||||||
let str_class = vm_env.find_class("java/lang/String")?;
|
|
||||||
let array = vm_env.new_object_array(2, str_class, JObject::null())?;
|
|
||||||
vm_env.set_object_array_element(array, 0, perm_name(&vm_env, "READ_EXTERNAL_STORAGE")?.l()?)?;
|
|
||||||
vm_env.set_object_array_element(
|
|
||||||
array,
|
|
||||||
1,
|
|
||||||
perm_name(&vm_env, "WRITE_EXTERNAL_STORAGE")?.l()?,
|
|
||||||
)?;
|
|
||||||
let activity_obj = JObject::from(native_activity.activity());
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if has_permission(
|
|
||||||
&vm_env,
|
|
||||||
&native_activity.activity(),
|
|
||||||
"READ_EXTERNAL_STORAGE",
|
|
||||||
)? && has_permission(
|
|
||||||
&vm_env,
|
|
||||||
&native_activity.activity(),
|
|
||||||
"WRITE_EXTERNAL_STORAGE",
|
|
||||||
)? {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
vm_env.call_method(
|
|
||||||
activity_obj,
|
|
||||||
"requestPermissions",
|
|
||||||
"([Ljava/lang/String;I)V",
|
|
||||||
&[JValue::from(array), JValue::from(0)],
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
|
||||||
#[cfg_attr(target_os = "android", ndk_glue::main(backtrace = "on"))]
|
|
||||||
pub fn android_main() {
|
pub fn android_main() {
|
||||||
println!("main invoked.");
|
|
||||||
|
|
||||||
request_perms().expect("Failed to attach to the JVM and request storage permissions.");
|
|
||||||
|
|
||||||
env::set_var("CAVESTORY_DATA_DIR", "/sdcard/doukutsu");
|
|
||||||
|
|
||||||
let _ = std::fs::create_dir("/sdcard/doukutsu/");
|
|
||||||
let _ = std::fs::write("/sdcard/doukutsu/.nomedia", b"");
|
|
||||||
|
|
||||||
init().unwrap();
|
init().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init() -> GameResult {
|
pub fn init() -> GameResult {
|
||||||
pretty_env_logger::env_logger::from_env(Env::default().default_filter_or("info")).init();
|
pretty_env_logger::env_logger::from_env(Env::default().default_filter_or("info"))
|
||||||
|
//.filter(Some("ndk_glue"), LevelFilter::Trace)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
let resource_dir = if let Ok(data_dir) = env::var("CAVESTORY_DATA_DIR") {
|
let resource_dir = if let Ok(data_dir) = env::var("CAVESTORY_DATA_DIR") {
|
||||||
PathBuf::from(data_dir)
|
PathBuf::from(data_dir)
|
||||||
} else {
|
} else {
|
||||||
|
@ -298,51 +208,53 @@ pub fn init() -> GameResult {
|
||||||
resource_dir
|
resource_dir
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
info!("Resource directory: {:?}", resource_dir);
|
info!("Resource directory: {:?}", resource_dir);
|
||||||
info!("Initializing engine...");
|
info!("Initializing engine...");
|
||||||
|
|
||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
mount_vfs(&mut context, Box::new(BuiltinFS::new()));
|
mount_vfs(&mut context, Box::new(BuiltinFS::new()));
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "android"))]
|
||||||
mount_vfs(&mut context, Box::new(PhysicalFS::new(&resource_dir, true)));
|
mount_vfs(&mut context, Box::new(PhysicalFS::new(&resource_dir, true)));
|
||||||
|
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
let project_dirs = match ProjectDirs::from("", "", "doukutsu-rs") {
|
let project_dirs = match ProjectDirs::from("", "", "doukutsu-rs") {
|
||||||
Some(dirs) => dirs,
|
Some(dirs) => dirs,
|
||||||
None => {
|
None => {
|
||||||
return Err(GameError::FilesystemError(String::from(
|
return Err(GameError::FilesystemError(String::from("No valid home directory path could be retrieved.")));
|
||||||
"No valid home directory path could be retrieved.",
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mount_user_vfs(
|
|
||||||
&mut context,
|
|
||||||
Box::new(PhysicalFS::new(project_dirs.data_local_dir(), false)),
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
{
|
{
|
||||||
loop {
|
let mut data_path =
|
||||||
match ndk_glue::native_window().as_ref() {
|
PathBuf::from(ndk_glue::native_activity().internal_data_path().to_string_lossy().to_string());
|
||||||
Some(_) => {
|
let mut user_path = data_path.clone();
|
||||||
println!("NativeScreen Found:{:?}", ndk_glue::native_window());
|
|
||||||
break;
|
data_path.push("data");
|
||||||
}
|
user_path.push("saves");
|
||||||
None => (),
|
|
||||||
}
|
let _ = std::fs::create_dir_all(&data_path);
|
||||||
}
|
let _ = std::fs::create_dir_all(&user_path);
|
||||||
|
|
||||||
|
log::info!("Android data directories: data_path={:?} user_path={:?}", &data_path, &user_path);
|
||||||
|
|
||||||
|
mount_vfs(&mut context, Box::new(PhysicalFS::new(&data_path, true)));
|
||||||
|
mount_user_vfs(&mut context, Box::new(PhysicalFS::new(&user_path, false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut game = Game::new(&mut context)?;
|
#[cfg(not(target_os = "android"))]
|
||||||
let state_ref = unsafe { &mut *game.state.get() };
|
mount_user_vfs(&mut context, Box::new(PhysicalFS::new(project_dirs.data_local_dir(), false)));
|
||||||
|
|
||||||
|
let game = UnsafeCell::new(Game::new(&mut context)?);
|
||||||
|
let state_ref = unsafe { &mut *((&mut *game.get()).state.get()) };
|
||||||
#[cfg(feature = "scripting")]
|
#[cfg(feature = "scripting")]
|
||||||
{
|
{
|
||||||
state_ref
|
state_ref.lua.update_refs(unsafe { (&*game.get()).state.get() }, &mut context as *mut Context);
|
||||||
.lua
|
|
||||||
.update_refs(game.state.get(), &mut context as *mut Context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state_ref.next_scene = Some(Box::new(LoadingScene::new()));
|
state_ref.next_scene = Some(Box::new(LoadingScene::new()));
|
||||||
context.run(&mut game)?;
|
context.run(unsafe { &mut *game.get() })?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ impl LoadingScene {
|
||||||
|
|
||||||
impl Scene for LoadingScene {
|
impl Scene for LoadingScene {
|
||||||
fn tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
fn tick(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||||
|
println!("**TICK**");
|
||||||
// deferred to let the loading image draw
|
// deferred to let the loading image draw
|
||||||
if self.tick == 1 {
|
if self.tick == 1 {
|
||||||
if let Err(err) = self.load_stuff(state, ctx) {
|
if let Err(err) = self.load_stuff(state, ctx) {
|
||||||
|
@ -66,6 +67,8 @@ impl Scene for LoadingScene {
|
||||||
batch.draw(ctx)?;
|
batch.draw(ctx)?;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
log::error!("Failed to load game data: {}", err);
|
||||||
|
|
||||||
state.next_scene = Some(Box::new(NoDataScene::new(err)));
|
state.next_scene = Some(Box::new(NoDataScene::new(err)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,7 +182,7 @@ impl Scene for TitleScene {
|
||||||
TimingMode::_60Hz => state.timing_mode = TimingMode::_50Hz,
|
TimingMode::_60Hz => state.timing_mode = TimingMode::_50Hz,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
state.settings.save(ctx);
|
let _ = state.settings.save(ctx);
|
||||||
|
|
||||||
*value = state.timing_mode == TimingMode::_50Hz;
|
*value = state.timing_mode == TimingMode::_50Hz;
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ impl Scene for TitleScene {
|
||||||
MenuSelectionResult::Selected(1, toggle) => {
|
MenuSelectionResult::Selected(1, toggle) => {
|
||||||
if let MenuEntry::Toggle(_, value) = toggle {
|
if let MenuEntry::Toggle(_, value) = toggle {
|
||||||
state.settings.shader_effects = !state.settings.shader_effects;
|
state.settings.shader_effects = !state.settings.shader_effects;
|
||||||
state.settings.save(ctx);
|
let _ = state.settings.save(ctx);
|
||||||
|
|
||||||
*value = state.settings.shader_effects;
|
*value = state.settings.shader_effects;
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ impl Scene for TitleScene {
|
||||||
if let MenuEntry::Toggle(_, value) = toggle {
|
if let MenuEntry::Toggle(_, value) = toggle {
|
||||||
state.settings.original_textures = !state.settings.original_textures;
|
state.settings.original_textures = !state.settings.original_textures;
|
||||||
state.reload_textures();
|
state.reload_textures();
|
||||||
state.settings.save(ctx);
|
let _ = state.settings.save(ctx);
|
||||||
|
|
||||||
*value = state.settings.original_textures;
|
*value = state.settings.original_textures;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ impl Scene for TitleScene {
|
||||||
if let MenuEntry::Toggle(_, value) = toggle {
|
if let MenuEntry::Toggle(_, value) = toggle {
|
||||||
state.settings.seasonal_textures = !state.settings.seasonal_textures;
|
state.settings.seasonal_textures = !state.settings.seasonal_textures;
|
||||||
state.reload_textures();
|
state.reload_textures();
|
||||||
state.settings.save(ctx);
|
let _ = state.settings.save(ctx);
|
||||||
|
|
||||||
*value = state.settings.seasonal_textures;
|
*value = state.settings.seasonal_textures;
|
||||||
}
|
}
|
||||||
|
|
58
src/scripting/doukutsu.d.ts
vendored
|
@ -1,7 +1,7 @@
|
||||||
declare type EventHandler<T> = (this: void, param: T) => void;
|
declare type EventHandler<T> = (this: void, param: T) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a
|
* Represents an in-game player.
|
||||||
*/
|
*/
|
||||||
declare interface DoukutsuPlayer {
|
declare interface DoukutsuPlayer {
|
||||||
/**
|
/**
|
||||||
|
@ -28,28 +28,40 @@ declare interface DoukutsuPlayer {
|
||||||
* Current velocity of player in Y axis (as floating point, not internal fixed point representation).
|
* Current velocity of player in Y axis (as floating point, not internal fixed point representation).
|
||||||
*/
|
*/
|
||||||
velY(): number;
|
velY(): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the position of player in X axis (as floating point, not internal fixed point representation).
|
||||||
|
*/
|
||||||
|
setX(value: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the position of player in Y axis (as floating point, not internal fixed point representation).
|
||||||
|
*/
|
||||||
|
setY(value: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the velocity of player in X axis (as floating point, not internal fixed point representation).
|
||||||
|
*/
|
||||||
|
setVelX(value: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the velocity of player in Y axis (as floating point, not internal fixed point representation).
|
||||||
|
*/
|
||||||
|
setVelY(value: number): void;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface DoukutsuScene {
|
declare interface DoukutsuStage {
|
||||||
/**
|
/**
|
||||||
* Returns the tick of current scene.
|
* Returns the tick of current stage.
|
||||||
*/
|
*/
|
||||||
tick(): number;
|
tick(): number;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of players connected to current game.
|
|
||||||
*/
|
|
||||||
onlinePlayers(): DoukutsuPlayer[];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of players on current map.
|
* Returns a list of players on current map.
|
||||||
*/
|
*/
|
||||||
mapPlayers(): DoukutsuPlayer[];
|
players(): DoukutsuPlayer[];
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the id of local player.
|
|
||||||
*/
|
|
||||||
localPlayerId(): number;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns player with specified id.
|
* Returns player with specified id.
|
||||||
|
@ -69,6 +81,22 @@ declare namespace doukutsu {
|
||||||
*/
|
*/
|
||||||
function playMusic(id: number): void;
|
function playMusic(id: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of a certain TSC flag.
|
||||||
|
* @param id the flag number
|
||||||
|
*/
|
||||||
|
function getFlag(id: number): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of players connected to current game.
|
||||||
|
*/
|
||||||
|
function onlinePlayers(): DoukutsuPlayer[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the id of local player.
|
||||||
|
*/
|
||||||
|
function localPlayerId(): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets an implementation-defined game setting.
|
* Sets an implementation-defined game setting.
|
||||||
* @param name
|
* @param name
|
||||||
|
@ -88,7 +116,7 @@ declare namespace doukutsu {
|
||||||
* @param event event name
|
* @param event event name
|
||||||
* @param handler event handler procedure
|
* @param handler event handler procedure
|
||||||
*/
|
*/
|
||||||
function on(event: "tick", handler: EventHandler<DoukutsuScene>): EventHandler<DoukutsuScene>;
|
function on(event: "tick", handler: EventHandler<DoukutsuStage>): EventHandler<DoukutsuStage>;
|
||||||
|
|
||||||
function on<T>(event: string, handler: EventHandler<T>): EventHandler<T>;
|
function on<T>(event: string, handler: EventHandler<T>): EventHandler<T>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,18 @@ impl Doukutsu {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn lua_set_setting(&self, state: &mut State) -> c_int {
|
||||||
|
if let Some(index) = state.to_int(2) {
|
||||||
|
let game_state = &mut (*(*self.ptr).state_ptr);
|
||||||
|
|
||||||
|
state.push(game_state.get_flag(index.max(0) as usize));
|
||||||
|
} else {
|
||||||
|
state.push_nil();
|
||||||
|
}
|
||||||
|
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn lua_get_flag(&self, state: &mut State) -> c_int {
|
unsafe fn lua_get_flag(&self, state: &mut State) -> c_int {
|
||||||
if let Some(index) = state.to_int(2) {
|
if let Some(index) = state.to_int(2) {
|
||||||
let game_state = &mut (*(*self.ptr).state_ptr);
|
let game_state = &mut (*(*self.ptr).state_ptr);
|
||||||
|
@ -55,9 +67,9 @@ impl LuaObject for Doukutsu {
|
||||||
|
|
||||||
fn lua_fns() -> Vec<luaL_Reg> {
|
fn lua_fns() -> Vec<luaL_Reg> {
|
||||||
vec![
|
vec![
|
||||||
lua_method!("play_sfx", Doukutsu, Doukutsu::lua_play_sfx),
|
lua_method!("playSfx", Doukutsu, Doukutsu::lua_play_sfx),
|
||||||
lua_method!("play_song", Doukutsu, Doukutsu::lua_play_song),
|
lua_method!("playSong", Doukutsu, Doukutsu::lua_play_song),
|
||||||
lua_method!("get_flag", Doukutsu, Doukutsu::lua_get_flag),
|
lua_method!("getFlag", Doukutsu, Doukutsu::lua_get_flag),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,6 +222,10 @@ impl SharedGameState {
|
||||||
self.texture_set = texture_set;
|
self.texture_set = texture_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn graphics_reset(&mut self) {
|
||||||
|
self.reload_textures();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn start_new_game(&mut self, ctx: &mut Context) -> GameResult {
|
pub fn start_new_game(&mut self, ctx: &mut Context) -> GameResult {
|
||||||
let mut next_scene = GameScene::new(self, ctx, 13)?;
|
let mut next_scene = GameScene::new(self, ctx, 13)?;
|
||||||
next_scene.player1.cond.set_alive(true);
|
next_scene.player1.cond.set_alive(true);
|
||||||
|
|
|
@ -526,9 +526,29 @@ where
|
||||||
},
|
},
|
||||||
err_fn,
|
err_fn,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
stream.play()?;
|
stream.play()?;
|
||||||
|
|
||||||
|
let mut saved_state = true;
|
||||||
loop {
|
loop {
|
||||||
std::thread::sleep(Duration::from_millis(10));
|
std::thread::sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
{
|
||||||
|
let mutex = crate::GAME_SUSPENDED.lock().unwrap();
|
||||||
|
let state = *mutex;
|
||||||
|
if saved_state != state {
|
||||||
|
saved_state = state;
|
||||||
|
|
||||||
|
if state {
|
||||||
|
if let Err(e) = stream.pause() {
|
||||||
|
log::error!("Failed to pause the stream: {}", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Err(e) = stream.play() {
|
||||||
|
log::error!("Failed to unpause the stream: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -729,7 +729,7 @@ impl TextScriptVM {
|
||||||
FromPrimitive::from_i32(read_cur_varint(&mut cursor).unwrap_or_else(|_| OpCode::END as i32));
|
FromPrimitive::from_i32(read_cur_varint(&mut cursor).unwrap_or_else(|_| OpCode::END as i32));
|
||||||
|
|
||||||
if let Some(op) = op_maybe {
|
if let Some(op) = op_maybe {
|
||||||
println!("opcode: {:?}", op);
|
log::info!("opcode: {:?}", op);
|
||||||
match op {
|
match op {
|
||||||
OpCode::_NOP => {
|
OpCode::_NOP => {
|
||||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||||
|
|