- Replace custom LoggerImpl with spdlog (stdout_color_sink + basic_file_sink),
QUAKE3_LOG_LEVEL env var controls level at runtime (trace/debug/info/warn/error)
- Fix HUD virtual canvas from 640×360 to 640×480 (ioq3 native resolution)
- Fix BSP entity field parsing: all numeric values in Q3 BSP entity lump are JSON
strings; use EntFloat() helper with stof() in movers_init and triggers_check
- Fix macOS 26 Metal crash: TAA shader had SPIRV path as default for MSL backend;
add postfx_taa.frag.metal MSL port and fix seed_game.json default path
- GPU init: disable SDL Metal debug layer by default (MTL_DEBUG_LAYER); re-enable
with SDL_GPU_DEBUG=1 env var; add MSL null-terminator guard in shader compile
- spdlog 1.15.1 added to conanfile.py BASE_REQUIRES and CMakeLists.txt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a new workflow step that renders the Quake3 MD3 player head to a small offscreen GPU render target each frame and exposes it to the overlay as "overlay.head_gpu_tex" with face rectangle metadata. Implement WorkflowQ3HudHeadStep (kHeadSz=64) and its header; register the step in the workflow registrar and add it to the CMake build and q3_overlay workflow JSON. Update q3 HUD drawing to use the live 3D portrait when available (fall back to the icon otherwise). Extend overlay.sw.end to blit the head texture into the HUD face rect (BlitHeadPortrait), with lazy allocation of a vertex buffer and sampler and proper cleanup. Also add resource release logic and small API includes where needed.
Breaks the monolithic Quake3 per-frame workflows into reusable include-based sub-workflows (input, physics, combat, render, overlay, postfx) and adds a screenshot-check component for the screenshot package. Introduces new workflow JSONs (q3_input, q3_physics, q3_combat, q3_render, q3_overlay, q3_postfx, q3_screenshot_check) and updates q3_frame and screenshot q3_frame to include them. Implements SDL software overlay steps (hud, crosshair, hitmarker, mapselect, menu_frame) and software overlay begin/end rendering steps with corresponding headers and source files; removes the old q3_overlay_draw implementation. Updates CMakeLists and workflow parser/registrar to register and build the new sources. This refactor improves composability and reusability of workflow sections.
HUD (always-visible, replaces text debug overlay):
- Large digit sprites from gfx/2d/numbers/*_32b.tga at 1.75x scale
- Bottom-left: armor value (gold) + iconr_yellow.tga + health value + face icon
- Bottom-right: icona_machinegun.tga + ammo count
- Crosshair from gfx/2d/crosshaira.tga (falls back to dot)
- Reads q3.player_health / q3.player_armor / q3.player_ammo context keys
Map-select screen (DrawMapSelectScreen, shown when q3.menu_screen == "map_select"):
- Levelshot image from levelshots/{MAP}.jpg, red-bordered, centered
- Map short name + long name from scripts/arenas.txt (ParseArenas)
- Bot opponent face icon from models/players/{bot}/icon_default.tga
- Left/right navigation arrows (gs_arrows_l/r.tga)
- BACK / SKIRMISH / FIGHT buttons at bottom
Infrastructure:
- ParseArenas() reads arenas.txt from PK3 into arena_data_ map at startup
- LoadOrGetLevelshot() caches levelshot SDL_Texture* by uppercase map name
- DrawHudNumber() draws integer using digit sprite array with gold tint
- All new textures cleaned up in destructor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace panel-box layout with full-screen black background
- Draw frame1_l + frame1_r side-by-side at full width to form the Q3A
circular bull-horn ring emblem behind the menu items
- Render "QUAKE III ARENA" title using prop font at 1.5×/1.1× scale with
an orange glow pass via font1_prop_glo.tga, matching Q3A style
- Menu items now render at 1.0× scale in red (unselected) or bright
yellow-white with glow halo (selected), centered on screen
- Add copyright footer matching Q3A exact text
- Load font1_prop_glo.tga as prop_glo_tex_ for title and hover effects
- Update menu.json main screen to Q3A items: SINGLE PLAYER, MULTIPLAYER,
SETUP, DEMOS, CINEMATICS, MODS, EXIT
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add workflow_q3_md3_load_step: load MD3 models from PK3 with correct
CCW winding, 1/64 xyz scale + 0.03125 world scale, and per-frame VBs
- Add workflow_q3_md3_draw_step: viewmodel (weapon) + world-space MD3
drawing; barrel oriented along model X → world forward
- Add workflow_q3_bots_draw_step: 3-part bot model chain
(lower→upper→head via MD3 tags) + weapon attachment
- Add workflow_q3_bots_spawn_step: spawn bots at indices 1+ so they
never overlap the player's spawn point (index 0)
- Add workflow_q3_bots_update_step: bot AI (idle/chase/shoot/dead FSM)
- Fix workflow_q3_menu_update_step: menu starts closed (was open)
- Fix workflow_postfx_composite_step: GPU readback via
SDL_DownloadFromGPUTexture captures full 3D scene for screenshots
- Fix Metal GPU validation: always bind 2 sampler slots; reuse albedo
as dummy shadow map when no shadow texture is available
- Reorder q3_frame.json: screenshot trigger nodes run before
postfx_composite so screenshot_output_path is set in time
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduce a new Quake3 pickups draw workflow step to render in-world pickup icons and register it: add WorkflowQ3PickupsDrawStep (header + implementation), register the step in WorkflowRegistrar, and include the source in CMakeLists. Update the q3_frame workflow JSON to insert a draw_pickups node into the frame graph. Enhance the overlay to show weapon damage in the HUD and draw weapon/hit visuals, and update weapon logic to mark hits and accumulate damage (q3.last_shot_hit, q3.hit_marker_until_frame, q3.damage_done). Also fix trailing newline in CMakeUserPresets.json.
- overlay.fps: SDL software renderer → GPU texture quad, top-right corner,
yellow EMA-smoothed FPS counter; LOADOP_LOAD preserves scene beneath it
- debug.screenshot: one-shot step that writes status txt + BMP then pushes
SDL_EVENT_QUIT for automated visual feedback loop
- Adaptive vsync: graphics.gpu.init "auto" present_mode queries actual monitor
refresh rate via SDL_GetCurrentDisplayMode; ≥120 Hz → VSYNC, <120 Hz → MAILBOX
Fixes vsync cap on 165/170 Hz monitors reporting as 240 Hz in settings
- Fixed present_mode wiring: q3_game.json gpu_init_viewport node now passes
present_mode as a direct parameter (workflow variables are not seeded into
context by the executor, so the variable section was dead data)
- Stair climbing: probeReach 0.45→0.70 for earlier detection, jam detection
nudges player up after 100 ms of horizontal blockage, step_height tuned to 0.6
- Physics dt: real wall-clock delta clamped to [1/600, 1/30] so 240 Hz displays
don't run physics 4× faster than intended
- GUI smart search paths: _candidate_build_dirs() scans all generator dirs ×
build types × flat and Conan-nested layouts, sorted by CMakeCache.txt mtime;
_find_binary() picks freshest sdl3_app.exe; packages loaded relative to
__file__ so gui works from any working directory
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace held-jump-extends-height (Mario-style) with a Q3-style impulse
jump: set vel.y once on press, gravity does the rest. Apply per-player
gravity scaling symmetrically in air (rising and falling) so jumps don't
feel floaty going up but heavy coming down.
Tune q3_frame for a fun, floaty feel rather than authentic Q3 numbers:
gravity_scale 0.55 (≈55% Earth) + jump_velocity 5.5 → ~2.8m apex,
~2s airtime. Trades rocket-dodge utility for hang-time enjoyment.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
physics.fps.move was directly setting linearVelocity each frame on the
ground, producing the classic "no inertia" snap-stop feel. Replace with
a CalcFriction-style ramp: velocity accelerates toward target by
ground_accel * dt, decelerates to zero by ground_friction * dt when
input is released.
Tune the quake3 frame loop to match a modern shooter rather than vanilla
Q3 arcade speeds:
- walk 4.5 m/s (was 8.0 — ~30 km/h is a sprint, not a walk)
- sprint 1.5x (was 2.0x — 6.75 m/s top speed)
- jump 0.9m / 0.22s (was 2.0m / 0.4s — Halo-ish hop, not a moon jump)
- air control 0.15 (was 0.5 — less floaty mid-jump)
- gravity_scale 1.6 (was 0.3 — was actually pushing the player UP
when falling because of how the (gravityScale - 1.0) extra-force
multiplier worked)
Defaults for the new ground_accel (35) / ground_friction (30) params
keep other workflows that use physics.fps.move feeling snappy without
having to update them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Quake 3 package was missing GPU shaders entirely. With these in place,
the engine boots quake3 successfully: pak0 loads, BSP parses, lightmap
atlas and geometry build, and shaders compile/bind correctly on the
Vulkan path.
bsp.vert: matches BspRenderVertex layout (position/uv/lmuv/normal) and
re-uses the existing VertexUniformData uniform block from the seed
pipeline so no C++ changes are needed.
bsp.frag: classic Q3 model — albedo × lightmap × overbright + ambient.
Skips PBR / shadow mapping entirely; Q3's baked lightmaps already encode
direct + bounce lighting and shadowing. Q3 shader-script effects
(animated sky, scrolling water, env-mapped chrome) render flat — adding
them is a follow-up.
SPIR-V only for now (Windows/Vulkan/D3D12 via SDL3 cross-compile). MSL
and DXIL still missing for Mac/native-D3D12 paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Workflow JSON params can now reference environment variables (e.g.
${env:QUAKE3_PAK0}) which are expanded at JSON load time. A new Python
detector reads the Windows registry and parses libraryfolders.vdf to
locate Steam libraries, then resolves known-game files into env vars
that dev_commands.py exports before launching the engine. Lets users
with legitimate Steam-owned game data run packages like quake3 without
hardcoded paths.
Also fixes os.execv on Windows (Invalid argument with spaced paths) by
falling back to subprocess.call.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When Conan's build output layout changes (e.g. build/generators/ vs
build/Release/generators/), CMakeUserPresets.json accumulates includes
that define the same preset names, causing CMake to fail with
"Duplicate preset". The fix detects preset name collisions across
included files and keeps only the newest, in addition to pruning
missing files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add explicit search paths for python.org installer (%APPDATA%\Python),
Chocolatey, macOS system Python (~/Library/Python), and ~/.local/bin.
Document coverage matrix for Windows (Store/python.org/Chocolatey),
macOS (Homebrew/system/pyenv), and Linux (apt/dnf/pip --user).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Searches PATH, interpreter/user Scripts dirs, site-packages sibling
dirs, and falls back to module invocation. Covers system Python,
Homebrew, Windows Store Python, pyenv, conda, pip --user, and venvs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Windows Store Python installs packages without adding Scripts to PATH,
causing FileNotFoundError when invoking conan directly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix CW→CCW winding bug on polygon/mesh faces (types 1,3) that caused
backface culling to discard half the geometry. Decompose the monolithic
bsp.load step (1028 lines) into atomic workflow steps chainable via
JSON connections — each step only runs when connected:
- bsp.load: open pk3, read + validate BSP, store raw data in context
- bsp.lightmap_atlas: build lightmap atlas, upload to GPU
- bsp.parse_spawn: parse entity lump for spawn point
- bsp.build_geometry: build face geometry with CW→CCW winding fix
- bsp.extract_textures: load textures from pk3 with mipmaps
- bsp.upload_geometry: upload merged VB/IB to GPU
- bsp.build_collision: create Bullet physics convex hull collision
Shared BSP structs extracted to bsp_types.hpp. Workflow JSON updated
to chain: load → lightmap → geometry → textures → upload → collision → spawn.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- postfx.taa: temporal anti-aliasing with Halton jitter, neighborhood clamping,
Karis tonemap for stable history, configurable blend_factor from JSON
- Texture loader: auto-generate full mipmap chain via SDL_GenerateMipmapsForGPUTexture
- 16x anisotropic filtering on all textures
- LOD bias 0.5 to reduce moire patterns on high-frequency textures at distance
- TAA shader: 3x3 neighborhood clamp with expanded bbox to reduce flicker
- Ping-pong history buffers for temporal accumulation
- Sub-pixel jitter via Halton(2,3) sequence, 16-frame cycle
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- map.load: Assimp-based glTF/GLB scene loader with auto physics generation
- draw.map: renders all map meshes with JSON-driven texture-to-mesh mapping
- export_room_gltf.py: exports seed workflow physics bodies to GLB
- Seed demo room exported as map.glb (14 static meshes)
- Texture mapping configurable per mesh name pattern in workflow JSON
- Maps can be edited in Blender and re-exported
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Shift to sprint (1.8x speed), Ctrl to crouch (0.4x speed + lower camera)
- Smooth animated crouch via eye height lerp (no snap)
- Variable-height jump: hold space longer = jump higher, release for short hop
- Raycast ground detection for reliable jump triggering
- Air control for mid-air strafing (Quake-style)
- Configurable gravity scale for floaty/snappy feel
- All parameters driven from workflow JSON (no hardcoded values)
- Ctrl polled in input.poll step
- Camera reads crouch height override from physics.fps.move context
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- spotlight.setup: generic parameter passthrough, no hardcoded defaults
- spotlight.update: all values from spotlight.state JSON, zero fallbacks
- aim_distance now explicit in workflow JSON (was hardcoded 50.0f)
- C++ steps are pure executors, all config lives in workflow definitions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract spotlight logic from render.prepare into dedicated spotlight.update step
- render.prepare now only handles camera, shadow, and lighting uniforms
- spotlight.update runs per-frame after render.prepare, reads spotlight.state from context
- Aim distance configurable via JSON (aim_distance parameter)
- Camera-local offset for spotlight origin (matches viewmodel position)
- Direction computed from torch position toward camera aim point (natural beam alignment)
- Add distance fog to whole room (exponential, dark blue-grey)
- Volumetric beam: 48 steps, UE4 interleaved gradient noise, cubic cone falloff
- Fog density increased for visible beam effect
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Build system:
- Fix generate_cmake.py backslash paths and UTF-8 encoding for Windows
- Auto C++20 in conan deps, auto-detect VS install location
- dev_commands.py: add generate, all --run commands, platform-aware bootstrap
- Add assimp to cmake_config.json link libraries
- Fix CMakeUserPresets.json duplicate preset issue
Cross-platform C++:
- UUID generation: Windows rpc.h/UuidCreate with #ifdef _WIN32
- HOME env var fallback to USERPROFILE on Windows
- Shader format detection for D3D12/DXIL Vulkan driver
Shader pipeline (12 new SPIRV shaders):
- Port all Metal shaders to Vulkan GLSL (PBR, shadows, post-FX, compute)
- SDL3 GPU descriptor set convention (set 0-3)
- Combined image samplers for Vulkan compatibility
- Bootstrap-driven shader path rewriting (msl↔spirv automatic per platform)
Rendering features:
- spotlight.setup: generic atomic workflow step, attach to camera or static
- PBR spotlight with cone attenuation, distance falloff, wrap lighting
- Volumetric light beam (16-step ray march through dust/fog in spotlight cone)
- geometry.create_flashlight: procedural flashlight mesh (cylinder + head + lens)
- draw.viewmodel: FPS weapon-style rendering locked to camera view
- model.load: Assimp-based 3D model loader (OBJ/GLB/FBX/BLEND)
- Indoor ambient lighting fix, SSAO bypass for Vulkan clip-space
Performance:
- Frame loop logging suppressed via _in_frame_loop context flag
Assets:
- Real PBR textures from ambientCG (CC0): wood floor, concrete ceiling
- Seed demo: dark room + flashlight beam + Quake-style viewmodel
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove stale dirs/files superseded by metabuilder-small's reorganization:
- Old YAML entity/seed files (migrated to JSON)
- Root-level workflowui/ (moved to frontends/workflowui/)
- Prisma, Pyodide, old hooks, bun.lock artifacts
- Legacy scratch docs (txt/, docs/, deployment/*.md)
- Stale CI workflows consolidated in small
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Moves 45 documentation files from centralized /docs/ to subproject directories
following proximity-based organization principle. All moves use git mv to preserve history.
Changes:
- workflow/ docs: Move 27 files from docs/workflow/ to workflow/docs/
- DAG executor docs, workflow compliance, executor analysis, loaderv2 guides, etc.
- Result: workflow/docs/ now has 27 files
- dbal/ docs: Move 11 files from docs/dbal/ to dbal/docs/
- DBAL architecture, analysis, integration, and workflow integration docs
- Result: dbal/docs/ now has 18 files (11 new + 7 pre-existing)
- gameengine/ docs: Move 7 files from docs/gameengine/ to gameengine/docs/
- GameEngine compliance audits, packages, Quake3, soundboard, engine tester
- Result: gameengine/docs/ now has 20 files (7 new + 13 pre-existing)
Benefits:
- Docs are now closer to their code (easier to keep in sync)
- Reduces /docs/ clutter
- Establishes pattern for per-subproject documentation
- All git history preserved via git mv
Next phases:
- Phase 2: Move package-specific docs to /packages/{id}/docs/
- Phase 3: Separate N8N compliance docs by scope
- Phase 4: Organize UI documentation
- Phase 5: Create cross-project indices
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Import SDL3CPlusPlus C++ game engine with:
- SDL3 + bgfx rendering backend
- Vulkan/Metal/DirectX shader support
- MaterialX material system
- Scene framework with ECS architecture
- Comprehensive test suite (TDD approach)
- Conan package management
- CMake build system
This provides the native C++ foundation for the Universal Platform's
Game and 3D capability modules.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>