Skip to content

Editor redesign: Monolith theme + undo/redo, command palette, Profiler, Beam, prefabs & scripting QoL - #30

Merged
sheazywi merged 55 commits into
devfrom
features/editor-redesign
Sep 4, 2026
Merged

sheazywi merged 55 commits into
devfrom
features/editor-redesign

Conversation

@sheazywi

@sheazywi sheazywi commented Aug 29, 2026

Copy link
Copy Markdown
Member

Redesigns the LuxEngine editor into the warm-graphite "Monolith, warmed" aesthetic (single acid-lime accent), de-Hazel-ifies the UI, reworks the panels, and adds several substantial systems on top: a full undo/redo stack, a command palette, an in-editor Profiler, a complete prefab system (serialization → instances → per-component overrides → edit mode → variant assets), hierarchy folders, viewport/entity bookmarks, and a scripting quality-of-life pass. Targets dev.

Added

  • Undo / redo system — snapshot-based, evolved to granular per-entity diff storage. Covers scene edits (transform, add/remove component, rename, delete, reparent, prefab), content-browser asset ops (rename / move / delete-to-trash), and renderer/project settings via closure commands. Mode-aware stacks (transient play-mode history), history bounded by bytes and step count, a History panel, undo/redo toasts, and a headless serializer round-trip self-test.
  • Command Palette (Ctrl+Shift+P, also under Tools) — fuzzy search over every menu action and panel toggle; keyboard-driven, disabled-aware.
  • Profiler panel — consolidated performance view over existing telemetry: FPS/frame/CPU/GPU stat chips, a CPU-vs-GPU frame-time graph with a budget line, per-zone CPU breakdown, per-pass GPU timings, and scene/VRAM stats. Replaces the old Statistics panel (its draw/instance/memory metrics were folded in).
  • Prefab system — a full pipeline built in phases:
    • Serialization — save / load .lprefab (delegates to SceneSerializer over the prefab's scene; root is the single parentless entity), registered with AssetImporter, plus Create Prefab from a selected hierarchy.
    • Instances — Create-Prefab links the selection as a live instance (every entity carries PrefabComponent{PrefabID, EntityID}); the inspector's Prefab section replaces the debug IDs with Revert / Apply.
    • Per-component overridesSceneSerializer::GetOverriddenComponentKeys diffs an instance against its source; the inspector lists changed / added / removed components with per-component Revert / Apply plus Revert-All / Apply-All. Scene::ReconcilePrefabComponents does exact add/replace/remove.
    • Edit mode — double-click a .lprefab to edit it in isolation (context swaps to a copy of its scene; Play/Simulate blocked; Ctrl+S saves). Saving propagates to un-overridden instances (transform-aware, so placed instances keep their position).
    • Variant assets — a variant is a self-contained prefab that remembers a BasePrefab (right-click → Create Variant); editing a base propagates to derived variants' un-overridden entities.
  • Hierarchy folders — a FolderComponent marks a purely organizational grouping node: folder icon, no editable transform / gizmo, children grouped without being moved. Create Folder in the hierarchy menu.
  • Viewport & entity bookmarks — numbered camera bookmarks (Ctrl+19 set, 19 jump; full orbit state restored via EditorCamera::SetOrbitState) and pinned entity bookmarks (Ctrl+B; jump selects and frames the entity).
  • Hierarchy per-entity lock + colour labelsTagComponent carries a lock flag and a label colour, serialized (only when non-default) and carried on copy / duplicate / prefab.
  • Scripting quality-of-life — live C# reload feedback (green success / red failure toast with script count, on every reload path), a "● Live" indicator while editing the running instance during Play, and attribute-driven inspector controls read from C# via Coral reflection: [Range(min,max)] → slider, [Header(text)] → grouping label, [Tooltip(text)] → hover help.
  • Content Browser remake — type-filter chips, grid/list toggle, Name/Type/Modified sort, pinned favourite folders, selected-asset details footer (all persisted).
  • Beam text editor — multi-tab documents, Ctrl+N/S/W/F/G keybinds, find/replace, mono status bar, unsaved-changes prompt on close.

Reworked / changed

  • Reskin the whole editor to "Monolith, warmed" (Colors::Theme) — warm-graphite surfaces, one lime accent used sparingly.
  • New font stack: Archivo (UI), JetBrains Mono (numeric readouts), Bricolage Grotesque (wordmarks); FontAwesome merged into the default face.
  • Redesigned titlebar (LUX wordmark + project/scene breadcrumb) with the play/simulate/stop + gizmo transport moved into the titlebar, centred and excluded from the drag zone.
  • Restyled Scene Hierarchy (type icons, lime selection, visibility eye, lock + label affordances) and Inspector (lime switch toggles, flat sections, accent header, bordered field boxes, lime Add Component).
  • Restyled Log panel (mono rows, retuned INFO/WARNING/ERROR tints).
  • Scene Renderer panel revamp (search + collapsible cards); Renderer Debugger reworked into tabs with ImPlot charts; Simple/Advanced layout modes.

Fixed

  • Shutdown segfault on manual exit — static-destruction-order fiasco; release assets before the device and leak the live-ref registry.
  • Content Browser: descending sort broke strict weak ordering (UB in std::sort); ToggleFavorite invalidated the iterator mid-loop; shared directory context-menu id.
  • Beam: kept a document clean on write failure (silent data loss) — now stays dirty and logs; refuse Save As onto a path another tab owns; confirm before discarding a dirty tab.
  • ImGuiEx::ToggleSwitch ignored keyboard activation (mouse-only IsItemClicked) — now nav-enabled.
  • Default dock layout referenced dead window names (Text Editor, Statistics) → Beam / Profiler.
  • Command palette Ctrl+Shift+P was swallowed by panel focus (now an IsKeyChordPressed global) and its list auto-scrolled to the selection every frame (now gated to keyboard navigation).
  • Transform vec3 control rendered ##X and broke widths; editor cursor stuck hidden after the camera went inactive mid-capture; double titlebar on Wayland (disable libdecor); Linux libatomic dropped under LTO/Dist; unsupported ray-query downgraded to a warning.

Build / tooling

  • Jolt FP-exception trapping is now Debug/Debug-AS only (was defined in Release, which can hard-crash on degenerate physics).
  • Linux build auto-fetches a checksum-verified Vulkan SDK (guarded against a failed download); Run honours an explicit VULKAN_SDK and fails loudly on a missing one; Run rebuilds first.
  • Shareable CLion .idea run configs.

Docs

  • New docs/Editor/ documentation set (architecture, panels — incl. Profiler & Command Palette, viewport/camera, content browser, theme/fonts/icons, keybindings, undo/redo, extension recipes) — website-ready, grounded in source.
  • .claude/docs corrected: libatomic/LTO linker guidance and the Debug-only FP-exception note.

Sample

  • Migrated SkyDiver to scene-level post-processing; the LaptopStart sample scene now shows a hierarchy folder grouping a camera plus a sphere.

Notes for review

  • Verified on Linux (release build + smoke test: no asserts, reaches the render loop; graceful shutdown). Wayland can't screenshot, so a few purely-visual details are best eyeballed by a reviewer.
  • Windows: new source files were added since the branch started — Editor/Source/CommandPalette.{h,cpp}, Editor/Source/Panels/ProfilerPanel.{h,cpp}, and Core/Source/Lux/Asset/PrefabSerializer.{h,cpp} (and StatisticsPanel.{h,cpp} was removed). Run scripts\Win-GenProjects.bat before building or the link fails (Premake doesn't self-regenerate). The Jolt FP-exception premake change also needs a regen to take effect.
  • The scripting inspector attributes ship in ScriptCore (Lux.RangeAttribute / HeaderAttribute / TooltipAttribute); rebuild ScriptCore so the editor's Resources/Scripts/ScriptCore.dll carries them.
  • CodeRabbit's PR review was addressed in 0c38215 (correctness fixes above); two findings were skipped with reason (an already-guarded null check, and a sample-scene content choice).
  • Vendored submodules (Box2D, msdf-atlas-gen) are intentionally not touched.

sheazywi and others added 26 commits August 27, 2026 12:24
Replaces the generic Hazel-derived dark-ImGui look with a distinct
identity across three areas:

- Theme (Colors.h, ImGuiLayer.cpp): warm-graphite neutrals and a single
  lime accent (#C8FF4D) replace the cool-graphite/indigo palette; the
  unused secondary indigo hues are dropped, tab/separator hover overlays
  become named accent-tinted constants, and control rounding drops from
  soft (4-9px) to sharp (2-3px) with the existing 1px hairline borders.

- Default panel layout (EditorLayer.cpp/.h): a new DockBuilder-based
  ResetDefaultDockLayout() docks Scene Hierarchy left, Viewport/Text
  Editor center-top, Content Browser/Log center-bottom, and Properties
  right. It runs on first launch (empty imgui.ini) and from a new View >
  Reset Layout menu item. Scene Renderer and Light Settings are now
  closed by default (still available from the View menu). imgui.ini is
  reset to empty so DockBuilder is the single source of truth for the
  default layout.

- Viewport overlays (EditorLayer.cpp/.h): a display-only 3-axis
  orientation gizmo (top-right, oriented from the camera view matrix)
  and a lime "<NAME> SELECTED" badge (top-left, shown when an entity is
  selected). Both follow the existing viewport-overlay window pattern.

Verified: Release build of Core + Editor is clean; the editor launches
without crashes or asserts and the re-saved imgui.ini confirms the new
dock tree.
Ubuntu's ld defaults to --as-needed, which drops -latomic before LTO's
deferred codegen inserts __atomic_store/__atomic_load calls for
non-lock-free atomics (e.g. RenderCommandBuffer's
std::atomic<PipelineStatistics>), causing undefined references at
final link. Force it to stay linked with --no-as-needed/--as-needed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A54GbKmpSf6NCXDjx9y8bL
ImPlot was already vendored under Core/vendor/imgui/implot and listed in the
ImGui static-lib premake project, but never compiled in, initialised, or
used. Create the ImPlot context immediately after the ImGui context and
destroy it immediately before, in both ImGui layer implementations, so any
ImPlot:: call has a valid context regardless of which layer is live.

Rebuilding the vendored ImGui lib now compiles implot.cpp / implot_items.cpp
(a clean checkout picks this up on first build).
Simple/Advanced layout modes (adapted from the LuckyEngine editor's
two-layout idea, game-editor only): a persisted Editor.SimpleLayout pref
drives two DockBuilder default layouts — Simple is the minimal arrangement,
Advanced additionally docks Scene Renderer, Light Settings, Statistics, and
the Renderer Debugger. SetEditorLayoutMode opens/closes the advanced-only
panels and defers the dock rebuild to the next frame. Toggle from
Settings > Editor > "Simple UX" and from the viewport gear's "Switch to
Simple Mode" (shown only in Advanced).

New Statistics panel: a lightweight, always-available performance overview
with a Tracy-style frame-time timeline drawn with ImPlot (shaded line,
budget-bucket colouring, a 16.67 ms reference line, built-in hover), plus
headline timing / thread / scene / memory metric tables — all from existing
data sources, no new instrumentation. Kept separate from the deep per-pass
Renderer Debugger.

Adds source files (StatisticsPanel.{h,cpp}) — regenerate the project.
Group the panel's sections into an Overview/Profiling/Memory/Render
Graph/GPU Scene/Shaders tab bar instead of one long scroll. Replace the
old ImGui::PlotLines frame/pass history with ImPlot: a dual CPU/GPU
frame-history line plot (shaded GPU series, 60 FPS budget line) and a
per-pass GPU-time horizontal bar chart sorted heaviest-first. Drop the
per-pass PassHistory ring map (and its unordered_map include); reuse
pre-sized scratch vectors for the chart so it doesn't reallocate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Rebuild the panel presentation from scratch: a header of status chips
(Ready/View/Output/Scale), a segmented quality-preset selector, and a
live settings-search box, over six richly-styled collapsible cards
(Debug Views, Quality & Performance, Screen-Space Effects, Shadows,
Post FX, Color Grading) with FontAwesome accent icons. Searching filters
rows by label and force-opens cards that still have a match. Boolean
settings use a custom drawn toggle switch (no undo entry, fine for
renderer settings); sliders/dropdowns/color keep ImGuiEx::Property*.

All ~60 settings, their conditional sub-settings, and every
projectSettingsChanged/screenSpaceResourcesChanged accumulator, clamp,
refresh and callback are preserved verbatim. The Fixed-Resolution preset
block closes and reopens the property grid in a balanced End/Begin pair
so it no longer leaks ImGui style vars and an ID entry each frame.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Whitelist .idea in .gitignore so only the portable project config is
tracked (vcs.xml, JetBrains' own .idea/.gitignore, and the
codeStyles/inspectionProfiles/runConfigurations dirs); per-user and
CLion-regenerated files (workspace.xml, editor.xml, *.iml, modules.xml)
stay ignored, as does any future IDE noise.

Add Shell Script run configurations so the Linux fetch/build/run scripts
are one click from CLion's run dropdown: Fetch, Build (Release|Debug),
Run (Release|Debug). Build/Run pass the config non-interactively and
execute in a terminal so logs are visible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
…g-only

Linux-Build.sh now downloads a pinned, isolated-extraction Vulkan SDK
(1.4.335.0, override via VULKAN_VERSION) into the vendored path when it's
missing, so a clean checkout needs no separate fetch step; an explicitly
set but missing VULKAN_SDK stays a hard error. Linux-Run.sh runs the
build first (LUX_SKIP_BUILD=1 to skip) so a forgotten recompile can't run
a stale binary, and resolves LUX_DIR from its own location. Linux-Fetch.sh
bumped to the same SDK version with the same safe tmp extraction.

Drop JPH_FLOATING_POINT_EXCEPTIONS_ENABLED from Jolt's Release defines so
degenerate-but-harmless physics state no longer hard-crashes release
builds; it stays on in Debug. Building.md documents all of the above.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
No renderer feature currently depends on ray queries, so a GPU/driver
that lacks them should log a warning and continue rather than erroring
out of device setup. Threading.md gains a note on why Linux executables
must link libatomic for atomics wider than 16 bytes (e.g.
PipelineStatistics), which fall back to libatomic's generic CAS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Move the SkyDiver scene onto the scene-owned PostProcess block and drop
the obsolete Post Process Volume entity / RenderVolumeComponent left over
from the per-volume system. Also refresh a stale StaticMesh AssetID and
the registry's FileLastWriteTime churn.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Replace Roboto with Archivo for all ImGui UI fonts, matching the Monolith
mock's body face. The swap is in place — font add-order (Fonts[0]="Bold",
Fonts[1]="Large") and the name keys ("Default"/"Medium"/...) are
preserved, so every index and named lookup still resolves and FontAwesome
still merges into Default. Both the live ImGuiLayer and the (currently
dormant) VulkanImGuiLayer are kept in lockstep so they can't diverge.

Register two new named faces appended after the UI fonts (indices
unchanged): "Mono" (JetBrains Mono) for numeric readouts and "Display"
(Bricolage Grotesque) for wordmarks/headers. Only the referenced weights
are vendored (Archivo Regular/Medium/SemiBold/Bold, JetBrains Mono Bold,
Bricolage Bold) with their OFL licenses; the unused Roboto family is
removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Merge the gizmo tools and the play/simulate/stop transport into one
centred bar drawn with flat vector glyphs (stroked outlines for the
gizmo tools, filled shapes for the transport) following the theme accent:
a bordered select/move/rotate/scale cluster, a divider, then a lime Play
triangle, fast-forward Simulate, and Stop square. The standalone
top-left gizmo overlay is gone (UI_GizmosToolbar removed), which frees
the corner for the selection badge (moved up from y+48 to y+12). The
viewport performance HUD now renders in the "Mono" (JetBrains Mono) face.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
On Wayland, GLFW prefers libdecor for client-side decorations whenever
it is installed. libdecor draws its own titlebar and does not honour
set_visibility(false) for our undecorated window on KWin, so its header
rendered on top of the editor's custom titlebar. Disable libdecor via
glfwInitHint before glfwInit so GLFW uses the native xdg-decoration
protocol instead: the undecorated window requests CLIENT_SIDE and KWin
draws no server titlebar of its own. The hint is Wayland-only and ignored
on Windows/X11.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Replace the Hazel logo with a vector LUX mark and a Display-font wordmark.
Swap the centered scene name and right-side project box for a left
breadcrumb (Project / Scene) drawn in the mono face, clipped to the
window controls so long names can't overrun them. Centre the menu bar
vertically in the tall titlebar so it lines up with the logo, breadcrumb,
and window buttons instead of hugging the top.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Give the hierarchy the Monolith sidebar look. Each row now draws a
per-type FontAwesome icon (cube/light/camera/audio/script/...) with a
category tint, over an empty-label tree node so the icon keeps its own
colour and the name turns accent-lime when selected, on a subtle lime
selection fill and hover highlight. Add an uppercase "HIERARCHY - N"
header with a live entity count, and a hover-revealed visibility eye on
mesh rows that toggles StaticMeshComponent.Visible (handled through the
node's own click, guarded by the eye rect, so it doesn't disturb the
drag-drop binding). Search, multi-select, drag-drop reparent/prefab drop,
and the context menu are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Adopt the concept's inspector look. Add ImGuiEx::ToggleSwitch (rounded
track + accent knob) and route the shared Property(bool) through it, so
every boolean in the editor becomes a lime switch instead of a checkbox.
Flatten the component-section header: an uppercase label + chevron drawn
over an empty-label node with a faint hover wash, dropping the framed
Hazel header and texture icon while keeping the collapse and the gear
Reset/Remove menu (via AllowOverlap). Replace the entity header's pencil
icon with an accent status dot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Viewport navigation hides/locks the cursor via DisableMouse(). When the
camera went inactive (viewport lost focus/hover) while still captured,
OnUpdate's early return re-enabled ImGui input but never restored the
GLFW cursor mode, leaving the mouse hidden and unusable until the window
lost focus. Restore the cursor to Normal in that path when it is found
non-normal. The new viewport overlays make the mid-capture hover flip
easy to hit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Give every inspector input the concept's bordered, slightly-inset "field
box" look via a scoped RAII frame style (border + rounding + inset
FrameBg), applied once so it unwinds cleanly across DrawComponents'
returns. Restyle the Add Component button as a lime call-to-action with a
plus glyph. Per-component field logic is untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
Add the JetBrains Mono Regular/Medium weights and switch the "Mono" UI
face from Bold to Medium (crisp, not heavy) in both ImGui layers. Push
the mono face around the ImPlot plots so the axis/tick labels render
monospaced, Tracy-style: the Statistics frame-time plot and both Renderer
Debugger charts (frame history + per-pass GPU). Each PushFont/PopFont
brackets the whole plot so the font stack stays balanced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YHCXdL86aTQMgQv2D3Tw7E
The X/Y/Z fields used ImGuiEx::Property with hidden "##X" labels, which
rendered the label literally as text and pushed their own item width,
ignoring PushMultiItemsWidths and breaking the row. Switch to raw
ImGui::DragFloat, add per-axis SameLine gaps and a trailing Dummy for row
spacing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Timestamp + message render in the Mono font with the timestamp dimmed;
INFO/WARNING/ERROR tags retuned to the Monolith blue/amber/red.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Rebrand the old text editor to Beam: per-file Document tabs, Ctrl+N/S/W/F/G
shortcuts, Ctrl+PageUp/Down tab cycling, a mono status bar, and a Display-font
wordmark.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Draw the gizmo tools + play/simulate/stop transport centred in the titlebar
(rect excluded from the window drag zone) instead of over the viewport, so it
stays usable when Beam covers the viewport. Viewport gains IsVisible(); the
settings/orientation/selection/perf overlays only draw when the viewport is the
active tab.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Full presentation remake: mono breadcrumb + right-aligned New/view/sort/options
controls, asset-type filter chips, grid/list view toggle, Name/Type/Modified
sorting, pinned favourite folders, and a selected-asset details footer. View
mode, sort, filter and favourites persist via Application settings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Website-ready reference for the editor: architecture, panels, viewport/camera,
content browser, theme/fonts/icons, keybindings, and extension recipes. Each
subject grounded in source (path:line) with how-it-was-made and how-to-modify
sections.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Add the LaptopStart sample scene, refresh the asset registry and project file
to reference it, and save the redesigned editor dock layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Copilot AI lite review requested due to automatic review settings August 29, 2026 21:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The change updates Linux build and run workflows, adds Vulkan SDK setup, refreshes the editor theme and panels, introduces Simple and Advanced layouts, adds Statistics and Beam features, updates sample scenes, and adds editor documentation.

