diff --git a/VortexEngine/src/Leds/Leds.cpp b/VortexEngine/src/Leds/Leds.cpp index 8bae7a6838..d07df9a667 100644 --- a/VortexEngine/src/Leds/Leds.cpp +++ b/VortexEngine/src/Leds/Leds.cpp @@ -155,30 +155,22 @@ void Leds::clearAllOdds() void Leds::setQuadrant(Quadrant quadrant, RGBColor col) { + if (quadrant == QUADRANT_5) { + led(LED_3) = col; + led(LED_10) = col; + led(LED_17) = col; + led(LED_24) = col; + return; + } // start from tip and go to top setRange(quadrantFirstLed(quadrant), quadrantLastLed(quadrant), col); } void Leds::setQuadrants(Quadrant first, Quadrant last, RGBColor col) { - // start from tip and go to top - setRange(quadrantFirstLed(first), quadrantLastLed(last), col); -} - -void Leds::setQuadrantFive(RGBColor col) -{ - led(LED_3) = col; - led(LED_10) = col; - led(LED_17) = col; - led(LED_24) = col; -} - -void Leds::clearQuadrantFive() -{ - led(LED_3) = RGB_OFF; - led(LED_10) = RGB_OFF; - led(LED_17) = RGB_OFF; - led(LED_24) = RGB_OFF; + for (Quadrant quad = first; quad <= last; ++quad) { + setQuadrant(quad, col); + } } void Leds::setRing(Ring ring, RGBColor col) @@ -301,13 +293,6 @@ void Leds::blinkQuadrant(Quadrant target, uint16_t offMs, uint16_t onMs, RGBColo } } -void Leds::blinkQuadrantFive(uint16_t offMs, uint16_t onMs, RGBColor col) -{ - if ((Time::getCurtime() % MS_TO_TICKS(offMs + onMs)) < MS_TO_TICKS(onMs)) { - setQuadrantFive(col); - } -} - void Leds::blinkMap(LedMap targets, uint16_t offMs, uint16_t onMs, RGBColor col) { if ((Time::getCurtime() % MS_TO_TICKS(offMs + onMs)) < MS_TO_TICKS(onMs)) { @@ -360,17 +345,10 @@ void Leds::breatheIndexVal(LedPos target, uint8_t hue, uint32_t variance, uint32 setIndex(target, HSVColor(hue, sat, 255 - (uint8_t)(val + 128 + ((sin(variance * 0.0174533) + 1) * magnitude)))); } -void Leds::breathQuadrant(Quadrant target, uint32_t hue, uint32_t variance, uint32_t magnitude, uint8_t sat, uint8_t val) +void Leds::breatheQuadrant(Quadrant target, uint32_t hue, uint32_t variance, uint32_t magnitude, uint8_t sat, uint8_t val) { for (uint8_t pos = 0; pos < 7; ++pos) { - setIndex((LedPos)((target * 7) + pos), HSVColor((uint8_t)(hue + ((sin(variance * 0.0174533) + 1) * magnitude)), sat, val)); - } -} - -void Leds::breathQuadrantFive(uint32_t hue, uint32_t variance, uint32_t magnitude, uint8_t sat, uint8_t val) -{ - for (int target = 0; target < 4; ++target) { - setIndex((LedPos)((target * 7) + 3), HSVColor((uint8_t)(hue + ((sin(variance * 0.0174533) + 1) * magnitude)), sat, val)); + setQuadrant(target, HSVColor((uint8_t)(hue + ((sin(variance * 0.0174533) + 1) * magnitude)), sat, val)); } } diff --git a/VortexEngine/src/Leds/Leds.h b/VortexEngine/src/Leds/Leds.h index d62f7f87d1..b28bca93a3 100644 --- a/VortexEngine/src/Leds/Leds.h +++ b/VortexEngine/src/Leds/Leds.h @@ -48,12 +48,10 @@ class Leds // Control full quadrants of Leds static void setQuadrant(Quadrant quadrant, RGBColor col); static void setQuadrants(Quadrant first, Quadrant last, RGBColor col); - static void setQuadrantFive(RGBColor col); // Turn off full quadrants - static void clearQuadrant(Quadrant quadrant) { setRange(quadrantFirstLed(quadrant), quadrantLastLed(quadrant), HSV_OFF); } - static void clearQuadrants(Quadrant first, Quadrant last) { setRange(quadrantFirstLed(first), quadrantLastLed(last), HSV_OFF); } - static void clearQuadrantFive(); + static void clearQuadrant(Quadrant quadrant) { setQuadrant(quadrant, RGB_OFF); } + static void clearQuadrants(Quadrant first, Quadrant last) { setQuadrants(first, last, RGB_OFF); } // set a ring of leds static void setRing(Ring ring, RGBColor col); @@ -94,7 +92,6 @@ class Leds static void blinkRange(LedPos first, LedPos last, uint16_t offMs = 250, uint16_t onMs = 500, RGBColor col = RGB_OFF); static void blinkQuadrantOffset(Quadrant target, uint32_t time, uint16_t offMs = 250, uint16_t onMs = 500, RGBColor col = RGB_OFF); static void blinkQuadrant(Quadrant target, uint16_t offMs = 250, uint16_t onMs = 500, RGBColor col = RGB_OFF); - static void blinkQuadrantFive(uint16_t offMs = 250, uint16_t onMs = 500, RGBColor col = RGB_OFF); static void blinkMap(LedMap targets, uint16_t offMs = 250, uint16_t onMs = 500, RGBColor col = RGB_OFF); static void blinkAll(uint16_t offMs = 250, uint16_t onMs = 500, RGBColor col = RGB_OFF); // Blink both LEDs on a pair @@ -111,9 +108,7 @@ class Leds uint32_t magnitude = 15, uint8_t sat = 255, uint8_t val = 210); static void breatheIndexVal(LedPos target, uint8_t hue, uint32_t variance, uint32_t magnitude = 15, uint8_t sat = 255, uint8_t val = 210); - static void breathQuadrant(Quadrant target, uint32_t hue, uint32_t variance, - uint32_t magnitude = 15, uint8_t sat = 255, uint8_t val = 210); - static void breathQuadrantFive(uint32_t hue, uint32_t variance, + static void breatheQuadrant(Quadrant target, uint32_t hue, uint32_t variance, uint32_t magnitude = 15, uint8_t sat = 255, uint8_t val = 210); // a very specialized api to hold all leds on a color for 250ms diff --git a/VortexEngine/src/Menus/Menu.cpp b/VortexEngine/src/Menus/Menu.cpp index bdf7d51e1b..5f999a498b 100644 --- a/VortexEngine/src/Menus/Menu.cpp +++ b/VortexEngine/src/Menus/Menu.cpp @@ -186,8 +186,8 @@ void Menu::showExit() Leds::setAll(RGB_RED); return; } - Leds::clearQuadrantFive(); - Leds::blinkQuadrantFive(250, 500, RGB_RED0); + Leds::clearQuadrant(QUADRANT_5); + Leds::blinkQuadrant(QUADRANT_5, 250, 500, RGB_RED0); } void Menu::onLedSelected() @@ -232,11 +232,10 @@ void Menu::blinkSelection(uint32_t offMs, uint32_t onMs) // exit thumb breathes red on the tip and is either blank or red on the top // depending on whether you've held for the short click threshold or not if (g_pButton->isPressed() && g_pButton->holdDuration() > SHORT_CLICK_THRESHOLD_TICKS) { - Leds::setQuadrantFive(RGB_WHITE); + Leds::setQuadrant(QUADRANT_5, RGB_WHITE); } else { - Leds::clearQuadrantFive(); - Leds::setQuadrantFive(RGB_RED); - Leds::blinkQuadrantFive(250, 500, RGB_WHITE0); + Leds::setQuadrant(QUADRANT_5, RGB_RED); + Leds::blinkQuadrant(QUADRANT_5, 250, 500, RGB_WHITE0); } break; case QUADRANT_COUNT: diff --git a/VortexEngine/src/Menus/Menu.h b/VortexEngine/src/Menus/Menu.h index 94d0b0c36e..24cf52ae32 100644 --- a/VortexEngine/src/Menus/Menu.h +++ b/VortexEngine/src/Menus/Menu.h @@ -41,7 +41,7 @@ class Menu protected: void showBulbSelection(); - void showExit(); + virtual void showExit(); // blink the selected finger virtual void blinkSelection(uint32_t offMs = 250, uint32_t onMs = 500); diff --git a/VortexEngine/src/Menus/MenuList/ColorSelect.cpp b/VortexEngine/src/Menus/MenuList/ColorSelect.cpp index 19e9b445f4..451d83baa8 100644 --- a/VortexEngine/src/Menus/MenuList/ColorSelect.cpp +++ b/VortexEngine/src/Menus/MenuList/ColorSelect.cpp @@ -395,11 +395,11 @@ void ColorSelect::blinkSelection(uint32_t offMs, uint32_t onMs) // if we're pressing down on a slot then glow the tip white/red if ((g_pButton->holdDuration() % (DELETE_CYCLE_TICKS * 2)) > DELETE_CYCLE_TICKS) { // breath red instead of white blink - Leds::breathQuadrant(m_curSelection, 0, g_pButton->holdDuration()); + Leds::breatheQuadrant(m_curSelection, 0, g_pButton->holdDuration()); return; } } else if (m_slot == (uint32_t)(m_colorset.numColors() + 1)) { - Leds::blinkQuadrantFive(150, 350, RGB_WHITE); + Leds::blinkQuadrant(QUADRANT_5, 150, 350, RGB_WHITE); } } // otherwise run the default blink logic diff --git a/VortexEngine/src/Menus/MenuList/PatternSelect.cpp b/VortexEngine/src/Menus/MenuList/PatternSelect.cpp index 06c519bb37..08782e590a 100644 --- a/VortexEngine/src/Menus/MenuList/PatternSelect.cpp +++ b/VortexEngine/src/Menus/MenuList/PatternSelect.cpp @@ -5,8 +5,8 @@ #include "../../Time/TimeControl.h" #include "../../Time/Timings.h" #include "../../Buttons/Button.h" -#include "../../Modes/Modes.h" #include "../../Menus/Menus.h" +#include "../../Modes/Modes.h" #include "../../Modes/Mode.h" #include "../../Leds/Leds.h" #include "../../Log/Log.h" @@ -29,7 +29,6 @@ bool PatternSelect::init() return false; } m_state = STATE_PICK_LIST; - m_newPatternID = PATTERN_FIRST; DEBUG_LOG("Entered pattern select"); return true; } @@ -60,156 +59,128 @@ Menu::MenuAction PatternSelect::run() void PatternSelect::showListSelection() { - for (Quadrant f = QUADRANT_FIRST; f <= QUADRANT_4; ++f) { + Leds::clearAll(); + for (Quadrant quad = QUADRANT_FIRST; quad < QUADRANT_LAST; ++quad) { // hue split into 4 quadrants of 90 - Leds::breathQuadrant(f, f * (255 / 4), (uint32_t)Time::getCurtime(), 10, 255, 255); + Leds::breatheRange(quadrantFirstLed(quad), quadrantLastLed(quad), quad * (255/4), (uint32_t)Time::getCurtime() / 3, 10, 255, 255); } - Leds::blinkQuadrantFive(10, 50, RGB_OFF); + Leds::setQuadrant(QUADRANT_5, RGB_WHITE6); } void PatternSelect::showPatternSelection() { - // run the current mode m_previewMode.play(); if (g_pButton->isPressed() && g_pButton->holdDuration() > SHORT_CLICK_THRESHOLD_TICKS) { Leds::setAll(RGB_WHITE4); } } -void PatternSelect::onShortClick() +void PatternSelect::onLedSelected() { - switch (m_state) { - case STATE_PICK_LIST: - // wrap at the index back to pinkie - m_curSelection = (Quadrant)((m_curSelection + 1) % (QUADRANT_COUNT)); - break; - case STATE_PICK_PATTERN: - nextPattern(); - break; + // need to ready up the preview mode for picking patterns, this can look different based on + // which pattern was already on this mode, and which leds they decided to pick + // for example if they had a multi-led pattern and they are targetting some grouping of singles now + // then we need to convert the multi into singles, maybe in the future we can allow singles to overlay + if (m_previewMode.isMultiLed() && m_targetLeds != MAP_LED_ALL && m_targetLeds != MAP_LED(LED_MULTI)) { + Colorset curSet = m_previewMode.getColorset(); + m_previewMode.setPattern(PATTERN_FIRST, LED_ALL_SINGLE, nullptr, &curSet); + // todo: clear multi a better way, automatically when setting singles? + m_previewMode.clearPattern(LED_MULTI); + m_previewMode.init(); + DEBUG_LOG("Converted existing multi-led pattern to singles for given led selection"); } } -void PatternSelect::onShortClick2() +void PatternSelect::onShortClick() { switch (m_state) { case STATE_PICK_LIST: // wrap at the index back to pinkie - if (!m_curSelection) { - m_curSelection = QUADRANT_LAST; - } else { - m_curSelection = m_curSelection - 1; - } + m_curSelection = (Quadrant)((m_curSelection + 1) % QUADRANT_COUNT); break; case STATE_PICK_PATTERN: - previousPattern(); + nextPattern(); break; } } -void PatternSelect::nextPattern() +void PatternSelect::nextPatternID() { - LedPos srcLed = LED_MULTI; - if (!m_previewMode.isMultiLed()) { - srcLed = ledmapGetFirstLed(m_targetLeds); - } - PatternID newID = (PatternID)(m_previewMode.getPatternID(srcLed) + 1); + // increment to next pattern PatternID endList = PATTERN_SINGLE_LAST; PatternID beginList = PATTERN_SINGLE_FIRST; #if VORTEX_SLIM == 0 - if (m_targetLeds == MAP_LED_ALL || m_targetLeds == MAP_LED(LED_MULTI)) { + // if targeted multi led or all singles, iterate through multis + if ((m_targetLeds == MAP_LED_ALL) || (m_targetLeds == MAP_LED(LED_MULTI))) { endList = PATTERN_MULTI_LAST; } - if (m_targetLeds == MAP_LED(LED_MULTI)) { + // if targeted multi then start at multis and only iterate multis + if ((m_targetLeds == MAP_LED(LED_MULTI))) { beginList = PATTERN_MULTI_FIRST; } #endif - if (newID > endList || newID < beginList) { - newID = beginList; - } - if (!m_started) { - m_started = true; - m_newPatternID = PATTERN_FIRST; - } - // set the new pattern id - if (isMultiLedPatternID(newID)) { - m_previewMode.setPattern(newID); - } else { - // TODO: clear multi a better way - m_previewMode.setPatternMap(m_targetLeds, newID); - m_previewMode.clearPattern(LED_MULTI); + m_newPatternID = (PatternID)((m_newPatternID + 1) % endList); + if (m_newPatternID > endList || m_newPatternID < beginList) { + m_newPatternID = beginList; } - m_previewMode.init(); - DEBUG_LOGF("Iterated to pattern id %d", newID); } -void PatternSelect::previousPattern() +void PatternSelect::nextPattern() { - LedPos srcLed = LED_MULTI; - if (!m_previewMode.isMultiLed()) { - srcLed = ledmapGetFirstLed(m_targetLeds); - } - PatternID newID = (PatternID)(m_previewMode.getPatternID(srcLed) - 1); - PatternID endList = PATTERN_SINGLE_LAST; - PatternID beginList = PATTERN_SINGLE_FIRST; -#if VORTEX_SLIM == 0 - if (m_targetLeds == MAP_LED_ALL || m_targetLeds == MAP_LED(LED_MULTI)) { - endList = PATTERN_MULTI_LAST; - } - if (m_targetLeds == MAP_LED(LED_MULTI)) { - beginList = PATTERN_MULTI_FIRST; - } -#endif - if (newID > endList || newID < beginList) { - newID = endList; - } - if (!m_started) { + if (m_started) { + nextPatternID(); + } else { m_started = true; - m_newPatternID = PATTERN_FIRST; + // Do not modify m_newPatternID Here! It has been set in the long click handler + // to be the start of the list we want to iterate } // set the new pattern id - if (isMultiLedPatternID(newID)) { - m_previewMode.setPattern(newID); + if (isMultiLedPatternID(m_newPatternID)) { + m_previewMode.setPattern(m_newPatternID); } else { + // if the user selected multi then just put singles on all leds + LedMap setLeds = (m_targetLeds == MAP_LED(LED_MULTI)) ? LED_ALL : m_targetLeds; + m_previewMode.setPatternMap(setLeds, m_newPatternID); // TODO: clear multi a better way - m_previewMode.setPatternMap(m_targetLeds, newID); m_previewMode.clearPattern(LED_MULTI); } m_previewMode.init(); - DEBUG_LOGF("Iterated to pattern id %d", newID); + DEBUG_LOGF("Iterated to pattern id %d", m_newPatternID); } void PatternSelect::onLongClick() { - Mode *cur = Modes::curMode(); bool needsSave = false; switch (m_state) { case STATE_PICK_LIST: - if (m_curSelection == QUADRANT_LAST) { + if (m_curSelection == QUADRANT_5) { leaveMenu(); return; } - m_state = STATE_PICK_PATTERN; - // start the new pattern ID selection based on the chosen list - m_newPatternID = (PatternID)(PATTERN_FIRST + (m_curSelection * (PATTERN_COUNT / 4))); - // need to ready up the preview mode for picking patterns, this can look different based on - // which pattern was already on this mode, and which leds they decided to pick - // for example if they had a multi-led pattern and they are targetting some grouping of singles now - // then we need to convert the multi into singles, maybe in the future we can allow singles to overlay - if (m_previewMode.isMultiLed() && m_targetLeds != MAP_LED_ALL && m_targetLeds != MAP_LED(LED_MULTI)) { - Colorset curSet = m_previewMode.getColorset(); - m_previewMode.clearPattern(LED_MULTI); - m_previewMode.setPattern(PATTERN_FIRST, LED_ALL_SINGLE, nullptr, &curSet); + // if targeted multi then start at multis and only iterate multis + if ((m_targetLeds == MAP_LED(LED_MULTI))) { + // the selected multi only iterate multis + m_newPatternID = (PatternID)(PATTERN_MULTI_FIRST + (m_curSelection * (PATTERN_MULTI_COUNT / 4))); + } else if ((m_targetLeds != MAP_LED_ALL)) { + // they selected some singles, only iterate single led patterns + m_newPatternID = (PatternID)(PATTERN_SINGLE_FIRST + (m_curSelection * (PATTERN_SINGLE_COUNT / 4))); + } else { + // otherwise they selected all divide the entire list + m_newPatternID = (PatternID)(PATTERN_FIRST + (m_curSelection * (PATTERN_COUNT / 4))); } - m_previewMode.setPatternMap(m_targetLeds, m_newPatternID); - m_previewMode.init(); - DEBUG_LOGF("Started picking pattern at %u", m_newPatternID); + m_state = STATE_PICK_PATTERN; break; case STATE_PICK_PATTERN: // need to save the new pattern if it's different from current - needsSave = (cur->getPatternID() != m_previewMode.getPatternID()); - // update the current mode with the new pattern - Modes::updateCurMode(&m_previewMode); - // then done here, save if the mode was different + needsSave = !Modes::curMode()->equals(&m_previewMode); + if (needsSave) { + // update the current mode with the new pattern + Modes::updateCurMode(&m_previewMode); + } + DEBUG_LOGF("Saving pattern %u", m_newPatternID); + // go back to beginning for next time + m_state = STATE_PICK_LIST; + // done in the pattern select menu leaveMenu(needsSave); break; } @@ -217,7 +188,11 @@ void PatternSelect::onLongClick() m_curSelection = QUADRANT_FIRST; } -void PatternSelect::onLongClick2() +void PatternSelect::showExit() { - leaveMenu(); + // don't show the exit when picking pattern + if (m_state == STATE_PICK_PATTERN) { + return; + } + Menu::showExit(); } diff --git a/VortexEngine/src/Menus/MenuList/PatternSelect.h b/VortexEngine/src/Menus/MenuList/PatternSelect.h index 9055b45121..e3f1781ca2 100644 --- a/VortexEngine/src/Menus/MenuList/PatternSelect.h +++ b/VortexEngine/src/Menus/MenuList/PatternSelect.h @@ -15,17 +15,20 @@ class PatternSelect : public Menu bool init() override; MenuAction run() override; + // callback after the user selects the target led + void onLedSelected() override; + // handlers for clicks void onShortClick() override; - void onShortClick2() override; void onLongClick() override; - void onLongClick2() override; private: void showListSelection(); void showPatternSelection(); + void nextPatternID(); void nextPattern(); - void previousPattern(); + + void showExit() override; // private enumeration for internal state of pattern selection enum PatternSelectState : uint32_t @@ -42,9 +45,6 @@ class PatternSelect : public Menu // the patternid of the current demo PatternID m_newPatternID; - // the preview mode itself - Mode m_patternMode; - // the pat select starts by showing the current pattern // then the first click begin cycling the list of pats bool m_started;