Strip FX writes from the Design View mode switch; split view.cpp into park/lanes/reconcile/tracks and add the record-scoped undo repair pass

This commit is contained in:
2026-08-06 17:19:43 -04:00
parent d455b9a2fa
commit c4038a9e9c
22 changed files with 1172 additions and 1146 deletions
+80
View File
@@ -0,0 +1,80 @@
// See view_reconcile.h. Compiled into the reaper_reasampler module; includes
// reaper_plugin_functions.h without REAPERAPI_IMPLEMENT (main.cpp owns that).
// The decision is pure (header, test_view_reconcile.cpp); this file owns the memo's
// lifetime and the writes.
#include "shell/view/view_reconcile.h"
#include <vector>
#include "shell/view/view_park.h" // trackFlagParm / writeIfChanged
#include "shell/view/view_tracks.h"
#define REAPERAPI_MINIMAL
#define REAPERAPI_WANT_EnumProjects
#define REAPERAPI_WANT_TrackList_AdjustWindows
#define REAPERAPI_WANT_Undo_BeginBlock2
#define REAPERAPI_WANT_Undo_EndBlock2
#define REAPERAPI_WANT_UpdateArrange
#define REAPERAPI_WANT_ValidatePtr2
#include "reaper_plugin_functions.h"
namespace reasampler {
namespace {
// What the last apply left driven, and in which project. The owner is COMPARE-ONLY
// and never dereferenced (the same discipline the panel's own project memos take): a
// closed project's pointer must never be followed, only found unequal. A project we
// hold no memo for gets no repair — the tool has no account of driving anything
// there, so it has no opinion.
ReaProject* g_appliedOwner = nullptr;
view::AppliedState g_applied;
} // namespace
void noteAppliedState(ReaProject* proj, const ViewModeModel& model) {
g_appliedOwner = proj ? proj : EnumProjects(-1, nullptr, 0);
g_applied = view::appliedState(model);
}
void reconcileAppliedFlags(ViewModeModel& model, ReaProject* proj) {
ReaProject* const project = proj ? proj : EnumProjects(-1, nullptr, 0);
if (!ValidatePtr2(nullptr, project, "ReaProject*")) return;
const view::AppliedState reloaded = view::appliedState(model);
const std::vector<TrackFlagOp> ops =
project == g_appliedOwner ? planReconcile(g_applied, reloaded)
: std::vector<TrackFlagOp>{};
// Adopted whether or not anything is written: from here the memo describes the
// project as it now stands, so a second reload cannot replay a repair that has
// already happened over values the user has since changed.
g_appliedOwner = project;
g_applied = reloaded;
if (ops.empty()) return;
TrackHandles handleByGuid;
readFolderEntries(project, handleByGuid);
const TrackByGuid trackByGuid = indexHandles(handleByGuid);
bool wrote = false;
Undo_BeginBlock2(project);
{
UiRefreshHold uiHold;
for (const TrackFlagOp& op : ops) {
MediaTrack* tr = resolve(trackByGuid, op.guid);
if (!tr) continue; // stale/deleted GUID — prune
if (writeIfChanged(tr, trackFlagParm(op.flag), static_cast<double>(op.value)))
wrote = true;
}
}
Undo_EndBlock2(project, "", 0); // discard form — see the header
if (wrote) {
TrackList_AdjustWindows(false); // tracks reappearing owe the full relayout
UpdateArrange();
}
}
} // namespace reasampler