fix(editor): debounce M2 rebuild to prevent clear+reload loop

ROOT CAUSE of NPC models not rendering: every NPC placement triggered
an immediate full clear+rebuild of ALL M2 models. During rapid clicking,
this created a destroy-reload cycle where models were cleared faster
than they could render — the log showed rebuild firing every ~200ms
with models loading OK but being destroyed before the next frame.

Fix: debounce rebuilds with a 0.5s timer. Multiple rapid placements
reset the timer, so the rebuild only fires once after the user stops
clicking. Models stay loaded and visible between placements.

Before: click → clear all → reload all → click → clear all → reload...
After:  click → click → click → (0.5s pause) → single rebuild
This commit is contained in:
Kelsi 2026-05-05 23:59:51 -07:00
parent 09e867eb07
commit 6f066dee48

View file

@ -138,15 +138,25 @@ void EditorApp::run() {
if (cmd == VK_NULL_HANDLE) continue;
// Rebuild objects AFTER beginFrame so instance SSBO uses correct frame index
// Debounce: wait 0.5s after last change before rebuilding to avoid
// clear+reload cycle on every click during rapid NPC placement
static float rebuildTimer = 0.0f;
if (objChanged || objectsDirty_) {
rebuildTimer = 0.5f;
objectsDirty_ = false;
lastObjCount_ = objCount;
if (objCount > 0 || npcCount > 0) {
vkDeviceWaitIdle(vkCtx->getDevice());
viewport_.rebuildObjects(objectPlacer_.getObjects(), npcSpawner_.getSpawns());
}
lastNpcCount_ = npcCount;
}
if (rebuildTimer > 0.0f) {
rebuildTimer -= dt;
if (rebuildTimer <= 0.0f) {
rebuildTimer = 0.0f;
if (objectPlacer_.objectCount() > 0 || npcSpawner_.spawnCount() > 0) {
vkDeviceWaitIdle(vkCtx->getDevice());
viewport_.rebuildObjects(objectPlacer_.getObjects(), npcSpawner_.getSpawns());
}
}
}
// Update M2 animations AFTER beginFrame (so getCurrentFrame is correct)
viewport_.update(dt);