fix(tools): importers clear the read-only LFS bit before saving; docs refresh

0.1.3 packaging and setup fixes from what 0.1.x actually exposed.

- New Tools/ue_common.py: make_writable() clears the read-only bit an LFS .umap
  checks out with (save_map() otherwise returns False silently and the staged actor
  is lost) and require_saved() makes that failure visible. ue_hero_facade_import and
  ue_import_north_buildings now call it; the map builders already did. Verified from
  a forced 0o444 map: chmod logged, save_map True, exit 0.
- Docs/build.md: pipeline table now lists the seven site FBXs plus frontage, north,
  hero and map steps and the shared FBX preset; packaging archive corrected to
  Builds/GigLineQA; packaged-log location and -qaselftest usage documented; new
  'Traps that cost real time in 0.1.x' table (read-only save, hero --out is the FBX,
  MPFB add-on path, shot actor quitting under QA, null-RHI trace trap).
- Docs/setup.md: fresh-checkout build marked verified 2026-11-08 and the blocker
  closed; new optional-keys section for OPENROUTER_API_KEY and MAPBOX_ACCESS_TOKEN
  (gitignored .env, not needed by build/tests/release).
- Docs/Architecture 07 + architecture.md: build-output path corrected, marked
  outside the repository.
- 5 new tests for ue_common (54 total).
This commit is contained in:
zwitschi committed 2026-11-08 18:50:37 +01:00
1 parent ba68dcfdbc
commit 1b722048ce
16 files changed
+305 -178

No files matched your search

+10 -16
View File
@@ -1,36 +1,30 @@
# Controls (`0.1.0` walkable demo)
Keyboard and mouse. The same list is shown in-game, bottom-right of the frame
(`AGigLineHUD`), and the packaged Linux build ships with these bindings.
Keyboard and mouse. The same list is shown in-game, bottom-right of the frame (`AGigLineHUD`), and the packaged Linux build ships with these bindings.
| Action | Key | Notes |
| --- | --- | --- |
| Move forward | `W` | 4 m/s walk |
| Move back | `S` | |
| Strafe right | `D` | |
| Strafe left | `A` | |
| Move back | `S` | |
| Strafe right | `D` | |
| Strafe left | `A` | |
| Look | Mouse | Captured on launch; `Escape` releases it |
| Jump | `Space` | |
| Jump | `Space` | |
| Reset to start | `R` | Returns to the grounded spawn point |
| Pause / release mouse | `Escape` | Second press resumes and recaptures the mouse |
## Notes
- Movement is relative to where you are looking (controller yaw), so the capsule
stays upright on the sloped street.
- The mouse is captured on launch, so looking works without clicking first.
`Escape` toggles the capture as part of pause.
- Bindings are Enhanced Input actions in `/Game/Input` built by
`Tools/ue_create_input_assets.py`; the mapping context is `IMC_Default`.
- Movement is relative to where you are looking (controller yaw), so the capsule stays upright on the sloped street.
- The mouse is captured on launch, so looking works without clicking first. `Escape` toggles the capture as part of pause.
- Bindings are Enhanced Input actions in `/Game/Input` built by `Tools/ue_create_input_assets.py`; the mapping context is `IMC_Default`.
## Testing input without a physical keyboard
`Tools/input_test.py` injects OS-level keyboard/mouse events through a virtual
`/dev/uinput` device (see `Tools/input_emulation.py`), e.g.:
`Tools/input_test.py` injects OS-level keyboard/mouse events through a virtual `/dev/uinput` device (see `Tools/input_emulation.py`), e.g.:
```bash
python3 Tools/input_test.py --sequence move:2,look:3
```
It drives the focused game window exactly like real hardware, which is how the
controls were regression-tested on the packaged build.
It drives the focused game window exactly like real hardware, which is how the controls were regression-tested on the packaged build.