0.1.0-2-beta.1.fix.3
This commit is contained in:
@@ -21,6 +21,8 @@ snake = ["dep:game-snake-poc"]
|
||||
[dependencies]
|
||||
engine-v1-common = { path = "../../engines/engine-v1-common" }
|
||||
engine-v1-sdl = { path = "../../engines/engine-v1-sdl" }
|
||||
game-logging-lib = { path = "../../common/game-logging-lib" }
|
||||
tracing.workspace = true
|
||||
game-reflex-poc = { path = "../../games/game-reflex-poc", optional = true }
|
||||
game-snake-poc = { path = "../../games/game-snake-poc", optional = true }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/apps/game-android-entrypoint/src/lib.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -21,7 +21,13 @@ extern "C" fn sdl_main(_argc: core::ffi::c_int, _argv: *mut *mut core::ffi::c_ch
|
||||
|
||||
#[unsafe(export_name = "Java_com_sasedev_games_common_NativeBridge_nativeContractVersion")]
|
||||
extern "C" fn native_contract_version(_environment: *mut core::ffi::c_void, _class: *mut core::ffi::c_void) -> core::ffi::c_int {
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
#[unsafe(export_name = "Java_com_sasedev_games_common_NativeBridge_nativeRequestPlatformBack")]
|
||||
extern "C" fn native_request_platform_back(_environment: *mut core::ffi::c_void, _class: *mut core::ffi::c_void) {
|
||||
engine_v1_sdl::request_platform_back();
|
||||
return;
|
||||
}
|
||||
|
||||
#[cfg(feature = "reflex")]
|
||||
@@ -48,9 +54,15 @@ fn run_game<G>(runtime: &engine_v1_sdl::SdlRuntime, game: &mut G) -> core::ffi::
|
||||
where
|
||||
G: engine_v1_common::EngineGame,
|
||||
{
|
||||
let logging_guard = game_logging_lib::init_console_tracing();
|
||||
match &logging_guard {
|
||||
std::result::Result::Ok(_) => tracing::info!(target: "games::android", "Android tracing initialized"),
|
||||
std::result::Result::Err(error) => eprintln!("Android tracing initialization skipped: {error}"),
|
||||
}
|
||||
match runtime.run(game) {
|
||||
std::result::Result::Ok(()) => return 0,
|
||||
std::result::Result::Err(error) => {
|
||||
tracing::error!(target: "games::android", error = %error, "Android SDL3 runtime failed");
|
||||
eprintln!("Android SDL3 runtime error: {error}");
|
||||
return 1;
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "game-reflex-poc-tauri",
|
||||
"private": true,
|
||||
"version": "0.1.0-2-beta.1.fix.2",
|
||||
"version": "0.1.0-2-beta.1.fix.3",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Reflex POC Tauri",
|
||||
"version": "0.1.0-2-beta.1.fix.2",
|
||||
"version": "0.1.0-2-beta.1.fix.3",
|
||||
"identifier": "com.sasedev.games.reflex.tauri",
|
||||
"build": {
|
||||
"beforeDevCommand": {
|
||||
|
||||
@@ -17,3 +17,6 @@ tracing-subscriber = { workspace = true, features = ["fmt"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
tracing-android.workspace = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/common/game-logging-lib/src/lib.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -10,11 +10,11 @@
|
||||
mod runtime;
|
||||
mod test_support;
|
||||
|
||||
/// Re-export of the console tracing initialization error.
|
||||
/// Re-export of the platform tracing initialization error.
|
||||
pub use self::runtime::LoggingInitError;
|
||||
/// Re-export of the guard keeping the non-blocking tracing writer alive.
|
||||
/// Re-export of the guard keeping platform tracing resources alive.
|
||||
pub use self::runtime::LoggingWorkerGuard;
|
||||
/// Re-export of the standard console tracing initializer.
|
||||
/// Re-export of the platform tracing initializer.
|
||||
pub use self::runtime::init_console_tracing;
|
||||
/// Re-export of the scoped tracing helper intended for tests.
|
||||
pub use self::test_support::with_test_tracing;
|
||||
|
||||
@@ -1,31 +1,50 @@
|
||||
// file: crates/common/game-logging-lib/src/runtime.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
/// Error returned when the process-global tracing subscriber is already configured.
|
||||
/// Error returned when the process-global tracing subscriber cannot be configured.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct LoggingInitError;
|
||||
|
||||
impl std::fmt::Display for LoggingInitError {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
return formatter.write_str("the process-global tracing subscriber is already configured");
|
||||
return formatter.write_str("the process-global tracing subscriber could not be configured");
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for LoggingInitError {}
|
||||
|
||||
/// Guard keeping the non-blocking tracing writer alive for the application lifetime.
|
||||
/// Guard keeping platform tracing resources alive for the application lifetime.
|
||||
pub struct LoggingWorkerGuard {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
_worker_guard: tracing_appender::non_blocking::WorkerGuard,
|
||||
}
|
||||
|
||||
/// Initializes a process-global non-blocking tracing subscriber writing formatted events to standard error.
|
||||
/// Initializes process-global tracing for the current platform.
|
||||
///
|
||||
/// Native desktop/Tauri processes write formatted events to standard error.
|
||||
/// Android processes write directly to logcat through the Android NDK logging API.
|
||||
///
|
||||
/// The returned guard must remain alive for as long as events may still be emitted.
|
||||
pub fn init_console_tracing() -> std::result::Result<LoggingWorkerGuard, LoggingInitError> {
|
||||
let (writer, worker_guard) = tracing_appender::non_blocking(std::io::stderr());
|
||||
let subscriber = tracing_subscriber::fmt().with_target(true).with_writer(writer).finish();
|
||||
if tracing::subscriber::set_global_default(subscriber).is_err() {
|
||||
return std::result::Result::Err(LoggingInitError);
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
let layer = match tracing_android::layer("games.sasedev") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(LoggingInitError),
|
||||
};
|
||||
let subscriber = tracing_subscriber::layer::SubscriberExt::with(tracing_subscriber::registry(), layer);
|
||||
if tracing::subscriber::set_global_default(subscriber).is_err() {
|
||||
return std::result::Result::Err(LoggingInitError);
|
||||
}
|
||||
return std::result::Result::Ok(LoggingWorkerGuard {});
|
||||
}
|
||||
#[cfg(not(target_os = "android"))]
|
||||
{
|
||||
let (writer, worker_guard) = tracing_appender::non_blocking(std::io::stderr());
|
||||
let subscriber = tracing_subscriber::fmt().with_target(true).with_writer(writer).finish();
|
||||
if tracing::subscriber::set_global_default(subscriber).is_err() {
|
||||
return std::result::Result::Err(LoggingInitError);
|
||||
}
|
||||
return std::result::Result::Ok(LoggingWorkerGuard { _worker_guard: worker_guard });
|
||||
}
|
||||
return std::result::Result::Ok(LoggingWorkerGuard { _worker_guard: worker_guard });
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/engines/engine-v1-sdl/src/lib.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -12,3 +12,5 @@ mod unit_tests;
|
||||
|
||||
/// Re-export of the minimal SDL3 runtime used by Desktop POC runners.
|
||||
pub use self::runtime::SdlRuntime;
|
||||
/// Re-export of the platform-native Back request bridge.
|
||||
pub use self::runtime::request_platform_back;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/engines/engine-v1-sdl/src/runtime.rs
|
||||
// version: 11
|
||||
// version: 12
|
||||
|
||||
/// Minimal SDL3 runtime used by Desktop and Android POC runners.
|
||||
pub struct SdlRuntime {
|
||||
@@ -9,6 +9,17 @@ pub struct SdlRuntime {
|
||||
frame_duration: std::time::Duration,
|
||||
}
|
||||
|
||||
static PLATFORM_BACK_REQUESTED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||
|
||||
/// Requests the active SDL runtime to evaluate a platform-native Back action.
|
||||
///
|
||||
/// Platform adapters use this signal when the host operating system does not expose Back
|
||||
/// as a normal SDL keyboard event.
|
||||
pub fn request_platform_back() {
|
||||
PLATFORM_BACK_REQUESTED.store(true, std::sync::atomic::Ordering::Release);
|
||||
return;
|
||||
}
|
||||
|
||||
impl SdlRuntime {
|
||||
/// Creates a minimal SDL3 runtime configuration.
|
||||
#[must_use]
|
||||
@@ -21,10 +32,6 @@ impl SdlRuntime {
|
||||
where
|
||||
G: engine_v1_common::EngineGame,
|
||||
{
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
let _ = sdl3::hint::set(sdl3::hint::names::ANDROID_TRAP_BACK_BUTTON, "1");
|
||||
}
|
||||
let sdl = match sdl3::init() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
|
||||
@@ -47,6 +54,12 @@ impl SdlRuntime {
|
||||
let mut pointer = engine_v1_common::PointerState::inactive();
|
||||
tracing::info!(title = %self.title, width = self.width, height = self.height, "SDL3 runtime started");
|
||||
'running: loop {
|
||||
if take_platform_back_request() {
|
||||
tracing::info!(source = "platform_back", "SDL3 platform Back requested");
|
||||
if quit_requested(game, engine_v1_common::QuitSource::PlatformBack) {
|
||||
break 'running;
|
||||
}
|
||||
}
|
||||
let mut input = engine_v1_common::InputState::none().with_pointer(pointer);
|
||||
for event in events.poll_iter() {
|
||||
match event {
|
||||
@@ -166,6 +179,10 @@ fn render_scene(canvas: &mut sdl3::render::WindowCanvas, scene: engine_v1_common
|
||||
|
||||
const SWIPE_DIRECTION_THRESHOLD: f32 = 0.04;
|
||||
|
||||
fn take_platform_back_request() -> bool {
|
||||
return PLATFORM_BACK_REQUESTED.swap(false, std::sync::atomic::Ordering::AcqRel);
|
||||
}
|
||||
|
||||
fn quit_requested<G>(game: &mut G, source: engine_v1_common::QuitSource) -> bool
|
||||
where
|
||||
G: engine_v1_common::EngineGame,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/engines/engine-v1-sdl/unit_tests/swipe.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
fn pointer(x: f32, y: f32) -> engine_v1_common::PointerState {
|
||||
return engine_v1_common::PointerState::normalized(true, x, y);
|
||||
@@ -48,3 +48,10 @@ fn runtime_respects_game_quit_decision() {
|
||||
assert!(!super::quit_requested(&mut game, engine_v1_common::QuitSource::PlatformBack));
|
||||
assert_eq!(game.requests, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn platform_back_bridge_is_consumed_once() {
|
||||
super::request_platform_back();
|
||||
assert!(super::take_platform_back_request());
|
||||
assert!(!super::take_platform_back_request());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user