Split out of #322 (p6-s8), where it is listed under Out of scope ("3D-render-to-thumbnail for props (glyph or first-frame fallback acceptable)").
Problem
An imported prop asset has no thumbnail, so its Library row falls back to a
themed glyph (editor/src/panels/library_panel.cpp:78-86). Every bundled prop
has a real preview, so the user's own assets are visibly the second-class rows in
their own library.
Why there is no easy answer today
Bundled prop thumbnails are not rendered by the editor. They are produced
offline by scripts/gen_library_thumbnails.py — a pure-stdlib software
rasteriser that draws an orthographic three-quarter view, painter's-sorted, flat
Lambert per part colour, at 96×96 (:147 render_model(), SIZE = 96 at :53)
— and the PNGs are committed. Nothing in the C++ product generates a prop
thumbnail at all. The material half of p6-s8 sidesteps this because a texture's
thumbnail is the image, scaled.
So this issue is "give the editor a prop previewer", and there are two honest
routes:
- Port the rasteriser to C++. Deterministic, headless, no GL context, works
in tests and on a build machine, and matches the bundled thumbnails exactly
because it is the same algorithm. Around 150 lines, QImage-only.
- Render through the real renderer into an offscreen FBO. Matches what the
scene actually draws (including any future prop texturing —
see the prop-texture follow-up), but needs a GL context at import time, which
the headless editor tests deliberately do not have.
Route 1 is the recommendation, precisely because it keeps thumbnail generation
testable headless — the same constraint that put signs::render_face in the
kernel rather than behind Qt.
Scope
- A headless prop previewer producing a 96×96 RGBA PNG from a
props::PropModel.
- Called on prop import; written to
<project>/assets/library/thumbnails/<slug>.png; the manifest entry's
thumbnail field points at it.
- Regenerating a bundled prop's thumbnail through the new code path produces a
visually equivalent image to the committed PNG (this is the correctness check —
not byte identity, which the Python rasteriser does not promise either).
- Test asserts a non-blank image with more than one distinct colour, so a
silently-black render cannot pass.
Split out of #322 (
p6-s8), where it is listed under Out of scope ("3D-render-to-thumbnail for props (glyph or first-frame fallback acceptable)").Problem
An imported prop asset has no thumbnail, so its Library row falls back to a
themed glyph (
editor/src/panels/library_panel.cpp:78-86). Every bundled prophas a real preview, so the user's own assets are visibly the second-class rows in
their own library.
Why there is no easy answer today
Bundled prop thumbnails are not rendered by the editor. They are produced
offline by
scripts/gen_library_thumbnails.py— a pure-stdlib softwarerasteriser that draws an orthographic three-quarter view, painter's-sorted, flat
Lambert per part colour, at 96×96 (
:147render_model(),SIZE = 96at:53)— and the PNGs are committed. Nothing in the C++ product generates a prop
thumbnail at all. The material half of
p6-s8sidesteps this because a texture'sthumbnail is the image, scaled.
So this issue is "give the editor a prop previewer", and there are two honest
routes:
in tests and on a build machine, and matches the bundled thumbnails exactly
because it is the same algorithm. Around 150 lines,
QImage-only.scene actually draws (including any future prop texturing —
see the prop-texture follow-up), but needs a GL context at import time, which
the headless editor tests deliberately do not have.
Route 1 is the recommendation, precisely because it keeps thumbnail generation
testable headless — the same constraint that put
signs::render_facein thekernel rather than behind Qt.
Scope
props::PropModel.<project>/assets/library/thumbnails/<slug>.png; the manifest entry'sthumbnailfield points at it.visually equivalent image to the committed PNG (this is the correctness check —
not byte identity, which the Python rasteriser does not promise either).
silently-black render cannot pass.