feat(view): D4 Design View action family + reapply-on-open wiring

Register toggle/activate/tag/untag/show-both actions driving the D2
shell and D3 model; reapply saved active mode on project load via a
persist load-signal seam. Shared guidString helper; pure nextModeId
unit-tested.
This commit is contained in:
2026-07-22 21:46:58 -04:00
parent 322581227c
commit ae41cad4f5
12 changed files with 418 additions and 16 deletions
+28 -2
View File
@@ -20,10 +20,12 @@
#include <string>
#include "actions.h"
#include "bank_model.h"
#include "bank_panel.h"
#include "capture.h"
#include "persist.h"
#include "view.h"
// Persistent action-id prefix for the ReaSampler action family.
// Every bindable action (capture / insert / slot / verify) mints its command id
@@ -63,6 +65,18 @@ static reasampler::ReaSamplerSession g_session;
static void OnTimer()
{
g_session.poll();
// D4 reapply-on-open glue. persist stays MODEL-ONLY (it loads the saved view
// model but deliberately does NOT apply visibility — that would couple persist
// to the view shell). Instead poll() raises a one-shot load signal; here — the
// integration layer that already drives both persist and the view shell — we
// drain it and reapply the SAVED active mode's visibility/processing so opening a
// project saved in Design mode parks the Arrange tracks automatically, no manual
// toggle. Fires exactly once per load (consumeLoadSignal clears it); idle ticks
// skip it. proj = nullptr -> REAPER's active project (the one poll just loaded).
if (g_session.consumeLoadSignal())
reasampler::applyMode(g_session.view(), g_session.view().activeModeId(), nullptr);
// Reflect a live bank change (capture / project load) in the docked grid.
// Cheap when the bank is unchanged (a fingerprint compare); repaints only on
// an actual change. No-op when the panel is closed.
@@ -118,6 +132,9 @@ static bool OnHookCommand(int command, int /*flag*/)
if (command == 0) return false;
if (command == g_cmdCaptureMasterSpike) { RunCaptureMasterSpike(); return true; }
if (command == g_cmdToggleBankPanel) { reasampler::bankPanelToggle(); return true; }
// Design View action family (D4). Claims only its own ids; returns false for the
// rest so this hook keeps looking (per the contract).
if (reasampler::designViewHandleCommand(command)) return true;
return false;
}
@@ -146,6 +163,9 @@ extern "C" REAPER_PLUGIN_DLL_EXPORT int REAPER_PLUGIN_ENTRYPOINT(
g_rec->Register("-timer", (void*)&OnTimer);
g_rec->Register("-toggleaction", (void*)&OnToggleAction);
g_rec->Register("-hookcommand", (void*)&OnHookCommand);
// Tear down the Design View action family (D4) — mirror-unregisters each
// gaccel + command_id with '-'-prefixed strings. After the hook is gone.
reasampler::designViewUnregisterActions(g_rec);
g_rec->Register("-gaccel", (void*)&g_accelToggleBankPanel);
g_rec->Register("-command_id",
(void*)(REASAMPLER_ACTION_PREFIX "TOGGLE_BANK_PANEL"));
@@ -201,8 +221,14 @@ extern "C" REAPER_PLUGIN_DLL_EXPORT int REAPER_PLUGIN_ENTRYPOINT(
rec->Register("toggleaction", (void*)&OnToggleAction);
}
// One hookcommand routes every ReaSampler action (spike + toggle). Registered
// once, after both command ids are minted.
// Register the Design View action family (D4): toggle/activate mode, tag/untag/
// show-both selected tracks. Each mints its own command_id + gaccel; the single
// hookcommand below routes them via designViewHandleCommand. Registered before
// the hook so every id is minted first.
reasampler::designViewRegisterActions(rec, &g_session);
// One hookcommand routes every ReaSampler action (spike + toggle + Design View).
// Registered once, after all command ids are minted.
rec->Register("hookcommand", (void*)&OnHookCommand);
// Drive project-load / Save-As detection (M4 persist). The timer polls the