Phase L L3: restyle VST editor + embed strip through the L1 kit (B pastel + spectral strip)
This commit is contained in:
@@ -9,11 +9,14 @@
|
||||
|
||||
#include "app_version.h" // vstPluginName (channel-derived embed label, S18)
|
||||
#include "bank_sync.h" // parseBankGeneration (S9 dirty-guard over the per-paint refresh)
|
||||
#include "component_geometry.h" // KitBox — the kit text/fill draw box (Phase L, L3)
|
||||
#include "draw_kit.h" // the L1 draw kit: fillSurface/text (L3)
|
||||
#include "editor_geometry.h" // Rect (shared with embed_strip)
|
||||
#include "embed_strip.h" // the pure strip layout + hit-test
|
||||
#include "ext_keys.h" // kProjExtBanksKey / kProjExtBankGenKey
|
||||
#include "reaper_bridge.h"
|
||||
#include "reasampler_processor.h"
|
||||
#include "theme.h" // Role / InteractionState / spectralColor (L3)
|
||||
|
||||
// wdltypes.h first: it defines INT_PTR portably (and pulls <windows.h> on Windows), which
|
||||
// reaper_plugin_fx_embed.h's REAPER_FXEMBED_IBitmap::Extended needs as its return type.
|
||||
@@ -41,15 +44,12 @@ namespace reasampler::vst {
|
||||
|
||||
namespace {
|
||||
#ifdef _WIN32
|
||||
// Palette — mirrored from reasampler_editor.cpp so the inline strip reads as the same tool.
|
||||
const LICE_pixel kColBackground = LICE_RGBA(28, 28, 30, 255);
|
||||
const LICE_pixel kColZone = LICE_RGBA(44, 44, 48, 255);
|
||||
const LICE_pixel kColZoneSel = LICE_RGBA(58, 96, 84, 255);
|
||||
const LICE_pixel kColZoneBorder = LICE_RGBA(20, 20, 22, 255);
|
||||
const LICE_pixel kColLevelBg = LICE_RGBA(20, 20, 22, 255);
|
||||
const LICE_pixel kColLevelFill = LICE_RGBA(120, 200, 160, 255);
|
||||
const LICE_pixel kColEmpty = LICE_RGBA(70, 70, 74, 255);
|
||||
const COLORREF kRgbText = RGB(210, 230, 220);
|
||||
// Kit adapter (Phase L, L3): the embed shell's Rect (editor_geometry) -> the kit's KitBox
|
||||
// (component_geometry). Every embed surface now draws by palette ROLE via the L1 kit, retiring
|
||||
// the local pre-L1 forest-green palette + raw GDI DrawTextA.
|
||||
KitBox toKitBox(const Rect& r) {
|
||||
return KitBox{r.left, r.top, r.width(), r.height()};
|
||||
}
|
||||
|
||||
// A short display name for a bank sample id, from the snapshotted list (the editor's helper,
|
||||
// duplicated small rather than shared across the shell/pure boundary).
|
||||
@@ -136,6 +136,12 @@ TPtrInt ReaSamplerEmbed::embed_message(int msg, TPtrInt parm2, TPtrInt parm3) {
|
||||
return 0; // not a build target off Windows
|
||||
#endif
|
||||
case REAPER_FXEMBED_WM_CREATE:
|
||||
#ifdef _WIN32
|
||||
// Create the kit's cached AA fonts before the first paint (Phase L, L3).
|
||||
// Idempotent + process-global (shared with the editor in this binary); NOT torn
|
||||
// down per-view — the OS reclaims the tiny static HFONT set at module unload.
|
||||
kitFontsInit();
|
||||
#endif
|
||||
refresh(); // prime the first paint's snapshot
|
||||
return 0;
|
||||
case REAPER_FXEMBED_WM_DESTROY:
|
||||
@@ -184,62 +190,65 @@ bool ReaSamplerEmbed::paint(TPtrInt bitmap, TPtrInt drawInfo) {
|
||||
|
||||
// REAPER hands us its own bitmap sized to the embed area; draw directly into it (unlike
|
||||
// the editor, which owns a LICE_SysBitmap and BitBlt's). Origin is the bitmap's (0,0).
|
||||
LICE_FillRect(bmp, 0, 0, w, h, kColBackground, 1.0f, 0);
|
||||
// Base canvas through the kit (bg/base + micro-gradient), Phase L L3.
|
||||
fillSurface(bmp, KitBox{0, 0, w, h}, Role::BgBase, InteractionState::Rest);
|
||||
|
||||
const EmbedLayout layout = layoutEmbed(w, h);
|
||||
|
||||
if (map_.zones.empty()) {
|
||||
// No opt-in zones authored: show a single faint band spanning the keymap area so the
|
||||
// strip reads as "present, no zones" — the default single-capture face lives in the
|
||||
// editor (this S6 strip mirrors the zones map only).
|
||||
// No opt-in zones authored: a faint bg/cell band spanning the keymap area so the strip
|
||||
// reads as "present, no zones" — the default single-capture face lives in the editor.
|
||||
LICE_FillRect(bmp, layout.keymap.left, layout.keymap.top, layout.keymap.width(),
|
||||
layout.keymap.height(), kColEmpty, 0.5f, 0);
|
||||
HDC dc = bmp->getDC();
|
||||
SetBkMode(dc, TRANSPARENT);
|
||||
SetTextColor(dc, kRgbText);
|
||||
RECT gr{layout.keymap.left + 4, layout.keymap.top, layout.keymap.right,
|
||||
layout.keymap.bottom};
|
||||
layout.keymap.height(), toLice(roleColor(Role::BgCell)), 0.5f, 0);
|
||||
const std::string label = reasampler::vstPluginName() + // channel-derived (S18)
|
||||
(samples_.empty() ? " (bank empty)" : " (no zones)");
|
||||
DrawTextA(dc, label.c_str(), -1, &gr,
|
||||
DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
|
||||
const Rect labelR{layout.keymap.left + 4, layout.keymap.top, layout.keymap.right,
|
||||
layout.keymap.bottom};
|
||||
text(bmp, toKitBox(labelR), label.c_str(), Font::Label, Role::TextPrimary, Align::Left);
|
||||
} else {
|
||||
// Draw each zone as a segment across the keymap span, first-match order (so the
|
||||
// painted order matches selection + playback). The selected zone is highlighted.
|
||||
// Draw each zone as a segment across the keymap span, first-match order (so the painted
|
||||
// order matches selection + playback). Each segment takes its PASTEL SPECTRAL hue from
|
||||
// the center of its key span (spectralColor — §4), so the strip reads as the same
|
||||
// spectrum as the editor's keyboard strip. The SELECTED zone lifts to accent-primary
|
||||
// + a static glow ("which zone is live", never a pulse — §3.5).
|
||||
for (int i = 0; i < static_cast<int>(map_.zones.size()); ++i) {
|
||||
const PerformanceZone& z = map_.zones[i];
|
||||
const Rect r = zoneSegmentRect(layout, z.lowNote, z.highNote);
|
||||
if (r.width() <= 0) continue;
|
||||
const bool sel = (i == selectedZone_);
|
||||
LICE_FillRect(bmp, r.left, r.top, r.width(), r.height(),
|
||||
sel ? kColZoneSel : kColZone, 1.0f, 0);
|
||||
LICE_DrawRect(bmp, r.left, r.top, r.width() - 1, r.height() - 1, kColZoneBorder,
|
||||
1.0f, 0);
|
||||
// Label the segment with the sample name when it is wide enough to read.
|
||||
if (sel) {
|
||||
// Static glow halo, then the crisp accent-primary fill.
|
||||
LICE_FillRect(bmp, r.left - 2, r.top, r.width() + 4, r.height(),
|
||||
toLice(roleColor(Role::AccentHot)), 0.30f, 0);
|
||||
LICE_FillRect(bmp, r.left, r.top, r.width(), r.height(),
|
||||
toLice(roleColor(Role::AccentPrimary)), 1.0f, 0);
|
||||
} else {
|
||||
const double t = ((z.lowNote + z.highNote) * 0.5) / 127.0;
|
||||
LICE_FillRect(bmp, r.left, r.top, r.width(), r.height(),
|
||||
toLice(spectralColor(t)), 0.65f, 0);
|
||||
}
|
||||
LICE_DrawRect(bmp, r.left, r.top, r.width() - 1, r.height() - 1,
|
||||
toLice(roleColor(Role::LineHairline)), 1.0f, 0);
|
||||
// Label the segment with the sample name when it is wide enough to read. The
|
||||
// selected (accent-fill) segment draws its label in bg/base for contrast (the
|
||||
// tight text-on-pastel pair, §4); the rest in text/primary.
|
||||
if (r.width() >= 24) {
|
||||
HDC dc = bmp->getDC();
|
||||
SetBkMode(dc, TRANSPARENT);
|
||||
SetTextColor(dc, kRgbText);
|
||||
RECT gr{r.left + 3, r.top, r.right - 2, r.bottom};
|
||||
const std::string label = sampleLabel(samples_, z.sampleId);
|
||||
DrawTextA(dc, label.c_str(), -1, &gr,
|
||||
DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS);
|
||||
const Rect lr{r.left + 3, r.top, r.right - 2, r.bottom};
|
||||
text(bmp, toKitBox(lr), sampleLabel(samples_, z.sampleId).c_str(),
|
||||
Font::Label, sel ? Role::BgBase : Role::TextPrimary, Align::Left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The level band: a static background here; a live activity level is a later refinement
|
||||
// (the processor would publish a peak the UI thread reads). Draw the empty band so the
|
||||
// strip's geometry is complete and the DAW-verify sees the band lifecycle now.
|
||||
// The level band: a recessed bg/cell channel with an accent-primary fill following the
|
||||
// live activity level (a direct level follow — the one permitted "motion", §3.5).
|
||||
if (layout.levelBand.height() > 0) {
|
||||
LICE_FillRect(bmp, layout.levelBand.left, layout.levelBand.top,
|
||||
layout.levelBand.width(), layout.levelBand.height(), kColLevelBg, 1.0f,
|
||||
0);
|
||||
fillSurface(bmp, toKitBox(layout.levelBand), Role::BgCell, InteractionState::Pressed);
|
||||
const double level = processor_ ? processor_->embedActivityLevel() : 0.0;
|
||||
const Rect fill = levelFillRect(layout, level);
|
||||
if (fill.width() > 0) {
|
||||
LICE_FillRect(bmp, fill.left, fill.top, fill.width(), fill.height(),
|
||||
kColLevelFill, 1.0f, 0);
|
||||
toLice(roleColor(Role::AccentPrimary)), 1.0f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user