D3: persist ViewModeModel in project ext state alongside bank

Add forever-stable "view_state" key under the "reasampler" namespace.
saveToActiveProject additionally serializes the ViewModeModel;
loadFromProject restores it on every load path, defaulting on an
absent/malformed key. Model state only — no visibility apply (D4).
This commit is contained in:
2026-07-22 20:56:04 -04:00
parent 2d040d6896
commit ae76653628
2 changed files with 55 additions and 0 deletions
+36
View File
@@ -163,10 +163,46 @@ void ReaSamplerSession::saveToActiveProject() {
const std::string json = bank_.serialize();
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
kProjExtIndexKey, json.c_str());
// Additive: the Design-View model rides alongside the bank in its own key.
// Independent write — does not disturb the bank_index above.
const std::string viewJson = view_.serialize();
SetProjExtState(static_cast<ReaProject*>(proj), kProjExtNamespace,
kProjExtViewKey, viewJson.c_str());
MarkProjectDirty(static_cast<ReaProject*>(proj));
}
namespace {
// Load the Design-View model from a project's view_state key, or return a fresh
// default. An absent/empty key (older project with no view state) yields a
// default-constructed model (Arrange + Design seeded, active = Arrange) — graceful,
// never a crash. Malformed JSON is warned and also falls back to default, mirroring
// the bank's malformed-index handling. The whole model round-trips: modes,
// membership, show-both, snapshots, and active mode all ride inside the one blob.
ViewModeModel loadViewModel(ReaProject* proj) {
if (!proj) return ViewModeModel{};
const std::string viewJson =
getProjExtStateString(proj, kProjExtNamespace, kProjExtViewKey);
if (viewJson.empty()) return ViewModeModel{}; // no stored view state -> default
std::optional<ViewModeModel> loaded = ViewModeModel::deserialize(viewJson);
if (!loaded) {
ShowConsoleMsg("ReaSampler: stored view state is malformed — ignoring.\n");
return ViewModeModel{};
}
return std::move(*loaded);
}
} // namespace
void ReaSamplerSession::loadFromProject(void* proj, const std::string& projectDir) {
// The view model is restored on EVERY load path (peer-symmetry with the bank
// reset below): switching to a project with no view state must clear stale
// in-memory state, not inherit the previous project's. D3 restores MODEL STATE
// only — no visibility/processing is applied here (that is D4).
view_ = loadViewModel(static_cast<ReaProject*>(proj));
if (!proj) {
bank_ = BankIndex{};
return;