Skip to content

Releases: Hekbas/Luth

v2.8.3 — tracy-on-demand

25 Apr 14:37

Choose a tag to compare

Date: 2026-04-25
Issue: #30

Overview

Hotfix for two memory leaks that share a single root cause: Tracy's per-thread serial queue accumulates zone, frame-mark, and (post-v2.8.2) global allocation events even when no profiler client is connected to drain them. Defining TRACY_ON_DEMAND makes every Tracy macro short-circuit to a no-op until Profiler::IsConnected() is true. Same leak at two scales — got dramatically worse after v2.8.2 wired global new/delete to TracyAlloc/TracyFree.

Key Changes

  • Add TRACY_ON_DEMAND to Debug + Release across all four premake configs (Tracy lib, Luth, Luthien, runtime)
  • Fixes ~10 MB/s ProjectLauncher leak (post-v2.8.2 regression) and ~0.2 MB/s in-game leak at 240 fps (#30, opened 3 weeks earlier)
  • MemoryTracker reads remained balanced — leaked bytes lived inside Tracy's own buffers, outside the LH_NEW/LH_DELETE path
  • Capture experience unchanged with Tracy GUI connected; trace begins at connection time (no retroactive history — acceptable trade-off for a development-only feature)
  • Tracy excluded from Dist as before — no impact there

Build Verification

Debug x64 builds clean. Launcher and in-game RSS flat over 60 s and 5 min respectively with no Tracy client. Capture flow unchanged with client connected.

v2.8.2 — engine-consolidation

25 Apr 00:46

Choose a tag to compare

Date: 2026-04-25
Issue: #95

Overview

Audit-driven housekeeping pass before resuming feature work. Restructures the roadmap, adds four arch sub-docs covering systems that existed in code but lacked documentation (memory / profiling / validation-layers / version-glossary), sanitizes comment banners across 14 files, wires Tracy global memory hooks for STL/heap visibility, and fills Tracy CPU coverage gaps across editor panels and individual render-graph passes.

Key Changes

  • ROADMAP: terse summaries, Effort scale (S/M/L/XL replaces calendar estimates), v2.7/v2.8 rows reordered chronologically
  • 4 new docs/development/arch/ sub-docs: memory, profiling, validation-layers, version-glossary
  • Comment banners normalized to v2.7.0 // ── Section ── form across jobs/, memory/, renderer/ (–104 LOC of cruft)
  • Tracy memory hooks via global operator new/delete overrides — STL containers + third-party libs visible in Memory tab
  • Tracy CPU coverage filled: 10 editor panels, RG individual passes, PickingSystem::Update, shader hot-reload
  • Issue renames: #92 frame-debugger-scrubframe-debugger-polish, #93 animation-assetsanimation-quick-pass (rescoped)

Build Verification

10 atomic commits on chore/engine-consolidation, each builds Debug x64 clean. Vulkan validation runs without new warnings.

v2.8.1 — game-panel

24 Apr 19:34

Choose a tag to compare

Date: 2026-04-24
Issue: #91

Overview

Dedicated Game panel rendering the first Component::Camera entity — letterbox/pillarbox respects the camera's aspect ratio; no editor overlays. Scene panel goes back to always using the editor camera. Replaces the v2.8.0 scene-camera-override stopgap and rebuilds the renderer to cleanly support multi-view.

Key Changes

  • RenderView threads per-view input (targets + camera + overlay flags) through RenderPipeline::Execute.
  • ViewResources cache keyed by FrameTargets* — per-view GlobalUBO + Set 0 + bloom/GTAO textures + PP/GTAO/outline/grid descriptor sets; multiple subgraphs share one primary command buffer without mid-frame descriptor aliasing.
  • Renderer::ExecuteGraph split into BeginPrimaryCmd + RecordGraph + EndPrimaryCmdAndSubmit; RenderingSystem::Update records queued views + scene view into one cmd buffer, one submit + present per frame.
  • RS::QueueView API; shared indirect buffer carries per-view regions (k_MaxViews * k_IndirectRegionsPerView).
  • ViewportRenderer::BeginViewport(aspectRatio) centers + letterboxes when > 0; GamePanel passes Camera.AspectRatio and pulls IBL/skybox intensities from EditorSettings.
  • Per-instance resize callback replaces the single-subscriber RenderResizeEvent bus.
  • Drive-by fixes (validation-layer hardening): depth textures gain VK_IMAGE_USAGE_TRANSFER_SRC_BIT; GeometryPass declares explicit builder.Read(gtaoFinal); PickingSystem barrier uses the actual COLOR_ATTACHMENT_OPTIMAL source layout.

Build Verification

Debug x64 clean across 12 commits on feat/game-panel. No new warnings. Manual smoke: scene + game panels render correctly in all play states, frame debugger enable/disable is clean, picking works, runtime target still links.

v2.8.0 — play-mode

23 Apr 12:51

Choose a tag to compare

Date: 2026-04-23
Issue: #66

Overview

First feature epic after the post-v2.6 editor architecture review. Adds an Editing → Playing → Paused → Editing state machine with scene snapshot / restore so Stop reverts cleanly. Gateway for v2.9.0 jolt-physics and any future gameplay-only system.

Key Changes

  • SceneSerializer::SaveToString / LoadFromString(preserveAssets) for in-memory JSON snapshot; Scene::ClearPreservingAssets skips AssetManager reload on Stop
  • Luth::PlayState on IEditorHooks (nullptr-safe default keeps headless runtime ticking normally)
  • App::Run gates AnimationSystem on Playing || (Paused && step) || (Editing && preview)
  • New PlayModeController + CommandHistory::SetBlocked — Inspector edits and Ctrl+Z are no-ops during play; snapshot rewind discards mutations on Stop
  • ScenePanel transport bar (Play/Pause/Stop/Step) with green/yellow viewport tint + scene-camera override when a Component::Camera entity exists
  • Fix: pre-existing skinned-mesh freeze on scene reload — GPUObjectBuffers now mirrors DrawListBuilder's entity-or-parent bone-offset lookup

Build Verification

10 atomic commits on feat/play-mode, every commit builds Debug x64 clean. User-tested Play→Stop cycles on skinned characters; transport controls + undo gating + scene-camera override all behave per checklist.

v2.7.5 — editor-scene-panel-slim

23 Apr 00:58

Choose a tag to compare

Date: 2026-04-23
Issue: #90

Overview

Sixth and final epic of the post-v2.6 editor architecture review. ScenePanel.cpp (1001 LOC) split across three dedicated collaborators under a new luthien/source/luthien/viewport/ folder. Pure refactor — no behavior change.

Key Changes

  • New ViewportRenderer — viewport size/bounds/focus/hover + scene-color VkDescriptorSet lifetime + per-frame resize-event dispatch.
  • New GizmoController — ImGuizmo operation + drag-undo coalesce + Q/W/E/R shortcuts + icon-click latch.
  • New ViewportOverlays — bone/light/camera/AABB overlays + 5 projection-and-clipping helpers as private methods; routes icon clicks through GizmoController::DrawGizmoIcon so the latch stays on the controller.
  • ScenePanel retains toolbar, picking dispatch, F/Shift-F camera framing, controls overlay, EditorCamera.
  • ScenePanel.cpp 1001 → 443 LOC (−56%); ScenePanel.h 82 → 44 LOC.

Build Verification

4 atomic commits; every commit builds Debug x64 clean (no new warnings). Runtime smoke: viewport renders + resizes cleanly, TRS gizmo + QWER shortcuts + drag-coalesced undo, all four overlays toggle, icon-click selection, F / Shift-F framing, controls-overlay chip.

v2.7.4 — editor-component-registry

23 Apr 00:21

Choose a tag to compare

Date: 2026-04-23
Issue: #89

Overview

Replace InspectorPanel::DrawEntityComponents' hand-written 12-arm DrawComponent<T> switch and 70-LOC Add Component dropdown with a type-erased ComponentDrawerRegistry. One drawer per component file; the inspector iterates the registry for both rendering and add-menu enumeration. Pure refactor — every command, IsDirty flag, and init-value quirk preserved. InspectorPanel.cpp shrinks 976 → 255 LOC (−73%).

Key Changes

  • New ComponentDrawerRegistry — static class holding std::vector<ComponentDrawerDescriptor>. Register<T>(name, drawFn, opts) closes over T at template instantiation; wraps the user lambda in BeginCollapsingHeader + Remove-context-menu; default OnAdd issues ComponentAddCommand<T>.
  • 8 per-component .cpps under luthien/source/luthien/inspectors/component_drawers/ (Transform / Camera / MeshRenderer / Animation / BoneAttachment / AnimationController / DirectionalLight / PointLight) + DebugDrawers.cpp consolidating ID/Parent/Children/WorldTransform under a single #if DEBUG guard. Canonical order held by insertion order in RegisterComponentDrawers.cpp.
  • Init-value / dependency quirks preserved via custom OnAdd + CanAdd: Animation snapshots MeshRenderer.ModelUUID; AnimationController requires Animation present and seeds a base BlendLayer from current Animation state.
  • MeshRenderer → MaterialEditor handoff via new InspectorPanel::SetActiveMaterial(UUID) + m_ActiveMaterialUUID member (reset per frame) — MeshRendererDrawer accesses it via Editor::GetPanel<InspectorPanel>().
  • Transform + ID: Removable=false; Transform + ID + all DEBUG drawers: ShowInAddMenu=false. DrawComponent<T> template deleted; legacy DEBUG-only Tag/Parent/Children add-menu entries dropped (hierarchy-managed, not user-addable).

Build Verification

6 atomic commits on refactor/editor-component-registry; every commit builds Debug x64 clean. Runtime smoke-tested: property edits + undo/redo, vector ops on AnimationController.Layers, Add-menu gating + init-value seeding, scene round-trip identical.

v2.7.3 — editor-undo-gaps

22 Apr 23:07

Choose a tag to compare

Date: 2026-04-23
Issue: #88

Overview

Wrap the 14 Editor::MarkDirty() callsites in InspectorPanel.cpp so the edits go through CommandHistory and survive Ctrl+Z. Most were vector-element edits inside AnimationController::Layers that bypassed undo because ComponentPropertyCommand<C, T> only addresses single member-pointers, not vec[i].field. EE4 of the post-v2.6 editor architecture review.

Key Changes

  • New commands/VectorCommands.h templates: VectorElementPropertyCommand<C, Elem, T>, VectorInsertCommand<C, Elem>, VectorEraseCommand<C, Elem>. Per-bone BoneMask[i] workaround: snapshot the whole std::vector<bool> (sidesteps proxy refs).
  • New EntityActiveCommand; BoneAttachment Target/Bone combos wrapped via BeginCompound/EndCompound so multi-field edits undo atomically.
  • New EXEC_COMPONENT_PROP macro derives T from decltype(OLD) and collapses the 6-line make_unique<ComponentPropertyCommand<...>>(...) boilerplate; applied to 8 representative existing callsites.
  • Drive-by: spurious MarkDirty() on EditorSettings::showBoneDebug deleted (editor preference, not scene state).
  • Drive-by fix surfaced by smoke test: Entity::isActive was a bool on the wrapper struct, destroyed on every Scene::FindEntityByUUID rebind — toggle visually snapped back next frame and active state never round-tripped through save/load. Replaced with a Component::Disabled empty tag (sparse registry storage); Entity::SetActive/IsActive now read/write via the registry.

Build Verification

7 atomic commits on epic/editor-undo-gaps; each builds Debug x64 clean. Runtime smoke (user-tested): all animation-layer + bone-mask + add/remove + entity-active + bone-attachment edits undo and redo correctly; entity-active toggle now persists across frames and across scene save/load.

v2.7.2 — editor-widgets-reorg

19 Apr 18:16

Choose a tag to compare

Date: 2026-04-19
Issue: #87

Overview

Split luthien/UI.{h,cpp} (506 LOC, ambiguous "UI" name) into five focused widget files under luthien/source/luthien/widgets/. All symbols stay in namespace Luth::UI so the 12 callsites only update their #include. EE3 of the post-v2.6 editor architecture review.

Key Changes

  • New widgets: Properties.{h,cpp} (Property<T>/PropertyColor/PropertyCombo + per-axis vector reset rows), AssetSlot.{h,cpp} (PropertyAsset + drag-drop), CollapsingHeader.{h,cpp}, InfoTable.{h,cpp}, TexturePreview.{h,cpp} (Vulkan ImGui descriptor cache).
  • PropertyLabel promoted to public so AssetSlot reuses the row layout from Properties.
  • widgets/Widgets.h umbrella re-includes the five widget headers; root UI.h/UI.cpp deleted; perl bulk-rewrite migrated all callers.
  • Drive-by: dead static PushMultiItemsWidths in old UI.cpp removed (real callsite uses ImGui::PushMultiItemsWidths).

Build Verification

6 atomic commits on epic/editor-widgets-reorg; each builds Debug x64 clean. Runtime smoke (user-tested): panels render, inspector drawers + asset drag-drop + texture previews work, no Vulkan validation warnings on shutdown.

v2.7.1 — editor-style-assets

19 Apr 16:51

Choose a tag to compare

Date: 2026-04-19
Issue: #86

Overview

StylePreset data moved from source into JSON assets under luth/assets/styles/. EditorStyle.cpp 616 → 280 LOC; Style menu gains Save / Load entries; Editor::LoadStyle(nameOrPath) replaces the four per-preset setters.

Key Changes

  • Flat JSON schema: name, font { mainFont, mainSize, mergeMainWithSolid, iconSize }, scalar style fields, colors { } keyed by stable ImGui::GetStyleColorName strings (obsolete aliases TabActive/TabUnfocused/NavHighlight resolve to canonical names).
  • EditorStyle::LoadBuiltin(name) + LoadFromFile / SaveToFile helpers.
  • EditorSettings::activeStylePath persists user-loaded paths; takes precedence over activeStyle.
  • Public API collapses from Set{Custom,Bubblegum,Matrix,Rider}Style to a single deferred Editor::LoadStyle(nameOrPath).
  • Drive-by fix: Bubblegum and Matrix now merge FA-Solid into the main font — previously panel titles like ICON_FA_LIST " Hierarchy" dropped their text glyphs under those styles.

Build Verification

7 atomic commits on epic/editor-style-assets; Debug x64 clean throughout. Runtime smoke: 4 built-in styles render, Save/Load round-trips, custom path persists, Bubblegum/Matrix panel titles fixed.

v2.7.0 - editor-cleanup

19 Apr 15:25

Choose a tag to compare

Date: 2026-04-19
Issue: #85

Overview

First epic of the post-v2.6 editor architecture review. Low-risk housekeeping across luthien/ — removes vestigial files, upgrades data structures, decomposes the Editor::Init() monolith, and establishes comment conventions for later editor-review epics. No runtime behavior change.

Key Changes

  • Command.cpp (2 stale comment lines) deleted; Command.h moved to commands/Commands.h.
  • CommandHistory stacks std::vectorstd::deque — FIFO eviction now O(1) instead of O(N).
  • Editor::GetPanel<T>() linear dynamic_cast scan replaced by std::unordered_map<std::type_index, Panel*> lookup (O(1)).
  • Editor::Init() decomposed into InitImGui + InitPanels + ApplyPersistence; public Init is a 5-line orchestrator.
  • Comment sweep across luthien/**: triple-line // ====== banners → // ── Section ── one-liners, stale TODO/debt blocks removed, /// doxygen normalized to //, redundant "what this field holds" prose dropped; WHY/gotcha comments preserved.

Build Verification

6 atomic commits on epic/editor-cleanup; Debug x64 clean. Runtime smoke (user-tested): all 9 panels render, undo/redo works, style switching works, settings persist across restart. Follow-up commit 776f1b3 on main fixed a font-atlas crash regression (fonts must load before the Vulkan atlas is built).