menu redesign: hierarchical entries
This commit is contained in:
+67
-67
@@ -1,5 +1,6 @@
|
||||
#include "UIManager.h"
|
||||
#include "config.h"
|
||||
#include "SharedState.h"
|
||||
|
||||
// --- HARDWARE CONFIGURATION ---
|
||||
#define SCREEN_WIDTH 128
|
||||
@@ -51,10 +52,7 @@ void UIManager::draw(UIState currentState, int menuSelection,
|
||||
int numScaleNotes, const int* scaleNotes, int melodySeed,
|
||||
bool mutationEnabled, bool songModeEnabled,
|
||||
const Step sequence[][NUM_STEPS], int playbackStep, bool isPlaying,
|
||||
const char* mainMenu[], int mainMenuCount,
|
||||
const char* randomizeMenu[], int randomizeMenuCount,
|
||||
const char* setupMenu[], int setupMenuCount, int theme1Index,
|
||||
PlayMode playMode, int randomizeTrack, const bool* trackMute) {
|
||||
int randomizeTrack, const bool* trackMute) {
|
||||
|
||||
display.clearDisplay();
|
||||
display.setTextSize(1);
|
||||
@@ -63,20 +61,7 @@ void UIManager::draw(UIState currentState, int menuSelection,
|
||||
|
||||
switch(currentState) {
|
||||
case UI_MENU_MAIN:
|
||||
drawMenu("MAIN MENU", mainMenu, mainMenuCount, menuSelection, currentState, midiChannel, tempo, currentStrategy->getName(), queuedTheme, currentThemeIndex, numScaleNotes, scaleNotes, melodySeed, mutationEnabled, songModeEnabled, theme1Index, playMode, randomizeTrack, trackMute);
|
||||
break;
|
||||
case UI_MENU_RANDOMIZE:
|
||||
{
|
||||
const char* title = "TRACK";
|
||||
// Main section items: Setup(0), Melody(1), Scale(2), Tempo(3), Song Mode(4)
|
||||
if (menuSelection <= 4) {
|
||||
title = "MAIN";
|
||||
}
|
||||
drawMenu(title, randomizeMenu, randomizeMenuCount, menuSelection, currentState, midiChannel, tempo, currentStrategy->getName(), queuedTheme, currentThemeIndex, numScaleNotes, scaleNotes, melodySeed, mutationEnabled, songModeEnabled, theme1Index, playMode, randomizeTrack, trackMute);
|
||||
}
|
||||
break;
|
||||
case UI_MENU_SETUP:
|
||||
drawMenu("SETUP", setupMenu, setupMenuCount, menuSelection, currentState, midiChannel, tempo, currentStrategy->getName(), queuedTheme, currentThemeIndex, numScaleNotes, scaleNotes, melodySeed, mutationEnabled, songModeEnabled, theme1Index, playMode, randomizeTrack, trackMute);
|
||||
drawMenu(menuSelection, currentState, midiChannel, tempo, currentStrategy->getName(), queuedTheme, currentThemeIndex, numScaleNotes, scaleNotes, melodySeed, mutationEnabled, songModeEnabled, randomizeTrack, trackMute);
|
||||
break;
|
||||
case UI_SETUP_CHANNEL_EDIT:
|
||||
display.println(F("SET MIDI CHANNEL"));
|
||||
@@ -111,16 +96,6 @@ void UIManager::draw(UIState currentState, int menuSelection,
|
||||
display.setCursor(0, 50);
|
||||
display.println(F(" (Press to confirm)"));
|
||||
break;
|
||||
case UI_SETUP_PLAYMODE_EDIT:
|
||||
display.println(F("SET PLAY MODE"));
|
||||
display.drawLine(0, 8, 128, 8, SSD1306_WHITE);
|
||||
display.setCursor(20, 25);
|
||||
display.setTextSize(2);
|
||||
display.print(playMode == MODE_MONO ? "Mono" : "Poly");
|
||||
display.setTextSize(1);
|
||||
display.setCursor(0, 50);
|
||||
display.println(F(" (Press to confirm)"));
|
||||
break;
|
||||
case UI_RANDOMIZE_TRACK_EDIT:
|
||||
display.println(F("SET TRACK"));
|
||||
display.drawLine(0, 8, 128, 8, SSD1306_WHITE);
|
||||
@@ -136,43 +111,58 @@ void UIManager::draw(UIState currentState, int menuSelection,
|
||||
display.display();
|
||||
}
|
||||
|
||||
void UIManager::drawMenu(const char* title, const char* items[], int count, int selection,
|
||||
UIState currentState, int midiChannel, int tempo, const char* flavourName,
|
||||
void UIManager::drawMenu(int selection, UIState currentState, int midiChannel, int tempo, const char* flavourName,
|
||||
int queuedTheme, int currentThemeIndex, int numScaleNotes,
|
||||
const int* scaleNotes, int melodySeed, bool mutationEnabled,
|
||||
bool songModeEnabled, int theme1Index, PlayMode playMode, int randomizeTrack, const bool* trackMute) {
|
||||
display.println(title);
|
||||
display.drawLine(0, 8, 128, 8, SSD1306_WHITE);
|
||||
bool songModeEnabled, int randomizeTrack, const bool* trackMute) {
|
||||
|
||||
int start = 0;
|
||||
if (selection >= 5) start = selection - 4;
|
||||
// Calculate visual cursor position and scroll offset
|
||||
int visualCursor = 0;
|
||||
for(int i=0; i<selection; i++) {
|
||||
if(isItemVisible(i)) visualCursor++;
|
||||
}
|
||||
|
||||
const int MAX_LINES = 7; // No title, so we have more space
|
||||
int startVisualIndex = 0;
|
||||
if (visualCursor >= MAX_LINES) {
|
||||
startVisualIndex = visualCursor - (MAX_LINES - 1);
|
||||
}
|
||||
|
||||
int currentVisualIndex = 0;
|
||||
int y = 0;
|
||||
|
||||
int y = 10;
|
||||
for (int i = start; i < count; i++) {
|
||||
if (y > 55) break;
|
||||
for (int i = 0; i < menuItemsCount; i++) {
|
||||
if (!isItemVisible(i)) continue;
|
||||
|
||||
if (currentVisualIndex >= startVisualIndex) {
|
||||
if (y > 55) break;
|
||||
|
||||
if (i == selection) {
|
||||
display.fillRect(0, y, 128, 8, SSD1306_WHITE);
|
||||
display.fillRect(0, y, 128, 9, SSD1306_WHITE);
|
||||
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
|
||||
} else {
|
||||
display.setTextColor(SSD1306_WHITE);
|
||||
}
|
||||
display.setCursor(2, y);
|
||||
display.print(items[i]);
|
||||
|
||||
int x = 2 + (menuItems[i].indentLevel * 6);
|
||||
display.setCursor(x, y + 1);
|
||||
|
||||
if (menuItems[i].isGroup) {
|
||||
display.print(menuItems[i].expanded ? F("v ") : F("> "));
|
||||
}
|
||||
|
||||
display.print(menuItems[i].label);
|
||||
|
||||
if (currentState == UI_MENU_SETUP && i == 1) {
|
||||
MenuItemID id = menuItems[i].id;
|
||||
|
||||
if (id == MENU_ID_CHANNEL) {
|
||||
display.print(F(": ")); display.print(midiChannel);
|
||||
}
|
||||
if (currentState == UI_MENU_RANDOMIZE && i >= theme1Index && queuedTheme == (i - theme1Index + 1)) {
|
||||
display.print(F(" [NEXT]"));
|
||||
}
|
||||
if (currentState == UI_MENU_RANDOMIZE && i >= theme1Index && currentThemeIndex == (i - theme1Index + 1)) {
|
||||
display.print(F(" *"));
|
||||
}
|
||||
if (currentState == UI_MENU_RANDOMIZE) {
|
||||
if (i == 1) { // Melody
|
||||
|
||||
// Dynamic values
|
||||
if (id == MENU_ID_MELODY) {
|
||||
display.print(F(": ")); display.print(melodySeed);
|
||||
} else if (i == 2) { // Scale
|
||||
} else if (id == MENU_ID_SCALE) {
|
||||
display.print(F(": "));
|
||||
if (numScaleNotes > 0) {
|
||||
const char* noteNames[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
|
||||
@@ -181,14 +171,23 @@ void UIManager::drawMenu(const char* title, const char* items[], int count, int
|
||||
if (j < min(numScaleNotes, 6) - 1) display.print(F(" "));
|
||||
}
|
||||
}
|
||||
} else if (i == 3) { display.print(F(": ")); display.print(tempo); }
|
||||
else if (i == 4) { display.print(F(": ")); display.print(songModeEnabled ? F("ON") : F("OFF")); }
|
||||
else if (i == 5) { display.print(F(": ")); display.print(randomizeTrack + 1); }
|
||||
else if (i == 6) { display.print(F(": ")); display.print(trackMute[randomizeTrack] ? F("YES") : F("NO")); }
|
||||
else if (i == 7) { display.print(F(": ")); display.print(flavourName); }
|
||||
else if (i == 8) { display.print(F(": ")); display.print(mutationEnabled ? F("ON") : F("OFF")); }
|
||||
}
|
||||
} else if (id == MENU_ID_TEMPO) { display.print(F(": ")); display.print(tempo); }
|
||||
else if (id == MENU_ID_SONG_MODE) { display.print(F(": ")); display.print(songModeEnabled ? F("ON") : F("OFF")); }
|
||||
else if (id == MENU_ID_TRACK_SELECT) { display.print(F(": ")); display.print(randomizeTrack + 1); }
|
||||
else if (id == MENU_ID_MUTE) { display.print(F(": ")); display.print(trackMute[randomizeTrack] ? F("YES") : F("NO")); }
|
||||
else if (id == MENU_ID_FLAVOUR) { display.print(F(": ")); display.print(flavourName); }
|
||||
else if (id == MENU_ID_MUTATION) { display.print(F(": ")); display.print(mutationEnabled ? F("ON") : F("OFF")); }
|
||||
|
||||
if (id >= MENU_ID_THEME_1 && id <= MENU_ID_THEME_7) {
|
||||
int themeIdx = id - MENU_ID_THEME_1 + 1;
|
||||
if (queuedTheme == themeIdx) display.print(F(" [NEXT]"));
|
||||
if (currentThemeIndex == themeIdx) display.print(F(" *"));
|
||||
}
|
||||
|
||||
y += 9;
|
||||
}
|
||||
|
||||
currentVisualIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +204,7 @@ int UIManager::getPixelIndex(int x, int y) {
|
||||
void UIManager::updateLeds(const Step sequence[][NUM_STEPS], int playbackStep, bool isPlaying,
|
||||
UIState currentState, bool songModeEnabled,
|
||||
int songRepeatsRemaining, bool sequenceChangeScheduled, PlayMode playMode,
|
||||
int numScaleNotes, const int* scaleNotes, const bool* trackMute) {
|
||||
int selectedTrack, int numScaleNotes, const int* scaleNotes, const bool* trackMute) {
|
||||
pixels.clear();
|
||||
|
||||
const uint32_t COLOR_PLAYHEAD = pixels.Color(0, 255, 0);
|
||||
@@ -240,21 +239,22 @@ void UIManager::updateLeds(const Step sequence[][NUM_STEPS], int playbackStep, b
|
||||
}
|
||||
} else {
|
||||
// --- Mono Mode (original) ---
|
||||
const Step* trackSequence = sequence[selectedTrack];
|
||||
for (int s = 0; s < NUM_STEPS; s++) {
|
||||
int x = s % 8;
|
||||
int yBase = (s / 8) * 4;
|
||||
uint32_t color = 0, dimColor = 0;
|
||||
bool isCursorHere = (isPlaying && s == playbackStep);
|
||||
if (sequence[0][s].note != -1) {
|
||||
color = getNoteColor(sequence[0][s].note, sequence[0][s].tie);
|
||||
dimColor = getNoteColor(sequence[0][s].note, true);
|
||||
if (trackSequence[s].note != -1) {
|
||||
color = getNoteColor(trackSequence[s].note, trackSequence[s].tie);
|
||||
dimColor = getNoteColor(trackSequence[s].note, true);
|
||||
}
|
||||
uint32_t c[4] = {0};
|
||||
if (sequence[0][s].note != -1) {
|
||||
int octave = sequence[0][s].note / 12;
|
||||
if (octave > 4) { c[0] = color; if (sequence[0][s].accent) c[1] = dimColor; }
|
||||
else if (octave < 4) { c[2] = color; if (sequence[0][s].accent) c[1] = dimColor; }
|
||||
else { c[1] = color; if (sequence[0][s].accent) { c[0] = dimColor; c[2] = dimColor; } }
|
||||
if (trackSequence[s].note != -1) {
|
||||
int octave = trackSequence[s].note / 12;
|
||||
if (octave > 4) { c[0] = color; if (trackSequence[s].accent) c[1] = dimColor; }
|
||||
else if (octave < 4) { c[2] = color; if (trackSequence[s].accent) c[1] = dimColor; }
|
||||
else { c[1] = color; if (trackSequence[s].accent) { c[0] = dimColor; c[2] = dimColor; } }
|
||||
}
|
||||
uint32_t cursorColor = pixels.Color(0, 0, 50);
|
||||
if (isPlaying) {
|
||||
|
||||
Reference in New Issue
Block a user