Improve editor workflows and thumbnail resilience
This commit is contained in:
parent
b5e561904c
commit
cc1fa6ea3b
28
.github/workflows/ci.yml
vendored
28
.github/workflows/ci.yml
vendored
@ -41,34 +41,22 @@ jobs:
|
||||
run: rustup show
|
||||
|
||||
- name: Check formatting
|
||||
run: cargo fmt --check
|
||||
run: cargo fmt --all --check
|
||||
|
||||
- name: Check workspace
|
||||
run: cargo check --workspace
|
||||
run: cargo check --workspace --all-targets
|
||||
|
||||
- name: Clippy
|
||||
run: cargo clippy --workspace
|
||||
- name: Clippy workspace
|
||||
run: cargo clippy --workspace --all-targets -- -D warnings
|
||||
|
||||
- name: Clippy foundation crates
|
||||
run: cargo clippy -p game -p shared -- -D warnings
|
||||
|
||||
- name: Test foundation helpers
|
||||
run: cargo test -p game --lib
|
||||
|
||||
- name: Test shared hydration and actor validation
|
||||
run: cargo test -p shared
|
||||
|
||||
- name: Test sim crate
|
||||
run: cargo test -p sim
|
||||
- name: Test workspace
|
||||
run: cargo test --workspace
|
||||
|
||||
- name: Validate level scenes
|
||||
run: cargo validate-levels
|
||||
|
||||
- name: Test scene schema crate
|
||||
run: cargo test -p scene
|
||||
|
||||
- name: Check editor (dev)
|
||||
run: cargo check -p editor --features dev
|
||||
- name: Clippy launch feature matrix
|
||||
run: cargo clippy -p editor -p game --bins --features dev,hot-reload -- -D warnings
|
||||
|
||||
- name: Build binaries
|
||||
run: |
|
||||
|
||||
244
.vscode/launch.json
vendored
244
.vscode/launch.json
vendored
@ -4,48 +4,222 @@
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug editor",
|
||||
"preLaunchTask": "build editor (dev fast-link)",
|
||||
"program": "${workspaceFolder}/target/debug/editor",
|
||||
"args": [],
|
||||
"env": {
|
||||
"BEVY_FPS_HDR": "0",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target",
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
|
||||
},
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug game",
|
||||
"preLaunchTask": "build game (dev fast-link)",
|
||||
"program": "${workspaceFolder}/target/debug/game",
|
||||
"args": [],
|
||||
"env": {
|
||||
"BEVY_FPS_HDR": "0",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target",
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
|
||||
},
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Run editor (release)",
|
||||
"name": "Editor: Debug",
|
||||
"cargo": {
|
||||
"args": ["build", "--release", "-p", "editor"],
|
||||
"filter": { "name": "editor", "kind": "bin" }
|
||||
"args": ["build", "-p", "editor", "--bin", "editor", "--features", "dev"],
|
||||
"filter": { "name": "editor", "kind": "bin" },
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"args": [],
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
|
||||
},
|
||||
"cwd": "${workspaceFolder}",
|
||||
"terminal": "integrated",
|
||||
"sourceLanguages": ["rust"],
|
||||
"gracefulShutdown": "SIGINT"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Editor: GPU validation",
|
||||
"cargo": {
|
||||
"args": ["build", "-p", "editor", "--bin", "editor", "--features", "dev"],
|
||||
"filter": { "name": "editor", "kind": "bin" },
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"args": [],
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"WGPU_VALIDATION": "1",
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
|
||||
},
|
||||
"cwd": "${workspaceFolder}",
|
||||
"terminal": "integrated",
|
||||
"sourceLanguages": ["rust"],
|
||||
"gracefulShutdown": "SIGINT"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Editor: Hot reload",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"build",
|
||||
"-p",
|
||||
"editor",
|
||||
"--bin",
|
||||
"editor",
|
||||
"--features",
|
||||
"dev,hot-reload"
|
||||
],
|
||||
"filter": { "name": "editor", "kind": "bin" },
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"args": [],
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
|
||||
},
|
||||
"cwd": "${workspaceFolder}",
|
||||
"terminal": "integrated",
|
||||
"sourceLanguages": ["rust"],
|
||||
"gracefulShutdown": "SIGINT"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Editor: SDR fallback",
|
||||
"cargo": {
|
||||
"args": ["build", "-p", "editor", "--bin", "editor", "--features", "dev"],
|
||||
"filter": { "name": "editor", "kind": "bin" },
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"args": [],
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"BEVY_FPS_HDR": "0",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/release/deps:${env:LD_LIBRARY_PATH}"
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
|
||||
},
|
||||
"cwd": "${workspaceFolder}"
|
||||
"cwd": "${workspaceFolder}",
|
||||
"terminal": "integrated",
|
||||
"sourceLanguages": ["rust"],
|
||||
"gracefulShutdown": "SIGINT"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Editor: Release",
|
||||
"cargo": {
|
||||
"args": ["build", "--release", "-p", "editor", "--bin", "editor"],
|
||||
"filter": { "name": "editor", "kind": "bin" },
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"args": [],
|
||||
"env": { "RUST_BACKTRACE": "1", "WGPU_VALIDATION": "0" },
|
||||
"cwd": "${workspaceFolder}",
|
||||
"terminal": "integrated",
|
||||
"sourceLanguages": ["rust"],
|
||||
"gracefulShutdown": "SIGINT"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Game: Debug",
|
||||
"cargo": {
|
||||
"args": ["build", "-p", "game", "--bin", "game", "--features", "dev"],
|
||||
"filter": { "name": "game", "kind": "bin" },
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"args": [],
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
|
||||
},
|
||||
"cwd": "${workspaceFolder}",
|
||||
"terminal": "integrated",
|
||||
"sourceLanguages": ["rust"],
|
||||
"gracefulShutdown": "SIGINT"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Game: GPU validation",
|
||||
"cargo": {
|
||||
"args": ["build", "-p", "game", "--bin", "game", "--features", "dev"],
|
||||
"filter": { "name": "game", "kind": "bin" },
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"args": [],
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"WGPU_VALIDATION": "1",
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
|
||||
},
|
||||
"cwd": "${workspaceFolder}",
|
||||
"terminal": "integrated",
|
||||
"sourceLanguages": ["rust"],
|
||||
"gracefulShutdown": "SIGINT"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Game: Hot reload",
|
||||
"cargo": {
|
||||
"args": [
|
||||
"build",
|
||||
"-p",
|
||||
"game",
|
||||
"--bin",
|
||||
"game",
|
||||
"--features",
|
||||
"dev,hot-reload"
|
||||
],
|
||||
"filter": { "name": "game", "kind": "bin" },
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"args": [],
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
|
||||
},
|
||||
"cwd": "${workspaceFolder}",
|
||||
"terminal": "integrated",
|
||||
"sourceLanguages": ["rust"],
|
||||
"gracefulShutdown": "SIGINT"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Game: SDR fallback",
|
||||
"cargo": {
|
||||
"args": ["build", "-p", "game", "--bin", "game", "--features", "dev"],
|
||||
"filter": { "name": "game", "kind": "bin" },
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"args": [],
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"BEVY_FPS_HDR": "0",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"LD_LIBRARY_PATH": "${workspaceFolder}/target/debug/deps:${env:LD_LIBRARY_PATH}"
|
||||
},
|
||||
"cwd": "${workspaceFolder}",
|
||||
"terminal": "integrated",
|
||||
"sourceLanguages": ["rust"],
|
||||
"gracefulShutdown": "SIGINT"
|
||||
},
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Game: Release",
|
||||
"cargo": {
|
||||
"args": ["build", "--release", "-p", "game", "--bin", "game"],
|
||||
"filter": { "name": "game", "kind": "bin" },
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||
"problemMatcher": "$rustc"
|
||||
},
|
||||
"args": [],
|
||||
"env": { "RUST_BACKTRACE": "1", "WGPU_VALIDATION": "0" },
|
||||
"cwd": "${workspaceFolder}",
|
||||
"terminal": "integrated",
|
||||
"sourceLanguages": ["rust"],
|
||||
"gracefulShutdown": "SIGINT"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
207
.vscode/tasks.json
vendored
207
.vscode/tasks.json
vendored
@ -2,42 +2,61 @@
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "cargo fmt (check)",
|
||||
"label": "cargo fmt (workspace check)",
|
||||
"type": "cargo",
|
||||
"command": "fmt",
|
||||
"args": ["--check"],
|
||||
"args": ["--all", "--check"],
|
||||
"problemMatcher": [],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "cargo check (workspace)",
|
||||
"label": "cargo check (workspace all targets)",
|
||||
"type": "cargo",
|
||||
"command": "check",
|
||||
"args": ["--workspace"],
|
||||
"args": ["--workspace", "--all-targets"],
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "cargo clippy (workspace)",
|
||||
"label": "cargo clippy (workspace strict)",
|
||||
"type": "cargo",
|
||||
"command": "clippy",
|
||||
"args": ["--workspace"],
|
||||
"args": ["--workspace", "--all-targets", "--", "-D", "warnings"],
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "cargo clippy (foundation strict)",
|
||||
"type": "cargo",
|
||||
"command": "clippy",
|
||||
"args": ["-p", "game", "-p", "shared", "--", "-D", "warnings"],
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "cargo test (foundation)",
|
||||
"label": "cargo test (workspace)",
|
||||
"type": "cargo",
|
||||
"command": "test",
|
||||
"args": ["-p", "game", "--lib"],
|
||||
"args": ["--workspace"],
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "test"
|
||||
},
|
||||
{
|
||||
"label": "cargo clippy (launch feature matrix)",
|
||||
"type": "cargo",
|
||||
"command": "clippy",
|
||||
"args": [
|
||||
"-p",
|
||||
"editor",
|
||||
"-p",
|
||||
"game",
|
||||
"--bins",
|
||||
"--features",
|
||||
"dev,hot-reload",
|
||||
"--",
|
||||
"-D",
|
||||
"warnings"
|
||||
],
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "validate level scenes",
|
||||
"type": "cargo",
|
||||
"command": "validate-levels",
|
||||
"args": [],
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "test"
|
||||
},
|
||||
@ -45,7 +64,7 @@
|
||||
"label": "build game (debug)",
|
||||
"type": "cargo",
|
||||
"command": "build",
|
||||
"args": ["-p", "game"],
|
||||
"args": ["-p", "game", "--bin", "game"],
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
},
|
||||
@ -53,47 +72,50 @@
|
||||
"label": "build editor (debug)",
|
||||
"type": "cargo",
|
||||
"command": "build",
|
||||
"args": ["-p", "editor"],
|
||||
"args": ["-p", "editor", "--bin", "editor"],
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": { "kind": "build", "isDefault": true }
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "build editor (dev fast-link)",
|
||||
"type": "cargo",
|
||||
"command": "build",
|
||||
"args": ["-p", "editor", "--features", "dev"],
|
||||
"args": ["-p", "editor", "--bin", "editor", "--features", "dev"],
|
||||
"options": {
|
||||
"env": {
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||
},
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
"group": { "kind": "build", "isDefault": true }
|
||||
},
|
||||
{
|
||||
"label": "build game (dev fast-link)",
|
||||
"type": "cargo",
|
||||
"command": "build",
|
||||
"args": ["-p", "game", "--features", "dev"],
|
||||
"args": ["-p", "game", "--bin", "game", "--features", "dev"],
|
||||
"options": {
|
||||
"env": {
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||
},
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "clean build editor (dev)",
|
||||
"type": "shell",
|
||||
"command": "cargo clean -p editor && cargo build -p editor --features dev",
|
||||
"label": "clean dev-link crates",
|
||||
"type": "cargo",
|
||||
"command": "clean",
|
||||
"args": ["-p", "editor", "-p", "game", "-p", "game_hot", "-p", "shared"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||
},
|
||||
"problemMatcher": ["$rustc"],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "clean build editor (dev)",
|
||||
"dependsOrder": "sequence",
|
||||
"dependsOn": ["clean dev-link crates", "build editor (dev fast-link)"],
|
||||
"problemMatcher": [],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
@ -102,9 +124,7 @@
|
||||
"command": "cargo clean-target",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"group": "build"
|
||||
@ -115,9 +135,7 @@
|
||||
"command": "cargo clean-target --apply",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"group": "build"
|
||||
@ -128,9 +146,7 @@
|
||||
"command": "cargo clean-target --include-artifacts --days 3 --apply",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"group": "build"
|
||||
@ -139,10 +155,11 @@
|
||||
"label": "run editor (dev fast-link)",
|
||||
"type": "cargo",
|
||||
"command": "run",
|
||||
"args": ["-p", "editor", "--features", "dev"],
|
||||
"args": ["-p", "editor", "--bin", "editor", "--features", "dev"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"BEVY_FPS_HDR": "0",
|
||||
"RUST_BACKTRACE": "1",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
@ -154,9 +171,83 @@
|
||||
"label": "run game (dev fast-link)",
|
||||
"type": "cargo",
|
||||
"command": "run",
|
||||
"args": ["-p", "game", "--features", "dev"],
|
||||
"args": ["-p", "game", "--bin", "game", "--features", "dev"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
},
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "run editor (hot reload)",
|
||||
"type": "cargo",
|
||||
"command": "run",
|
||||
"args": [
|
||||
"-p",
|
||||
"editor",
|
||||
"--bin",
|
||||
"editor",
|
||||
"--features",
|
||||
"dev,hot-reload"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
},
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "run game (hot reload)",
|
||||
"type": "cargo",
|
||||
"command": "run",
|
||||
"args": ["-p", "game", "--bin", "game", "--features", "dev,hot-reload"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
},
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "run editor (SDR fallback)",
|
||||
"type": "cargo",
|
||||
"command": "run",
|
||||
"args": ["-p", "editor", "--bin", "editor", "--features", "dev"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"BEVY_FPS_HDR": "0",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
},
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build"
|
||||
},
|
||||
{
|
||||
"label": "run game (SDR fallback)",
|
||||
"type": "cargo",
|
||||
"command": "run",
|
||||
"args": ["-p", "game", "--bin", "game", "--features", "dev"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"RUST_BACKTRACE": "1",
|
||||
"BEVY_FPS_HDR": "0",
|
||||
"WGPU_VALIDATION": "0",
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
@ -171,28 +262,28 @@
|
||||
"command": "cargo watch -w crates/game_hot -w crates/sim -x \"build -p game_hot --features dylib\"",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}",
|
||||
"env": {
|
||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||
}
|
||||
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||
},
|
||||
"problemMatcher": ["$rustc"],
|
||||
"group": "build",
|
||||
"isBackground": true
|
||||
"isBackground": true,
|
||||
"detail": "Requires cargo-watch: cargo install cargo-watch --locked"
|
||||
},
|
||||
{
|
||||
"label": "verify foundation",
|
||||
"label": "verify workspace",
|
||||
"dependsOrder": "sequence",
|
||||
"dependsOn": [
|
||||
"cargo fmt (check)",
|
||||
"cargo check (workspace)",
|
||||
"cargo clippy (workspace)",
|
||||
"cargo clippy (foundation strict)",
|
||||
"cargo test (foundation)",
|
||||
"cargo fmt (workspace check)",
|
||||
"cargo check (workspace all targets)",
|
||||
"cargo clippy (workspace strict)",
|
||||
"cargo test (workspace)",
|
||||
"cargo clippy (launch feature matrix)",
|
||||
"validate level scenes",
|
||||
"build game (debug)",
|
||||
"build editor (debug)"
|
||||
],
|
||||
"problemMatcher": [],
|
||||
"group": { "kind": "build", "isDefault": true }
|
||||
"group": "build"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
22
README.md
22
README.md
@ -21,12 +21,12 @@ native Bevy scene save/load, and BRP support for external tooling.
|
||||
|
||||
```bash
|
||||
# Check everything
|
||||
cargo fmt --check
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace
|
||||
cargo clippy -p game -p shared -p protocol -p sim -- -D warnings
|
||||
cargo test -p game --lib
|
||||
cargo test -p sim
|
||||
cargo fmt --all --check
|
||||
cargo check --workspace --all-targets
|
||||
cargo clippy --workspace --all-targets -- -D warnings
|
||||
cargo clippy -p editor -p game --bins --features dev,hot-reload -- -D warnings
|
||||
cargo test --workspace
|
||||
cargo validate-levels
|
||||
|
||||
# Runtime game
|
||||
cargo run -p game
|
||||
@ -53,7 +53,7 @@ cargo watch -w crates/game_hot -w crates/sim -x "build -p game_hot --features dy
|
||||
cargo run -p editor --features dev,hot-reload
|
||||
```
|
||||
|
||||
Or use the VS Code task **watch game_hot (hot reload)** alongside **run editor (dev fast-link)** (enable the `hot-reload` feature on the editor run task when using dylib iteration).
|
||||
Or use the VS Code task **watch game_hot (hot reload)** alongside **run editor (hot reload)**, or choose **Editor: Hot reload** in Run and Debug. The watcher task requires `cargo-watch` (`cargo install cargo-watch --locked`).
|
||||
|
||||
| Input | Action |
|
||||
|-------|--------|
|
||||
@ -90,8 +90,8 @@ deep-stale variants.
|
||||
- The native game/editor windows force an opaque Wayland surface and opaque camera clears to avoid compositor alpha issues on mixed HDR/SDR desktops.
|
||||
- If the window maps but appears transparent on Hyprland or another Wayland compositor, launch with `BEVY_FPS_HDR=0` to force the SDR camera path while debugging monitor/compositor behavior.
|
||||
- Bevy 0.19 removed the prior local `bevy_render` swapchain-timeout patch; launch troubleshooting should start from current wgpu/driver/compositor logs.
|
||||
- Debug launch configs and run tasks set `WGPU_VALIDATION=0` to quiet the known wgpu/Vulkan validation-layer warning `VUID-StandaloneSpirv-MemorySemantics-10871`. This only disables the Vulkan validation layer for those launches; Rust panics and application errors still surface normally.
|
||||
- If **CodeLLDB / mold** fails with hundreds of `undefined symbol` linker errors, the incremental `target/` cache is stale. Run the VS Code task **clean build editor (dev)** or `cargo clean -p editor && cargo build -p editor --features dev`, then launch **Debug editor** again. Use `cargo run -p editor --features dev` from the terminal if you need `libbevy_dylib` on `LD_LIBRARY_PATH` automatically.
|
||||
- Normal Debug and run configurations preserve project HDR and set `WGPU_VALIDATION=0` to suppress known Bevy/Solari Vulkan memory-model VUID noise on this stack. Use **GPU validation** when actively debugging renderer work; it forces `WGPU_VALIDATION=1` and may report those known upstream/driver messages. Use **SDR fallback** for compositor/HDR mapping failures; it additionally sets `BEVY_FPS_HDR=0`.
|
||||
- If **CodeLLDB / mold** fails with hundreds of `undefined symbol` linker errors, the incremental `target/` cache is stale. Run the VS Code task **clean build editor (dev)** or `cargo clean -p editor -p game -p game_hot -p shared && cargo build -p editor --bin editor --features dev`, then launch **Editor: Debug** again. Use `cargo run -p editor --features dev` from the terminal if you need `libbevy_dylib` on `LD_LIBRARY_PATH` automatically.
|
||||
|
||||
## Editor Controls
|
||||
|
||||
@ -238,8 +238,8 @@ The `.vscode/` folder is preconfigured:
|
||||
- `extensions.json` recommends rust-analyzer, Even Better TOML, CodeLLDB, crates, and Error Lens.
|
||||
- `settings.json` runs `clippy` on save, enables proc-macro/build-script support, formats on save,
|
||||
and excludes `target/` from search/watch.
|
||||
- `tasks.json` provides workspace check/clippy plus game/editor build/run tasks.
|
||||
- `launch.json` provides CodeLLDB launch configs for the editor and game.
|
||||
- `tasks.json` mirrors the full workspace formatting, all-target check, strict Clippy, test, level-validation, build/run, hot-reload, and target-cleanup workflows. **build editor (dev fast-link)** is the default build task.
|
||||
- `launch.json` uses CodeLLDB Cargo artifact filtering for editor/game Debug, GPU-validation, hot-reload, SDR fallback, and Release configurations. Normal launches keep HDR enabled while quieting known Vulkan validation noise; dynamic-link launches set the required `LD_LIBRARY_PATH` automatically.
|
||||
- `.github/workflows/ci.yml` mirrors local formatting, check, clippy, test, and binary build verification.
|
||||
|
||||
## Architecture Decisions
|
||||
|
||||
@ -6,7 +6,7 @@ use bevy::prelude::*;
|
||||
use bevy_egui::{egui, EguiPrimaryContextPass, EguiTextureHandle, EguiUserTextures};
|
||||
use egui_phosphor_icons::icons;
|
||||
|
||||
use super::sources::gltf::gltf_base_color_texture_path;
|
||||
use super::sources::gltf::{gltf_base_color_texture_path, validate_gltf_dependencies};
|
||||
use super::studio::{model_file_exists, ThumbnailStudio};
|
||||
use super::ThumbnailJobSource;
|
||||
use crate::assets::{
|
||||
@ -100,13 +100,12 @@ impl AssetThumbnailCache {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(texture_path) = gltf_base_color_texture_path(&model_path) {
|
||||
self.request_texture(key, texture_path, asset_server);
|
||||
if !self.model_source_ready(&key, &model_path) {
|
||||
return;
|
||||
}
|
||||
|
||||
if !model_file_exists(&model_path) {
|
||||
self.mark_studio_failed(&key, "file not found", false);
|
||||
if let Some(texture_path) = gltf_base_color_texture_path(&model_path) {
|
||||
self.request_texture(key, texture_path, asset_server);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -130,8 +129,7 @@ impl AssetThumbnailCache {
|
||||
{
|
||||
return;
|
||||
}
|
||||
if !model_file_exists(&model_path) {
|
||||
self.mark_studio_failed(&key, "file not found", false);
|
||||
if !self.model_source_ready(&key, &model_path) {
|
||||
return;
|
||||
}
|
||||
if studio.enqueue_source(
|
||||
@ -160,8 +158,7 @@ impl AssetThumbnailCache {
|
||||
{
|
||||
return;
|
||||
}
|
||||
if !model_file_exists(&model_path) {
|
||||
self.mark_studio_failed(&key, "file not found", false);
|
||||
if !self.model_source_ready(&key, &model_path) {
|
||||
return;
|
||||
}
|
||||
if studio.enqueue_source(
|
||||
@ -206,6 +203,18 @@ impl AssetThumbnailCache {
|
||||
}
|
||||
}
|
||||
|
||||
fn model_source_ready(&mut self, key: &str, model_path: &str) -> bool {
|
||||
if !model_file_exists(model_path) {
|
||||
self.mark_studio_failed(key, "file not found", false);
|
||||
return false;
|
||||
}
|
||||
if let Err(reason) = validate_gltf_dependencies(model_path) {
|
||||
self.mark_studio_failed(key, &reason, false);
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub(crate) fn complete_studio_thumbnail(
|
||||
&mut self,
|
||||
key: &str,
|
||||
|
||||
@ -29,6 +29,41 @@ pub fn gltf_base_color_texture_path(model_asset_path: &str) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Verifies local external buffers and images before Bevy starts an async glTF load.
|
||||
pub fn validate_gltf_dependencies(model_asset_path: &str) -> Result<(), String> {
|
||||
let model_path = Path::new(model_asset_path);
|
||||
if !is_gltf_path(model_path) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let gltf = gltf::Gltf::open(model_path).map_err(|error| format!("invalid glTF: {error}"))?;
|
||||
let mut uris = Vec::new();
|
||||
for buffer in gltf.buffers() {
|
||||
if let gltf::buffer::Source::Uri(uri) = buffer.source() {
|
||||
uris.push(uri);
|
||||
}
|
||||
}
|
||||
for image in gltf.images() {
|
||||
if let gltf::image::Source::Uri { uri, .. } = image.source() {
|
||||
uris.push(uri);
|
||||
}
|
||||
}
|
||||
|
||||
let model_dir = model_path.parent().unwrap_or_else(|| Path::new(""));
|
||||
for uri in uris {
|
||||
if uri.starts_with("data:") || uri.contains("://") {
|
||||
continue;
|
||||
}
|
||||
let dependency = model_dir.join(uri);
|
||||
if !dependency.is_file() {
|
||||
let display = normalize_asset_path(&dependency)
|
||||
.unwrap_or_else(|| dependency.to_string_lossy().replace('\\', "/"));
|
||||
return Err(format!("missing dependency: {display}"));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct GltfThumbnailSource;
|
||||
|
||||
fn is_gltf_path(path: &Path) -> bool {
|
||||
@ -61,7 +96,9 @@ fn normalize_asset_path(path: &Path) -> Option<String> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
#[test]
|
||||
fn normalize_asset_path_keeps_assets_prefix() {
|
||||
@ -79,4 +116,25 @@ mod tests {
|
||||
Some("assets/models/textures/chair_albedo.png".into())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dependency_validation_reports_missing_external_buffer() {
|
||||
let nonce = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos();
|
||||
let directory = std::env::temp_dir().join(format!("blacksite-gltf-{nonce}"));
|
||||
fs::create_dir_all(&directory).unwrap();
|
||||
let model = directory.join("missing-buffer.gltf");
|
||||
fs::write(
|
||||
&model,
|
||||
r#"{"asset":{"version":"2.0"},"buffers":[{"uri":"missing.bin","byteLength":4}]}"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let error = validate_gltf_dependencies(model.to_str().unwrap()).unwrap_err();
|
||||
assert!(error.contains("missing.bin"));
|
||||
|
||||
fs::remove_dir_all(directory).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,6 +315,9 @@ fn process_thumbnail_studio(
|
||||
ThumbnailStudioLayer,
|
||||
RenderLayers::layer(THUMBNAIL_LAYER),
|
||||
Transform::default(),
|
||||
Visibility::Visible,
|
||||
InheritedVisibility::default(),
|
||||
ViewVisibility::default(),
|
||||
))
|
||||
.id();
|
||||
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
//! Runtime game crate: FPS player, rendering, and starter world.
|
||||
#![allow(clippy::type_complexity)]
|
||||
#![cfg_attr(
|
||||
feature = "hot-reload",
|
||||
allow(
|
||||
clippy::too_many_arguments,
|
||||
reason = "hot-lib-reloader wrappers preserve Bevy system signatures and macro spans"
|
||||
)
|
||||
)]
|
||||
|
||||
pub mod editor_ext;
|
||||
pub mod launch;
|
||||
@ -62,8 +69,8 @@ mod systems {
|
||||
mod hot {
|
||||
use avian3d::prelude::*;
|
||||
use bevy::input::mouse::AccumulatedMouseMotion;
|
||||
use bevy::light::atmosphere::ScatteringMedium;
|
||||
use bevy::light::CascadeShadowConfig;
|
||||
use bevy::pbr::ScatteringMedium;
|
||||
use bevy::prelude::*;
|
||||
use bevy::time::Fixed;
|
||||
use bevy::window::{CursorOptions, PrimaryWindow};
|
||||
|
||||
@ -41,7 +41,7 @@ Docs for the in-process egui editor (`crates/editor/`). Update this index when a
|
||||
- **Dedicated egui `Camera2d`** at full window — never attach `PrimaryEguiContext` to a viewport-cropped 3D camera (NaN layout panic).
|
||||
- **Unified viewport** uses one render-to-texture target for both the editor fly camera and the possessed player camera so HDR/atmosphere is not broken by sub-viewport cropping.
|
||||
- **PIE:** F8 possess/eject while sim runs; **F6** pauses/resumes simulation in Play; project settings drive shared rendering for the active viewport camera.
|
||||
- **Asset browser** mirrors the on-disk `assets/` directory with project tree, breadcrumb, search/filter/sort, grid/list views, texture/model/material thumbnails, a details pane, and context-aware row/menu actions; narrow docks prioritize content, keep the root panel fixed, switch list view to a compact single-column layout, and hide tree/details panes when they would crowd the content area. The footer stays pinned while only the project tree, asset content, and details panels scroll. **Built-ins** holds spawnable primitives and lights. **Materials** folder scans `assets/materials/*.ron`, renders material thumbnails on a sphere using `MaterialDesc`, and exposes shader-schema-driven parameters/textures in the details editor; **Shaders** holds shader schema RON files. glTF/GLB/FBX rows can expand into a shelf of normalized embedded mesh, material, and texture subassets with independent generated thumbnails. Mesh subassets can be selected, dragged into the viewport, or placed from details/context menus; material subassets render source-material spheres; texture subassets can be applied to the selected actor. Model import settings are staged with **Apply** / **Revert**, asset context menus can regenerate thumbnails, material asset details edit shared `MaterialAsset` fields, and file asset deletion moves sources/generated artifacts into `assets/.trash/`.
|
||||
- **Asset browser** mirrors the on-disk `assets/` directory with project tree, breadcrumb, search/filter/sort, grid/list views, texture/model/material thumbnails, a details pane, and context-aware row/menu actions; narrow docks prioritize content, keep the root panel fixed, switch list view to a compact single-column layout, and hide tree/details panes when they would crowd the content area. The footer stays pinned while only the project tree, asset content, and details panels scroll. **Built-ins** holds spawnable primitives and lights. **Materials** folder scans `assets/materials/*.ron`, renders material thumbnails on a sphere using `MaterialDesc`, and exposes shader-schema-driven parameters/textures in the details editor; **Shaders** holds shader schema RON files. glTF/GLB/FBX rows can expand into a shelf of normalized embedded mesh, material, and texture subassets with independent generated thumbnails. Mesh subassets can be selected, dragged into the viewport, or placed from details/context menus; material subassets render source-material spheres; texture subassets can be applied to the selected actor. Model import settings are staged with **Apply** / **Revert**, asset context menus can regenerate thumbnails, material asset details edit shared `MaterialAsset` fields, and file asset deletion moves sources/generated artifacts into `assets/.trash/`. Before thumbnail loading, glTF sources preflight local external buffers/images and show a stable non-retryable failure state when a dependency is missing instead of repeatedly invoking the asset loader.
|
||||
- **Static mesh renderer** — model drag/drop defaults to `ActorKind::StaticMesh + StaticMeshRenderer` using normalized artifacts under `assets/meshes/generated/`. Renderer slots store imported `EditorAssetRef` mesh/material references, not source FBX/glTF paths. `SceneInstance` placement keeps the legacy `ImportedModel + ModelRef` path for full scene playback.
|
||||
- **Brush authoring** — `ActorKind::Brush + BrushDesc` stores persisted convex blockout faces, validates authored geometry in the inspector and Window → Brush Diagnostics, and hydrates active valid brushes into generated mesh children. See [brushes.md](brushes.md).
|
||||
- **Draw Brush** — `B`, toolbar pencil, or command `brush.draw` enters a floor-polygon draw mode. LMB places snapped points, Backspace removes the last point, Enter locks the outline for height editing, mouse up/down adjusts height, and Enter/LMB creates additive prism brushes through history. Esc/right-click cancels. Simple concave outlines decompose into convex brush parts; self-intersections remain blocked.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user