mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-01-06 02:56:41 +00:00
update some deps + android build fix and downloader
This commit is contained in:
parent
eaaa11d4f6
commit
75e05c5ca5
|
@ -59,7 +59,7 @@ cpal = { git = "https://github.com/doukutsu-rs/cpal.git", rev = "4218ff23242834d
|
|||
directories = "3"
|
||||
funty = "=1.1.0" # https://github.com/bitvecto-rs/bitvec/issues/105
|
||||
glutin = { git = "https://github.com/doukutsu-rs/glutin.git", rev = "8dd457b9adb7dbac7ade337246b6356c784272d9", optional = true, default_features = false, features = ["x11"] }
|
||||
imgui = "0.7.0"
|
||||
imgui = "0.8.0"
|
||||
image = { version = "0.23", default-features = false, features = ["png", "bmp"] }
|
||||
itertools = "0.10"
|
||||
lazy_static = "1.4.0"
|
||||
|
|
|
@ -62,6 +62,11 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation 'com.android.support:support-annotations:28.0.0'
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
implementation 'com.android.support:design:28.0.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:2.0.1'
|
||||
implementation 'android.arch.navigation:navigation-fragment:1.0.0'
|
||||
implementation 'android.arch.navigation:navigation-ui:1.0.0'
|
||||
}
|
||||
|
||||
println("cargo target: ${project.buildDir.getAbsolutePath()}/rust-target")
|
||||
|
|
|
@ -1,40 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="io.github.doukutsu_rs">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.github.doukutsu_rs">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:extractNativeLibs="true"
|
||||
<application android:allowBackup="true" android:extractNativeLibs="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="drsandroid" />
|
||||
<activity android:name=".DownloadActivity" android:label="Download" android:screenOrientation="sensorLandscape"
|
||||
android:theme="@style/Theme.Doukutsurs.NoActionBar"></activity>
|
||||
<activity android:name=".MainActivity" android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:label="doukutsu-rs" android:launchMode="standard" android:screenOrientation="sensorLandscape">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data android:name="android.app.lib_name" android:value="drsandroid" />
|
||||
</activity>
|
||||
|
||||
<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>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
package io.github.doukutsu_rs;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class DownloadActivity extends AppCompatActivity {
|
||||
private TextView txtProgress;
|
||||
private ProgressBar progressBar;
|
||||
private DownloadThread downloadThread;
|
||||
private String basePath;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_download);
|
||||
txtProgress = findViewById(R.id.txtProgress);
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
basePath = getFilesDir().getAbsolutePath() + "/data/";
|
||||
|
||||
downloadThread = new DownloadThread();
|
||||
downloadThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
downloadThread.interrupt();
|
||||
}
|
||||
|
||||
private class DownloadThread extends Thread {
|
||||
private static final String DOWNLOAD_URL = "https://github.com/doukutsu-rs/game-data/archive/refs/heads/master.zip";
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
HttpURLConnection connection = null;
|
||||
try {
|
||||
URL url = new URL(DOWNLOAD_URL);
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.connect();
|
||||
|
||||
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||
throw new IllegalStateException("Bad HTTP response code: " + connection.getResponseCode());
|
||||
}
|
||||
|
||||
int fileLength = connection.getContentLength();
|
||||
if (fileLength == 0) {
|
||||
progressBar.setIndeterminate(true);
|
||||
}
|
||||
|
||||
byte[] zipFile;
|
||||
{
|
||||
InputStream input = new BufferedInputStream(connection.getInputStream());
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
|
||||
int downloadedLast = 0;
|
||||
int downloaded = 0;
|
||||
byte[] buffer = new byte[4096];
|
||||
int count;
|
||||
long last = System.currentTimeMillis();
|
||||
|
||||
while ((count = input.read(buffer)) != -1) {
|
||||
downloaded += count;
|
||||
|
||||
output.write(buffer, 0, count);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
if (last + 1000 >= now) {
|
||||
int speed = (int) ((downloaded - downloadedLast) / 1024.0);
|
||||
String text = (fileLength > 0)
|
||||
? String.format(Locale.ENGLISH, "Downloading... %d%% (%d/%d KiB, %d KiB/s)", downloaded * 100 / fileLength, downloaded / 1024, fileLength / 1024, speed)
|
||||
: String.format(Locale.ENGLISH, "Downloading... --%% (%d KiB, %d KiB/s)", downloaded / 1024, speed);
|
||||
|
||||
txtProgress.setText(text);
|
||||
|
||||
downloadedLast = downloaded;
|
||||
last = now;
|
||||
}
|
||||
}
|
||||
|
||||
output.flush();
|
||||
zipFile = output.toByteArray();
|
||||
output.close();
|
||||
}
|
||||
|
||||
new File(basePath).mkdirs();
|
||||
try (ZipInputStream in = new ZipInputStream(new ByteArrayInputStream(zipFile))) {
|
||||
ZipEntry entry;
|
||||
byte[] buffer = new byte[4096];
|
||||
while ((entry = in.getNextEntry()) != null) {
|
||||
String entryName = entry.getName();
|
||||
|
||||
// strip prefix
|
||||
if (entryName.startsWith("game-data-master/")) {
|
||||
entryName = entryName.substring("game-data-master/".length());
|
||||
}
|
||||
|
||||
txtProgress.setText("Unpacking: " + entryName);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
new File(basePath + entryName).mkdirs();
|
||||
} else {
|
||||
try (FileOutputStream fos = new FileOutputStream(basePath + entryName)) {
|
||||
int count;
|
||||
while ((count = in.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
in.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
txtProgress.setText("Done!");
|
||||
|
||||
Intent intent = new Intent(DownloadActivity.this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
|
||||
startActivity(intent);
|
||||
DownloadActivity.this.finish();
|
||||
} catch (Exception e) {
|
||||
if (txtProgress != null) txtProgress.setText(e.getMessage());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (connection != null) connection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package io.github.doukutsu_rs;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.NativeActivity;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Build;
|
||||
|
@ -8,6 +10,8 @@ import android.os.Bundle;
|
|||
import android.view.OrientationEventListener;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
public class MainActivity extends NativeActivity {
|
||||
|
@ -16,6 +20,18 @@ public class MainActivity extends NativeActivity {
|
|||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
File f = new File(getFilesDir().getAbsolutePath() + "/data/");
|
||||
String[] list = f.list();
|
||||
if (!f.exists() || (list != null && list.length == 0)) {
|
||||
|
||||
messageBox("Missing data files", "No data files found, would you like to download them?", () -> {
|
||||
Intent intent = new Intent(this, DownloadActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
|
||||
startActivity(intent);
|
||||
this.finish();
|
||||
});
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
listener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_UI) {
|
||||
|
@ -70,6 +86,8 @@ public class MainActivity extends NativeActivity {
|
|||
this.displayInsets[1] = Math.max(this.displayInsets[1], insets.getStableInsetTop());
|
||||
this.displayInsets[2] = Math.max(this.displayInsets[2], insets.getStableInsetRight());
|
||||
this.displayInsets[3] = Math.max(this.displayInsets[3], insets.getStableInsetBottom());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDK_INT >= Build.VERSION_CODES.P) {
|
||||
|
@ -84,4 +102,19 @@ public class MainActivity extends NativeActivity {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
private void messageBox(String title, String message, Runnable callback) {
|
||||
this.runOnUiThread(() -> {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this);
|
||||
alert.setTitle(title);
|
||||
alert.setMessage(message);
|
||||
alert.setPositiveButton(android.R.string.yes, (dialog, whichButton) -> {
|
||||
callback.run();
|
||||
});
|
||||
alert.setNegativeButton(android.R.string.no, (dialog, whichButton) -> {
|
||||
// hide
|
||||
});
|
||||
alert.show();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
42
app/app/src/main/res/layout/activity_download.xml
Normal file
42
app/app/src/main/res/layout/activity_download.xml
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".DownloadActivity">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginStart="32dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Downloading game data"
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Display1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtProgress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="..."
|
||||
android:textAlignment="center"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
3
app/app/src/main/res/values/dimens.xml
Normal file
3
app/app/src/main/res/values/dimens.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
|
@ -3,4 +3,13 @@
|
|||
<style name="Theme.Doukutsurs" parent="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen">
|
||||
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
<style name="Theme.Doukutsurs.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Doukutsurs.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="Theme.Doukutsurs.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
</resources>
|
||||
|
|
|
@ -8,7 +8,7 @@ buildscript {
|
|||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:4.0.2"
|
||||
classpath "com.android.tools.build:gradle:4.2.0"
|
||||
classpath "gradle.plugin.com.github.willir.rust:plugin:0.3.4"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
|
|
@ -5,9 +5,8 @@ use std::ffi::c_void;
|
|||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
|
||||
use imgui::{ConfigFlags, DrawCmd, DrawData, ImString, Key, MouseCursor, TextureId};
|
||||
use imgui::internal::RawWrapper;
|
||||
use sdl2::{EventPump, keyboard, pixels, Sdl, VideoSubsystem};
|
||||
use imgui::{ConfigFlags, DrawCmd, DrawData, Key, MouseCursor, TextureId};
|
||||
use sdl2::event::{Event, WindowEvent};
|
||||
use sdl2::keyboard::Scancode;
|
||||
use sdl2::mouse::{Cursor, SystemCursor};
|
||||
|
@ -15,6 +14,7 @@ use sdl2::pixels::PixelFormatEnum;
|
|||
use sdl2::render::{Texture, TextureCreator, WindowCanvas};
|
||||
use sdl2::video::GLProfile;
|
||||
use sdl2::video::WindowContext;
|
||||
use sdl2::{keyboard, pixels, EventPump, Sdl, VideoSubsystem};
|
||||
|
||||
use crate::common::{Color, Rect};
|
||||
use crate::framework::backend::{
|
||||
|
@ -309,7 +309,7 @@ impl SDL2Renderer {
|
|||
let mut imgui = init_imgui()?;
|
||||
let mut imgui_textures = HashMap::new();
|
||||
|
||||
imgui.set_renderer_name(ImString::new("SDL2Renderer"));
|
||||
imgui.set_renderer_name("SDL2Renderer".to_owned());
|
||||
{
|
||||
let refs = refs.clone();
|
||||
let mut fonts = imgui.fonts();
|
||||
|
@ -1006,23 +1006,23 @@ pub struct ImguiSdl2 {
|
|||
struct Sdl2ClipboardBackend(sdl2::clipboard::ClipboardUtil);
|
||||
|
||||
impl imgui::ClipboardBackend for Sdl2ClipboardBackend {
|
||||
fn get(&mut self) -> Option<imgui::ImString> {
|
||||
fn get(&mut self) -> Option<String> {
|
||||
if !self.0.has_clipboard_text() {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.0.clipboard_text().ok().map(imgui::ImString::new)
|
||||
self.0.clipboard_text().ok()
|
||||
}
|
||||
|
||||
fn set(&mut self, value: &imgui::ImStr) {
|
||||
let _ = self.0.set_clipboard_text(value.to_str());
|
||||
fn set(&mut self, value: &str) {
|
||||
let _ = self.0.set_clipboard_text(value);
|
||||
}
|
||||
}
|
||||
|
||||
impl ImguiSdl2 {
|
||||
pub fn new(imgui: &mut imgui::Context, window: &sdl2::video::Window) -> Self {
|
||||
let clipboard_util = window.subsystem().clipboard();
|
||||
imgui.set_clipboard_backend(Box::new(Sdl2ClipboardBackend(clipboard_util)));
|
||||
imgui.set_clipboard_backend(Sdl2ClipboardBackend(clipboard_util));
|
||||
|
||||
imgui.io_mut().key_map[Key::Tab as usize] = Scancode::Tab as u32;
|
||||
imgui.io_mut().key_map[Key::LeftArrow as usize] = Scancode::Left as u32;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use imgui::{CollapsingHeader, Condition, im_str, ImStr, ImString, Slider, Window};
|
||||
use imgui::{ CollapsingHeader, Condition, ImStr, ImString, Slider, Window};
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::scene::game_scene::GameScene;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::scripting::tsc::text_script::TextScriptExecutionState;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
#[repr(u8)]
|
||||
|
@ -49,7 +49,13 @@ impl LiveDebugger {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn run_ingame(&mut self, game_scene: &mut GameScene, state: &mut SharedGameState, ctx: &mut Context, ui: &mut imgui::Ui) -> GameResult {
|
||||
pub fn run_ingame(
|
||||
&mut self,
|
||||
game_scene: &mut GameScene,
|
||||
state: &mut SharedGameState,
|
||||
ctx: &mut Context,
|
||||
ui: &mut imgui::Ui,
|
||||
) -> GameResult {
|
||||
if self.last_stage_id != game_scene.stage_id {
|
||||
self.last_stage_id = game_scene.stage_id;
|
||||
self.events.clear();
|
||||
|
@ -60,7 +66,7 @@ impl LiveDebugger {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
Window::new(im_str!("Debugger"))
|
||||
Window::new("Debugger")
|
||||
.resizable(false)
|
||||
.collapsed(true, Condition::FirstUseEver)
|
||||
.position([5.0, 5.0], Condition::FirstUseEver)
|
||||
|
@ -91,14 +97,11 @@ impl LiveDebugger {
|
|||
game_scene.player1.booster_fuel
|
||||
));
|
||||
|
||||
|
||||
ui.text(format!("Game speed ({:.1} TPS):", state.current_tps()));
|
||||
let mut speed = state.settings.speed;
|
||||
Slider::new(im_str!(""))
|
||||
.range(0.1..=3.0)
|
||||
.build(ui, &mut speed);
|
||||
ui.same_line(0.0);
|
||||
if ui.button(im_str!("Reset"), [0.0, 0.0]) {
|
||||
Slider::new("", 0.1, 3.0).build(ui, &mut speed);
|
||||
ui.same_line();
|
||||
if ui.button("Reset") {
|
||||
speed = 1.0
|
||||
}
|
||||
|
||||
|
@ -107,47 +110,47 @@ impl LiveDebugger {
|
|||
state.set_speed(speed);
|
||||
}
|
||||
|
||||
if ui.button(im_str!("Maps"), [0.0, 0.0]) {
|
||||
if ui.button("Maps") {
|
||||
self.map_selector_visible = !self.map_selector_visible;
|
||||
}
|
||||
|
||||
ui.same_line(0.0);
|
||||
if ui.button(im_str!("TSC Scripts"), [0.0, 0.0]) {
|
||||
ui.same_line();
|
||||
if ui.button("TSC Scripts") {
|
||||
self.events_visible = !self.events_visible;
|
||||
}
|
||||
|
||||
ui.same_line(0.0);
|
||||
if ui.button(im_str!("Flags"), [0.0, 0.0]) {
|
||||
ui.same_line();
|
||||
if ui.button("Flags") {
|
||||
self.flags_visible = !self.flags_visible;
|
||||
}
|
||||
|
||||
#[cfg(feature = "scripting-lua")]
|
||||
{
|
||||
ui.same_line(0.0);
|
||||
if ui.button(im_str!("Reload Lua Scripts"), [0.0, 0.0]) {
|
||||
if let Err(err) = state.lua.reload_scripts(ctx) {
|
||||
log::error!("Error reloading scripts: {:?}", err);
|
||||
self.error = Some(ImString::new(err.to_string()));
|
||||
}
|
||||
{
|
||||
ui.same_line();
|
||||
if ui.button("Reload Lua Scripts") {
|
||||
if let Err(err) = state.lua.reload_scripts(ctx) {
|
||||
log::error!("Error reloading scripts: {:?}", err);
|
||||
self.error = Some(ImString::new(err.to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if game_scene.player2.cond.alive() {
|
||||
if ui.button(im_str!("Drop Player 2"), [0.0, 0.0]) {
|
||||
if ui.button("Drop Player 2") {
|
||||
game_scene.drop_player2();
|
||||
}
|
||||
} else if ui.button(im_str!("Add Player 2"), [0.0, 0.0]) {
|
||||
} else if ui.button("Add Player 2") {
|
||||
game_scene.add_player2();
|
||||
}
|
||||
ui.same_line(0.0);
|
||||
ui.same_line();
|
||||
|
||||
if ui.button(im_str!("NPC Inspector"), [0.0, 0.0]) {
|
||||
if ui.button("NPC Inspector") {
|
||||
self.npc_inspector_visible = !self.npc_inspector_visible;
|
||||
}
|
||||
});
|
||||
|
||||
if self.map_selector_visible {
|
||||
Window::new(im_str!("Map selector"))
|
||||
Window::new("Map selector")
|
||||
.resizable(false)
|
||||
.position([80.0, 80.0], Condition::Appearing)
|
||||
.size([240.0, 280.0], Condition::Appearing)
|
||||
|
@ -157,17 +160,18 @@ impl LiveDebugger {
|
|||
self.stages.push(ImString::new(s.name.to_owned()));
|
||||
}
|
||||
|
||||
self.selected_stage = match state.stages.iter().find_position(|s| s.name == game_scene.stage.data.name) {
|
||||
Some((pos, _)) => { pos as i32 }
|
||||
_ => { -1 }
|
||||
};
|
||||
self.selected_stage =
|
||||
match state.stages.iter().find_position(|s| s.name == game_scene.stage.data.name) {
|
||||
Some((pos, _)) => pos as i32,
|
||||
_ => -1,
|
||||
};
|
||||
}
|
||||
let stages: Vec<&ImStr> = self.stages.iter().map(|e| e.as_ref()).collect();
|
||||
|
||||
ui.push_item_width(-1.0);
|
||||
ui.list_box(im_str!(""), &mut self.selected_stage, &stages, 10);
|
||||
ui.list_box("", &mut self.selected_stage, &stages, 10);
|
||||
|
||||
if ui.button(im_str!("Load"), [0.0, 0.0]) {
|
||||
if ui.button("Load") {
|
||||
match GameScene::new(state, ctx, self.selected_stage as usize) {
|
||||
Ok(mut scene) => {
|
||||
let tile_size = scene.stage.map.tile_size.as_int() * 0x200;
|
||||
|
@ -204,7 +208,7 @@ impl LiveDebugger {
|
|||
}
|
||||
|
||||
if self.events_visible {
|
||||
Window::new(im_str!("TSC Scripts"))
|
||||
Window::new("TSC Scripts")
|
||||
.resizable(false)
|
||||
.position([80.0, 80.0], Condition::Appearing)
|
||||
.size([300.0, 320.0], Condition::Appearing)
|
||||
|
@ -236,13 +240,19 @@ impl LiveDebugger {
|
|||
}
|
||||
let events: Vec<&ImStr> = self.events.iter().map(|e| e.as_ref()).collect();
|
||||
|
||||
ui.text_wrapped(&ImString::new(format!("TextScript execution state: {:?}", state.textscript_vm.state)));
|
||||
ui.text_wrapped(&ImString::new(format!("CreditScript execution state: {:?}", state.creditscript_vm.state)));
|
||||
ui.text_wrapped(&ImString::new(format!(
|
||||
"TextScript execution state: {:?}",
|
||||
state.textscript_vm.state
|
||||
)));
|
||||
ui.text_wrapped(&ImString::new(format!(
|
||||
"CreditScript execution state: {:?}",
|
||||
state.creditscript_vm.state
|
||||
)));
|
||||
|
||||
ui.push_item_width(-1.0);
|
||||
ui.list_box(im_str!(""), &mut self.selected_event, &events, 10);
|
||||
ui.list_box("", &mut self.selected_event, &events, 10);
|
||||
|
||||
if ui.button(im_str!("Execute"), [0.0, 0.0]) {
|
||||
if ui.button("Execute") {
|
||||
assert_eq!(self.event_ids.len(), self.events.len());
|
||||
|
||||
if let Some((_, event_num)) = self.event_ids.get(self.selected_event as usize) {
|
||||
|
@ -252,8 +262,8 @@ impl LiveDebugger {
|
|||
}
|
||||
}
|
||||
|
||||
ui.same_line(0.0);
|
||||
if ui.button(im_str!("Decompile"), [0.0, 0.0]) {
|
||||
ui.same_line();
|
||||
if ui.button("Decompile") {
|
||||
if let Some((stype, event_num)) = self.event_ids.get(self.selected_event as usize) {
|
||||
let id = ((*stype as u32) << 16) | (*event_num as u32);
|
||||
if !self.text_windows.iter().any(|(e, _, _)| *e == id) {
|
||||
|
@ -270,11 +280,14 @@ impl LiveDebugger {
|
|||
self.text_windows.push((
|
||||
id,
|
||||
ImString::new(format!("Decompiled event: #{:04}", *event_num)),
|
||||
ImString::new(code)
|
||||
ImString::new(code),
|
||||
));
|
||||
}
|
||||
Err(e) => {
|
||||
self.error = Some(ImString::new(format!("Error decompiling TextScript #{:04}: {}", *event_num, e)));
|
||||
self.error = Some(ImString::new(format!(
|
||||
"Error decompiling TextScript #{:04}: {}",
|
||||
*event_num, e
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -284,55 +297,57 @@ impl LiveDebugger {
|
|||
}
|
||||
|
||||
if self.flags_visible {
|
||||
Window::new(im_str!("Flags"))
|
||||
Window::new("Flags")
|
||||
.position([80.0, 80.0], Condition::FirstUseEver)
|
||||
.size([280.0, 300.0], Condition::FirstUseEver)
|
||||
.build(ui, || {
|
||||
if CollapsingHeader::new(im_str!("Control flags")).default_open(false).build(&ui) {
|
||||
ui.checkbox_flags(im_str!("Tick world"), &mut state.control_flags.0, 1);
|
||||
ui.checkbox_flags(im_str!("Control enabled"), &mut state.control_flags.0, 2);
|
||||
ui.checkbox_flags(im_str!("Interactions disabled"), &mut state.control_flags.0, 4);
|
||||
ui.checkbox_flags(im_str!("Credits running"), &mut state.control_flags.0, 8);
|
||||
if CollapsingHeader::new("Control flags").default_open(false).build(&ui) {
|
||||
ui.checkbox_flags("Tick world", &mut state.control_flags.0, 1);
|
||||
ui.checkbox_flags("Control enabled", &mut state.control_flags.0, 2);
|
||||
ui.checkbox_flags("Interactions disabled", &mut state.control_flags.0, 4);
|
||||
ui.checkbox_flags("Credits running", &mut state.control_flags.0, 8);
|
||||
ui.separator();
|
||||
ui.checkbox_flags(im_str!("[Internal] Windy level"), &mut state.control_flags.0, 15);
|
||||
ui.checkbox_flags("[Internal] Windy level", &mut state.control_flags.0, 15);
|
||||
}
|
||||
|
||||
if CollapsingHeader::new(im_str!("Player condition flags")).default_open(false).build(&ui) {
|
||||
if CollapsingHeader::new("Player condition flags").default_open(false).build(&ui) {
|
||||
cond_flags(&ui, &mut game_scene.player1.cond);
|
||||
}
|
||||
|
||||
if CollapsingHeader::new(im_str!("Player equipment")).default_open(false).build(&ui) {
|
||||
ui.checkbox_flags(im_str!("Booster 0.8"), &mut game_scene.player1.equip.0, 1);
|
||||
ui.checkbox_flags(im_str!("Map System"), &mut game_scene.player1.equip.0, 2);
|
||||
ui.checkbox_flags(im_str!("Arms Barrier"), &mut game_scene.player1.equip.0, 4);
|
||||
ui.checkbox_flags(im_str!("Turbocharge"), &mut game_scene.player1.equip.0, 8);
|
||||
ui.checkbox_flags(im_str!("Air Tank"), &mut game_scene.player1.equip.0, 16);
|
||||
ui.checkbox_flags(im_str!("Booster 2.0"), &mut game_scene.player1.equip.0, 32);
|
||||
ui.checkbox_flags(im_str!("Mimiga Mask"), &mut game_scene.player1.equip.0, 64);
|
||||
ui.checkbox_flags(im_str!("Whimsical Star"), &mut game_scene.player1.equip.0, 128);
|
||||
ui.checkbox_flags(im_str!("Nikumaru Counter"), &mut game_scene.player1.equip.0, 256);
|
||||
if CollapsingHeader::new("Player equipment").default_open(false).build(&ui) {
|
||||
ui.checkbox_flags("Booster 0.8", &mut game_scene.player1.equip.0, 1);
|
||||
ui.checkbox_flags("Map System", &mut game_scene.player1.equip.0, 2);
|
||||
ui.checkbox_flags("Arms Barrier", &mut game_scene.player1.equip.0, 4);
|
||||
ui.checkbox_flags("Turbocharge", &mut game_scene.player1.equip.0, 8);
|
||||
ui.checkbox_flags("Air Tank", &mut game_scene.player1.equip.0, 16);
|
||||
ui.checkbox_flags("Booster 2.0", &mut game_scene.player1.equip.0, 32);
|
||||
ui.checkbox_flags("Mimiga Mask", &mut game_scene.player1.equip.0, 64);
|
||||
ui.checkbox_flags("Whimsical Star", &mut game_scene.player1.equip.0, 128);
|
||||
ui.checkbox_flags("Nikumaru Counter", &mut game_scene.player1.equip.0, 256);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if self.npc_inspector_visible {
|
||||
Window::new(im_str!("NPC Inspector"))
|
||||
Window::new("NPC Inspector")
|
||||
.position([80.0, 80.0], Condition::FirstUseEver)
|
||||
.size([280.0, 300.0], Condition::FirstUseEver)
|
||||
.scrollable(true)
|
||||
.always_vertical_scrollbar(true)
|
||||
.build(ui, || {
|
||||
for npc in game_scene.npc_list.iter_alive() {
|
||||
if CollapsingHeader::new(&ImString::from(format!("id={} type={}", npc.id, npc.npc_type))).default_open(false).build(&ui) {
|
||||
if CollapsingHeader::new(&ImString::from(format!("id={} type={}", npc.id, npc.npc_type)))
|
||||
.default_open(false)
|
||||
.build(&ui)
|
||||
{
|
||||
let mut position = [npc.x as f32 / 512.0, npc.y as f32 / 512.0];
|
||||
ui.input_float2(im_str!("Position:"), &mut position)
|
||||
.build();
|
||||
ui.input_float2("Position:", &mut position).build();
|
||||
|
||||
npc.x = (position[0] * 512.0) as i32;
|
||||
npc.y = (position[1] * 512.0) as i32;
|
||||
|
||||
let content = &ImString::from(
|
||||
format!("\
|
||||
let content = &ImString::from(format!(
|
||||
"\
|
||||
Velocity: ({:.1},{:.1})\n\
|
||||
Vel2/State2: ({:.1},{:.1} / {} {})\n\
|
||||
Animation: frame={}, counter={}\n\
|
||||
|
@ -340,13 +355,24 @@ impl LiveDebugger {
|
|||
Health: {}, Experience drop: {}\n\
|
||||
Event ID: {}, Flag ID: {}\n\
|
||||
Parent: {}, Shock: {}, Size: {}",
|
||||
npc.vel_x as f32 / 512.0, npc.vel_y as f32 / 512.0,
|
||||
npc.vel_x2 as f32 / 512.0, npc.vel_y2 as f32 / 512.0, npc.vel_x2, npc.vel_y2,
|
||||
npc.anim_num, npc.anim_counter,
|
||||
npc.action_num, npc.action_counter, npc.action_counter2,
|
||||
npc.life, npc.exp,
|
||||
npc.event_num, npc.flag_num,
|
||||
npc.parent_id, npc.shock, npc.size
|
||||
npc.vel_x as f32 / 512.0,
|
||||
npc.vel_y as f32 / 512.0,
|
||||
npc.vel_x2 as f32 / 512.0,
|
||||
npc.vel_y2 as f32 / 512.0,
|
||||
npc.vel_x2,
|
||||
npc.vel_y2,
|
||||
npc.anim_num,
|
||||
npc.anim_counter,
|
||||
npc.action_num,
|
||||
npc.action_counter,
|
||||
npc.action_counter2,
|
||||
npc.life,
|
||||
npc.exp,
|
||||
npc.event_num,
|
||||
npc.flag_num,
|
||||
npc.parent_id,
|
||||
npc.shock,
|
||||
npc.size
|
||||
));
|
||||
ui.text_wrapped(content);
|
||||
|
||||
|
@ -378,16 +404,19 @@ impl LiveDebugger {
|
|||
}
|
||||
|
||||
if self.error.is_some() {
|
||||
Window::new(im_str!("Error!"))
|
||||
Window::new("Error!")
|
||||
.resizable(false)
|
||||
.collapsible(false)
|
||||
.position([((state.screen_size.0 - 300.0) / 2.0).floor(), ((state.screen_size.1 - 100.0) / 2.0).floor()], Condition::Appearing)
|
||||
.position(
|
||||
[((state.screen_size.0 - 300.0) / 2.0).floor(), ((state.screen_size.1 - 100.0) / 2.0).floor()],
|
||||
Condition::Appearing,
|
||||
)
|
||||
.size([300.0, 100.0], Condition::Appearing)
|
||||
.build(ui, || {
|
||||
ui.push_item_width(-1.0);
|
||||
ui.text_wrapped(self.error.as_ref().unwrap());
|
||||
|
||||
if ui.button(im_str!("OK"), [0.0, 0.0]) {
|
||||
if ui.button("OK") {
|
||||
self.error = None;
|
||||
}
|
||||
});
|
||||
|
@ -398,12 +427,12 @@ impl LiveDebugger {
|
|||
}
|
||||
|
||||
fn cond_flags(ui: &imgui::Ui, cond: &mut crate::common::Condition) {
|
||||
ui.checkbox_flags(im_str!("Interacted"), &mut cond.0, 1);
|
||||
ui.checkbox_flags(im_str!("Hidden"), &mut cond.0, 2);
|
||||
ui.checkbox_flags(im_str!("Fallen"), &mut cond.0, 4);
|
||||
ui.checkbox_flags(im_str!("Built-in NPC destroy handler"), &mut cond.0, 8);
|
||||
ui.checkbox_flags(im_str!("Damage first boss NPC"), &mut cond.0, 16);
|
||||
ui.checkbox_flags(im_str!("Increased acceleration"), &mut cond.0, 32);
|
||||
ui.checkbox_flags(im_str!("Unknown (0x40)"), &mut cond.0, 64);
|
||||
ui.checkbox_flags(im_str!("Alive"), &mut cond.0, 128);
|
||||
ui.checkbox_flags("Interacted", &mut cond.0, 1);
|
||||
ui.checkbox_flags("Hidden", &mut cond.0, 2);
|
||||
ui.checkbox_flags("Fallen", &mut cond.0, 4);
|
||||
ui.checkbox_flags("Built-in NPC destroy handler", &mut cond.0, 8);
|
||||
ui.checkbox_flags("Damage first boss NPC", &mut cond.0, 16);
|
||||
ui.checkbox_flags("Increased acceleration", &mut cond.0, 32);
|
||||
ui.checkbox_flags("Unknown (0x40)", &mut cond.0, 64);
|
||||
ui.checkbox_flags("Alive", &mut cond.0, 128);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue