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
|
run: rustup show
|
||||||
|
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
run: cargo fmt --check
|
run: cargo fmt --all --check
|
||||||
|
|
||||||
- name: Check workspace
|
- name: Check workspace
|
||||||
run: cargo check --workspace
|
run: cargo check --workspace --all-targets
|
||||||
|
|
||||||
- name: Clippy
|
- name: Clippy workspace
|
||||||
run: cargo clippy --workspace
|
run: cargo clippy --workspace --all-targets -- -D warnings
|
||||||
|
|
||||||
- name: Clippy foundation crates
|
- name: Test workspace
|
||||||
run: cargo clippy -p game -p shared -- -D warnings
|
run: cargo test --workspace
|
||||||
|
|
||||||
- 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: Validate level scenes
|
- name: Validate level scenes
|
||||||
run: cargo validate-levels
|
run: cargo validate-levels
|
||||||
|
|
||||||
- name: Test scene schema crate
|
- name: Clippy launch feature matrix
|
||||||
run: cargo test -p scene
|
run: cargo clippy -p editor -p game --bins --features dev,hot-reload -- -D warnings
|
||||||
|
|
||||||
- name: Check editor (dev)
|
|
||||||
run: cargo check -p editor --features dev
|
|
||||||
|
|
||||||
- name: Build binaries
|
- name: Build binaries
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
244
.vscode/launch.json
vendored
244
.vscode/launch.json
vendored
@ -4,48 +4,222 @@
|
|||||||
{
|
{
|
||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug editor",
|
"name": "Editor: Debug",
|
||||||
"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)",
|
|
||||||
"cargo": {
|
"cargo": {
|
||||||
"args": ["build", "--release", "-p", "editor"],
|
"args": ["build", "-p", "editor", "--bin", "editor", "--features", "dev"],
|
||||||
"filter": { "name": "editor", "kind": "bin" }
|
"filter": { "name": "editor", "kind": "bin" },
|
||||||
|
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" },
|
||||||
|
"problemMatcher": "$rustc"
|
||||||
},
|
},
|
||||||
"args": [],
|
"args": [],
|
||||||
"env": {
|
"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",
|
"BEVY_FPS_HDR": "0",
|
||||||
"WGPU_VALIDATION": "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",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"label": "cargo fmt (check)",
|
"label": "cargo fmt (workspace check)",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "fmt",
|
"command": "fmt",
|
||||||
"args": ["--check"],
|
"args": ["--all", "--check"],
|
||||||
"problemMatcher": [],
|
"problemMatcher": [],
|
||||||
"group": "build"
|
"group": "build"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "cargo check (workspace)",
|
"label": "cargo check (workspace all targets)",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "check",
|
"command": "check",
|
||||||
"args": ["--workspace"],
|
"args": ["--workspace", "--all-targets"],
|
||||||
"problemMatcher": ["$rustc"],
|
"problemMatcher": ["$rustc"],
|
||||||
"group": "build"
|
"group": "build"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "cargo clippy (workspace)",
|
"label": "cargo clippy (workspace strict)",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "clippy",
|
"command": "clippy",
|
||||||
"args": ["--workspace"],
|
"args": ["--workspace", "--all-targets", "--", "-D", "warnings"],
|
||||||
"problemMatcher": ["$rustc"],
|
"problemMatcher": ["$rustc"],
|
||||||
"group": "build"
|
"group": "build"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "cargo clippy (foundation strict)",
|
"label": "cargo test (workspace)",
|
||||||
"type": "cargo",
|
|
||||||
"command": "clippy",
|
|
||||||
"args": ["-p", "game", "-p", "shared", "--", "-D", "warnings"],
|
|
||||||
"problemMatcher": ["$rustc"],
|
|
||||||
"group": "build"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "cargo test (foundation)",
|
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "test",
|
"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"],
|
"problemMatcher": ["$rustc"],
|
||||||
"group": "test"
|
"group": "test"
|
||||||
},
|
},
|
||||||
@ -45,7 +64,7 @@
|
|||||||
"label": "build game (debug)",
|
"label": "build game (debug)",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "build",
|
"command": "build",
|
||||||
"args": ["-p", "game"],
|
"args": ["-p", "game", "--bin", "game"],
|
||||||
"problemMatcher": ["$rustc"],
|
"problemMatcher": ["$rustc"],
|
||||||
"group": "build"
|
"group": "build"
|
||||||
},
|
},
|
||||||
@ -53,47 +72,50 @@
|
|||||||
"label": "build editor (debug)",
|
"label": "build editor (debug)",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "build",
|
"command": "build",
|
||||||
"args": ["-p", "editor"],
|
"args": ["-p", "editor", "--bin", "editor"],
|
||||||
"problemMatcher": ["$rustc"],
|
"problemMatcher": ["$rustc"],
|
||||||
"group": { "kind": "build", "isDefault": true }
|
"group": "build"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "build editor (dev fast-link)",
|
"label": "build editor (dev fast-link)",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "build",
|
"command": "build",
|
||||||
"args": ["-p", "editor", "--features", "dev"],
|
"args": ["-p", "editor", "--bin", "editor", "--features", "dev"],
|
||||||
"options": {
|
"options": {
|
||||||
"env": {
|
"cwd": "${workspaceFolder}",
|
||||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"problemMatcher": ["$rustc"],
|
"problemMatcher": ["$rustc"],
|
||||||
"group": "build"
|
"group": { "kind": "build", "isDefault": true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "build game (dev fast-link)",
|
"label": "build game (dev fast-link)",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "build",
|
"command": "build",
|
||||||
"args": ["-p", "game", "--features", "dev"],
|
"args": ["-p", "game", "--bin", "game", "--features", "dev"],
|
||||||
"options": {
|
"options": {
|
||||||
"env": {
|
"cwd": "${workspaceFolder}",
|
||||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"problemMatcher": ["$rustc"],
|
"problemMatcher": ["$rustc"],
|
||||||
"group": "build"
|
"group": "build"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "clean build editor (dev)",
|
"label": "clean dev-link crates",
|
||||||
"type": "shell",
|
"type": "cargo",
|
||||||
"command": "cargo clean -p editor && cargo build -p editor --features dev",
|
"command": "clean",
|
||||||
|
"args": ["-p", "editor", "-p", "game", "-p", "game_hot", "-p", "shared"],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"env": {
|
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||||
"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"
|
"group": "build"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -102,9 +124,7 @@
|
|||||||
"command": "cargo clean-target",
|
"command": "cargo clean-target",
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"env": {
|
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"problemMatcher": [],
|
"problemMatcher": [],
|
||||||
"group": "build"
|
"group": "build"
|
||||||
@ -115,9 +135,7 @@
|
|||||||
"command": "cargo clean-target --apply",
|
"command": "cargo clean-target --apply",
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"env": {
|
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"problemMatcher": [],
|
"problemMatcher": [],
|
||||||
"group": "build"
|
"group": "build"
|
||||||
@ -128,9 +146,7 @@
|
|||||||
"command": "cargo clean-target --include-artifacts --days 3 --apply",
|
"command": "cargo clean-target --include-artifacts --days 3 --apply",
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"env": {
|
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"problemMatcher": [],
|
"problemMatcher": [],
|
||||||
"group": "build"
|
"group": "build"
|
||||||
@ -139,10 +155,11 @@
|
|||||||
"label": "run editor (dev fast-link)",
|
"label": "run editor (dev fast-link)",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "run",
|
"command": "run",
|
||||||
"args": ["-p", "editor", "--features", "dev"],
|
"args": ["-p", "editor", "--bin", "editor", "--features", "dev"],
|
||||||
"options": {
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
"env": {
|
"env": {
|
||||||
"BEVY_FPS_HDR": "0",
|
"RUST_BACKTRACE": "1",
|
||||||
"WGPU_VALIDATION": "0",
|
"WGPU_VALIDATION": "0",
|
||||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
||||||
}
|
}
|
||||||
@ -154,9 +171,83 @@
|
|||||||
"label": "run game (dev fast-link)",
|
"label": "run game (dev fast-link)",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"command": "run",
|
"command": "run",
|
||||||
"args": ["-p", "game", "--features", "dev"],
|
"args": ["-p", "game", "--bin", "game", "--features", "dev"],
|
||||||
"options": {
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
"env": {
|
"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",
|
"BEVY_FPS_HDR": "0",
|
||||||
"WGPU_VALIDATION": "0",
|
"WGPU_VALIDATION": "0",
|
||||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
"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\"",
|
"command": "cargo watch -w crates/game_hot -w crates/sim -x \"build -p game_hot --features dylib\"",
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"env": {
|
"env": { "CARGO_TARGET_DIR": "${workspaceFolder}/target" }
|
||||||
"CARGO_TARGET_DIR": "${workspaceFolder}/target"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"problemMatcher": ["$rustc"],
|
"problemMatcher": ["$rustc"],
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"isBackground": true
|
"isBackground": true,
|
||||||
|
"detail": "Requires cargo-watch: cargo install cargo-watch --locked"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "verify foundation",
|
"label": "verify workspace",
|
||||||
"dependsOrder": "sequence",
|
"dependsOrder": "sequence",
|
||||||
"dependsOn": [
|
"dependsOn": [
|
||||||
"cargo fmt (check)",
|
"cargo fmt (workspace check)",
|
||||||
"cargo check (workspace)",
|
"cargo check (workspace all targets)",
|
||||||
"cargo clippy (workspace)",
|
"cargo clippy (workspace strict)",
|
||||||
"cargo clippy (foundation strict)",
|
"cargo test (workspace)",
|
||||||
"cargo test (foundation)",
|
"cargo clippy (launch feature matrix)",
|
||||||
|
"validate level scenes",
|
||||||
"build game (debug)",
|
"build game (debug)",
|
||||||
"build editor (debug)"
|
"build editor (debug)"
|
||||||
],
|
],
|
||||||
"problemMatcher": [],
|
"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
|
```bash
|
||||||
# Check everything
|
# Check everything
|
||||||
cargo fmt --check
|
cargo fmt --all --check
|
||||||
cargo check --workspace
|
cargo check --workspace --all-targets
|
||||||
cargo clippy --workspace
|
cargo clippy --workspace --all-targets -- -D warnings
|
||||||
cargo clippy -p game -p shared -p protocol -p sim -- -D warnings
|
cargo clippy -p editor -p game --bins --features dev,hot-reload -- -D warnings
|
||||||
cargo test -p game --lib
|
cargo test --workspace
|
||||||
cargo test -p sim
|
cargo validate-levels
|
||||||
|
|
||||||
# Runtime game
|
# Runtime game
|
||||||
cargo run -p 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
|
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 |
|
| 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.
|
- 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.
|
- 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.
|
- 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.
|
- 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 && 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.
|
- 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
|
## Editor Controls
|
||||||
|
|
||||||
@ -238,8 +238,8 @@ The `.vscode/` folder is preconfigured:
|
|||||||
- `extensions.json` recommends rust-analyzer, Even Better TOML, CodeLLDB, crates, and Error Lens.
|
- `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,
|
- `settings.json` runs `clippy` on save, enables proc-macro/build-script support, formats on save,
|
||||||
and excludes `target/` from search/watch.
|
and excludes `target/` from search/watch.
|
||||||
- `tasks.json` provides workspace check/clippy plus game/editor build/run tasks.
|
- `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` provides CodeLLDB launch configs for the editor and game.
|
- `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.
|
- `.github/workflows/ci.yml` mirrors local formatting, check, clippy, test, and binary build verification.
|
||||||
|
|
||||||
## Architecture Decisions
|
## Architecture Decisions
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use bevy::prelude::*;
|
|||||||
use bevy_egui::{egui, EguiPrimaryContextPass, EguiTextureHandle, EguiUserTextures};
|
use bevy_egui::{egui, EguiPrimaryContextPass, EguiTextureHandle, EguiUserTextures};
|
||||||
use egui_phosphor_icons::icons;
|
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::studio::{model_file_exists, ThumbnailStudio};
|
||||||
use super::ThumbnailJobSource;
|
use super::ThumbnailJobSource;
|
||||||
use crate::assets::{
|
use crate::assets::{
|
||||||
@ -100,13 +100,12 @@ impl AssetThumbnailCache {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(texture_path) = gltf_base_color_texture_path(&model_path) {
|
if !self.model_source_ready(&key, &model_path) {
|
||||||
self.request_texture(key, texture_path, asset_server);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !model_file_exists(&model_path) {
|
if let Some(texture_path) = gltf_base_color_texture_path(&model_path) {
|
||||||
self.mark_studio_failed(&key, "file not found", false);
|
self.request_texture(key, texture_path, asset_server);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,8 +129,7 @@ impl AssetThumbnailCache {
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if !model_file_exists(&model_path) {
|
if !self.model_source_ready(&key, &model_path) {
|
||||||
self.mark_studio_failed(&key, "file not found", false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if studio.enqueue_source(
|
if studio.enqueue_source(
|
||||||
@ -160,8 +158,7 @@ impl AssetThumbnailCache {
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if !model_file_exists(&model_path) {
|
if !self.model_source_ready(&key, &model_path) {
|
||||||
self.mark_studio_failed(&key, "file not found", false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if studio.enqueue_source(
|
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(
|
pub(crate) fn complete_studio_thumbnail(
|
||||||
&mut self,
|
&mut self,
|
||||||
key: &str,
|
key: &str,
|
||||||
|
|||||||
@ -29,6 +29,41 @@ pub fn gltf_base_color_texture_path(model_asset_path: &str) -> Option<String> {
|
|||||||
None
|
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;
|
pub struct GltfThumbnailSource;
|
||||||
|
|
||||||
fn is_gltf_path(path: &Path) -> bool {
|
fn is_gltf_path(path: &Path) -> bool {
|
||||||
@ -61,7 +96,9 @@ fn normalize_asset_path(path: &Path) -> Option<String> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn normalize_asset_path_keeps_assets_prefix() {
|
fn normalize_asset_path_keeps_assets_prefix() {
|
||||||
@ -79,4 +116,25 @@ mod tests {
|
|||||||
Some("assets/models/textures/chair_albedo.png".into())
|
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,
|
ThumbnailStudioLayer,
|
||||||
RenderLayers::layer(THUMBNAIL_LAYER),
|
RenderLayers::layer(THUMBNAIL_LAYER),
|
||||||
Transform::default(),
|
Transform::default(),
|
||||||
|
Visibility::Visible,
|
||||||
|
InheritedVisibility::default(),
|
||||||
|
ViewVisibility::default(),
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,12 @@
|
|||||||
//! Runtime game crate: FPS player, rendering, and starter world.
|
//! Runtime game crate: FPS player, rendering, and starter world.
|
||||||
#![allow(clippy::type_complexity)]
|
#![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 editor_ext;
|
||||||
pub mod launch;
|
pub mod launch;
|
||||||
@ -62,8 +69,8 @@ mod systems {
|
|||||||
mod hot {
|
mod hot {
|
||||||
use avian3d::prelude::*;
|
use avian3d::prelude::*;
|
||||||
use bevy::input::mouse::AccumulatedMouseMotion;
|
use bevy::input::mouse::AccumulatedMouseMotion;
|
||||||
|
use bevy::light::atmosphere::ScatteringMedium;
|
||||||
use bevy::light::CascadeShadowConfig;
|
use bevy::light::CascadeShadowConfig;
|
||||||
use bevy::pbr::ScatteringMedium;
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::time::Fixed;
|
use bevy::time::Fixed;
|
||||||
use bevy::window::{CursorOptions, PrimaryWindow};
|
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).
|
- **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.
|
- **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.
|
- **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.
|
- **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).
|
- **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.
|
- **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