Skip to content

Commit 5346bc5

Browse files
committed
qmlui: improve external controller mapping by layout
1 parent 20b5a8f commit 5346bc5

3 files changed

Lines changed: 653 additions & 78 deletions

File tree

qmlui/stagewizard/stagewizard.h

Lines changed: 104 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include <QVector3D>
2727
#include <QColor>
2828

29+
#include <climits>
30+
2931
#include "vcpage.h"
3032

3133
class Doc;
@@ -459,26 +461,112 @@ private slots:
459461
QString name; ///< Profile channel name (for logging/preview)
460462
};
461463

462-
/** Pools of still-unassigned controller channels, refilled by
463-
* buildControllerPools() at the start of a mapping run. */
464-
struct CtrlPools
464+
/** The role a VC widget plays, which decides WHERE on the controller it
465+
* lands. On a grid surface each role owns a horizontal band of rows, so a
466+
* given kind of control always sits in the same place no matter which page
467+
* is showing — that spatial stability is the whole point of mapping to a
468+
* grid rather than handing out channels in creation order. */
469+
enum CtrlRole
465470
{
466-
QList<CtrlChannel> buttons; ///< Button-type channels
467-
QList<CtrlChannel> faders; ///< Slider/Knob/Encoder-type channels
468-
int buttonTotal = 0; ///< Pool sizes before any hand-out
469-
int faderTotal = 0;
470-
int nextButton = 0; ///< Hand-out cursors
471-
int nextFader = 0;
471+
CtrlRolePageTab, ///< Frame page selector (shared across pages)
472+
CtrlRoleColor, ///< Colour / colour-wheel swatch
473+
CtrlRoleEffect, ///< Movement, shutter, strobe, blinder …
474+
CtrlRoleShowCue, ///< Blackout / Open / Big Moment … (shared)
475+
CtrlRoleCount
476+
};
477+
478+
/** How the wizard understood the patched controller. */
479+
enum CtrlSurfaceKind
480+
{
481+
CtrlSurfaceNone, ///< Nothing patched / nothing usable
482+
CtrlSurfaceGrid, ///< A rows x cols pad matrix was recognised
483+
CtrlSurfaceStrip, ///< Mixer-style: faders only, buttons left alone
484+
CtrlSurfaceLinear ///< Unknown layout: hand out buttons in order
472485
};
473486

474-
/** Fill $pools from the input profile patched on m_ctrlUniverse. With no
475-
* profile assigned, falls back to a synthetic layout (channels 0..7 faders,
476-
* 8.. buttons) so a bare MIDI/OSC patch still gets a usable mapping. */
477-
void buildControllerPools(CtrlPools &pools) const;
487+
/** A recognised pad grid. $cells is row-major and normalised so that row 0
488+
* is always the PHYSICAL TOP row: profiles disagree on whether "row 1" is
489+
* the top or the bottom (APC mini numbers from the bottom, Launchpad Mini
490+
* MK3 from the top), so buildControllerSurface() flips when needed. A cell
491+
* with channel == invalidChannel is a hole in the matrix. */
492+
struct CtrlGrid
493+
{
494+
int rows = 0;
495+
int cols = 0;
496+
QList<CtrlChannel> cells; ///< rows * cols, row-major, top row first
497+
498+
static const quint32 invalidChannel = UINT_MAX;
499+
500+
bool isValid() const { return rows > 0 && cols > 0; }
501+
const CtrlChannel *at(int r, int c) const
502+
{
503+
if (r < 0 || c < 0 || r >= rows || c >= cols)
504+
return nullptr;
505+
const CtrlChannel &cc = cells.at(r * cols + c);
506+
return cc.channel == invalidChannel ? nullptr : &cc;
507+
}
508+
};
509+
510+
/** A contiguous band of grid rows reserved for one role, plus the cursor
511+
* tracking how far into it we have allocated. */
512+
struct CtrlBand
513+
{
514+
int firstRow = 0;
515+
int rowCount = 0;
516+
int nextCell = 0; ///< Running index within the band, row-major
517+
};
518+
519+
/** Everything the mapper knows about the patched controller: the grid (when
520+
* one was recognised), the per-role bands, and the leftover pools. */
521+
struct CtrlSurface
522+
{
523+
CtrlSurfaceKind kind = CtrlSurfaceNone;
524+
525+
CtrlGrid grid;
526+
CtrlBand bands[CtrlRoleCount];
527+
528+
/// Buttons that are NOT grid cells (Shift, Scene launch, arrows, …).
529+
/// Used as overflow once a role's band is full.
530+
QList<CtrlChannel> aux;
531+
int nextAux = 0;
532+
533+
/// Buttons in plain creation order — CtrlSurfaceLinear only.
534+
QList<CtrlChannel> buttons;
535+
int nextButton = 0;
536+
537+
QList<CtrlChannel> faders;
538+
int nextFader = 0;
539+
540+
int buttonTotal = 0; ///< Mappable counts, for the step 5 preview
541+
int faderTotal = 0;
542+
};
478543

479-
/** Take the next free button/fader channel. Returns false when exhausted. */
480-
bool nextButtonChannel(CtrlPools &pools, quint32 &channel) const;
481-
bool nextFaderChannel(CtrlPools &pools, quint32 &channel) const;
544+
/** Inspect the profile patched on m_ctrlUniverse and decide how to lay the
545+
* VC out on it: recognise a pad grid from the channel names, split the
546+
* non-grid buttons into the aux pool, and reserve a row band per role.
547+
* With no profile, falls back to a synthetic linear layout so a bare
548+
* MIDI/OSC patch still gets a usable mapping. */
549+
void buildControllerSurface(CtrlSurface &surface) const;
550+
551+
/** Parse $profile's button names into a normalised grid. Returns false when
552+
* no grid convention is recognised; $aux collects the buttons left over. */
553+
static bool parseControllerGrid(const QLCInputProfile *profile,
554+
CtrlGrid &grid, QList<CtrlChannel> &aux);
555+
556+
/** Reserve a band of rows per role, sized for the layout the VC generator
557+
* is about to build ($pageCount pages, $colorRows rows of swatches). */
558+
static void assignControllerBands(CtrlSurface &surface, int pageCount,
559+
int colorRows);
560+
561+
/** Take the next channel for $role. On a grid this walks the role's band
562+
* left-to-right / top-to-bottom and spills into the aux pool when full;
563+
* otherwise it just pops the linear button pool. Returns false when
564+
* everything is exhausted. */
565+
bool nextRoleChannel(CtrlSurface &surface, CtrlRole role,
566+
quint32 &channel) const;
567+
568+
/** Take the next free fader channel. Returns false when exhausted. */
569+
bool nextFaderChannel(CtrlSurface &surface, quint32 &channel) const;
482570

483571
/** Attach a controller input source to $widget's control $controlID, and
484572
* apply feedback / colour feedback when enabled. $color is the widget's

0 commit comments

Comments
 (0)