Changes

Linux workflow

Layer / File(s) Summary
Linux build, runtime, and IDE workflow
.claude/docs/Building.md, .claude/docs/Threading.md, scripts/*, .idea/*, Editor/premake5.lua, Lux-Runtime/premake5.lua
Linux builds can fetch a pinned Vulkan SDK. Linux runs can build automatically. IDE run configurations are included. Linux links include libatomic.

Editor shell and visual foundation

Layer / File(s) Summary
Theme, fonts, and editor controls
Core/Source/Lux/ImGui/*, Core/Source/Lux/Editor/EditorConsolePanel.cpp, Core/Source/Lux/Editor/SceneHierarchyPanel.cpp, Editor/Resources/Fonts/*
The theme, fonts, ImPlot lifecycle, toggle controls, console, and hierarchy styling were updated.
Editor shell, layout, and statistics
Editor/Source/EditorLayer.*, Editor/Source/Panels/ApplicationSettingsPanel.*, Editor/Source/Panels/StatisticsPanel.*, Editor/Source/Viewport/Viewport.h, Editor/imgui.ini
The editor gains Statistics, Simple and Advanced layouts, dock reset handling, titlebar transport, viewport overlays, and persisted layout preferences.

Editor panels

Layer / File(s) Summary
Content, renderer, and Beam panels
Editor/Source/Panels/ContentBrowser*, Editor/Source/Panels/RendererDebuggerPanel.*, Editor/Source/Panels/SceneRendererPanel.*, Editor/Source/Panels/TextEditorPanel.*
The Content Browser gains filters, favorites, sorting, list view, and persistence. Renderer panels gain searchable cards, charts, and tabs. Beam becomes a multi-document editor.

Sample content

Layer / File(s) Summary
Sample project scenes and registry
Editor/LuxSampleProject/Assets/*, Editor/LuxSampleProject/LuxSample.luxproj
The sample project starts with LaptopStart.luxscene. Asset registry statuses and timestamps were updated. SkyDiver.luxscene now stores post-processing settings at scene level.

Documentation

Layer / File(s) Summary
Editor documentation
docs/Editor/*
New documentation covers editor architecture, panels, content browsing, extension points, keybindings, theme resources, and viewport behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🟠 High · up to bd31a

This redesign currently risks data loss in Beam, undefined behavior in Content Browser operations, and a non-rendering default sample scene; its build changes can also terminate Release physics workers or leave Vulkan SDK setup unusable. Merge should be blocked until these concrete issues are fixed or explicitly accepted.

Sequence Diagram(s)

sequenceDiagram
  participant EditorLayer
  participant PanelManager
  participant ContentBrowserPanel
  participant StatisticsPanel
  participant SceneRenderer
  EditorLayer->>PanelManager: register editor panels
  EditorLayer->>ContentBrowserPanel: render persisted browser state
  EditorLayer->>StatisticsPanel: set SceneRenderer context
  StatisticsPanel->>SceneRenderer: read frame and scene metrics
  ContentBrowserPanel-->>EditorLayer: report selection or rename action
Loading

Poem

A rabbit hops through lime-lit code
New panels bloom along the road
Vulkan waits by scripts so neat
Beam tabs dance on nimble feet
Charts hum softly, scenes take flight
The editor glows warm graphite-bright

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.70% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 126 functions across 29 files. (26 skippe… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main editor redesign and names several changes covered by the pull request, including the Monolith theme, profiler, and Beam text editor. Some listed features are not …
Full details: Docstring Coverage

Explanation

Docstring coverage is 12.70% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 126 functions across 29 files. (26 skipped: 26 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch features/editor-redesign

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sheazywi sheazywi self-assigned this Aug 29, 2026
sheazywi and others added 11 commits August 30, 2026 21:56
Phase 4 — after an undo/redo, select the entities that step touched (that still
exist), so the user sees what changed; handles multi-select and structural edits
(undo a delete re-selects the recreated entity). RestoreSelection derives the set
from the command's EntityDeltas rather than storing a separate selection snapshot.

Phase 5 — UndoHistoryPanel (View > History): a header-only EditorPanel that reads
the stack through function bindings and renders it Photoshop-style (past states top,
current middle, redoable below); click a row to jump to that state. Transaction
grouping proved unnecessary — the whole-scene diff at commit already makes one action
one step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
UndoCommand gains optional CustomUndo/CustomRedo closures; when set, undo/redo call
them instead of applying a scene diff, so one stack (and one Ctrl+Z / menu / History
panel) holds both scene and non-scene commands. EditorLayer::PushUndoCommand is the
entry point.

Renderer/project settings are captured as a ProjectSceneRendererSettings (via
SceneRenderer::WriteProjectSettings, which excludes the transient debug-view toggles),
diffed against a baseline, and restored via ApplyProjectSettings (the canonical
apply+refresh used on project load). Shows as "Undo Renderer Settings". Scene
post-processing and material assignment were already covered by the scene diff.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Play/Simulate get their own transient undo stack (m_Play*), baselined on Play/
Simulate and cleared on Stop, so a play session never touches the edit-mode history.
Undo/redo route through ActiveUndoStack() (edit stack in Edit mode, play stack
otherwise), so the same Ctrl+Z, Edit menu, and History panel drive both; edit-mode
behaviour is unchanged.

A play step is a closure command whose restore rebuilds the runtime scene from the
snapshot and restarts its runtime (OnRuntimeStop -> DeserializeFromSnapshots ->
OnRuntimeStart, via AdoptRuntimeScene) -- so undoing during Play resets physics/scripts
to that point. A headless self-test confirmed the round-trip including the mid-play
restart. CaptureSceneEntities is now parameterized by scene so the play path reuses it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Each UndoCommand records its heap payload size (ApproxBytes = entity/meta YAML);
TrimUndoStack evicts the oldest steps until under both a step cap (s_MaxUndoDepth,
64 -> 256) and a byte budget (s_MaxUndoBytes = 128 MB), always keeping at least one.
Applies to the edit and play stacks. Replaces the fixed 64-step cap at all commit
sites, so a few huge diffs can't blow up memory while small edits keep a long history.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
SceneSerializer::RunRoundTripSelfTests (following the RunValidationSelfTests pattern)
builds a scene with a hierarchy + components, does split -> reassemble -> re-split, and
confirms every entity's YAML and the scene metadata are reproduced exactly. Surfaced as
a button in the Renderer Debugger next to the render-graph self-tests, so a regression in
the snapshot path the undo system depends on is one click from being caught.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Asset rename/move/delete are now reversible closure commands pushed onto the editor
undo stack via ContentBrowserPanel::SetUndoPush -> EditorLayer::PushUndoCommand.
Reversible primitives are static RawRenameAsset/RawMoveAsset/TrashAsset/RestoreAsset;
the public ops call the primitive then push {undo,redo} closures that reverse it and
Refresh the browser.

Delete is fail-safe: it never calls FileSystem::DeleteFile — it moves the file to
<project>/.trash/<handle>__<name> (outside the scanned asset dir so ProcessDirectory
won't re-import it), deregisters the handle, and undo moves it back and re-registers the
SAME handle so scene references still resolve. Trash is never auto-purged. Directory ops
keep their existing permanent-delete path (not covered). The trash file-move round-trip
was verified; the full delete->undo flow needs interactive testing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
After an undo or redo, EditorLayer::UI_UndoToast fades a short "Undo: <label>" /
"Redo: <label>" pill in at the bottom of the window (~1.6s + 0.5s fade) so the action
registers even when the change is subtle or off-screen. Other Phase 9 items (held-Ctrl+Z
repeat, per-widget coalescing, extra history-panel a11y) deliberately skipped -- see
docs/Editor/Undo-Redo.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
…f registry

On exit (File > Exit / SIGTERM), the editor segfaulted while destroying GPU resources.
Root cause was a static-destruction-order fiasco: Project::s_AssetManager is an inline
static Ref that outlives Application shutdown, so its cached scenes' Vulkan resources
(IndexBuffer, etc.) were freed at program exit — after the device was already gone.

Two fixes:
- EditorLayer::OnDetach now calls Project::SetActive(nullptr), which runs the asset
  manager's Shutdown() and drops the static Ref while the Vulkan device is still alive.
- RefUtils' live-reference registry (Ref.cpp) is now an intentionally-leaked, construct-
  on-first-use singleton, so it outlives every static Ref and RemoveFromLiveReferences()
  can never erase() into a freed hash table (the deeper latent cause of the same crash).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
- New-tab '+': drop ImGuiTabItemFlags_Trailing and render it after the tab loop so it
  sits inline with the tabs; hide the tab bar entirely when no file is open (the lone '+'
  looked orphaned below the toolbar).
- Replace the toolbar separator (it collided with the tab strip) with a definite gap.
- Editor/Diff toggle now pins flush-right (width was overstated at 120px).
- Status bar moved below the editor (was between the tabs and the text).
- 'BEAM' wordmark: push the display font before AlignTextToFramePadding so it lines up
  with the toolbar buttons.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011rEemocEgDwnS1Lm7W9TDQ
Add a fuzzy command palette (Ctrl+Shift+P) over every menu action and
panel toggle, and a consolidated Profiler panel — frame-time graph,
CPU zone breakdown, GPU pass timings, and scene/memory stats — built
purely over existing Application/SceneRenderer telemetry (no new
instrumentation).

The Profiler supersedes the lightweight Statistics panel; its unique
draw-call / visible-instance / VRAM metrics are folded into the new
Scene & Memory section, and StatisticsPanel is removed.

Also: neutralize Beam's tab-strip styling (kills the stray lime tab
underline) and fix the content-browser top bar so the breadcrumb no
longer overlaps the search box.

The palette shortcut reads the chord through ImGui input so it fires
regardless of which panel holds focus; results auto-scroll only on
keyboard nav, leaving wheel scrolling free.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
Correctness fixes:
- Content browser: descending sort no longer returns !less (that broke
  strict weak ordering — UB in std::sort); reverse the operands instead.
- Content browser: defer ToggleFavorite out of the range-for so it can't
  invalidate the iterator / dangle the favorite path.
- Content browser: unique per-directory context-menu id (was shared).
- Beam: keep a document dirty and log when the write fails (was marking
  it clean on failure — silent data loss); refuse Save As onto a path a
  another tab already owns; prompt Save/Discard/Cancel before closing a
  dirty tab.
- ImGuiEx::ToggleSwitch: InvisibleButton with EnableNav + its return value
  so keyboard/gamepad activation works (IsItemClicked is mouse-only).

Build/docs:
- premake: JPH_FLOATING_POINT_EXCEPTIONS_ENABLED is Debug/Debug-AS only
  now (was defined in Release, which can hard-crash on degenerate physics).
- Default dock layout: dock "Beam"/"Profiler" (were the dead names
  "Text Editor"/"Statistics").
- Strip stray </content>/</invoke> artifacts from the editor docs.
- Threading.md: correct the libatomic/LTO linker guidance.
- Linux-Fetch.sh: guard the Vulkan SDK swap on a successful download.
- Linux-Run.sh: honor an explicit VULKAN_SDK; fail loudly on a missing SDK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
@sheazywi sheazywi changed the title Editor redesign: Monolith theme, reworked panels, Beam, docs Editor redesign: Monolith theme + undo/redo, command palette, Profiler, Beam Sep 2, 2026
sheazywi and others added 10 commits September 2, 2026 15:25
Extend TagComponent with editor-only Locked and LabelColor (packed RGBA),
serialized with the scene (emitted only when set, so existing scenes stay
byte-identical) and read with safe defaults for older scenes.

Hierarchy: a colour-label stripe on the row's left edge; a lock badge and
dimmed name when locked; a right-click menu for Lock/Unlock and a label
palette (6 swatches + None). Every change raises an undo step.

Locked = protected: no drag-reparent, no delete (also filtered out of a
multi-selection delete), and the Inspector is read-only with an Unlock
button. Search/filter and the mesh-visibility eye already existed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
Add EditorCamera::SetOrbitState to restore a full orbit pose (focal
point, distance, pitch, yaw), and wire nine session-local viewport
bookmarks in EditorLayer: Ctrl+<1-9> captures the current view, <1-9>
jumps to it (gated on the viewport being hovered and no text field
focused). A View -> Camera Bookmarks submenu exposes Set/Jump per slot.

Persistence across sessions is a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
Pin the current selection with Ctrl+B (also a palette command and a
View -> Entity Bookmarks submenu). Selecting a bookmark selects the
entity and frames the editor camera on its world position via
EditorCamera::Focus.

Bookmarks are per-scene UUIDs: cleared on scene load, and stale handles
(e.g. deleted entities) are skipped in the menu. Session-only for now.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
Prefabs had no disk persistence: AssetImporter had no serializer for
AssetType::Prefab, so a .lprefab hit the "no loader" fallback and
GetAsset<Prefab> failed. Add PrefabSerializer (mirrors SceneAssetSerializer):
Serialize writes the prefab's sub-hierarchy as a scene via SceneSerializer;
TryLoadData deserializes it and re-identifies the single parentless root.
Registered in AssetImporter; PrefabSerializer befriended by Prefab.

Editor: "Create Prefab from Selection" (Edit menu + command palette) builds
a Prefab from the selected entity, writes the .lprefab, and imports it.

This is the foundation focus-mode save-back needs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
A panel to inspect the SceneRenderer's intermediate targets: final
composite, HDR scene colour, and the G-buffer attachments (base colour,
normals, metal/rough, material ID, object ID, velocity), with fit/zoom
and a resolution readout.

It only reads the renderer's existing stable image accessors and draws
them via ImGuiEx::Image on the main-thread ImGui path the viewport
already uses — no render-graph, shader, or pass changes, so it can't
perturb the frame it is viewing. Unavailable targets (feature off / not
yet produced) show a note instead of asserting.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
TagComponent is excluded from AllComponents/DuplicateComponents (its name
is copied specially at entity creation), so the editor-only Locked and
LabelColor fields were dropped by Scene::Copy and DuplicateEntity —
Ctrl+D on a locked or colour-labelled entity produced a bare duplicate.
Carry both fields explicitly in both paths, alongside the name copy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
Drop FrameDebuggerPanel and its EditorLayer wiring. Its render-target
views largely duplicated what the existing debug-view-mode switch
already surfaces, so it wasn't worth keeping as a separate panel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
LoadProjectAssembly now records a ScriptEngine::ReloadStatus (success +
script count, or a failure reason) exposed via GetLastReloadStatus().
EditorLayer routes all three reload entry points (Ctrl+R, Edit menu,
command palette) through ReloadScriptsWithFeedback(), which pops a green
"C# reloaded" / red "C# reload failed" toast; detailed errors still go
to the Log.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
Live script-field editing already worked: during Play the hierarchy
context is the runtime scene and FieldStorage reads/writes the live Coral
instance, so the inspector controls reflect and edit the running object.
Add a green "● Live" marker to the Script section while the scene runs so
that's obvious rather than looking like the stored snapshot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZz1zmqCagPaqQwAu6Ci9x
Add C# editor-hint attributes read by ScriptEngine::BuildAssemblyCache via
Coral field reflection and applied in the inspector's Script section:
- [Range(min,max)] draws a slider for Float/Int fields
- [Header(text)] draws a bold grouping label above a field
- [Tooltip(text)] shows help text on hover

FieldMetadata carries the hints; DrawScriptFieldControl takes an optional
range. No new files, no serialization or system-boundary change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LS429QSrsmSZ7NZBQ44tsk
@sheazywi sheazywi changed the title Editor redesign: Monolith theme + undo/redo, command palette, Profiler, Beam Editor redesign: Monolith theme + undo/redo, command palette, Profiler, Beam, prefabs & scripting QoL Sep 4, 2026
sheazywi and others added 6 commits September 3, 2026 23:59
Add a FolderComponent marker so an entity can act as a pure grouping node
in the hierarchy. Folders reuse the existing entity parent/child tree, so
drag-drop, nesting, and serialization work unchanged; their identity
TransformComponent is kept (world-space math untouched) but not editable,
so dropping entities into a folder never moves them.

- Components.h: FolderComponent (non-empty for entt's empty-type opt),
  added to AllComponents / DuplicateComponents / PrefabInstantiationComponents
- Scene.cpp: OnComponentAdded<FolderComponent> specialization
- SceneSerializer: Folder marker written and read
- SceneHierarchyPanel: Create Folder menu, folder icon (open/closed by
  expand state), hide Transform section + Add Component for folders
- EditorLayer: skip the gizmo when the selected entity is a folder

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LS429QSrsmSZ7NZBQ44tsk
Make prefab instances first-class in the editor:
- Create Prefab from Selection now links the source hierarchy as a live
  instance (each entity carries PrefabComponent{PrefabID, EntityID}),
  instead of leaving plain entities. Prefab::Create optionally returns the
  source-to-prefab UUID map used to stamp the link.
- Scene::CopyPrefabInstanceComponents(dst, src) syncs the prefab-tracked
  components across scenes.
- The Prefab inspector section replaces the debug PrefabID/EntityID inputs
  with the source name + Revert to Prefab (prefab -> instance) and Apply to
  Prefab (instance -> asset, re-serialized, behind a confirm modal).

Value-sync only for now; per-component add/remove and variant assets come
in later phases. Architecture doc updated with the prefab-instance model.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LS429QSrsmSZ7NZBQ44tsk
Surface and manage prefab instance overrides at component granularity:
- SceneSerializer::GetOverriddenComponentKeys diffs an instance against its
  prefab source (changed / instance-only / prefab-only components) by
  comparing their serialized blocks; YAML stays inside the serializer.
- Scene::ReconcilePrefabComponents replaces the value-only copy with exact
  add/replace/remove reconciliation, so revert/apply are exact (kills the
  Phase 1 limitation).
- Prefab inspector: an Overrides list with per-component Revert/Apply, plus
  Revert All / Apply All (apply behind a confirm modal). 'No overrides' when
  the instance matches its prefab.

Architecture doc updated. Detection/row/reconcile sets are kept in lockstep
with what SerializeEntity emits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LS429QSrsmSZ7NZBQ44tsk
Edit a prefab in isolation and push changes back to its instances:
- Double-click a .lprefab (Content Browser) to enter edit mode: the editing
  context swaps to a copy of the prefab's scene (ApplyEditorScene, factored
  out of OpenScene). A banner shows 'Editing Prefab: <name>' with Save &
  Return / Discard & Return; Ctrl+S saves the prefab; Play/Simulate are
  blocked while focused.
- SavePrefabEdits writes the asset, reloads the cache, and propagates.
- Scene::PropagatePrefabEdits refreshes un-overridden instances in the
  returned scene to the edited prefab. Transform-aware: a placed root keeps
  its position while still adopting other changes; overridden instances are
  left for per-component revert.

Covers component-value changes on existing prefab entities (structural
add/delete of entities doesn't propagate). Completes prefab variants
Phases 1-3. Architecture doc updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LS429QSrsmSZ7NZBQ44tsk
A variant is a self-contained prefab that remembers a base prefab:
- Prefab carries a BasePrefab handle; PrefabSerializer::WritePrefabFile is
  the single prefab-write path, writing an optional top-level BasePrefab key
  (backward-compatible). All prefab-write sites route through it so a
  variant's base link survives every save.
- Content Browser: right-click a .lprefab -> Create Variant (a copy of the
  base scene + base link). It instantiates and edits like any prefab; the
  edit banner shows '(variant of X)'.
- Base inheritance: saving a base prefab calls EditorLayer::PropagateToVariants,
  which refreshes each derived variant asset via Scene::AdoptPrefabBaseEdits
  (UUID-matched; un-overridden entities adopt the base edit, overridden kept).

Value-level inheritance on existing entities; structural and nested-variant
cascades are out of scope. Completes prefab variants Phases 1-4. Arch doc updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LS429QSrsmSZ7NZBQ44tsk
…yout

Populate the LaptopStart sample scene with a hierarchy folder grouping a
camera, plus a sphere mesh — a small demonstration of the new folders
feature. Register the Cylinder material and update the editor dock layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LS429QSrsmSZ7NZBQ44tsk
@sheazywi
sheazywi merged commit 3c8d424 into dev Sep 4, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants