0.1.0-1-alpha.2-fix.2
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# file: crates/apps/game-reflex-poc-tauri/Cargo.toml
|
||||
# version: 1
|
||||
# version: 3
|
||||
|
||||
[package]
|
||||
name = "game-reflex-poc-tauri"
|
||||
@@ -9,24 +9,24 @@ license.workspace = true
|
||||
repository.workspace = true
|
||||
authors.workspace = true
|
||||
publish.workspace = true
|
||||
build = "build.rs"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
name = "game_reflex_poc_tauri_lib"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
engine-v1-common = { path = "../../engines/engine-v1-common" }
|
||||
engine-v1-platform-api = { path = "../../engines/engine-v1-platform-api" }
|
||||
game-reflex-poc = { path = "../../games/game-reflex-poc" }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
tauri.workspace = true
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
wasm-bindgen.workspace = true
|
||||
[[bin]]
|
||||
name = "game-reflex-poc-tauri"
|
||||
path = "src/main.rs"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build.workspace = true
|
||||
|
||||
[dependencies]
|
||||
engine-v1-platform-api = { path = "../../engines/engine-v1-platform-api" }
|
||||
tauri.workspace = true
|
||||
tauri-plugin-tracing.workspace = true
|
||||
tracing.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/build.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
//! Tauri build script skipped for the WebAssembly library target.
|
||||
//! Native Tauri build script for the Reflex Desktop WebView runner.
|
||||
|
||||
fn main() {
|
||||
let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH");
|
||||
match target_arch {
|
||||
std::result::Result::Ok(value) if value == "wasm32" => return,
|
||||
_ => {},
|
||||
}
|
||||
tauri_build::build();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Default capability for Reflex Tauri POC",
|
||||
"windows": ["main"],
|
||||
"permissions": ["core:default", "tracing:default"]
|
||||
}
|
||||
17
crates/apps/game-reflex-poc-tauri/frontend/index.html
Normal file
17
crates/apps/game-reflex-poc-tauri/frontend/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Reflex POC Tauri</title>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<main id="app">
|
||||
<canvas id="game" aria-label="Reflex POC"></canvas>
|
||||
<output id="score">Score : 0</output>
|
||||
<output id="runtime">Initialisation…</output>
|
||||
</main>
|
||||
<script type="module" src="/ts/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
45
crates/apps/game-reflex-poc-tauri/frontend/style.css
Normal file
45
crates/apps/game-reflex-poc-tauri/frontend/style.css
Normal file
@@ -0,0 +1,45 @@
|
||||
/* file: crates/apps/game-reflex-poc-tauri/frontend/style.css */
|
||||
/* version: 1 */
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: rgb(18 18 24);
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#app {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#game {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
#score,
|
||||
#runtime {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
padding: 6px 8px;
|
||||
border-radius: 4px;
|
||||
background: rgb(0 0 0 / 55%);
|
||||
color: white;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#score {
|
||||
top: 12px;
|
||||
}
|
||||
|
||||
#runtime {
|
||||
bottom: 12px;
|
||||
font-size: 12px;
|
||||
}
|
||||
12
crates/apps/game-reflex-poc-tauri/frontend/ts/bridge.ts
Normal file
12
crates/apps/game-reflex-poc-tauri/frontend/ts/bridge.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/bridge.ts
|
||||
// version: 1
|
||||
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
export async function getRuntimeLabel(): Promise<string> {
|
||||
return await invoke<string>("get_runtime_label");
|
||||
}
|
||||
|
||||
export async function notifyFrontendReady(): Promise<void> {
|
||||
await invoke("frontend_ready");
|
||||
}
|
||||
67
crates/apps/game-reflex-poc-tauri/frontend/ts/game.ts
Normal file
67
crates/apps/game-reflex-poc-tauri/frontend/ts/game.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/game.ts
|
||||
// version: 1
|
||||
|
||||
import init, { ReflexWasmGame } from "../wasm/game_reflex_poc_wasm.js";
|
||||
import { tracingDebug, tracingTrace } from "./logging";
|
||||
|
||||
const FRAME_MS = 16;
|
||||
|
||||
function color(red: number, green: number, blue: number): string {
|
||||
return `rgb(${red} ${green} ${blue})`;
|
||||
}
|
||||
|
||||
function resizeCanvas(canvas: HTMLCanvasElement): void {
|
||||
const ratio = window.devicePixelRatio || 1;
|
||||
const width = Math.max(1, Math.floor(canvas.clientWidth * ratio));
|
||||
const height = Math.max(1, Math.floor(canvas.clientHeight * ratio));
|
||||
if (canvas.width !== width || canvas.height !== height) {
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
function render(game: ReflexWasmGame, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, score: HTMLOutputElement): void {
|
||||
resizeCanvas(canvas);
|
||||
context.fillStyle = color(game.background_red(), game.background_green(), game.background_blue());
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
const count = game.rectangle_count();
|
||||
for (let index = 0; index < count; index += 1) {
|
||||
context.fillStyle = color(game.rectangle_red(index), game.rectangle_green(index), game.rectangle_blue(index));
|
||||
context.fillRect(
|
||||
game.rectangle_x(index) * canvas.width,
|
||||
game.rectangle_y(index) * canvas.height,
|
||||
game.rectangle_width(index) * canvas.width,
|
||||
game.rectangle_height(index) * canvas.height,
|
||||
);
|
||||
}
|
||||
score.value = `Score : ${game.score()}`;
|
||||
}
|
||||
|
||||
export async function startGame(canvas: HTMLCanvasElement, score: HTMLOutputElement): Promise<void> {
|
||||
await init();
|
||||
await tracingDebug("Reflex WASM module initialized");
|
||||
const context = canvas.getContext("2d");
|
||||
if (context === null) {
|
||||
throw new Error("2D canvas context is unavailable");
|
||||
}
|
||||
const game = new ReflexWasmGame();
|
||||
canvas.addEventListener("pointerdown", event => {
|
||||
const bounds = canvas.getBoundingClientRect();
|
||||
const x = (event.clientX - bounds.left) / bounds.width;
|
||||
const y = (event.clientY - bounds.top) / bounds.height;
|
||||
game.pointer_down(x, y);
|
||||
render(game, canvas, context, score);
|
||||
void tracingTrace(`pointerdown x=${x.toFixed(4)} y=${y.toFixed(4)} score=${game.score()}`);
|
||||
});
|
||||
let previous = performance.now();
|
||||
function frame(now: number): void {
|
||||
while (now - previous >= FRAME_MS) {
|
||||
game.tick();
|
||||
previous += FRAME_MS;
|
||||
}
|
||||
render(game, canvas, context, score);
|
||||
window.requestAnimationFrame(frame);
|
||||
}
|
||||
render(game, canvas, context, score);
|
||||
window.requestAnimationFrame(frame);
|
||||
}
|
||||
38
crates/apps/game-reflex-poc-tauri/frontend/ts/logging.ts
Normal file
38
crates/apps/game-reflex-poc-tauri/frontend/ts/logging.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/logging.ts
|
||||
// version: 1
|
||||
|
||||
import { attachConsole, debug, error, info, trace, warn } from "@fltsci/tauri-plugin-tracing";
|
||||
|
||||
let detachRustConsole: (() => void) | null = null;
|
||||
|
||||
export async function initializeTracing(): Promise<void> {
|
||||
detachRustConsole = await attachConsole();
|
||||
await info("Reflex Tauri frontend tracing initialized", "games::tauri::reflex::frontend");
|
||||
}
|
||||
|
||||
export async function tracingTrace(message: string): Promise<void> {
|
||||
await trace(message, "games::tauri::reflex::frontend");
|
||||
}
|
||||
|
||||
export async function tracingDebug(message: string): Promise<void> {
|
||||
await debug(message, "games::tauri::reflex::frontend");
|
||||
}
|
||||
|
||||
export async function tracingInfo(message: string): Promise<void> {
|
||||
await info(message, "games::tauri::reflex::frontend");
|
||||
}
|
||||
|
||||
export async function tracingWarn(message: string): Promise<void> {
|
||||
await warn(message, "games::tauri::reflex::frontend");
|
||||
}
|
||||
|
||||
export async function tracingError(message: string): Promise<void> {
|
||||
await error(message, "games::tauri::reflex::frontend");
|
||||
}
|
||||
|
||||
export function detachTracingConsole(): void {
|
||||
if (detachRustConsole !== null) {
|
||||
detachRustConsole();
|
||||
detachRustConsole = null;
|
||||
}
|
||||
}
|
||||
25
crates/apps/game-reflex-poc-tauri/frontend/ts/main.ts
Normal file
25
crates/apps/game-reflex-poc-tauri/frontend/ts/main.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/frontend/ts/main.ts
|
||||
// version: 1
|
||||
|
||||
import { getRuntimeLabel, notifyFrontendReady } from "./bridge";
|
||||
import { startGame } from "./game";
|
||||
import { initializeTracing, tracingError, tracingInfo } from "./logging";
|
||||
|
||||
async function main(): Promise<void> {
|
||||
await initializeTracing();
|
||||
const canvas = document.querySelector<HTMLCanvasElement>("#game");
|
||||
const score = document.querySelector<HTMLOutputElement>("#score");
|
||||
const runtime = document.querySelector<HTMLOutputElement>("#runtime");
|
||||
if (canvas === null || score === null || runtime === null) {
|
||||
throw new Error("Reflex Tauri frontend DOM is incomplete");
|
||||
}
|
||||
runtime.value = await getRuntimeLabel();
|
||||
await startGame(canvas, score);
|
||||
await notifyFrontendReady();
|
||||
await tracingInfo("Reflex Tauri frontend started");
|
||||
}
|
||||
|
||||
void main().catch(async caughtError => {
|
||||
const message = caughtError instanceof Error ? caughtError.stack ?? caughtError.message : String(caughtError);
|
||||
await tracingError(`Reflex Tauri frontend startup failed: ${message}`);
|
||||
});
|
||||
20
crates/apps/game-reflex-poc-tauri/package.json
Normal file
20
crates/apps/game-reflex-poc-tauri/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "game-reflex-poc-tauri",
|
||||
"private": true,
|
||||
"version": "0.1.0-1-alpha.2.fix.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fltsci/tauri-plugin-tracing": "^0.3",
|
||||
"@tauri-apps/api": "^2.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2.11",
|
||||
"@types/node": "^26.1",
|
||||
"typescript": "^7.0",
|
||||
"vite": "^8.2"
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,19 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/src/lib.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
//! Tauri desktop application facade for the Reflex WebAssembly POC.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
//! WebAssembly adapter for the Reflex POC when hosted by the Tauri variant.
|
||||
mod runtime;
|
||||
mod tauri;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod wasm_runtime;
|
||||
/// Runs the Reflex Tauri desktop application.
|
||||
pub use self::tauri::run;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
/// Re-export of the Reflex WebAssembly runtime adapter.
|
||||
pub use self::wasm_runtime::ReflexWasmGame;
|
||||
/// Records that the Vite/TypeScript frontend reached its ready state.
|
||||
pub(crate) use self::runtime::record_frontend_ready;
|
||||
/// Returns the runtime label exposed by the Tauri bridge.
|
||||
pub(crate) use self::runtime::runtime_label;
|
||||
|
||||
@@ -1,25 +1,20 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/src/main.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
//! Binary entry point for the Reflex Tauri desktop application.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
//! Native Tauri host for the local Reflex WebAssembly POC.
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn main() {
|
||||
let result = tauri::Builder::default().run(tauri::generate_context!());
|
||||
match result {
|
||||
std::result::Result::Ok(()) => {},
|
||||
fn main() -> std::process::ExitCode {
|
||||
let result = game_reflex_poc_tauri_lib::run();
|
||||
return match result {
|
||||
std::result::Result::Ok(()) => std::process::ExitCode::SUCCESS,
|
||||
std::result::Result::Err(error) => {
|
||||
eprintln!("Reflex POC Tauri runner failed: {error}");
|
||||
eprintln!("Reflex Tauri application error: {error}");
|
||||
std::process::ExitCode::FAILURE
|
||||
},
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn main() {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
18
crates/apps/game-reflex-poc-tauri/src/runtime.rs
Normal file
18
crates/apps/game-reflex-poc-tauri/src/runtime.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/src/runtime.rs
|
||||
// version: 1
|
||||
|
||||
/// Stable label for the current Tauri/WASM runtime combination.
|
||||
pub(crate) fn runtime_label() -> &'static str {
|
||||
return "Desktop / TauriWebView / Wasm / KeyboardMouse";
|
||||
}
|
||||
|
||||
/// Records that the frontend completed its startup sequence.
|
||||
pub(crate) fn record_frontend_ready() {
|
||||
tracing::info!(
|
||||
target: "games::tauri::reflex",
|
||||
action = "frontend_ready",
|
||||
runtime = crate::runtime_label(),
|
||||
"Reflex Tauri frontend ready"
|
||||
);
|
||||
return;
|
||||
}
|
||||
39
crates/apps/game-reflex-poc-tauri/src/tauri.rs
Normal file
39
crates/apps/game-reflex-poc-tauri/src/tauri.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/src/tauri.rs
|
||||
// version: 1
|
||||
|
||||
#[tauri::command]
|
||||
fn get_runtime_label() -> String {
|
||||
return crate::runtime_label().to_string();
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn frontend_ready() {
|
||||
crate::record_frontend_ready();
|
||||
return;
|
||||
}
|
||||
|
||||
fn configure_plugins(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tauri::Wry> {
|
||||
let tracing_plugin = tauri_plugin_tracing::Builder::new().build::<tauri::Wry>();
|
||||
return builder.plugin(tracing_plugin);
|
||||
}
|
||||
|
||||
#[allow(clippy::question_mark_used)] // Tauri generates the question-mark operator internally for command dispatch.
|
||||
fn configure_commands(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tauri::Wry> {
|
||||
return builder.invoke_handler(tauri::generate_handler![get_runtime_label, frontend_ready]);
|
||||
}
|
||||
|
||||
/// Runs the Reflex Tauri desktop application.
|
||||
pub fn run() -> std::result::Result<(), String> {
|
||||
tracing::info!(
|
||||
target: "games::tauri::reflex",
|
||||
action = "runtime_start",
|
||||
"Starting Reflex Tauri runtime"
|
||||
);
|
||||
let builder = tauri::Builder::default();
|
||||
let builder = configure_plugins(builder);
|
||||
let builder = configure_commands(builder);
|
||||
return match builder.run(tauri::generate_context!()) {
|
||||
std::result::Result::Ok(()) => std::result::Result::Ok(()),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
|
||||
};
|
||||
}
|
||||
@@ -1,14 +1,24 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Reflex POC Tauri",
|
||||
"version": "0.1.0-1-alpha.2.fix.1",
|
||||
"version": "0.1.0-1-alpha.2.fix.2",
|
||||
"identifier": "com.sasedev.games.reflex.tauri",
|
||||
"build": {
|
||||
"frontendDist": "../../../Tauri/game-reflex-poc/frontend"
|
||||
"beforeDevCommand": {
|
||||
"script": "python3 ../../../scripts/build_reflex_tauri_wasm.py && npm run dev",
|
||||
"cwd": "."
|
||||
},
|
||||
"devUrl": "http://localhost:1432",
|
||||
"beforeBuildCommand": {
|
||||
"script": "python3 ../../../scripts/build_reflex_tauri_wasm.py && npm run build",
|
||||
"cwd": "."
|
||||
},
|
||||
"frontendDist": "../../../builds/sasedev-games/game-reflex-poc-tauri/dist"
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"label": "main",
|
||||
"title": "Reflex POC Tauri",
|
||||
"width": 405,
|
||||
"height": 720,
|
||||
@@ -16,10 +26,11 @@
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' ipc: http://ipc.localhost"
|
||||
"csp": "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' ipc: http://ipc.localhost http://localhost:1432 ws://localhost:1433"
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": false
|
||||
"active": false,
|
||||
"icon": ["icons/icon.png"]
|
||||
}
|
||||
}
|
||||
|
||||
19
crates/apps/game-reflex-poc-tauri/tsconfig.json
Normal file
19
crates/apps/game-reflex-poc-tauri/tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["frontend/**/*.ts", "vite.config.ts"]
|
||||
}
|
||||
36
crates/apps/game-reflex-poc-tauri/vite.config.ts
Normal file
36
crates/apps/game-reflex-poc-tauri/vite.config.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/vite.config.ts
|
||||
// version: 1
|
||||
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { resolve } from "node:path";
|
||||
import { defineConfig, normalizePath } from "vite";
|
||||
|
||||
const appRoot = fileURLToPath(new URL(".", import.meta.url));
|
||||
const frontendRoot = normalizePath(resolve(appRoot, "frontend"));
|
||||
const frontendDist = normalizePath(resolve(appRoot, "../../../builds/sasedev-games/game-reflex-poc-tauri/dist"));
|
||||
const devHost = process.env.TAURI_DEV_HOST;
|
||||
|
||||
export default defineConfig({
|
||||
clearScreen: false,
|
||||
root: frontendRoot,
|
||||
publicDir: false,
|
||||
build: {
|
||||
outDir: frontendDist,
|
||||
emptyOutDir: true,
|
||||
minify: true,
|
||||
sourcemap: false,
|
||||
},
|
||||
server: {
|
||||
port: 1432,
|
||||
strictPort: true,
|
||||
host: devHost || false,
|
||||
ws: {
|
||||
protocol: "ws",
|
||||
host: devHost || "localhost",
|
||||
port: 1433,
|
||||
},
|
||||
watch: {
|
||||
ignored: ["**/src/**"],
|
||||
},
|
||||
},
|
||||
});
|
||||
22
crates/apps/game-reflex-poc-wasm/Cargo.toml
Normal file
22
crates/apps/game-reflex-poc-wasm/Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
# file: crates/apps/game-reflex-poc-wasm/Cargo.toml
|
||||
# version: 1
|
||||
|
||||
[package]
|
||||
name = "game-reflex-poc-wasm"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
authors.workspace = true
|
||||
publish.workspace = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
engine-v1-common = { path = "../../engines/engine-v1-common" }
|
||||
game-reflex-poc = { path = "../../games/game-reflex-poc" }
|
||||
wasm-bindgen.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
13
crates/apps/game-reflex-poc-wasm/src/lib.rs
Normal file
13
crates/apps/game-reflex-poc-wasm/src/lib.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
// file: crates/apps/game-reflex-poc-wasm/src/lib.rs
|
||||
// version: 1
|
||||
|
||||
//! WebAssembly adapter facade for the Reflex POC.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
mod runtime;
|
||||
|
||||
/// Re-export of the Reflex WebAssembly runtime adapter.
|
||||
pub use self::runtime::ReflexWasmGame;
|
||||
@@ -1,7 +1,7 @@
|
||||
// file: crates/apps/game-reflex-poc-tauri/src/wasm_runtime.rs
|
||||
// file: crates/apps/game-reflex-poc-wasm/src/runtime.rs
|
||||
// version: 1
|
||||
|
||||
/// WebAssembly-owned Reflex game state consumed by the local Tauri WebView.
|
||||
/// WebAssembly-owned Reflex game state consumed by the Tauri WebView.
|
||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
pub struct ReflexWasmGame {
|
||||
runner: engine_v1_common::FixedStepRunner,
|
||||
@@ -10,7 +10,7 @@ pub struct ReflexWasmGame {
|
||||
|
||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
impl ReflexWasmGame {
|
||||
/// Creates a fresh Reflex POC session using the same gameplay crate as native Desktop.
|
||||
/// Creates a fresh Reflex POC session using the shared gameplay crate.
|
||||
#[wasm_bindgen::prelude::wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
return Self {
|
||||
@@ -65,7 +65,7 @@ impl ReflexWasmGame {
|
||||
return count;
|
||||
}
|
||||
|
||||
/// Returns one rectangle's normalized left coordinate or `-1.0` if the index is absent.
|
||||
/// Returns one rectangle's normalized left coordinate or `-1.0` if absent.
|
||||
pub fn rectangle_x(&self, index: u32) -> f32 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.rect().x(),
|
||||
@@ -73,7 +73,7 @@ impl ReflexWasmGame {
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's normalized top coordinate or `-1.0` if the index is absent.
|
||||
/// Returns one rectangle's normalized top coordinate or `-1.0` if absent.
|
||||
pub fn rectangle_y(&self, index: u32) -> f32 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.rect().y(),
|
||||
@@ -81,7 +81,7 @@ impl ReflexWasmGame {
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's normalized width or `0.0` if the index is absent.
|
||||
/// Returns one rectangle's normalized width or `0.0` if absent.
|
||||
pub fn rectangle_width(&self, index: u32) -> f32 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.rect().width(),
|
||||
@@ -89,7 +89,7 @@ impl ReflexWasmGame {
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's normalized height or `0.0` if the index is absent.
|
||||
/// Returns one rectangle's normalized height or `0.0` if absent.
|
||||
pub fn rectangle_height(&self, index: u32) -> f32 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.rect().height(),
|
||||
@@ -97,7 +97,7 @@ impl ReflexWasmGame {
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's red channel or zero if the index is absent.
|
||||
/// Returns one rectangle's red channel or zero if absent.
|
||||
pub fn rectangle_red(&self, index: u32) -> u8 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.color().red(),
|
||||
@@ -105,7 +105,7 @@ impl ReflexWasmGame {
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's green channel or zero if the index is absent.
|
||||
/// Returns one rectangle's green channel or zero if absent.
|
||||
pub fn rectangle_green(&self, index: u32) -> u8 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.color().green(),
|
||||
@@ -113,7 +113,7 @@ impl ReflexWasmGame {
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns one rectangle's blue channel or zero if the index is absent.
|
||||
/// Returns one rectangle's blue channel or zero if absent.
|
||||
pub fn rectangle_blue(&self, index: u32) -> u8 {
|
||||
return match self.rectangle(index) {
|
||||
Some(rectangle) => rectangle.color().blue(),
|
||||
Reference in New Issue
Block a user