From a9d9d8dd8fd7b001af1b5038dec8662d6d29bf5f Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Thu, 24 Oct 2024 06:59:03 +0100 Subject: [PATCH 001/121] Initial Pixel rewrite --- configs/Haute42COSMOX/BoardConfig.h | 41 +++ headers/addons/neopicoleds.h | 49 +++- lib/AnimationStation/src/Pixel.hpp | 81 ++++++ src/addons/neopicoleds.cpp | 429 +++++++++++++++------------- src/config_utils.cpp | 4 + 5 files changed, 389 insertions(+), 215 deletions(-) diff --git a/configs/Haute42COSMOX/BoardConfig.h b/configs/Haute42COSMOX/BoardConfig.h index 57225ef6c7..8859efece1 100644 --- a/configs/Haute42COSMOX/BoardConfig.h +++ b/configs/Haute42COSMOX/BoardConfig.h @@ -97,6 +97,47 @@ #define LEDS_BUTTON_R3 14 #define LEDS_BUTTON_A2 15 +//Data format = {first led index, leds on this light, xcoord, ycoord, GPIO pin, Type} +//Eg, your first light would be "first led index" = 0 and "leds on this light" = 2. +// your second light would be "first led index" = 2 (as 0 and 1 were just taken by the first light) +//T16 + +//LED order list on haute 42 +//left +//down +//right +//up (thumb) +//b3 +//b4 +//r1 +//l1 +//b1 +//b2 +//r2 +//l2 +//m1 (extra button 1) +//l3 +//r3 +//m2 (extra button 2) +#define LIGHT_DATA_SIZE 16 //number of sets in the below data +#define LIGHT_DATA \ +0, 1, 0, 2, 5, LightType::LightType_ActionButton, \ +1, 1, 2, 2, 3, LightType::LightType_ActionButton, \ +2, 1, 4, 3, 4, LightType::LightType_ActionButton, \ +3, 1, 6, 7, 2, LightType::LightType_ActionButton, \ +4, 1, 6, 2, 10, LightType::LightType_ActionButton, \ +5, 1, 8, 1, 11, LightType::LightType_ActionButton, \ +6, 1, 10, 1, 12, LightType::LightType_ActionButton, \ +7, 1, 12, 1, 13, LightType::LightType_ActionButton, \ +8, 1, 6, 4, 6, LightType::LightType_ActionButton, \ +9, 1, 8, 3, 7, LightType::LightType_ActionButton, \ +10, 1, 10, 3, 8, LightType::LightType_ActionButton, \ +11, 1, 12, 3, 9, LightType::LightType_ActionButton, \ +12, 1, 3, 0, 27, LightType::LightType_ActionButton, \ +13, 1, 6, 0, 18, LightType::LightType_ActionButton, \ +14, 1, 8, 5, 19, LightType::LightType_ActionButton, \ +15, 1, 3, 6, 26, LightType::LightType_ActionButton + #define HAS_I2C_DISPLAY 1 #define I2C0_ENABLED 1 #define I2C0_PIN_SDA 0 diff --git a/headers/addons/neopicoleds.h b/headers/addons/neopicoleds.h index 0bffaa7e83..1453564ef5 100644 --- a/headers/addons/neopicoleds.h +++ b/headers/addons/neopicoleds.h @@ -34,6 +34,13 @@ #define LED_FORMAT LED_FORMAT_GRB #endif +#ifndef LIGHT_DATA_SIZE +#define LIGHT_DATA_SIZE 0 +#endif +#ifndef LIGHT_DATA +#define LIGHT_DATA 0,0,0,0,0,LightType::LightType_ActionButton +#endif + #ifndef LEDS_PER_PIXEL #define LEDS_PER_PIXEL 1 #endif @@ -155,7 +162,6 @@ #endif void configureAnimations(AnimationStation *as); -AnimationHotkey animationHotkeys(Gamepad *gamepad); PixelMatrix createLedButtonLayout(ButtonLayout layout, int ledsPerPixel); PixelMatrix createLedButtonLayout(ButtonLayout layout, std::vector *positions); @@ -173,30 +179,51 @@ class NeoPicoPlayerLEDs : public PlayerLEDs // NeoPico LED Addon class NeoPicoLEDAddon : public GPAddon { public: + + //GP Addon functions virtual bool available(); virtual void setup(); virtual void preprocess() {} virtual void process(); virtual std::string name() { return NeoPicoLEDName; } + void configureLEDs(); uint32_t frame[100]; private: - std::vector * getLEDPositions(std::string button, std::vector> *positions); - std::vector> generatedLEDButtons(std::vector> *positions); - std::vector> generatedLEDStickless(std::vector> *positions); - std::vector> generatedLEDWasd(std::vector> *positions); - std::vector> generatedLEDWasdFBM(std::vector> *positions); - std::vector> createLEDLayout(ButtonLayout layout, uint8_t ledsPerPixel, uint8_t ledButtonCount); + + AnimationHotkey ProcessAnimationHotkeys(Gamepad *gamepad); + + //Legacy setup functions + void generateLegacyIndividualLight(int lightIndex, int firstLedIndex, int xCoord, int yCoord, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, GpioAction actionButton); + void generatedLEDButtons(std::vector> *positions, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize); + void generatedLEDStickless(std::vector> *positions, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize); + void generatedLEDWasd(std::vector> *positions, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize); + void generatedLEDWasdFBM(std::vector> *positions, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize); + void createLEDLayout(ButtonLayout layout, uint8_t ledsPerPixel, uint8_t ledButtonCount, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize); uint8_t setupButtonPositions(); + + //New co-ordinated setup + void GenerateLights(LEDOptions_lightData_t InLightData, uint32_t InLightDataSize); + + //Controls the actual lights on the board. Writes out state each frame + NeoPico *neopico; + + //Classes to control the player LEDS + PLEDAnimationState animationState; // NeoPico can control the player LEDs + NeoPicoPlayerLEDs * neoPLEDs = nullptr; + + //Data representation of the lights + Lights RGBLights; + + //Animation class. Handles idle animations, special move animations and pressed button effects + AnimationStation AnimStation; + + const uint32_t intervalMS = 10; absolute_time_t nextRunTime; uint8_t ledCount; PixelMatrix matrix; - NeoPico *neopico; InputMode inputMode; // HACK - PLEDAnimationState animationState; // NeoPico can control the player LEDs - NeoPicoPlayerLEDs * neoPLEDs = nullptr; - AnimationStation as; std::map buttonPositions; bool turnOffWhenSuspended; }; diff --git a/lib/AnimationStation/src/Pixel.hpp b/lib/AnimationStation/src/Pixel.hpp index 17af8a1751..2c48fedb9f 100644 --- a/lib/AnimationStation/src/Pixel.hpp +++ b/lib/AnimationStation/src/Pixel.hpp @@ -54,4 +54,85 @@ inline bool operator==(const Pixel &lhs, const Pixel &rhs) { return lhs.index == rhs.index; } +// Enums ////////////////////////////////////////////////////////////////////////// + +// Structs ////////////////////////////////////////////////////////////////////////// + +//Grid position of a single RGB Light +struct LightPosition +{ + LightPosition() {} + + LightPosition(uint32_t xCoord, uint32_t yCoord) + { + XPosition = xCoord; + YPosition = yCoord; + } + + int XPosition = 0; + int YPosition = 0; +}; + +//A single RGB light on the device. Replaced Pixel +struct Light +{ + Light(uint8_t InFirstLedIndex, uint8_t InNumLedsPerLight, LightPosition InPosition, uint8_t GIPOPin, uint8_t InType) + { + FirstLedIndex = InFirstLedIndex; + Position = InPosition; + Type = InType; + LedsPerLight = InNumLedsPerLight; + //GamePadMask = GamePadMask; + GIPOPin = GIPOPin; + } + + // index of first LED + uint32_t FirstLedIndex; + + // Approximate grid position of Light on the device + LightPosition Position; + + // Type of light, used in animations to allow users to seperate off lights for different anims + uint8_t Type; + + //How many leds make up this light. + uint8_t LedsPerLight; + + //Game pad mask (if applicaple) (Needed to do SOCD on Lights) + // uint32_t GamePadMask; + + //GIPO pin this action (if applicaple) is on + int32_t GIPOPin = -1; +}; + +//All RGB lights on the device. Replaced PixelMatrix +struct Lights +{ +public: + Lights() {} + + void Setup(std::vector InLights) + { + AllLights = InLights; + } + + inline uint8_t GetLedCount() const + { + int count; + for(const Light& thisLight : AllLights ) + { + count += thisLight.LedsPerLight; + } + return count; + } + + inline uint16_t GetLightsCount() const + { + return AllLights.size(); + } + + //Array of all the lights + std::vector AllLights; +}; + #endif diff --git a/src/addons/neopicoleds.cpp b/src/addons/neopicoleds.cpp index 6571a05b78..1705f250e9 100644 --- a/src/addons/neopicoleds.cpp +++ b/src/addons/neopicoleds.cpp @@ -37,6 +37,10 @@ const std::string BUTTON_LABEL_A2 = "A2"; static std::vector EMPTY_VECTOR; +////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Player LEDs //////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + uint32_t rgbPLEDValues[4]; // Move to Proto Enums @@ -191,6 +195,18 @@ PLEDAnimationState getPS4AnimationNEOPICO(uint32_t flashOn, uint32_t flashOff) return animationState; } +////////////////////////////////////////////////////////////////////////////////////////////////////////// +//END Player LEDs //////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +//RBG LEDs /////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////// +//GP Addon functions +/////////////////////////////////// + bool NeoPicoLEDAddon::available() { const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); return isValidPin(ledOptions.dataPin); @@ -221,12 +237,14 @@ void NeoPicoLEDAddon::setup() void NeoPicoLEDAddon::process() { + //Check we have LEDs enabled and is it time to update const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); if (!isValidPin(ledOptions.dataPin) || !time_reached(this->nextRunTime)) return; + //Process hotkeys and action any requests Gamepad * gamepad = Storage::getInstance().GetProcessedGamepad(); - AnimationHotkey action = animationHotkeys(gamepad); + AnimationHotkey action = ProcessAnimationHotkeys(gamepad); if (ledOptions.pledType == PLED_TYPE_RGB) { inputMode = gamepad->getOptions().inputMode; // HACK if (gamepad->auxState.playerID.enabled && gamepad->auxState.playerID.active) { @@ -255,9 +273,10 @@ void NeoPicoLEDAddon::process() } if ( action != HOTKEY_LEDS_NONE ) { - as.HandleEvent(action); + AnimStation.HandleEvent(action); } + //Legacy check for button pressed for animation. Needs changing to pin check instead uint32_t buttonState = gamepad->state.dpad << 16 | gamepad->state.buttons; vector pressed; for (auto row : matrix.pixels) @@ -269,19 +288,22 @@ void NeoPicoLEDAddon::process() } } if (pressed.size() > 0) - as.HandlePressed(pressed); + AnimStation.HandlePressed(pressed); else - as.ClearPressed(); + AnimStation.ClearPressed(); - as.Animate(); + //Update idle, button and special move animations + AnimStation.Animate(); + //check if need to turn off due to usb suspension if (turnOffWhenSuspended && get_usb_suspended()) { - as.DimBrightnessTo0(); + AnimStation.DimBrightnessTo0(); } else { - as.SetBrightness(AnimationStation::GetBrightness()); + AnimStation.SetBrightness(AnimationStation::GetBrightness()); } - as.ApplyBrightness(frame); + //Grab led values this frame + AnimStation.ApplyBrightness(frame); // Apply the player LEDs to our first 4 leds if we're in NEOPIXEL mode if (ledOptions.pledType == PLED_TYPE_RGB) { @@ -302,223 +324,180 @@ void NeoPicoLEDAddon::process() } } + //Set led values out to the actual leds neopico->SetFrame(frame); neopico->Show(); AnimationStore.save(); + //queue up next frame time this->nextRunTime = make_timeout_time_ms(NeoPicoLEDAddon::intervalMS); } -std::vector * NeoPicoLEDAddon::getLEDPositions(string button, std::vector> *positions) +/////////////////////////////////// +// Old Pixel Setup functions +// Left here for legacy setup until all configs are converted +/////////////////////////////////// + +void NeoPicoLEDAddon::generateLegacyIndividualLight(int lightIndex, int firstLedIndex, int xCoord, int yCoord, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, GpioAction actionButton) { - int buttonPosition = buttonPositions[button]; - if (buttonPosition < 0) - return &EMPTY_VECTOR; - else - return &positions->at(buttonPosition); -} + const GpioMappings& pinMappings = Storage::getInstance().getGpioMappings(); -// Macro for Pixel() declarations -#define PIXEL(BUTTON, MASK) \ - Pixel(buttonPositions[BUTTON], MASK, *getLEDPositions(BUTTON, positions)) + int gpioPin = -1; + for(int configIndex = 0; configIndex < pinMappings.pins_count; ++configIndex) + { + if(actionButton == pinMappings.pins[configIndex].action) + gpioPin = configIndex; + } + + int arrayOffset = lightIndex * 6; + out_lightData.bytes[arrayOffset] = firstLedIndex; //first led index + out_lightData.bytes[arrayOffset+1] = ledsPerPixel; //leds on this light + out_lightData.bytes[arrayOffset+2] = xCoord; //xcoord + out_lightData.bytes[arrayOffset+3] = yCoord; //ycoord + out_lightData.bytes[arrayOffset+4] = gpioPin; //GPIO pin + out_lightData.bytes[arrayOffset+5] = LightType::LightType_ActionButton; //Type +} /** * @brief Create an LED layout using a 2x4 matrix. */ -std::vector> NeoPicoLEDAddon::generatedLEDButtons(std::vector> *positions) +void NeoPicoLEDAddon::generatedLEDButtons(std::vector> *positions, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize) { - std::vector> pixels = - { - { - PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), - PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), - }, - { - PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), - PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), - }, - { - PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), - PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), - }, - { - PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), - PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), - }, - { - PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), - PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), - PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), - PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), - PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), - PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), - PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), - PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), - PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), - PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), - }, - }; - - return pixels; + out_lightDataSize = 18; + + //8 action buttons in 2x4 array + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B3], ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 0, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B1], ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 0, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B4], ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B2], ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 1, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R1], ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 2, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R2], ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 2, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L1], ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L2], ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 3, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); + + //extras + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_LEFT], ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 4, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_DOWN], ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_RIGHT], ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 4, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_UP], ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 4, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S1], ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 4, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S2], ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 4, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L3], ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 4, 6, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R3], ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 4, 7, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A1], ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 4, 8, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A2], ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 4, 9, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); } /** * @brief Create an LED layout using a 3x8 matrix. */ -std::vector> NeoPicoLEDAddon::generatedLEDStickless(vector> *positions) +void NeoPicoLEDAddon::generatedLEDStickless(vector> *positions, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize) { - std::vector> pixels = - { - { - PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), - NO_PIXEL, - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), - NO_PIXEL, - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), - NO_PIXEL, - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), - NO_PIXEL, - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), - PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), - PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), - PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), - PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), - NO_PIXEL, - }, - { - PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), - PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), - PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), - PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), - PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), - PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), - }, - }; + out_lightDataSize = 18; + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_LEFT], ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 0, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_DOWN], ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_RIGHT], ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 2, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); - return pixels; + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_UP], ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B3], ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 4, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B1], ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B4], ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 5, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B2], ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 5, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R1], ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 6, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R2], ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 6, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L1], ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 7, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L2], ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 7, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); + + //extras + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S1], ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 8, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S2], ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 8, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L3], ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 8, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R3], ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 8, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A1], ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 8, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A2], ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 8, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); } /** * @brief Create an LED layout using a 2x7 matrix. */ -std::vector> NeoPicoLEDAddon::generatedLEDWasd(std::vector> *positions) +void NeoPicoLEDAddon::generatedLEDWasd(std::vector> *positions, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize) { - std::vector> pixels = - { - { - NO_PIXEL, - PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), - }, - { - PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), - PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), - }, - { - NO_PIXEL, - PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), - }, - { - PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), - PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), - }, - { - PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), - PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), - }, - { - PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), - PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), - }, - { - PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), - PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), - }, - { - PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), - PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), - PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), - PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), - PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), - PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), - }, - }; + out_lightDataSize = 18; + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_LEFT], ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 0, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_UP], ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_DOWN], ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 1, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_RIGHT], ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 2, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B3], ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B1], ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 3, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B4], ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 4, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B2], ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R1], ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 5, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R2], ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 5, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L1], ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 6, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L2], ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 6, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); - return pixels; + //extras + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S1], ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 7, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S2], ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 7, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L3], ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 7, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R3], ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 7, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A1], ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 7, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A2], ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 7, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); } /** * @brief Create an LED layout using a 2x7 matrix for the mirrored Fightboard. */ -std::vector> NeoPicoLEDAddon::generatedLEDWasdFBM(std::vector> *positions) +void NeoPicoLEDAddon::generatedLEDWasdFBM(std::vector> *positions, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize) { - std::vector> pixels = - { - { - PIXEL(BUTTON_LABEL_L1, GAMEPAD_MASK_L1), - PIXEL(BUTTON_LABEL_L2, GAMEPAD_MASK_L2), - }, - { - PIXEL(BUTTON_LABEL_R1, GAMEPAD_MASK_R1), - PIXEL(BUTTON_LABEL_R2, GAMEPAD_MASK_R2), - }, - { - PIXEL(BUTTON_LABEL_B4, GAMEPAD_MASK_B4), - PIXEL(BUTTON_LABEL_B2, GAMEPAD_MASK_B2), - }, - { - PIXEL(BUTTON_LABEL_B3, GAMEPAD_MASK_B3), - PIXEL(BUTTON_LABEL_B1, GAMEPAD_MASK_B1), - }, - { - NO_PIXEL, - PIXEL(BUTTON_LABEL_LEFT, GAMEPAD_MASK_DL), - }, - { - PIXEL(BUTTON_LABEL_UP, GAMEPAD_MASK_DU), - PIXEL(BUTTON_LABEL_DOWN, GAMEPAD_MASK_DD), - }, - { - NO_PIXEL, - PIXEL(BUTTON_LABEL_RIGHT, GAMEPAD_MASK_DR), - }, - { - PIXEL(BUTTON_LABEL_S1, GAMEPAD_MASK_S1), - PIXEL(BUTTON_LABEL_S2, GAMEPAD_MASK_S2), - PIXEL(BUTTON_LABEL_L3, GAMEPAD_MASK_L3), - PIXEL(BUTTON_LABEL_R3, GAMEPAD_MASK_R3), - PIXEL(BUTTON_LABEL_A1, GAMEPAD_MASK_A1), - PIXEL(BUTTON_LABEL_A2, GAMEPAD_MASK_A2), - }, - }; + out_lightDataSize = 18; + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L1], ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 0, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L2], ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 0, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); - return pixels; + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R1], ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R2], ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 1, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B4], ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 2, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B2], ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 2, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B3], ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B1], ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 3, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_LEFT], ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_UP], ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 5, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_DOWN], ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 5, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); + + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_RIGHT], ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 6, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); + + //extras + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S1], ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 7, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S2], ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 7, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L3], ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 7, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R3], ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 7, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A1], ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 7, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); + generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A2], ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 7, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); } -std::vector> NeoPicoLEDAddon::createLEDLayout(ButtonLayout layout, uint8_t ledsPerPixel, uint8_t ledButtonCount) +void NeoPicoLEDAddon::createLEDLayout(ButtonLayout layout, uint8_t ledsPerPixel, uint8_t ledButtonCount, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize) { vector> positions(ledButtonCount); for (int i = 0; i != ledButtonCount; i++) @@ -537,12 +516,12 @@ std::vector> NeoPicoLEDAddon::createLEDLayout(ButtonLayout la case BUTTON_LAYOUT_STICKLESS_16: case BUTTON_LAYOUT_STICKLESS_R16: case BUTTON_LAYOUT_BOARD_DEFINED_A: - return generatedLEDStickless(&positions); + generatedLEDStickless(&positions, ledsPerPixel, out_lightData, out_lightDataSize); case BUTTON_LAYOUT_FIGHTBOARD_MIRRORED: - return generatedLEDWasdFBM(&positions); + generatedLEDWasdFBM(&positions, ledsPerPixel, out_lightData, out_lightDataSize); case BUTTON_LAYOUT_BUTTONS_ANGLED: case BUTTON_LAYOUT_FIGHTBOARD_STICK: - return generatedLEDWasd(&positions); + generatedLEDWasd(&positions, ledsPerPixel, out_lightData, out_lightDataSize); case BUTTON_LAYOUT_BLANKA: case BUTTON_LAYOUT_BUTTONS_BASIC: case BUTTON_LAYOUT_KEYBOARD_ANGLED: @@ -552,11 +531,8 @@ std::vector> NeoPicoLEDAddon::createLEDLayout(ButtonLayout la case BUTTON_LAYOUT_ARCADE: case BUTTON_LAYOUT_VLXA: default: - return generatedLEDButtons(&positions); + generatedLEDButtons(&positions, ledsPerPixel, out_lightData, out_lightDataSize); } - - assert(false); - return std::vector>(); } uint8_t NeoPicoLEDAddon::setupButtonPositions() @@ -594,10 +570,23 @@ uint8_t NeoPicoLEDAddon::setupButtonPositions() void NeoPicoLEDAddon::configureLEDs() { const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); - uint8_t buttonCount = setupButtonPositions(); - vector> pixels = createLEDLayout(static_cast(ledOptions.ledLayout), ledOptions.ledsPerButton, buttonCount); - matrix.setup(pixels, ledOptions.ledsPerButton); - ledCount = matrix.getLedCount(); + + //New grid based setup + LEDOptions_lightData_t lightData = ledOptions.lightData; + int32_t lightDataSize = ledOptions.lightDataSize; + if(lightDataSize == 0) + { + //fall back to old matrix setup which will now approximate a grid and return the same data struct ready for light creation + uint8_t buttonCount = setupButtonPositions(); + createLEDLayout(static_cast(ledOptions.ledLayout), ledOptions.ledsPerButton, buttonCount, lightData, lightDataSize); + } + + GenerateLights(lightData, lightDataSize); + ledCount = RGBLights.GetLedCount(); + + //matrix.setup(pixels, ledOptions.ledsPerButton); + //ledCount = matrix.getLedCount(); + if (ledOptions.pledType == PLED_TYPE_RGB && PLED_COUNT > 0) ledCount += PLED_COUNT; @@ -607,15 +596,43 @@ void NeoPicoLEDAddon::configureLEDs() neopico->Off(); Animation::format = static_cast(ledOptions.ledFormat); - as.ConfigureBrightness(ledOptions.brightnessMaximum, ledOptions.brightnessSteps); + AnimStation.ConfigureBrightness(ledOptions.brightnessMaximum, ledOptions.brightnessSteps); AnimationOptions animationOptions = AnimationStore.getAnimationOptions(); addStaticThemes(ledOptions, animationOptions); - as.SetOptions(animationOptions); - as.SetMatrix(matrix); - as.SetMode(as.options.baseAnimationIndex); + AnimStation.SetOptions(animationOptions); + AnimStation.SetMatrix(matrix); + AnimStation.SetMode(as.options.baseAnimationIndex); } -AnimationHotkey animationHotkeys(Gamepad *gamepad) +//////////////////////////////////////////// +//New RGBLight setups +//////////////////////////////////////////// + +void NeoPicoLEDAddon::GenerateLights(LEDOptions_lightData_t InLightData, uint32_t InLightDataSize) +{ + std::vector generatedLights; + for(int index = 0; index < (int)InLightDataSize; ++index) + { + int arrayOffset = index*6; + //Data format = {first led index, leds on this light, xcoord, ycoord, GPIO pin, Type} + LightPosition newLightPos (InLightData.bytes[arrayOffset+2], InLightData.bytes[arrayOffset+3]); + Light newLight (InLightData.bytes[arrayOffset], + InLightData.bytes[arrayOffset+1], + newLightPos, + InLightData.bytes[arrayOffset+4], + InLightData.bytes[arrayOffset+5]); + + generatedLights.push_back(newLight); + } + + RGBLights.Setup(generatedLights); +} + +//////////////////////////////////////////// +//Helper functions +//////////////////////////////////////////// + +AnimationHotkey NeoPicoLEDAddon::ProcessAnimationHotkeys(Gamepad *gamepad) { AnimationHotkey action = HOTKEY_LEDS_NONE; @@ -675,3 +692,7 @@ AnimationHotkey animationHotkeys(Gamepad *gamepad) return action; } + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +//END RBG LEDs /////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 05bc0e0f87..14eb5dbe34 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -470,6 +470,10 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.ledOptions, pledIndex2, PLED2_PIN); INIT_UNSET_PROPERTY(config.ledOptions, pledIndex3, PLED3_PIN); INIT_UNSET_PROPERTY(config.ledOptions, pledIndex4, PLED4_PIN); + // lightEntries + INIT_UNSET_PROPERTY(config.ledOptions, lightDataSize, LIGHT_DATA_SIZE); + const uint8_t lightData[] = { LIGHT_DATA }; + INIT_UNSET_PROPERTY_BYTES(config.ledOptions, lightData, lightData); // animationOptions INIT_UNSET_PROPERTY(config.animationOptions, baseAnimationIndex, LEDS_BASE_ANIMATION_INDEX); From ce8b6f9e151b5c7c2b4cccaf2b563e8eb84d906e Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Sun, 27 Oct 2024 23:22:19 +0000 Subject: [PATCH 002/121] animation system rewrite code dump --- lib/AnimationStation/src/Animation.cpp | 121 ++++++------ lib/AnimationStation/src/Animation.hpp | 42 ++-- lib/AnimationStation/src/AnimationStation.hpp | 104 +++++----- lib/AnimationStation/src/Effects/Rainbow.cpp | 179 ++++++++++++++---- src/addons/neopicoleds.cpp | 39 ++-- 5 files changed, 279 insertions(+), 206 deletions(-) diff --git a/lib/AnimationStation/src/Animation.cpp b/lib/AnimationStation/src/Animation.cpp index c5814ae892..72b0efd1af 100644 --- a/lib/AnimationStation/src/Animation.cpp +++ b/lib/AnimationStation/src/Animation.cpp @@ -7,77 +7,83 @@ #define PRESS_COOLDOWN_MIN 0 LEDFormat Animation::format; -std::map Animation::times = {}; -std::map Animation::hitColor = {}; - -Animation::Animation(PixelMatrix &matrix) : matrix(&matrix) { - for (size_t r = 0; r != matrix.pixels.size(); r++) { - for (size_t c = 0; c != matrix.pixels[r].size(); c++) { - if (matrix.pixels[r][c].index == NO_PIXEL.index) - continue; - times.insert_or_assign(matrix.pixels[r][c].index, 0); - hitColor.insert_or_assign(matrix.pixels[r][c].index, defaultColor); - } + +Animation::Animation(Lights& InRGBLights) : RGBLights(&InRGBLights) +{ + fadeTimes.clear(); + for(int ledIndex = 0; ledIndex < RGBLights->GetLedCount(); ++ledIndex) + { + fadeTimes.push_back(0); } + + holdTimeInMs = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].buttonPressHoldTimeInMs; + fadeoutTimeInMs = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].buttonPressFadeOutTimeInMs; + + //Since we use the fadeTimes array to know if a light is held. make sure that we hold for at least 1 ms. + if(holdTimeInMs <= 0) + holdTimeInMs = 1; } -void Animation::UpdatePixels(std::vector inpixels) { - this->pixels = inpixels; +void Animation::UpdatePressed(std::vector InPressedPins) +{ + this->pressedPins = InPressedPins; } -void Animation::UpdateTime() { - coolDownTimeInMs = AnimationStation::options.buttonPressColorCooldownTimeInMs; +void Animation::ClearPressed() +{ + this->pressedPins.clear(); +} +void Animation::UpdateTime() +{ absolute_time_t currentTime = get_absolute_time(); updateTimeInMs = absolute_time_diff_us(lastUpdateTime, currentTime) / 1000; lastUpdateTime = currentTime; } -void Animation::UpdatePresses(RGB (&frame)[100]) { - // Queue up blend on hit - for (size_t p = 0; p < pixels.size(); p++) { - if (pixels[p].index != NO_PIXEL.index) { - times[pixels[p].index] = coolDownTimeInMs; - hitColor[pixels[p].index] = frame[pixels[p].positions[0]]; +void Animation::UpdatePresses() +{ + //Set hold/fade time for all pressed buttons + for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + for(int pressedPinIndex = 0; pressedPinIndex < pressedPins.size(); ++pressedPinIndex) + { + if(pressedPins[pressedPinIndex] == RGBLights->AllLights[lightIndex].GIPOPin) + { + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + fadeTimes[ledIndex] = holdTimeInMs + fadeoutTimeInMs; + } + } } } } -void Animation::DecrementFadeCounter(int32_t index) { - times[index] -= updateTimeInMs; - if (times[index] < 0) { - times[index] = 0; - }; -} - -void Animation::ClearPixels() { - this->pixels.clear(); -} - -/* Some of these animations are filtered to specific pixels, such as button press animations. -This somewhat backwards named method determines if a specific pixel is _not_ included in the filter */ -bool Animation::notInFilter(Pixel pixel) { - if (!this->filtered) { - return false; - } - - for (size_t i = 0; i < this->pixels.size(); i++) { - if (pixel == this->pixels.at(i)) { - return false; - } +void Animation::DecrementFadeCounters() +{ + for(int ledIndex = 0; ledIndex < RGBLights->GetLedCount(); ++ledIndex) + { + fadeTimes[ledIndex] -= updateTimeInMs; + if (fadeTimes[ledIndex] < 0) + fadeTimes[ledIndex] = 0; } - - return true; } -RGB Animation::BlendColor(RGB start, RGB end, uint32_t timeRemainingInMs) { +RGB Animation::BlendColor(RGB start, RGB end, uint32_t timeRemainingInMs) +{ RGB result = ColorBlack; - if (timeRemainingInMs <= 0) { + //fade over? + if (timeRemainingInMs <= 0) return end; - } - float progress = 1.0f - (static_cast(timeRemainingInMs) / static_cast(coolDownTimeInMs)); + //still in hold time? + if(timeRemainingInMs > fadeoutTimeInMs) + return start; + + float progress = 1.0f - (static_cast(timeRemainingInMs) / static_cast(fadeoutTimeInMs)); if (progress < 0.0f) progress = 0.0f; if (progress > 1.0f) progress = 1.0f; @@ -87,20 +93,3 @@ RGB Animation::BlendColor(RGB start, RGB end, uint32_t timeRemainingInMs) { return result; } - - -void Animation::FadeTimeUp() { - AnimationStation::options.buttonPressColorCooldownTimeInMs = AnimationStation::options.buttonPressColorCooldownTimeInMs + PRESS_COOLDOWN_INCREMENT; - - if (AnimationStation::options.buttonPressColorCooldownTimeInMs > PRESS_COOLDOWN_MAX) { - AnimationStation::options.buttonPressColorCooldownTimeInMs = PRESS_COOLDOWN_MAX; - } -} - -void Animation::FadeTimeDown() { - AnimationStation::options.buttonPressColorCooldownTimeInMs = AnimationStation::options.buttonPressColorCooldownTimeInMs - PRESS_COOLDOWN_INCREMENT; - - if (AnimationStation::options.buttonPressColorCooldownTimeInMs > PRESS_COOLDOWN_MAX) { - AnimationStation::options.buttonPressColorCooldownTimeInMs = PRESS_COOLDOWN_MIN; - } -} diff --git a/lib/AnimationStation/src/Animation.hpp b/lib/AnimationStation/src/Animation.hpp index 884d11b9b3..e056c67e3c 100644 --- a/lib/AnimationStation/src/Animation.hpp +++ b/lib/AnimationStation/src/Animation.hpp @@ -105,43 +105,45 @@ inline const std::vector colors { class Animation { public: - Animation(PixelMatrix &matrix); - virtual void UpdatePixels(std::vector pixels); - void ClearPixels(); + Animation(Lights& InRGBLights); virtual ~Animation(){}; + //Which buttons are held at the moment + virtual void UpdatePressed(std::vector InPressedPins); + void ClearPressed(); + static LEDFormat format; - bool notInFilter(Pixel pixel); virtual void Animate(RGB (&frame)[100]) = 0; + + //gets current frame time void UpdateTime(); - void UpdatePresses(RGB (&frame)[100]); - void DecrementFadeCounter(int32_t index); + + //Update timers for pressed buttons this frame + void UpdatePresses(); + void DecrementFadeCounters(); virtual void ParameterUp() = 0; virtual void ParameterDown() = 0; - virtual void FadeTimeUp(); - virtual void FadeTimeDown(); - RGB BlendColor(RGB start, RGB end, uint32_t frame); protected: -/* We track both the full matrix as well as individual pixels here to support -button press changes. Rather than adjusting the matrix to represent a subset of pixels, -we provide a subset of pixels to use as a filter. */ - PixelMatrix *matrix; - std::vector pixels; - bool filtered = false; + //Light data + Lights* RGBLights; + + //Pins currently pressed + std::vector pressedPins; // Color fade - RGB defaultColor = ColorBlack; - static std::map times; - static std::map hitColor; + std::vector fadeTimes; + absolute_time_t lastUpdateTime = nil_time; - uint32_t coolDownTimeInMs = 1000; - int64_t updateTimeInMs = 20; + uint32_t holdTimeInMs = 1000; + uint32_t fadeoutTimeInMs = 1000; + + int64_t updateTimeInMs = 20; }; #endif diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index 70943546ee..6d9dbd1104 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -17,13 +17,13 @@ #include "Effects/StaticColor.hpp" #include "Effects/StaticTheme.hpp" +//List of non-pressed animation types typedef enum { EFFECT_STATIC_COLOR, - EFFECT_RAINBOW, + EFFECT_RAINBOW_SYNCED, + EFFECT_RAINBOW_ROTATE, EFFECT_CHASE, - EFFECT_STATIC_THEME, - EFFECT_CUSTOM_THEME, } AnimationEffects; const int TOTAL_EFFECTS = 4; // Exclude custom theme until verified present @@ -31,66 +31,35 @@ const int TOTAL_EFFECTS = 4; // Exclude custom theme until verified present typedef enum { HOTKEY_LEDS_NONE, - HOTKEY_LEDS_ANIMATION_UP, - HOTKEY_LEDS_ANIMATION_DOWN, - HOTKEY_LEDS_PARAMETER_UP, + HOTKEY_LEDS_PROFILE_UP, + HOTKEY_LEDS_PROFILE_DOWN, HOTKEY_LEDS_PRESS_PARAMETER_UP, HOTKEY_LEDS_PRESS_PARAMETER_DOWN, + HOTKEY_LEDS_PARAMETER_UP, HOTKEY_LEDS_PARAMETER_DOWN, HOTKEY_LEDS_BRIGHTNESS_UP, HOTKEY_LEDS_BRIGHTNESS_DOWN, - HOTKEY_LEDS_FADETIME_UP, - HOTKEY_LEDS_FADETIME_DOWN } AnimationHotkey; +struct __attribute__ ((__packed__)) AnimationProfile +{ + AnimationEffects baseAnimationEffect; + + int16_t baseCycleTime; + + uint32_t notPressedStaticColors[NUM_BANK0_GPIOS]; + uint32_t pressedStaticColors[NUM_BANK0_GPIOS]; + + uint32_t buttonPressHoldTimeInMs; + uint32_t buttonPressFadeOutTimeInMs; +}; + struct __attribute__ ((__packed__)) AnimationOptions { uint32_t checksum; - uint8_t baseAnimationIndex; + std::vector profiles; uint8_t brightness; - uint8_t staticColorIndex; - uint8_t buttonColorIndex; - int16_t chaseCycleTime; - int16_t rainbowCycleTime; - uint8_t themeIndex; - bool hasCustomTheme; - uint32_t customThemeUp; - uint32_t customThemeDown; - uint32_t customThemeLeft; - uint32_t customThemeRight; - uint32_t customThemeB1; - uint32_t customThemeB2; - uint32_t customThemeB3; - uint32_t customThemeB4; - uint32_t customThemeL1; - uint32_t customThemeR1; - uint32_t customThemeL2; - uint32_t customThemeR2; - uint32_t customThemeS1; - uint32_t customThemeS2; - uint32_t customThemeL3; - uint32_t customThemeR3; - uint32_t customThemeA1; - uint32_t customThemeA2; - uint32_t customThemeUpPressed; - uint32_t customThemeDownPressed; - uint32_t customThemeLeftPressed; - uint32_t customThemeRightPressed; - uint32_t customThemeB1Pressed; - uint32_t customThemeB2Pressed; - uint32_t customThemeB3Pressed; - uint32_t customThemeB4Pressed; - uint32_t customThemeL1Pressed; - uint32_t customThemeR1Pressed; - uint32_t customThemeL2Pressed; - uint32_t customThemeR2Pressed; - uint32_t customThemeS1Pressed; - uint32_t customThemeS2Pressed; - uint32_t customThemeL3Pressed; - uint32_t customThemeR3Pressed; - uint32_t customThemeA1Pressed; - uint32_t customThemeA2Pressed; - uint32_t buttonPressColorCooldownTimeInMs; + uint8_t baseProfileIndex; }; class AnimationStation @@ -101,15 +70,20 @@ class AnimationStation void Animate(); void HandleEvent(AnimationHotkey action); void Clear(); - void ChangeAnimation(int changeSize); void ApplyBrightness(uint32_t *frameValue); + + //Change profiles + void ChangeProfile(int changeSize); uint16_t AdjustIndex(int changeSize); - void HandlePressed(std::vector pressed); - void ClearPressed(); + + //What buttons (physical gpio pins) are pressed this frame + void HandlePressedPins(std::vector pressedPins); uint8_t GetMode(); void SetMode(uint8_t mode); - void SetMatrix(PixelMatrix matrix); + void SetLights(Lights InRGBLights); + + //Brightness settings static void ConfigureBrightness(uint8_t max, uint8_t steps); static float GetBrightnessX(); static uint8_t GetBrightness(); @@ -117,14 +91,24 @@ class AnimationStation static void DecreaseBrightness(); static void IncreaseBrightness(); static void DimBrightnessTo0(); + + //passed in user options static void SetOptions(AnimationOptions options); + //Running non-pressed animation Animation* baseAnimation; + + //Running pressed animation Animation* buttonAnimation; - std::vector lastPressed; + + //Buttons pressed (physical gipo pins) last frame, used when changing button theme so starts initialised + std::vector lastPressed; + static AnimationOptions options; + static absolute_time_t nextChange; - static uint8_t effectCount; + + //Colour of all lights this frame RGB frame[100]; protected: @@ -132,7 +116,9 @@ class AnimationStation static uint8_t brightnessMax; static uint8_t brightnessSteps; static float brightnessX; - PixelMatrix matrix; + + //Light data + Lights RGBLights; }; #endif diff --git a/lib/AnimationStation/src/Effects/Rainbow.cpp b/lib/AnimationStation/src/Effects/Rainbow.cpp index e73f6f3dff..ac40be6971 100644 --- a/lib/AnimationStation/src/Effects/Rainbow.cpp +++ b/lib/AnimationStation/src/Effects/Rainbow.cpp @@ -1,66 +1,175 @@ #include "Rainbow.hpp" -Rainbow::Rainbow(PixelMatrix &matrix) : Animation(matrix) { +#define RAINBOW_COLORWHEEL_FRAME_MAX 255 + +// clamp rainbowCycleTime to [1 ... INT16_MAX] +#define RAINBOW_CYCLE_INCREMENT 10 +#define RAINBOW_CYCLE_MAX INT16_MAX - RAINBOW_CYCLE_INCREMENT +#define RAINBOW_CYCLE_MIN 1 + RAINBOW_CYCLE_INCREMENT + +//grid distance to frame offset value +#define RAINBOW_GRID_OFFSET_ADJUST 30 + +RainbowSynced::RainbowSynced(Lights& InRGBLights) : Animation(InRGBLights) +{ } -void Rainbow::Animate(RGB (&frame)[100]) { - if (!time_reached(this->nextRunTime)) { +void RainbowSynced::Animate(RGB (&frame)[100]) +{ + if (!time_reached(this->nextRunTime)) + { return; } UpdateTime(); - UpdatePresses(frame); - - for (auto &col : matrix->pixels) { - for (auto &pixel : col) { - if (pixel.index == NO_PIXEL.index) - continue; + UpdatePresses(); - // Count down the timer - DecrementFadeCounter(pixel.index); - - RGB color = RGB::wheel(this->currentFrame); - for (auto &pos : pixel.positions) - frame[pos] = BlendColor(hitColor[pixel.index], color, times[pixel.index]); + RGB color = RGB::wheel(this->currentFrame); + for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + for(int pressedPinIndex = 0; pressedPinIndex < pressedPins.size(); ++pressedPinIndex) + { + if(pressedPins[pressedPinIndex] == RGBLights->AllLights[lightIndex].GIPOPin) + { + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + //Non pressed simply sets the RGB colour + frame[ledIndex] = color; + } + } } } - if (reverse) { + DecrementFadeCounters(); + + if (reverse) + { currentFrame--; - if (currentFrame < 0) { + if (currentFrame < 0) + { currentFrame = 1; reverse = false; } - } else { + } + else + { currentFrame++; - if (currentFrame > 255) { - currentFrame = 254; + if (currentFrame > RAINBOW_COLORWHEEL_FRAME_MAX) + { + currentFrame = RAINBOW_COLORWHEEL_FRAME_MAX - 1; reverse = true; } } - this->nextRunTime = make_timeout_time_ms(AnimationStation::options.rainbowCycleTime); + this->nextRunTime = make_timeout_time_ms(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime); } -// clamp rainbowCycleTime to [1 ... INT16_MAX] -#define RAINBOW_CYCLE_INCREMENT 10 -#define RAINBOW_CYCLE_MAX INT16_MAX - RAINBOW_CYCLE_INCREMENT -#define RAINBOW_CYCLE_MIN 1 + RAINBOW_CYCLE_INCREMENT +void RainbowSynced::ParameterUp() +{ + int16_t& cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; -void Rainbow::ParameterUp() { - if (AnimationStation::options.rainbowCycleTime < RAINBOW_CYCLE_MAX) { - AnimationStation::options.rainbowCycleTime = AnimationStation::options.rainbowCycleTime + RAINBOW_CYCLE_INCREMENT; - } else { - AnimationStation::options.rainbowCycleTime = INT16_MAX; + if (cycleTime < RAINBOW_CYCLE_MAX) + { + cycleTime = cycleTime + RAINBOW_CYCLE_INCREMENT; + } + else + { + cycleTime = INT16_MAX; } } -void Rainbow::ParameterDown() { - if (AnimationStation::options.rainbowCycleTime > RAINBOW_CYCLE_MIN) { - AnimationStation::options.rainbowCycleTime = AnimationStation::options.rainbowCycleTime - RAINBOW_CYCLE_INCREMENT; - } else { - AnimationStation::options.rainbowCycleTime = 1; +void RainbowSynced::ParameterDown() +{ + int16_t& cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; + + if (cycleTime > RAINBOW_CYCLE_MIN) + { + cycleTime = cycleTime - RAINBOW_CYCLE_INCREMENT; + } + else + { + cycleTime = 1; } } + +//////////////////////////////////////////////////////////////////////////////////////////// +RainbowRotate::RainbowRotate(Lights& InRGBLights) : Animation(InRGBLights) +{ +} + +void RainbowRotate::Animate(RGB (&frame)[100]) +{ + if (!time_reached(this->nextRunTime)) + { + return; + } + + UpdateTime(); + UpdatePresses(); + + //the way this works is we offset the current frame by the distance from the top left of the grid + int thisFrame = this->currentFrame; + for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + for(int pressedPinIndex = 0; pressedPinIndex < pressedPins.size(); ++pressedPinIndex) + { + if(pressedPins[pressedPinIndex] == RGBLights->AllLights[lightIndex].GIPOPin) + { + int gridOffset = RGBLights->AllLights[lightIndex].Position.XPosition + RGBLights->AllLights[lightIndex].Position.YPosition; + int thisLightFrame = (thisFrame + (gridOffset * RAINBOW_GRID_OFFSET_ADJUST)) % RAINBOW_COLORWHEEL_FRAME_MAX; + RGB color = RGB::wheel(this->currentFrame); + + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + //Non pressed simply sets the RGB colour + frame[ledIndex] = color; + } + } + } + } + + DecrementFadeCounters(); + + currentFrame++; + + if (currentFrame >= 255) + { + currentFrame = 0; + } + + this->nextRunTime = make_timeout_time_ms(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime); +} + +void RainbowRotate::ParameterUp() +{ + int16_t& cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; + + if (cycleTime < RAINBOW_CYCLE_MAX) + { + cycleTime = cycleTime + RAINBOW_CYCLE_INCREMENT; + } + else + { + cycleTime = INT16_MAX; + } +} + +void RainbowRotate::ParameterDown() +{ + int16_t& cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; + + if (cycleTime > RAINBOW_CYCLE_MIN) + { + cycleTime = cycleTime - RAINBOW_CYCLE_INCREMENT; + } + else + { + cycleTime = 1; + } +} \ No newline at end of file diff --git a/src/addons/neopicoleds.cpp b/src/addons/neopicoleds.cpp index 1705f250e9..bb3d4df6d4 100644 --- a/src/addons/neopicoleds.cpp +++ b/src/addons/neopicoleds.cpp @@ -244,7 +244,6 @@ void NeoPicoLEDAddon::process() //Process hotkeys and action any requests Gamepad * gamepad = Storage::getInstance().GetProcessedGamepad(); - AnimationHotkey action = ProcessAnimationHotkeys(gamepad); if (ledOptions.pledType == PLED_TYPE_RGB) { inputMode = gamepad->getOptions().inputMode; // HACK if (gamepad->auxState.playerID.enabled && gamepad->auxState.playerID.active) { @@ -272,25 +271,23 @@ void NeoPicoLEDAddon::process() } } + //Check for button combos that change animation settings + AnimationHotkey action = ProcessAnimationHotkeys(gamepad); if ( action != HOTKEY_LEDS_NONE ) { AnimStation.HandleEvent(action); } - //Legacy check for button pressed for animation. Needs changing to pin check instead - uint32_t buttonState = gamepad->state.dpad << 16 | gamepad->state.buttons; - vector pressed; - for (auto row : matrix.pixels) + //New check for buttons being pressed. this is a direct check to see if a pin is held + Mask_t values = Storage::getInstance().GetGamepad()->debouncedGpio; + vector pressedPins; + for(auto thisLight : RGBLights.AllLights) { - for (auto pixel : row) + if(values & 1 << thisLight.GIPOPin) { - if (buttonState & pixel.mask) - pressed.push_back(pixel); + pressedPins.push_back(thisLight.GIPOPin); } } - if (pressed.size() > 0) - AnimStation.HandlePressed(pressed); - else - AnimStation.ClearPressed(); + AnimStation.HandlePressedPins(pressedPins); //Update idle, button and special move animations AnimStation.Animate(); @@ -600,8 +597,8 @@ void NeoPicoLEDAddon::configureLEDs() AnimationOptions animationOptions = AnimationStore.getAnimationOptions(); addStaticThemes(ledOptions, animationOptions); AnimStation.SetOptions(animationOptions); - AnimStation.SetMatrix(matrix); - AnimStation.SetMode(as.options.baseAnimationIndex); + AnimStation.SetLights(RGBLights); + AnimStation.SetMode(as.options.baseProfileIndex); } //////////////////////////////////////////// @@ -640,12 +637,12 @@ AnimationHotkey NeoPicoLEDAddon::ProcessAnimationHotkeys(Gamepad *gamepad) { if (gamepad->pressedB3()) { - action = HOTKEY_LEDS_ANIMATION_UP; + action = HOTKEY_LEDS_PROFILE_UP; gamepad->state.buttons &= ~(GAMEPAD_MASK_B3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); } else if (gamepad->pressedB1()) { - action = HOTKEY_LEDS_ANIMATION_DOWN; + action = HOTKEY_LEDS_PROFILE_DOWN; gamepad->state.buttons &= ~(GAMEPAD_MASK_B1 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); } else if (gamepad->pressedB4()) @@ -678,16 +675,6 @@ AnimationHotkey NeoPicoLEDAddon::ProcessAnimationHotkeys(Gamepad *gamepad) action = HOTKEY_LEDS_PRESS_PARAMETER_DOWN; gamepad->state.buttons &= ~(GAMEPAD_MASK_L2 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); } - else if (gamepad->pressedL3()) - { - action = HOTKEY_LEDS_FADETIME_DOWN; - gamepad->state.buttons &= ~(GAMEPAD_MASK_L3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } - else if (gamepad->pressedR3()) - { - action = HOTKEY_LEDS_FADETIME_UP; - gamepad->state.buttons &= ~(GAMEPAD_MASK_R3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); - } } return action; From 7ebe18e41d91ec2db269033eaf88a19f9113f4b5 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Sun, 27 Oct 2024 23:28:58 +0000 Subject: [PATCH 003/121] animation station code dump --- lib/AnimationStation/src/Animation.hpp | 5 +- lib/AnimationStation/src/AnimationStation.cpp | 226 +++++++++++------- lib/AnimationStation/src/AnimationStation.hpp | 20 +- lib/AnimationStation/src/Effects/Rainbow.hpp | 26 +- 4 files changed, 174 insertions(+), 103 deletions(-) diff --git a/lib/AnimationStation/src/Animation.hpp b/lib/AnimationStation/src/Animation.hpp index e056c67e3c..eec661f246 100644 --- a/lib/AnimationStation/src/Animation.hpp +++ b/lib/AnimationStation/src/Animation.hpp @@ -121,7 +121,7 @@ class Animation { //Update timers for pressed buttons this frame void UpdatePresses(); - void DecrementFadeCounters(); + void DecrementFadeCounters(); virtual void ParameterUp() = 0; virtual void ParameterDown() = 0; @@ -132,6 +132,9 @@ class Animation { //Light data Lights* RGBLights; + //Is this running as a button animation + bool isButtonAnimation = false; + //Pins currently pressed std::vector pressedPins; diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index 0277dc1a24..eef24af451 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -12,108 +12,115 @@ uint8_t AnimationStation::brightnessSteps = 5; float AnimationStation::brightnessX = 0; absolute_time_t AnimationStation::nextChange = nil_time; AnimationOptions AnimationStation::options = {}; -uint8_t AnimationStation::effectCount = TOTAL_EFFECTS; - -AnimationStation::AnimationStation() { +AnimationStation::AnimationStation() +{ AnimationStation::SetBrightness(1); } -void AnimationStation::ConfigureBrightness(uint8_t max, uint8_t steps) { +void AnimationStation::ConfigureBrightness(uint8_t max, uint8_t steps) +{ brightnessMax = max; brightnessSteps = steps; } -void AnimationStation::HandleEvent(AnimationHotkey action) { - if (action == HOTKEY_LEDS_NONE || !time_reached(AnimationStation::nextChange)) { +void AnimationStation::HandleEvent(AnimationHotkey action) +{ + if (action == HOTKEY_LEDS_NONE || !time_reached(AnimationStation::nextChange)) + { return; } AnimationStation::nextChange = make_timeout_time_ms(250); - if (action == HOTKEY_LEDS_BRIGHTNESS_UP) { + //Adjust brigness + if (action == HOTKEY_LEDS_BRIGHTNESS_UP) + { AnimationStation::IncreaseBrightness(); } - - if (action == HOTKEY_LEDS_BRIGHTNESS_DOWN) { + if (action == HOTKEY_LEDS_BRIGHTNESS_DOWN) + { AnimationStation::DecreaseBrightness(); } - if (action == HOTKEY_LEDS_ANIMATION_UP) { - ChangeAnimation(1); + //Switch to new profile + if (action == HOTKEY_LEDS_PROFILE_UP) + { + ChangeProfile(1); } - - if (action == HOTKEY_LEDS_ANIMATION_DOWN) { - ChangeAnimation(-1); + if (action == HOTKEY_LEDS_PROFILE_DOWN) + { + ChangeProfile(-1); } - - if (this->baseAnimation == nullptr || this->buttonAnimation == nullptr) { + //Adjust existing profile hotkeys + if (this->baseAnimation == nullptr || this->buttonAnimation == nullptr) + { return; } - - if (action == HOTKEY_LEDS_PARAMETER_UP) { + + if (action == HOTKEY_LEDS_PARAMETER_UP) + { this->baseAnimation->ParameterUp(); } - - if (action == HOTKEY_LEDS_PARAMETER_DOWN) { + if (action == HOTKEY_LEDS_PARAMETER_DOWN) + { this->baseAnimation->ParameterDown(); } - - if (action == HOTKEY_LEDS_PRESS_PARAMETER_UP) { + if (action == HOTKEY_LEDS_PRESS_PARAMETER_UP) + { this->buttonAnimation->ParameterUp(); } - - if (action == HOTKEY_LEDS_PRESS_PARAMETER_DOWN) { + if (action == HOTKEY_LEDS_PRESS_PARAMETER_DOWN) + { this->buttonAnimation->ParameterDown(); - } - - if (action == HOTKEY_LEDS_FADETIME_UP) { - this->baseAnimation->FadeTimeUp(); - } - - if (action == HOTKEY_LEDS_FADETIME_DOWN) { - this->baseAnimation->FadeTimeDown(); } - } -void AnimationStation::ChangeAnimation(int changeSize) { +void AnimationStation::ChangeProfile(int changeSize) +{ this->SetMode(this->AdjustIndex(changeSize)); } -uint16_t AnimationStation::AdjustIndex(int changeSize) { - int newIndex = (int)this->options.baseAnimationIndex + changeSize; +uint16_t AnimationStation::AdjustIndex(int changeSize) +{ + //if no profiles defined then return -1 to turn everything off + if(this->options.profiles.size()) + return -1; + + int newIndex = (int)this->options.baseProfileIndex + changeSize; - if (newIndex >= AnimationStation::effectCount) { + if (newIndex >= this->options.profiles.size()) + { return 0; } - if (newIndex < 0) { - return (AnimationStation::effectCount - 1); + if (newIndex < 0) + { + return (this->options.profiles.size() - 1); } return (uint16_t)newIndex; } -void AnimationStation::HandlePressed(std::vector pressed) { - this->lastPressed = pressed; - this->baseAnimation->UpdatePixels(pressed); - this->buttonAnimation->UpdatePixels(pressed); -} - -void AnimationStation::ClearPressed() { - if (this->buttonAnimation != nullptr) { - this->buttonAnimation->ClearPixels(); +void AnimationStation::HandlePressedPins(std::vector pressedPins) +{ + if(pressedPins.size()) + { + this->lastPressed = pressedPins; + this->buttonAnimation->UpdatePressed(pressedPins); } - if (this->baseAnimation != nullptr) { - this->baseAnimation->ClearPixels(); + else + { + this->lastPressed.clear(); + this->buttonAnimation->ClearPressed(); } - - this->lastPressed.clear(); } -void AnimationStation::Animate() { - if (baseAnimation == nullptr || buttonAnimation == nullptr) { +void AnimationStation::Animate() +{ + //If no profiles running + if (baseAnimation == nullptr || buttonAnimation == nullptr) + { this->Clear(); return; } @@ -122,71 +129,93 @@ void AnimationStation::Animate() { buttonAnimation->Animate(this->frame); } -void AnimationStation::Clear() { memset(frame, 0, sizeof(frame)); } - -float AnimationStation::GetBrightnessX() { - return AnimationStation::brightnessX; +void AnimationStation::Clear() +{ + //sets all lights to black (off) + memset(frame, 0, sizeof(frame)); } -uint8_t AnimationStation::GetBrightness() { - return AnimationStation::options.brightness; +uint8_t AnimationStation::GetMode() +{ + return this->options.baseProfileIndex; } -uint8_t AnimationStation::GetMode() { return this->options.baseAnimationIndex; } +void AnimationStation::SetMode(uint8_t mode) +{ + this->options.baseProfileIndex = mode; -void AnimationStation::SetMode(uint8_t mode) { - this->options.baseAnimationIndex = mode; - AnimationEffects newEffect = - static_cast(this->options.baseAnimationIndex); - - if (this->baseAnimation != nullptr) { + //remove old animations + if (this->baseAnimation != nullptr) + { delete this->baseAnimation; } - if (this->buttonAnimation != nullptr) { + if (this->buttonAnimation != nullptr) + { delete this->buttonAnimation; } + //turn off all lights this->Clear(); - switch (newEffect) { - case AnimationEffects::EFFECT_RAINBOW: - this->baseAnimation = new Rainbow(matrix); - this->buttonAnimation = new StaticColor(matrix, lastPressed); + //no profiles + if(mode == -1) + return; + + //set new profile nonpressed animation + switch ((AnimationNonPressedEffects)this->options.profiles[this->options.baseProfileIndex].baseAnimationEffect) + { + case AnimationNonPressedEffects::NONPRESSED_EFFECT_RAINBOW_SYNCED: + this->baseAnimation = new RainbowSynced(RGBLights); break; - case AnimationEffects::EFFECT_CHASE: - this->baseAnimation = new Chase(matrix); - this->buttonAnimation = new StaticColor(matrix, lastPressed); + + case AnimationNonPressedEffects::NONPRESSED_EFFECT_RAINBOW_ROTATE: + this->baseAnimation = new RainbowRotate(RGBLights); break; - case AnimationEffects::EFFECT_STATIC_THEME: - this->baseAnimation = new StaticTheme(matrix); - this->buttonAnimation = new StaticColor(matrix, lastPressed); + + case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE: + this->baseAnimation = new Chase(RGBLights); break; - case AnimationEffects::EFFECT_CUSTOM_THEME: - this->baseAnimation = new CustomTheme(matrix); - this->buttonAnimation = new CustomThemePressed(matrix, lastPressed); + + case AnimationNonPressedEffects::NONPRESSED_EFFECT_STATIC_COLOR: + this->baseAnimation = new StaticColor(RGBLights); break; + default: - this->baseAnimation = new StaticColor(matrix); - this->buttonAnimation = new StaticColor(matrix, lastPressed); break; } -} -void AnimationStation::SetMatrix(PixelMatrix matrix) { - this->matrix = matrix; + //set new profile pressed animation + switch ((AnimationPressedEffects)this->options.profiles[this->options.baseProfileIndex].basePressedEffect) + { + case AnimationPressedEffects::PRESSED_EFFECT_RANDOM: + this->buttonAnimation = new RandomColour(RGBLights, lastPressed); + + case AnimationPressedEffects::PRESSED_EFFECT_STATIC_COLOR: + this->buttonAnimation = new StaticColor(RGBLights, lastPressed); + + default: + break; + } } -void AnimationStation::SetOptions(AnimationOptions options) { +void AnimationStation::SetOptions(AnimationOptions options) +{ AnimationStation::options = options; AnimationStation::SetBrightness(options.brightness); } -void AnimationStation::ApplyBrightness(uint32_t *frameValue) { +/////////////////////////////////// +// Brightness functions +/////////////////////////////////// + +void AnimationStation::ApplyBrightness(uint32_t *frameValue) +{ for (int i = 0; i < 100; i++) frameValue[i] = this->frame[i].value(Animation::format, brightnessX); } -void AnimationStation::SetBrightness(uint8_t brightness) { +void AnimationStation::SetBrightness(uint8_t brightness) +{ AnimationStation::options.brightness = (brightness > brightnessSteps) ? brightnessSteps : options.brightness; AnimationStation::brightnessX = @@ -198,18 +227,31 @@ void AnimationStation::SetBrightness(uint8_t brightness) { AnimationStation::brightnessX = 0; } -void AnimationStation::DecreaseBrightness() { +void AnimationStation::DecreaseBrightness() +{ if (AnimationStation::options.brightness > 0) AnimationStation::SetBrightness(--AnimationStation::options.brightness); } -void AnimationStation::IncreaseBrightness() { +void AnimationStation::IncreaseBrightness() +{ if (AnimationStation::options.brightness < getBrightnessStepSize()) AnimationStation::SetBrightness(++AnimationStation::options.brightness); else if (AnimationStation::options.brightness > getBrightnessStepSize()) AnimationStation::SetBrightness(brightnessSteps); } -void AnimationStation::DimBrightnessTo0() { +void AnimationStation::DimBrightnessTo0() +{ AnimationStation::brightnessX = 0; } + +float AnimationStation::GetBrightnessX() +{ + return AnimationStation::brightnessX; +} + +uint8_t AnimationStation::GetBrightness() +{ + return AnimationStation::options.brightness; +} \ No newline at end of file diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index 6d9dbd1104..d5034611a1 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -20,13 +20,18 @@ //List of non-pressed animation types typedef enum { - EFFECT_STATIC_COLOR, - EFFECT_RAINBOW_SYNCED, - EFFECT_RAINBOW_ROTATE, - EFFECT_CHASE, -} AnimationEffects; + NONPRESSED_EFFECT_STATIC_COLOR, + NONPRESSED_EFFECT_RAINBOW_SYNCED, + NONPRESSED_EFFECT_RAINBOW_ROTATE, + NONPRESSED_EFFECT_CHASE, +} AnimationNonPressedEffects; -const int TOTAL_EFFECTS = 4; // Exclude custom theme until verified present +//List of non-pressed animation types +typedef enum +{ + PRESSED_EFFECT_STATIC_COLOR, + PRESSED_EFFECT_RANDOM, +} AnimationPressedEffects; typedef enum { @@ -43,7 +48,8 @@ typedef enum struct __attribute__ ((__packed__)) AnimationProfile { - AnimationEffects baseAnimationEffect; + AnimationNonPressedEffects baseAnimationEffect; + AnimationPressedEffects basePressedEffect; int16_t baseCycleTime; diff --git a/lib/AnimationStation/src/Effects/Rainbow.hpp b/lib/AnimationStation/src/Effects/Rainbow.hpp index b8d6fbe644..a9f6a68ea5 100644 --- a/lib/AnimationStation/src/Effects/Rainbow.hpp +++ b/lib/AnimationStation/src/Effects/Rainbow.hpp @@ -8,12 +8,15 @@ #include #include "../AnimationStation.hpp" -class Rainbow : public Animation { +class RainbowSynced : public Animation +{ public: - Rainbow(PixelMatrix &matrix); - ~Rainbow() {}; + RainbowSynced(Lights& InRGBLights); + ~RainbowSynced() {}; void Animate(RGB (&frame)[100]); + + //These change the speed of the rainbow changing color void ParameterUp(); void ParameterDown(); @@ -23,4 +26,21 @@ class Rainbow : public Animation { absolute_time_t nextRunTime = nil_time; }; +class RainbowRotate : public Animation +{ +public: + RainbowRotate(Lights& InRGBLights); + ~RainbowRotate() {}; + + void Animate(RGB (&frame)[100]); + + //These change the speed of the rainbow changing color + void ParameterUp(); + void ParameterDown(); + +protected: + int currentFrame = 0; + absolute_time_t nextRunTime = nil_time; +}; + #endif From dcff107d6c46b1ebac858956f8f29e4b809e5078 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Wed, 30 Oct 2024 08:31:05 +0000 Subject: [PATCH 004/121] Started updating config/animation options --- configs/Haute42COSMOX/BoardConfig.h | 32 ++--- headers/themes.h | 4 +- lib/AnimationStation/CMakeLists.txt | 4 +- lib/AnimationStation/src/Animation.cpp | 26 ++++ lib/AnimationStation/src/Animation.hpp | 15 +- lib/AnimationStation/src/AnimationStation.cpp | 59 ++++++-- lib/AnimationStation/src/AnimationStation.hpp | 18 ++- .../src/Effects/CustomTheme.cpp | 48 ------- .../src/Effects/CustomTheme.hpp | 22 --- .../src/Effects/CustomThemePressed.cpp | 36 ----- .../src/Effects/CustomThemePressed.hpp | 26 ---- lib/AnimationStation/src/Effects/Rainbow.cpp | 50 +++---- .../src/Effects/RandomColor.cpp | 52 +++++++ .../src/Effects/RandomColor.hpp | 25 ++++ .../src/Effects/StaticColor.cpp | 101 ++++---------- .../src/Effects/StaticColor.hpp | 9 +- .../src/Effects/StaticTheme.cpp | 56 -------- .../src/Effects/StaticTheme.hpp | 28 ---- lib/AnimationStation/src/Pixel.hpp | 13 +- proto/config.proto | 64 +++------ src/config_utils.cpp | 69 +++------ src/storagemanager.cpp | 131 ++++++------------ 22 files changed, 338 insertions(+), 550 deletions(-) delete mode 100644 lib/AnimationStation/src/Effects/CustomTheme.cpp delete mode 100644 lib/AnimationStation/src/Effects/CustomTheme.hpp delete mode 100644 lib/AnimationStation/src/Effects/CustomThemePressed.cpp delete mode 100644 lib/AnimationStation/src/Effects/CustomThemePressed.hpp create mode 100644 lib/AnimationStation/src/Effects/RandomColor.cpp create mode 100644 lib/AnimationStation/src/Effects/RandomColor.hpp delete mode 100644 lib/AnimationStation/src/Effects/StaticTheme.cpp delete mode 100644 lib/AnimationStation/src/Effects/StaticTheme.hpp diff --git a/configs/Haute42COSMOX/BoardConfig.h b/configs/Haute42COSMOX/BoardConfig.h index 8859efece1..3089f66dac 100644 --- a/configs/Haute42COSMOX/BoardConfig.h +++ b/configs/Haute42COSMOX/BoardConfig.h @@ -121,22 +121,22 @@ //m2 (extra button 2) #define LIGHT_DATA_SIZE 16 //number of sets in the below data #define LIGHT_DATA \ -0, 1, 0, 2, 5, LightType::LightType_ActionButton, \ -1, 1, 2, 2, 3, LightType::LightType_ActionButton, \ -2, 1, 4, 3, 4, LightType::LightType_ActionButton, \ -3, 1, 6, 7, 2, LightType::LightType_ActionButton, \ -4, 1, 6, 2, 10, LightType::LightType_ActionButton, \ -5, 1, 8, 1, 11, LightType::LightType_ActionButton, \ -6, 1, 10, 1, 12, LightType::LightType_ActionButton, \ -7, 1, 12, 1, 13, LightType::LightType_ActionButton, \ -8, 1, 6, 4, 6, LightType::LightType_ActionButton, \ -9, 1, 8, 3, 7, LightType::LightType_ActionButton, \ -10, 1, 10, 3, 8, LightType::LightType_ActionButton, \ -11, 1, 12, 3, 9, LightType::LightType_ActionButton, \ -12, 1, 3, 0, 27, LightType::LightType_ActionButton, \ -13, 1, 6, 0, 18, LightType::LightType_ActionButton, \ -14, 1, 8, 5, 19, LightType::LightType_ActionButton, \ -15, 1, 3, 6, 26, LightType::LightType_ActionButton +0, 1, 0, 2, 5, LightType_Proto::LightType_Proto_ActionButton, \ +1, 1, 2, 2, 3, LightType_Proto::LightType_Proto_ActionButton, \ +2, 1, 4, 3, 4, LightType_Proto::LightType_Proto_ActionButton, \ +3, 1, 6, 7, 2, LightType_Proto::LightType_Proto_ActionButton, \ +4, 1, 6, 2, 10, LightType_Proto::LightType_Proto_ActionButton, \ +5, 1, 8, 1, 11, LightType_Proto::LightType_Proto_ActionButton, \ +6, 1, 10, 1, 12, LightType_Proto::LightType_Proto_ActionButton, \ +7, 1, 12, 1, 13, LightType_Proto::LightType_Proto_ActionButton, \ +8, 1, 6, 4, 6, LightType_Proto::LightType_Proto_ActionButton, \ +9, 1, 8, 3, 7, LightType_Proto::LightType_Proto_ActionButton, \ +10, 1, 10, 3, 8, LightType_Proto::LightType_Proto_ActionButton, \ +11, 1, 12, 3, 9, LightType_Proto::LightType_Proto_ActionButton, \ +12, 1, 3, 0, 27, LightType_Proto::LightType_Proto_ActionButton, \ +13, 1, 6, 0, 18, LightType_Proto::LightType_Proto_ActionButton, \ +14, 1, 8, 5, 19, LightType_Proto::LightType_Proto_ActionButton, \ +15, 1, 3, 6, 26, LightType_Proto::LightType_Proto_ActionButton #define HAS_I2C_DISPLAY 1 #define I2C0_ENABLED 1 diff --git a/headers/themes.h b/headers/themes.h index acd5cde7f2..000aa40211 100644 --- a/headers/themes.h +++ b/headers/themes.h @@ -17,7 +17,7 @@ using namespace std; void addStaticThemes(const LEDOptions& options, const AnimationOptions& animationOptions) { - map themeStaticRainbow({ +/* map themeStaticRainbow({ { GAMEPAD_MASK_DL, ColorRed }, { GAMEPAD_MASK_DD, ColorOrange }, { GAMEPAD_MASK_DR, ColorYellow }, @@ -358,7 +358,7 @@ void addStaticThemes(const LEDOptions& options, const AnimationOptions& animatio customThemePressed[GAMEPAD_MASK_L3] = RGB(animationOptions.customThemeL3Pressed); customThemePressed[GAMEPAD_MASK_R3] = RGB(animationOptions.customThemeR3Pressed); CustomThemePressed::SetCustomTheme(customThemePressed); - } + }*/ } #endif diff --git a/lib/AnimationStation/CMakeLists.txt b/lib/AnimationStation/CMakeLists.txt index a549510e0e..bc9f428261 100644 --- a/lib/AnimationStation/CMakeLists.txt +++ b/lib/AnimationStation/CMakeLists.txt @@ -1,10 +1,8 @@ add_library(AnimationStation src/Effects/Chase.cpp -src/Effects/CustomTheme.cpp -src/Effects/CustomThemePressed.cpp src/Effects/Rainbow.cpp src/Effects/StaticColor.cpp -src/Effects/StaticTheme.cpp +src/Effects/RandomColor.cpp src/AnimationStation.cpp src/Animation.cpp ) diff --git a/lib/AnimationStation/src/Animation.cpp b/lib/AnimationStation/src/Animation.cpp index 72b0efd1af..c1d95a6272 100644 --- a/lib/AnimationStation/src/Animation.cpp +++ b/lib/AnimationStation/src/Animation.cpp @@ -52,10 +52,19 @@ void Animation::UpdatePresses() { uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + bool wasPressedOrFading = false; for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { + if(fadeTimes[ledIndex] > 0) + wasPressedOrFading = true; fadeTimes[ledIndex] = holdTimeInMs + fadeoutTimeInMs; } + + //if this is a new press, let effects know + if(!wasPressedOrFading) + { + NewPressForPin(lightIndex); + } } } } @@ -93,3 +102,20 @@ RGB Animation::BlendColor(RGB start, RGB end, uint32_t timeRemainingInMs) return result; } + +//Type helpers +bool Animation::LightTypeIsForNonPressedAnimation(LightType Type) +{ + if(Type == LightType::LightType_ActionButton || Type == LightType::LightType_Case) + return true; + + return false; +} + +bool Animation::LightTypeIsForPressedAnimation(LightType Type) +{ + if(Type == LightType::LightType_ActionButton) + return true; + + return false; +} \ No newline at end of file diff --git a/lib/AnimationStation/src/Animation.hpp b/lib/AnimationStation/src/Animation.hpp index eec661f246..956745f6c2 100644 --- a/lib/AnimationStation/src/Animation.hpp +++ b/lib/AnimationStation/src/Animation.hpp @@ -116,6 +116,12 @@ class Animation { virtual void Animate(RGB (&frame)[100]) = 0; + //param adjustment + virtual void ParameterUp() {}; + virtual void ParameterDown() {}; + +protected: + //gets current frame time void UpdateTime(); @@ -123,12 +129,15 @@ class Animation { void UpdatePresses(); void DecrementFadeCounters(); - virtual void ParameterUp() = 0; - virtual void ParameterDown() = 0; + //notifies + virtual void NewPressForPin(int lightIndex) {}; RGB BlendColor(RGB start, RGB end, uint32_t frame); -protected: + //Type Helpers + bool LightTypeIsForNonPressedAnimation(LightType Type); + bool LightTypeIsForPressedAnimation(LightType Type); + //Light data Lights* RGBLights; diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index eef24af451..5e1a3d58ff 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -5,6 +5,11 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include "Effects/Chase.hpp" +#include "Effects/Rainbow.hpp" +#include "Effects/StaticColor.hpp" +#include "Effects/RandomColor.hpp" + #include "AnimationStation.hpp" uint8_t AnimationStation::brightnessMax = 100; @@ -16,6 +21,9 @@ AnimationOptions AnimationStation::options = {}; AnimationStation::AnimationStation() { AnimationStation::SetBrightness(1); + + //ensure valid profile set + ChangeProfile(0); } void AnimationStation::ConfigureBrightness(uint8_t max, uint8_t steps) @@ -83,23 +91,46 @@ void AnimationStation::ChangeProfile(int changeSize) uint16_t AnimationStation::AdjustIndex(int changeSize) { + std::vector validIndexes; + //if no profiles defined then return -1 to turn everything off - if(this->options.profiles.size()) + for(int index = 0; index < MAX_ANIMATION_PROFILES; ++index) + { + if(options.profiles[index].bIsValidProfile) + validIndexes.push_back(index); + } + + if(validIndexes.size() == 0) return -1; - int newIndex = (int)this->options.baseProfileIndex + changeSize; + //find index of current profile + int indexOfCurrentProfile = 0; + for(int index = 0; index < validIndexes.size(); ++index) + { + if(validIndexes[index] == (int)this->options.baseProfileIndex) + { + indexOfCurrentProfile = index; + break; + } + } + + //if we cant find it then this is probably the first call and the first profile isnt valid. Just return whichever is the first valid profile + if(indexOfCurrentProfile == -1) + return validIndexes[0]; - if (newIndex >= this->options.profiles.size()) + int newProfileIndex = indexOfCurrentProfile + changeSize; + + if (newProfileIndex >= validIndexes.size()) { - return 0; + return validIndexes[0]; } - if (newIndex < 0) + if (newProfileIndex < 0) { - return (this->options.profiles.size() - 1); + return validIndexes[validIndexes.size() - 1]; } - return (uint16_t)newIndex; + return (uint16_t)validIndexes[newProfileIndex]; } void AnimationStation::HandlePressedPins(std::vector pressedPins) @@ -135,12 +166,12 @@ void AnimationStation::Clear() memset(frame, 0, sizeof(frame)); } -uint8_t AnimationStation::GetMode() +int8_t AnimationStation::GetMode() { return this->options.baseProfileIndex; } -void AnimationStation::SetMode(uint8_t mode) +void AnimationStation::SetMode(int8_t mode) { this->options.baseProfileIndex = mode; @@ -162,7 +193,7 @@ void AnimationStation::SetMode(uint8_t mode) return; //set new profile nonpressed animation - switch ((AnimationNonPressedEffects)this->options.profiles[this->options.baseProfileIndex].baseAnimationEffect) + switch ((AnimationNonPressedEffects)this->options.profiles[this->options.baseProfileIndex].baseNonPressedEffect) { case AnimationNonPressedEffects::NONPRESSED_EFFECT_RAINBOW_SYNCED: this->baseAnimation = new RainbowSynced(RGBLights); @@ -172,10 +203,10 @@ void AnimationStation::SetMode(uint8_t mode) this->baseAnimation = new RainbowRotate(RGBLights); break; - case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE: +/* case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE: this->baseAnimation = new Chase(RGBLights); break; - +*/ case AnimationNonPressedEffects::NONPRESSED_EFFECT_STATIC_COLOR: this->baseAnimation = new StaticColor(RGBLights); break; @@ -187,9 +218,9 @@ void AnimationStation::SetMode(uint8_t mode) //set new profile pressed animation switch ((AnimationPressedEffects)this->options.profiles[this->options.baseProfileIndex].basePressedEffect) { - case AnimationPressedEffects::PRESSED_EFFECT_RANDOM: +/* case AnimationPressedEffects::PRESSED_EFFECT_RANDOM: this->buttonAnimation = new RandomColour(RGBLights, lastPressed); - +*/ case AnimationPressedEffects::PRESSED_EFFECT_STATIC_COLOR: this->buttonAnimation = new StaticColor(RGBLights, lastPressed); diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index d5034611a1..a1d74e95c4 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -10,12 +10,8 @@ #include "NeoPico.hpp" #include "Animation.hpp" -#include "Effects/Chase.hpp" -#include "Effects/CustomTheme.hpp" -#include "Effects/CustomThemePressed.hpp" -#include "Effects/Rainbow.hpp" -#include "Effects/StaticColor.hpp" -#include "Effects/StaticTheme.hpp" + +#define MAX_ANIMATION_PROFILES 8 //List of non-pressed animation types typedef enum @@ -48,7 +44,9 @@ typedef enum struct __attribute__ ((__packed__)) AnimationProfile { - AnimationNonPressedEffects baseAnimationEffect; + bool bIsValidProfile; + + AnimationNonPressedEffects baseNonPressedEffect; AnimationPressedEffects basePressedEffect; int16_t baseCycleTime; @@ -63,7 +61,7 @@ struct __attribute__ ((__packed__)) AnimationProfile struct __attribute__ ((__packed__)) AnimationOptions { uint32_t checksum; - std::vector profiles; + AnimationProfile profiles[MAX_ANIMATION_PROFILES]; uint8_t brightness; uint8_t baseProfileIndex; }; @@ -85,8 +83,8 @@ class AnimationStation //What buttons (physical gpio pins) are pressed this frame void HandlePressedPins(std::vector pressedPins); - uint8_t GetMode(); - void SetMode(uint8_t mode); + int8_t GetMode(); + void SetMode(int8_t mode); void SetLights(Lights InRGBLights); //Brightness settings diff --git a/lib/AnimationStation/src/Effects/CustomTheme.cpp b/lib/AnimationStation/src/Effects/CustomTheme.cpp deleted file mode 100644 index 07c5ac26ae..0000000000 --- a/lib/AnimationStation/src/Effects/CustomTheme.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "CustomTheme.hpp" - -std::map CustomTheme::theme; - -CustomTheme::CustomTheme(PixelMatrix &matrix) : Animation(matrix) { -} - -void CustomTheme::Animate(RGB (&frame)[100]) { - UpdateTime(); - UpdatePresses(frame); - - for (size_t r = 0; r != matrix->pixels.size(); r++) { - for (size_t c = 0; c != matrix->pixels[r].size(); c++) { - if (matrix->pixels[r][c].index == NO_PIXEL.index) - continue; - - // Count down the timer - DecrementFadeCounter(matrix->pixels[r][c].index); - - auto itr = theme.find(matrix->pixels[r][c].mask); - if (itr != theme.end()) { - for (size_t p = 0; p != matrix->pixels[r][c].positions.size(); p++) { - // Interpolate from hitColor (color the button was assigned when pressed) back to the theme color - frame[matrix->pixels[r][c].positions[p]] = BlendColor(hitColor[matrix->pixels[r][c].index], itr->second, times[matrix->pixels[r][c].index]); - } - } else { - for (size_t p = 0; p != matrix->pixels[r][c].positions.size(); p++) { - frame[matrix->pixels[r][c].positions[p]] = defaultColor; - } - } - } - } -} - -bool CustomTheme::HasTheme() { - return CustomTheme::theme.size() > 0; -} - -void CustomTheme::SetCustomTheme(std::map customTheme) { - CustomTheme::theme = customTheme; - AnimationStation::effectCount = TOTAL_EFFECTS + 1; -} - -void CustomTheme::ParameterUp() { -} - -void CustomTheme::ParameterDown() { -} diff --git a/lib/AnimationStation/src/Effects/CustomTheme.hpp b/lib/AnimationStation/src/Effects/CustomTheme.hpp deleted file mode 100644 index ca11a5e83c..0000000000 --- a/lib/AnimationStation/src/Effects/CustomTheme.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CUSTOM_THEME_H_ -#define CUSTOM_THEME_H_ - -#include -#include "../Animation.hpp" -#include "../AnimationStation.hpp" - -class CustomTheme : public Animation { -public: - CustomTheme(PixelMatrix &matrix); - ~CustomTheme() { }; - - static bool HasTheme(); - static void SetCustomTheme(std::map customTheme); - void Animate(RGB (&frame)[100]); - void ParameterUp(); - void ParameterDown(); -protected: - static std::map theme; -}; - -#endif diff --git a/lib/AnimationStation/src/Effects/CustomThemePressed.cpp b/lib/AnimationStation/src/Effects/CustomThemePressed.cpp deleted file mode 100644 index f5e3ce8baf..0000000000 --- a/lib/AnimationStation/src/Effects/CustomThemePressed.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "CustomThemePressed.hpp" - -std::map CustomThemePressed::theme; - -CustomThemePressed::CustomThemePressed(PixelMatrix &matrix) : Animation(matrix) { - this->filtered = true; -} - -CustomThemePressed::CustomThemePressed(PixelMatrix &matrix, std::vector &pixels) : Animation(matrix), pixels(&pixels) { - this->filtered = true; -} - -void CustomThemePressed::Animate(RGB (&frame)[100]) { - for (size_t r = 0; r != matrix->pixels.size(); r++) { - for (size_t c = 0; c != matrix->pixels[r].size(); c++) { - if (matrix->pixels[r][c].index == NO_PIXEL.index || this->notInFilter(matrix->pixels[r][c])) - continue; - - auto itr = theme.find(matrix->pixels[r][c].mask); - if (itr != theme.end()) - for (size_t p = 0; p != matrix->pixels[r][c].positions.size(); p++) - frame[matrix->pixels[r][c].positions[p]] = itr->second; - else - for (size_t p = 0; p != matrix->pixels[r][c].positions.size(); p++) - frame[matrix->pixels[r][c].positions[p]] = defaultColor; - } - } -} - -bool CustomThemePressed::HasTheme() { - return CustomThemePressed::theme.size() > 0; -} - -void CustomThemePressed::SetCustomTheme(std::map customTheme) { - CustomThemePressed::theme = customTheme; -} diff --git a/lib/AnimationStation/src/Effects/CustomThemePressed.hpp b/lib/AnimationStation/src/Effects/CustomThemePressed.hpp deleted file mode 100644 index 8e16109e4c..0000000000 --- a/lib/AnimationStation/src/Effects/CustomThemePressed.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _CUSTOM_THEME_PRESSED_H_ -#define _CUSTOM_THEME_PRESSED_H_ - -#include -#include -#include "../Animation.hpp" -#include "../AnimationStation.hpp" - -class CustomThemePressed : public Animation { -public: - CustomThemePressed(PixelMatrix &matrix); - CustomThemePressed(PixelMatrix &matrix, std::vector &pixels); - ~CustomThemePressed() { pixels = nullptr; }; - - static bool HasTheme(); - static void SetCustomTheme(std::map customTheme); - void Animate(RGB (&frame)[100]); - void ParameterUp() { } - void ParameterDown() { } -protected: - std::vector *pixels; - RGB defaultColor = ColorBlack; - static std::map theme; -}; - -#endif diff --git a/lib/AnimationStation/src/Effects/Rainbow.cpp b/lib/AnimationStation/src/Effects/Rainbow.cpp index ac40be6971..50b53f0aa7 100644 --- a/lib/AnimationStation/src/Effects/Rainbow.cpp +++ b/lib/AnimationStation/src/Effects/Rainbow.cpp @@ -21,28 +21,25 @@ void RainbowSynced::Animate(RGB (&frame)[100]) return; } - UpdateTime(); - UpdatePresses(); + //UpdateTime(); + //UpdatePresses(); RGB color = RGB::wheel(this->currentFrame); for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { - for(int pressedPinIndex = 0; pressedPinIndex < pressedPins.size(); ++pressedPinIndex) + if(LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { - if(pressedPins[pressedPinIndex] == RGBLights->AllLights[lightIndex].GIPOPin) + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { - uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; - uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; - for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) - { - //Non pressed simply sets the RGB colour - frame[ledIndex] = color; - } + //Non pressed simply sets the RGB colour + frame[ledIndex] = color; } } } - DecrementFadeCounters(); + //DecrementFadeCounters(); if (reverse) { @@ -108,33 +105,30 @@ void RainbowRotate::Animate(RGB (&frame)[100]) return; } - UpdateTime(); - UpdatePresses(); + //UpdateTime(); + //UpdatePresses(); //the way this works is we offset the current frame by the distance from the top left of the grid int thisFrame = this->currentFrame; for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { - for(int pressedPinIndex = 0; pressedPinIndex < pressedPins.size(); ++pressedPinIndex) + if(LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { - if(pressedPins[pressedPinIndex] == RGBLights->AllLights[lightIndex].GIPOPin) + int gridOffset = RGBLights->AllLights[lightIndex].Position.XPosition + RGBLights->AllLights[lightIndex].Position.YPosition; + int thisLightFrame = (thisFrame + (gridOffset * RAINBOW_GRID_OFFSET_ADJUST)) % RAINBOW_COLORWHEEL_FRAME_MAX; + RGB color = RGB::wheel(thisLightFrame); + + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { - int gridOffset = RGBLights->AllLights[lightIndex].Position.XPosition + RGBLights->AllLights[lightIndex].Position.YPosition; - int thisLightFrame = (thisFrame + (gridOffset * RAINBOW_GRID_OFFSET_ADJUST)) % RAINBOW_COLORWHEEL_FRAME_MAX; - RGB color = RGB::wheel(this->currentFrame); - - uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; - uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; - for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) - { - //Non pressed simply sets the RGB colour - frame[ledIndex] = color; - } + //Non pressed simply sets the RGB colour + frame[ledIndex] = color; } } } - DecrementFadeCounters(); + //DecrementFadeCounters(); currentFrame++; diff --git a/lib/AnimationStation/src/Effects/RandomColor.cpp b/lib/AnimationStation/src/Effects/RandomColor.cpp new file mode 100644 index 0000000000..a607ff44d8 --- /dev/null +++ b/lib/AnimationStation/src/Effects/RandomColor.cpp @@ -0,0 +1,52 @@ +#include "RandomColor.hpp" + +RandomColor::RandomColor(Lights& InRGBLights) : Animation(InRGBLights) +{ +} + +RandomColor::RandomColor(Lights& InRGBLights, std::vector &InPressedPins) : Animation(InRGBLights) +{ + isButtonAnimation = true; + pressedPins = InPressedPins; + + savedPressedColour.clear(); + for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + savedPressedColour.push_back(RGB(0)); + } +} + +void RandomColor::NewPressForPin(int lightIndex) +{ + savedPressedColour[lightIndex] = colors[rand() % colors.size()]; +} + +void RandomColor::Animate(RGB (&frame)[100]) +{ + UpdateTime(); + UpdatePresses(); + + for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + + for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + //Non pressed simply sets the RGB colour + if(!isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) + { + frame[ledIndex] = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin]; + } + else if (isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) + { + frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin], + frame[ledIndex], + fadeTimes[ledIndex]); + } + } + } + + // Count down the timer + DecrementFadeCounters(); +} \ No newline at end of file diff --git a/lib/AnimationStation/src/Effects/RandomColor.hpp b/lib/AnimationStation/src/Effects/RandomColor.hpp new file mode 100644 index 0000000000..f804530a4d --- /dev/null +++ b/lib/AnimationStation/src/Effects/RandomColor.hpp @@ -0,0 +1,25 @@ +#ifndef _RANDOM_COLOR_H_ +#define _RANDOM_COLOR_H_ + +#include +#include +#include +#include "../Animation.hpp" +#include "../AnimationStation.hpp" + +class RandomColor : public Animation { +public: + RandomColor(Lights& InRGBLights); + RandomColor(Lights& InRGBLights, std::vector &InPressedPins); + ~RandomColor() { }; + + void Animate(RGB (&frame)[100]); + +protected: + + virtual void NewPressForPin(int lightIndex) override; + + std::vector savedPressedColour; +}; + +#endif diff --git a/lib/AnimationStation/src/Effects/StaticColor.cpp b/lib/AnimationStation/src/Effects/StaticColor.cpp index 748586beee..7b1d4b22d0 100644 --- a/lib/AnimationStation/src/Effects/StaticColor.cpp +++ b/lib/AnimationStation/src/Effects/StaticColor.cpp @@ -1,82 +1,41 @@ #include "StaticColor.hpp" -StaticColor::StaticColor(PixelMatrix &matrix) : Animation(matrix) { +StaticColor::StaticColor(Lights& InRGBLights) : Animation(InRGBLights) +{ } -StaticColor::StaticColor(PixelMatrix &matrix, std::vector &inpixels) : Animation(matrix) { - this->filtered = true; - pixels = inpixels; +StaticColor::StaticColor(Lights& InRGBLights, std::vector &InPressedPins) : Animation(InRGBLights) +{ + isButtonAnimation = true; + pressedPins = InPressedPins; } -void StaticColor::Animate(RGB (&frame)[100]) { +void StaticColor::Animate(RGB (&frame)[100]) +{ UpdateTime(); - UpdatePresses(frame); - - for (size_t r = 0; r != matrix->pixels.size(); r++) { - for (size_t c = 0; c != matrix->pixels[r].size(); c++) { - if (matrix->pixels[r][c].index == NO_PIXEL.index || this->notInFilter(matrix->pixels[r][c])) - continue; - - // Count down the timer - DecrementFadeCounter(matrix->pixels[r][c].index); - - for (size_t p = 0; p != matrix->pixels[r][c].positions.size(); p++) { - // Interpolate from hitColor (color the button was assigned when pressed) back to the theme color - if (!this->filtered) { - frame[matrix->pixels[r][c].positions[p]] = BlendColor(hitColor[matrix->pixels[r][c].index], colors[this->GetColor()], times[matrix->pixels[r][c].index]); - } else { - frame[matrix->pixels[r][c].positions[p]] = colors[this->GetColor()]; - } + UpdatePresses(); + + for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + + for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + //Non pressed simply sets the RGB colour + if(!isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) + { + frame[ledIndex] = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin]; + } + else if (isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) + { + frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin], + frame[ledIndex], + fadeTimes[ledIndex]); } } } -} -uint8_t StaticColor::GetColor() { - if (this->filtered) { - return AnimationStation::options.buttonColorIndex; - } else { - return AnimationStation::options.staticColorIndex; - } -} - -void StaticColor::ParameterUp() { - uint8_t colorIndex; - if (this->filtered) { - colorIndex = AnimationStation::options.buttonColorIndex; - } else { - colorIndex = AnimationStation::options.staticColorIndex; - } - - if (colorIndex < colors.size() - 1) { - colorIndex++; - } else { - colorIndex = 0; - } - - this->SaveIndexOptions(colorIndex); -} - -void StaticColor::SaveIndexOptions(uint8_t colorIndex) { - if (this->filtered) { - AnimationStation::options.buttonColorIndex = colorIndex; - } else { - AnimationStation::options.staticColorIndex = colorIndex; - } -} - -void StaticColor::ParameterDown() { - uint8_t colorIndex; - if (this->filtered) { - colorIndex = AnimationStation::options.buttonColorIndex; - } else { - colorIndex = AnimationStation::options.staticColorIndex; - } - - if (colorIndex > 0) { - colorIndex--; - } else { - colorIndex = colors.size() - 1; - } - this->SaveIndexOptions(colorIndex); -} + // Count down the timer + DecrementFadeCounters(); +} \ No newline at end of file diff --git a/lib/AnimationStation/src/Effects/StaticColor.hpp b/lib/AnimationStation/src/Effects/StaticColor.hpp index da5d59a81c..4e5c1c829f 100644 --- a/lib/AnimationStation/src/Effects/StaticColor.hpp +++ b/lib/AnimationStation/src/Effects/StaticColor.hpp @@ -9,15 +9,12 @@ class StaticColor : public Animation { public: - StaticColor(PixelMatrix &matrix); - StaticColor(PixelMatrix &matrix, std::vector &pixels); + StaticColor(Lights& InRGBLights); + StaticColor(Lights& InRGBLights, std::vector &InPressedPins); ~StaticColor() { }; void Animate(RGB (&frame)[100]); - void SaveIndexOptions(uint8_t colorIndex); - uint8_t GetColor(); - void ParameterUp(); - void ParameterDown(); + protected: }; diff --git a/lib/AnimationStation/src/Effects/StaticTheme.cpp b/lib/AnimationStation/src/Effects/StaticTheme.cpp deleted file mode 100644 index afbd60a3c4..0000000000 --- a/lib/AnimationStation/src/Effects/StaticTheme.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "StaticTheme.hpp" - -std::vector> StaticTheme::themes = {}; - -StaticTheme::StaticTheme(PixelMatrix &matrix) : Animation(matrix) { - if (AnimationStation::options.themeIndex >= StaticTheme::themes.size()) { - AnimationStation::options.themeIndex = 0; - } -} - -void StaticTheme::Animate(RGB (&frame)[100]) { - if (StaticTheme::themes.size() > 0) { - UpdateTime(); - UpdatePresses(frame); - - for (size_t r = 0; r != matrix->pixels.size(); r++) { - for (size_t c = 0; c != matrix->pixels[r].size(); c++) { - if (matrix->pixels[r][c].index == NO_PIXEL.index) - continue; - - // Count down the timer - DecrementFadeCounter(matrix->pixels[r][c].index); - - std::map theme = StaticTheme::themes.at(AnimationStation::options.themeIndex); - - auto itr = theme.find(matrix->pixels[r][c].mask); - if (itr != theme.end()) { - for (size_t p = 0; p != matrix->pixels[r][c].positions.size(); p++) { - // Interpolate from hitColor (color the button was assigned when pressed) back to the theme color - frame[matrix->pixels[r][c].positions[p]] = BlendColor(hitColor[matrix->pixels[r][c].index], itr->second, times[matrix->pixels[r][c].index]); - } - } else { - for (size_t p = 0; p != matrix->pixels[r][c].positions.size(); p++) { - frame[matrix->pixels[r][c].positions[p]] = defaultColor; - } - } - } - } - } -} - -void StaticTheme::ParameterUp() { - if (AnimationStation::options.themeIndex < StaticTheme::themes.size() - 1) { - AnimationStation::options.themeIndex++; - } else { - AnimationStation::options.themeIndex = 0; - } -} - -void StaticTheme::ParameterDown() { - if (AnimationStation::options.themeIndex > 0) { - AnimationStation::options.themeIndex--; - } else { - AnimationStation::options.themeIndex = StaticTheme::themes.size() - 1; - } -} diff --git a/lib/AnimationStation/src/Effects/StaticTheme.hpp b/lib/AnimationStation/src/Effects/StaticTheme.hpp deleted file mode 100644 index e6d2e422b5..0000000000 --- a/lib/AnimationStation/src/Effects/StaticTheme.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef STATIC_THEME_H_ -#define STATIC_THEME_H_ - -#include -#include -#include -#include -#include -#include -#include "../Animation.hpp" -#include "../AnimationStation.hpp" - -class StaticTheme : public Animation { -public: - StaticTheme(PixelMatrix &matrix); - ~StaticTheme() {}; - - static void AddTheme(const std::map& theme) { themes.push_back(theme); } - static void ClearThemes() { themes.clear(); } - void Animate(RGB (&frame)[100]); - void ParameterUp(); - void ParameterDown(); -protected: - RGB defaultColor = ColorBlack; - static std::vector> themes; -}; - -#endif diff --git a/lib/AnimationStation/src/Pixel.hpp b/lib/AnimationStation/src/Pixel.hpp index 2c48fedb9f..1892f1ff43 100644 --- a/lib/AnimationStation/src/Pixel.hpp +++ b/lib/AnimationStation/src/Pixel.hpp @@ -6,6 +6,15 @@ #include #include +typedef enum _LightType +{ + LightType_ActionButton = 0, + LightType_Case = 1, + LightType_Turbo = 2, + LightType_PlayerLight = 3, + LightType_MAX = 4, +} LightType; + struct Pixel { Pixel(int index, uint32_t mask = 0) : index(index), mask(mask) { } Pixel(int index, std::vector positions) : index(index), positions(positions) { } @@ -76,7 +85,7 @@ struct LightPosition //A single RGB light on the device. Replaced Pixel struct Light { - Light(uint8_t InFirstLedIndex, uint8_t InNumLedsPerLight, LightPosition InPosition, uint8_t GIPOPin, uint8_t InType) + Light(uint8_t InFirstLedIndex, uint8_t InNumLedsPerLight, LightPosition InPosition, uint8_t GIPOPin, LightType InType) { FirstLedIndex = InFirstLedIndex; Position = InPosition; @@ -93,7 +102,7 @@ struct Light LightPosition Position; // Type of light, used in animations to allow users to seperate off lights for different anims - uint8_t Type; + LightType Type; //How many leds make up this light. uint8_t LedsPerLight; diff --git a/proto/config.proto b/proto/config.proto index 44593ec4d9..c377722691 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -290,55 +290,29 @@ message LEDOptions optional int32 pledIndex4 = 35; }; +// This has to be kept in sync with AnimationOptions in AnimationStation.hpp +message AnimationProfile_Proto +{ + optional bool bIsValidProfile = 1; + + optional AnimationNonPressedEffects_Proto baseNonPressedEffect = 2; + optional AnimationPressedEffects_Proto basePressedEffect = 3; + + optional int32 baseCycleTime = 4; + + optional uint32 notPressedStaticColors[NUM_BANK0_GPIOS] = 5; + optional uint32 pressedStaticColors[NUM_BANK0_GPIOS] = 6; + + optional uint32 buttonPressHoldTimeInMs = 7; + optional uint32 buttonPressFadeOutTimeInMs = 8; +}; + // This has to be kept in sync with AnimationOptions in AnimationStation.hpp message AnimationOptions_Proto { - optional uint32 baseAnimationIndex = 1; + optional AnimationProfile profiles = 1; [(nanopb).max_count = 8]; //MAX_ANIMATION_PROFILES from AnimationStation.hpp optional uint32 brightness = 2; - optional uint32 staticColorIndex = 3; - optional uint32 buttonColorIndex = 4; - optional int32 chaseCycleTime = 5; - optional int32 rainbowCycleTime = 6; - optional uint32 themeIndex = 7; - - optional bool hasCustomTheme = 8; - optional uint32 customThemeUp = 9; - optional uint32 customThemeDown = 10; - optional uint32 customThemeLeft = 11; - optional uint32 customThemeRight = 12; - optional uint32 customThemeB1 = 13; - optional uint32 customThemeB2 = 14; - optional uint32 customThemeB3 = 15; - optional uint32 customThemeB4 = 16; - optional uint32 customThemeL1 = 17; - optional uint32 customThemeR1 = 18; - optional uint32 customThemeL2 = 19; - optional uint32 customThemeR2 = 20; - optional uint32 customThemeS1 = 21; - optional uint32 customThemeS2 = 22; - optional uint32 customThemeL3 = 23; - optional uint32 customThemeR3 = 24; - optional uint32 customThemeA1 = 25; - optional uint32 customThemeA2 = 26; - optional uint32 customThemeUpPressed = 27; - optional uint32 customThemeDownPressed = 28; - optional uint32 customThemeLeftPressed = 29; - optional uint32 customThemeRightPressed = 30; - optional uint32 customThemeB1Pressed = 31; - optional uint32 customThemeB2Pressed = 32; - optional uint32 customThemeB3Pressed = 33; - optional uint32 customThemeB4Pressed = 34; - optional uint32 customThemeL1Pressed = 35; - optional uint32 customThemeR1Pressed = 36; - optional uint32 customThemeL2Pressed = 37; - optional uint32 customThemeR2Pressed = 38; - optional uint32 customThemeS1Pressed = 39; - optional uint32 customThemeS2Pressed = 40; - optional uint32 customThemeL3Pressed = 41; - optional uint32 customThemeR3Pressed = 42; - optional uint32 customThemeA1Pressed = 43; - optional uint32 customThemeA2Pressed = 44; - optional uint32 buttonPressColorCooldownTimeInMs = 45; + optional uint32 baseProfileIndex = 3; } message BootselButtonOptions diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 14eb5dbe34..64108a7244 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -472,56 +472,33 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.ledOptions, pledIndex4, PLED4_PIN); // lightEntries INIT_UNSET_PROPERTY(config.ledOptions, lightDataSize, LIGHT_DATA_SIZE); - const uint8_t lightData[] = { LIGHT_DATA }; + const unsigned char lightData[] = { LIGHT_DATA }; INIT_UNSET_PROPERTY_BYTES(config.ledOptions, lightData, lightData); // animationOptions - INIT_UNSET_PROPERTY(config.animationOptions, baseAnimationIndex, LEDS_BASE_ANIMATION_INDEX); + if(config.animationOptions.has_profiles == false) + { + config.animationOptions.has_profiles = true; + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], bIsValidProfile, true); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], baseNonPressedEffect, AnimationNonPressedEffects_Proto::NONPRESSED_Proto_EFFECT_RAINBOW_ROTATE); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], basePressedEffect, AnimationPressedEffects_Proto::PRESSED_Proto_EFFECT_RANDOM); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], baseCycleTime, 1); + for (int index = 0; index < NUM_BANK0_GPIOS; ++index) + { + if(!config.animationOptions.profiles[0].has_notPressedStaticColors) + config.animationOptions.profiles[0].notPressedStaticColors[index] = 0; + if(!config.animationOptions.profiles[0].has_pressedStaticColors) + config.animationOptions.profiles[0].pressedStaticColors[index] = 0; + } + config.animationOptions.profiles[0].has_notPressedStaticColors = true; + config.animationOptions.profiles[0].has_pressedStaticColors = true; + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], buttonPressHoldTimeInMs, 0); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], buttonPressFadeOutTimeInMs, 0); + } + //INIT_UNSET_PROPERTY(config.animationOptions, profiles[0], defaultProfile); INIT_UNSET_PROPERTY(config.animationOptions, brightness, LEDS_BRIGHTNESS); - INIT_UNSET_PROPERTY(config.animationOptions, staticColorIndex, LEDS_STATIC_COLOR_INDEX); - INIT_UNSET_PROPERTY(config.animationOptions, buttonColorIndex, LEDS_BUTTON_COLOR_INDEX); - INIT_UNSET_PROPERTY(config.animationOptions, chaseCycleTime, LEDS_CHASE_CYCLE_TIME); - INIT_UNSET_PROPERTY(config.animationOptions, rainbowCycleTime, LEDS_RAINBOW_CYCLE_TIME); - INIT_UNSET_PROPERTY(config.animationOptions, themeIndex, LEDS_THEME_INDEX); - INIT_UNSET_PROPERTY(config.animationOptions, hasCustomTheme, false); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeUp, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeDown, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeLeft, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeRight, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeB1, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeB2, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeB3, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeB4, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeL1, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeR1, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeL2, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeR2, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeS1, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeS2, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeL3, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeR3, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeA1, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeA2, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeUpPressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeDownPressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeLeftPressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeRightPressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeB1Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeB2Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeB3Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeB4Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeL1Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeR1Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeL2Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeR2Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeS1Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeS2Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeL3Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeR3Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeA1Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, customThemeA2Pressed, 0); - INIT_UNSET_PROPERTY(config.animationOptions, buttonPressColorCooldownTimeInMs, LEDS_PRESS_COLOR_COOLDOWN_TIME); - + INIT_UNSET_PROPERTY(config.animationOptions, baseProfileIndex, 0); + // addonOptions.bootselButtonOptions INIT_UNSET_PROPERTY(config.addonOptions.bootselButtonOptions, enabled, !!BOOTSEL_BUTTON_ENABLED); INIT_UNSET_PROPERTY(config.addonOptions.bootselButtonOptions, buttonMap, BOOTSEL_BUTTON_MASK); diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index c8d2121fe5..ea4aed161e 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -36,51 +36,22 @@ static void updateAnimationOptionsProto(const AnimationOptions& options) { AnimationOptions_Proto& optionsProto = Storage::getInstance().getAnimationOptions(); - optionsProto.baseAnimationIndex = options.baseAnimationIndex; + for(int index = 0; index < 8; ++index) //MAX_ANIMATION_PROFILES from AnimationStation.hpp + { + optionsProto.profiles[index].bIsValidProfile = options.profiles[index].bIsValidProfile; + optionsProto.profiles[index].baseNonPressedEffect = (AnimationNonPressedEffects_Proto)((int)options.profiles[index].baseNonPressedEffect); + optionsProto.profiles[index].basePressedEffect = (AnimationPressedEffects_Proto)((int)options.profiles[index].basePressedEffect); + optionsProto.profiles[index].baseCycleTime = options.profiles[index].baseCycleTime; + for(int pinIndex = 0; pinIndex < NUM_BANK0_GPIOS; ++pinIndex) + { + optionsProto.profiles[index].notPressedStaticColors[pinIndex] = options.profiles[index].notPressedStaticColors[pinIndex]; + optionsProto.profiles[index].pressedStaticColors[pinIndex] = options.profiles[index].pressedStaticColors[pinIndex]; + } + optionsProto.profiles[index].buttonPressHoldTimeInMs = options.profiles[index].buttonPressHoldTimeInMs; + optionsProto.profiles[index].buttonPressFadeOutTimeInMs = options.profiles[index].buttonPressFadeOutTimeInMs; + } optionsProto.brightness = options.brightness; - optionsProto.staticColorIndex = options.staticColorIndex; - optionsProto.buttonColorIndex = options.buttonColorIndex; - optionsProto.chaseCycleTime = options.chaseCycleTime; - optionsProto.rainbowCycleTime = options.rainbowCycleTime; - optionsProto.themeIndex = options.themeIndex; - optionsProto.hasCustomTheme = options.hasCustomTheme; - optionsProto.customThemeUp = options.customThemeUp; - optionsProto.customThemeDown = options.customThemeDown; - optionsProto.customThemeLeft = options.customThemeLeft; - optionsProto.customThemeRight = options.customThemeRight; - optionsProto.customThemeB1 = options.customThemeB1; - optionsProto.customThemeB2 = options.customThemeB2; - optionsProto.customThemeB3 = options.customThemeB3; - optionsProto.customThemeB4 = options.customThemeB4; - optionsProto.customThemeL1 = options.customThemeL1; - optionsProto.customThemeR1 = options.customThemeR1; - optionsProto.customThemeL2 = options.customThemeL2; - optionsProto.customThemeR2 = options.customThemeR2; - optionsProto.customThemeS1 = options.customThemeS1; - optionsProto.customThemeS2 = options.customThemeS2; - optionsProto.customThemeA1 = options.customThemeA1; - optionsProto.customThemeA2 = options.customThemeA2; - optionsProto.customThemeL3 = options.customThemeL3; - optionsProto.customThemeR3 = options.customThemeR3; - optionsProto.customThemeUpPressed = options.customThemeUpPressed; - optionsProto.customThemeDownPressed = options.customThemeDownPressed; - optionsProto.customThemeLeftPressed = options.customThemeLeftPressed; - optionsProto.customThemeRightPressed = options.customThemeRightPressed; - optionsProto.customThemeB1Pressed = options.customThemeB1Pressed; - optionsProto.customThemeB2Pressed = options.customThemeB2Pressed; - optionsProto.customThemeB3Pressed = options.customThemeB3Pressed; - optionsProto.customThemeB4Pressed = options.customThemeB4Pressed; - optionsProto.customThemeL1Pressed = options.customThemeL1Pressed; - optionsProto.customThemeR1Pressed = options.customThemeR1Pressed; - optionsProto.customThemeL2Pressed = options.customThemeL2Pressed; - optionsProto.customThemeR2Pressed = options.customThemeR2Pressed; - optionsProto.customThemeS1Pressed = options.customThemeS1Pressed; - optionsProto.customThemeS2Pressed = options.customThemeS2Pressed; - optionsProto.customThemeA1Pressed = options.customThemeA1Pressed; - optionsProto.customThemeA2Pressed = options.customThemeA2Pressed; - optionsProto.customThemeL3Pressed = options.customThemeL3Pressed; - optionsProto.customThemeR3Pressed = options.customThemeR3Pressed; - optionsProto.buttonPressColorCooldownTimeInMs = options.buttonPressColorCooldownTimeInMs; + optionsProto.baseProfileIndex = options.baseProfileIndex; } void Storage::performEnqueuedSaves() @@ -223,52 +194,36 @@ AnimationOptions AnimationStorage::getAnimationOptions() AnimationOptions options; const AnimationOptions_Proto& optionsProto = Storage::getInstance().getAnimationOptions(); + bool bIsValidProfile; + + AnimationNonPressedEffects baseNonPressedEffect; + AnimationPressedEffects basePressedEffect; + + int16_t baseCycleTime; + + uint32_t notPressedStaticColors[NUM_BANK0_GPIOS]; + uint32_t pressedStaticColors[NUM_BANK0_GPIOS]; + + uint32_t buttonPressHoldTimeInMs; + uint32_t buttonPressFadeOutTimeInMs; + options.checksum = 0; - options.baseAnimationIndex = std::min(optionsProto.baseAnimationIndex, 255); + for(int index = 0; index < 8; ++index) //MAX_ANIMATION_PROFILES from AnimationStation.hpp + { + options.profiles[index].bIsValidProfile = optionsProto.profiles[index].bIsValidProfile; + options.profiles[index].baseNonPressedEffect = (AnimationNonPressedEffects)((int)optionsProto.profiles[index].baseNonPressedEffect); + options.profiles[index].basePressedEffect = (AnimationPressedEffects)((int)optionsProto.profiles[index].basePressedEffect); + options.profiles[index].baseCycleTime = optionsProto.profiles[index].baseCycleTime; + for(int pinIndex = 0; pinIndex < NUM_BANK0_GPIOS; ++pinIndex) + { + options.profiles[index].notPressedStaticColors[pinIndex] = optionsProto.profiles[index].notPressedStaticColors[pinIndex]; + options.profiles[index].pressedStaticColors[pinIndex] = optionsProto.profiles[index].pressedStaticColors[pinIndex]; + } + options.profiles[index].buttonPressHoldTimeInMs = optionsProto.profiles[index].buttonPressHoldTimeInMs; + options.profiles[index].buttonPressFadeOutTimeInMs = optionsProto.profiles[index].buttonPressFadeOutTimeInMs; + } options.brightness = std::min(optionsProto.brightness, 255); - options.staticColorIndex = std::min(optionsProto.staticColorIndex, 255); - options.buttonColorIndex = std::min(optionsProto.buttonColorIndex, 255); - options.chaseCycleTime = std::min(optionsProto.chaseCycleTime, 65535); - options.rainbowCycleTime = std::min(optionsProto.rainbowCycleTime, 65535); - options.themeIndex = std::min(optionsProto.themeIndex, 255); - options.hasCustomTheme = optionsProto.hasCustomTheme; - options.customThemeUp = optionsProto.customThemeUp; - options.customThemeDown = optionsProto.customThemeDown; - options.customThemeLeft = optionsProto.customThemeLeft; - options.customThemeRight = optionsProto.customThemeRight; - options.customThemeB1 = optionsProto.customThemeB1; - options.customThemeB2 = optionsProto.customThemeB2; - options.customThemeB3 = optionsProto.customThemeB3; - options.customThemeB4 = optionsProto.customThemeB4; - options.customThemeL1 = optionsProto.customThemeL1; - options.customThemeR1 = optionsProto.customThemeR1; - options.customThemeL2 = optionsProto.customThemeL2; - options.customThemeR2 = optionsProto.customThemeR2; - options.customThemeS1 = optionsProto.customThemeS1; - options.customThemeS2 = optionsProto.customThemeS2; - options.customThemeA1 = optionsProto.customThemeA1; - options.customThemeA2 = optionsProto.customThemeA2; - options.customThemeL3 = optionsProto.customThemeL3; - options.customThemeR3 = optionsProto.customThemeR3; - options.customThemeUpPressed = optionsProto.customThemeUpPressed; - options.customThemeDownPressed = optionsProto.customThemeDownPressed; - options.customThemeLeftPressed = optionsProto.customThemeLeftPressed; - options.customThemeRightPressed = optionsProto.customThemeRightPressed; - options.customThemeB1Pressed = optionsProto.customThemeB1Pressed; - options.customThemeB2Pressed = optionsProto.customThemeB2Pressed; - options.customThemeB3Pressed = optionsProto.customThemeB3Pressed; - options.customThemeB4Pressed = optionsProto.customThemeB4Pressed; - options.customThemeL1Pressed = optionsProto.customThemeL1Pressed; - options.customThemeR1Pressed = optionsProto.customThemeR1Pressed; - options.customThemeL2Pressed = optionsProto.customThemeL2Pressed; - options.customThemeR2Pressed = optionsProto.customThemeR2Pressed; - options.customThemeS1Pressed = optionsProto.customThemeS1Pressed; - options.customThemeS2Pressed = optionsProto.customThemeS2Pressed; - options.customThemeA1Pressed = optionsProto.customThemeA1Pressed; - options.customThemeA2Pressed = optionsProto.customThemeA2Pressed; - options.customThemeL3Pressed = optionsProto.customThemeL3Pressed; - options.customThemeR3Pressed = optionsProto.customThemeR3Pressed; - options.buttonPressColorCooldownTimeInMs = optionsProto.buttonPressColorCooldownTimeInMs; + options.baseProfileIndex = std::min(optionsProto.baseProfileIndex, 255); return options; } From d149664a79d63d8e0892d5703160f4163fa804bf Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Mon, 4 Nov 2024 09:14:54 +0000 Subject: [PATCH 005/121] first life! --- headers/storagemanager.h | 2 + lib/AnimationStation/src/Animation.cpp | 14 ++++- lib/AnimationStation/src/Animation.hpp | 2 +- lib/AnimationStation/src/AnimationStation.cpp | 22 ++++--- lib/AnimationStation/src/AnimationStation.hpp | 7 ++- lib/AnimationStation/src/Effects/Chase.cpp | 19 +++--- lib/AnimationStation/src/Effects/Chase.hpp | 2 +- lib/AnimationStation/src/Effects/Rainbow.cpp | 24 +++++--- .../src/Effects/RandomColor.cpp | 10 +-- .../src/Effects/StaticColor.cpp | 4 +- lib/AnimationStation/src/Pixel.hpp | 6 +- proto/config.proto | 61 +++++++++++++++++-- proto/enums.proto | 25 ++++++++ src/addons/neopicoleds.cpp | 8 +-- src/config_utils.cpp | 32 +++++----- src/configs/webconfig.cpp | 8 +-- src/display/ui/screens/ButtonLayoutScreen.cpp | 23 ++++++- src/storagemanager.cpp | 17 +----- 18 files changed, 196 insertions(+), 90 deletions(-) diff --git a/headers/storagemanager.h b/headers/storagemanager.h index 8778e58421..191b2728d6 100644 --- a/headers/storagemanager.h +++ b/headers/storagemanager.h @@ -72,6 +72,8 @@ class Storage { void ResetSettings(); // EEPROM Reset Feature + std::string printfs[4]; + private: Storage() {} bool CONFIG_MODE = false; // Config mode (boot) diff --git a/lib/AnimationStation/src/Animation.cpp b/lib/AnimationStation/src/Animation.cpp index c1d95a6272..fa944716e9 100644 --- a/lib/AnimationStation/src/Animation.cpp +++ b/lib/AnimationStation/src/Animation.cpp @@ -43,10 +43,18 @@ void Animation::UpdateTime() void Animation::UpdatePresses() { + if(!isButtonAnimation) + return; + + //AnimationStation::printfs[0] = "UpdatePresses"; + //AnimationStation::printfs[1] = std::to_string(pressedPins.size()); + //if(pressedPins.size() > 0) + // AnimationStation::printfs[2] = std::to_string(pressedPins[0]); + //Set hold/fade time for all pressed buttons - for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { - for(int pressedPinIndex = 0; pressedPinIndex < pressedPins.size(); ++pressedPinIndex) + for(unsigned int pressedPinIndex = 0; pressedPinIndex < pressedPins.size(); ++pressedPinIndex) { if(pressedPins[pressedPinIndex] == RGBLights->AllLights[lightIndex].GIPOPin) { @@ -72,7 +80,7 @@ void Animation::UpdatePresses() void Animation::DecrementFadeCounters() { - for(int ledIndex = 0; ledIndex < RGBLights->GetLedCount(); ++ledIndex) + for(unsigned int ledIndex = 0; ledIndex < RGBLights->GetLedCount(); ++ledIndex) { fadeTimes[ledIndex] -= updateTimeInMs; if (fadeTimes[ledIndex] < 0) diff --git a/lib/AnimationStation/src/Animation.hpp b/lib/AnimationStation/src/Animation.hpp index 956745f6c2..94d050e135 100644 --- a/lib/AnimationStation/src/Animation.hpp +++ b/lib/AnimationStation/src/Animation.hpp @@ -148,7 +148,7 @@ class Animation { std::vector pressedPins; // Color fade - std::vector fadeTimes; + std::vector fadeTimes; absolute_time_t lastUpdateTime = nil_time; diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index 5e1a3d58ff..315ffc9bb5 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -17,6 +17,7 @@ uint8_t AnimationStation::brightnessSteps = 5; float AnimationStation::brightnessX = 0; absolute_time_t AnimationStation::nextChange = nil_time; AnimationOptions AnimationStation::options = {}; +std::string AnimationStation::printfs[4]; AnimationStation::AnimationStation() { @@ -26,6 +27,11 @@ AnimationStation::AnimationStation() ChangeProfile(0); } +void AnimationStation::SetLights(Lights InRGBLights) +{ + RGBLights = InRGBLights; +} + void AnimationStation::ConfigureBrightness(uint8_t max, uint8_t steps) { brightnessMax = max; @@ -105,7 +111,7 @@ uint16_t AnimationStation::AdjustIndex(int changeSize) //find index of current profile int indexOfCurrentProfile = 0; - for(int index = 0; index < validIndexes.size(); ++index) + for(unsigned int index = 0; index < validIndexes.size(); ++index) { if(validIndexes[index] == (int)this->options.baseProfileIndex) { @@ -120,7 +126,7 @@ uint16_t AnimationStation::AdjustIndex(int changeSize) int newProfileIndex = indexOfCurrentProfile + changeSize; - if (newProfileIndex >= validIndexes.size()) + if (newProfileIndex >= (int)validIndexes.size()) { return validIndexes[0]; } @@ -218,20 +224,22 @@ void AnimationStation::SetMode(int8_t mode) //set new profile pressed animation switch ((AnimationPressedEffects)this->options.profiles[this->options.baseProfileIndex].basePressedEffect) { -/* case AnimationPressedEffects::PRESSED_EFFECT_RANDOM: - this->buttonAnimation = new RandomColour(RGBLights, lastPressed); -*/ + case AnimationPressedEffects::PRESSED_EFFECT_RANDOM: + this->buttonAnimation = new RandomColor(RGBLights, lastPressed); + break; + case AnimationPressedEffects::PRESSED_EFFECT_STATIC_COLOR: this->buttonAnimation = new StaticColor(RGBLights, lastPressed); + break; default: break; } } -void AnimationStation::SetOptions(AnimationOptions options) +void AnimationStation::SetOptions(AnimationOptions InOptions) { - AnimationStation::options = options; + options = InOptions; AnimationStation::SetBrightness(options.brightness); } diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index a1d74e95c4..8e58969667 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -6,12 +6,13 @@ #include #include #include +#include #include "hardware/clocks.h" #include "NeoPico.hpp" #include "Animation.hpp" -#define MAX_ANIMATION_PROFILES 8 +#define MAX_ANIMATION_PROFILES 4 //List of non-pressed animation types typedef enum @@ -97,7 +98,7 @@ class AnimationStation static void DimBrightnessTo0(); //passed in user options - static void SetOptions(AnimationOptions options); + static void SetOptions(AnimationOptions InOptions); //Running non-pressed animation Animation* baseAnimation; @@ -115,6 +116,8 @@ class AnimationStation //Colour of all lights this frame RGB frame[100]; + static std::string printfs[4]; + protected: inline static uint8_t getBrightnessStepSize() { return (brightnessMax / brightnessSteps); } static uint8_t brightnessMax; diff --git a/lib/AnimationStation/src/Effects/Chase.cpp b/lib/AnimationStation/src/Effects/Chase.cpp index e1a18130e3..40bc659209 100644 --- a/lib/AnimationStation/src/Effects/Chase.cpp +++ b/lib/AnimationStation/src/Effects/Chase.cpp @@ -4,11 +4,11 @@ #define CHASE_CYCLE_MAX INT16_MAX/2 #define CHASE_CYCLE_MIN 10 -Chase::Chase(PixelMatrix &matrix) : Animation(matrix) { +Chase::Chase(Lights& InRGBLights) : Animation(InRGBLights) { } void Chase::Animate(RGB (&frame)[100]) { - if (!time_reached(this->nextRunTime)) { +/* if (!time_reached(this->nextRunTime)) { return; } @@ -63,7 +63,7 @@ void Chase::Animate(RGB (&frame)[100]) { AnimationStation::options.chaseCycleTime = CHASE_CYCLE_MAX; } - this->nextRunTime = make_timeout_time_ms(AnimationStation::options.chaseCycleTime); + this->nextRunTime = make_timeout_time_ms(AnimationStation::options.chaseCycleTime);*/ } bool Chase::IsChasePixel(int i) { @@ -76,7 +76,7 @@ bool Chase::IsChasePixel(int i) { } int Chase::WheelFrame(int i) { - int frame = this->currentFrame; +/* int frame = this->currentFrame; int pixelCount = matrix->getPixelCount(); if (i == (this->currentPixel - 1) % pixelCount) { if (this->reverse) { @@ -98,19 +98,20 @@ int Chase::WheelFrame(int i) { return 0; } - return frame; + return frame;*/ + return 0; } void Chase::ParameterUp() { - AnimationStation::options.chaseCycleTime = AnimationStation::options.chaseCycleTime + CHASE_CYCLE_INCREMENT; +/* AnimationStation::options.chaseCycleTime = AnimationStation::options.chaseCycleTime + CHASE_CYCLE_INCREMENT; if (AnimationStation::options.chaseCycleTime > CHASE_CYCLE_MAX) { AnimationStation::options.chaseCycleTime = CHASE_CYCLE_MAX; - } + }*/ } void Chase::ParameterDown() { - AnimationStation::options.chaseCycleTime = AnimationStation::options.chaseCycleTime - CHASE_CYCLE_INCREMENT; +/* AnimationStation::options.chaseCycleTime = AnimationStation::options.chaseCycleTime - CHASE_CYCLE_INCREMENT; if (AnimationStation::options.chaseCycleTime < CHASE_CYCLE_MIN) { AnimationStation::options.chaseCycleTime = CHASE_CYCLE_MIN; - } + }*/ } diff --git a/lib/AnimationStation/src/Effects/Chase.hpp b/lib/AnimationStation/src/Effects/Chase.hpp index edf1451b91..54fe7af6d1 100644 --- a/lib/AnimationStation/src/Effects/Chase.hpp +++ b/lib/AnimationStation/src/Effects/Chase.hpp @@ -10,7 +10,7 @@ class Chase : public Animation { public: - Chase(PixelMatrix &matrix); + Chase(Lights& InRGBLights); ~Chase() {}; void Animate(RGB (&frame)[100]); diff --git a/lib/AnimationStation/src/Effects/Rainbow.cpp b/lib/AnimationStation/src/Effects/Rainbow.cpp index 50b53f0aa7..b2dd20bbc7 100644 --- a/lib/AnimationStation/src/Effects/Rainbow.cpp +++ b/lib/AnimationStation/src/Effects/Rainbow.cpp @@ -25,13 +25,13 @@ void RainbowSynced::Animate(RGB (&frame)[100]) //UpdatePresses(); RGB color = RGB::wheel(this->currentFrame); - for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { if(LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; - for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { //Non pressed simply sets the RGB colour frame[ledIndex] = color; @@ -67,7 +67,7 @@ void RainbowSynced::Animate(RGB (&frame)[100]) void RainbowSynced::ParameterUp() { - int16_t& cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; + int16_t cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; if (cycleTime < RAINBOW_CYCLE_MAX) { @@ -77,11 +77,13 @@ void RainbowSynced::ParameterUp() { cycleTime = INT16_MAX; } + + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = cycleTime; } void RainbowSynced::ParameterDown() { - int16_t& cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; + int16_t cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; if (cycleTime > RAINBOW_CYCLE_MIN) { @@ -91,6 +93,8 @@ void RainbowSynced::ParameterDown() { cycleTime = 1; } + + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = cycleTime; } //////////////////////////////////////////////////////////////////////////////////////////// @@ -110,7 +114,7 @@ void RainbowRotate::Animate(RGB (&frame)[100]) //the way this works is we offset the current frame by the distance from the top left of the grid int thisFrame = this->currentFrame; - for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { if(LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { @@ -120,7 +124,7 @@ void RainbowRotate::Animate(RGB (&frame)[100]) uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; - for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { //Non pressed simply sets the RGB colour frame[ledIndex] = color; @@ -142,7 +146,7 @@ void RainbowRotate::Animate(RGB (&frame)[100]) void RainbowRotate::ParameterUp() { - int16_t& cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; + int16_t cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; if (cycleTime < RAINBOW_CYCLE_MAX) { @@ -152,11 +156,13 @@ void RainbowRotate::ParameterUp() { cycleTime = INT16_MAX; } + + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = cycleTime; } void RainbowRotate::ParameterDown() { - int16_t& cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; + int16_t cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; if (cycleTime > RAINBOW_CYCLE_MIN) { @@ -166,4 +172,6 @@ void RainbowRotate::ParameterDown() { cycleTime = 1; } + + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = cycleTime; } \ No newline at end of file diff --git a/lib/AnimationStation/src/Effects/RandomColor.cpp b/lib/AnimationStation/src/Effects/RandomColor.cpp index a607ff44d8..3cd9e7bf34 100644 --- a/lib/AnimationStation/src/Effects/RandomColor.cpp +++ b/lib/AnimationStation/src/Effects/RandomColor.cpp @@ -10,7 +10,7 @@ RandomColor::RandomColor(Lights& InRGBLights, std::vector &InPressedPin pressedPins = InPressedPins; savedPressedColour.clear(); - for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { savedPressedColour.push_back(RGB(0)); } @@ -18,7 +18,9 @@ RandomColor::RandomColor(Lights& InRGBLights, std::vector &InPressedPin void RandomColor::NewPressForPin(int lightIndex) { - savedPressedColour[lightIndex] = colors[rand() % colors.size()]; + savedPressedColour[lightIndex] = colors[rand() % colors.size()]; + + AnimationStation::printfs[3] = std::to_string(lightIndex); } void RandomColor::Animate(RGB (&frame)[100]) @@ -26,12 +28,12 @@ void RandomColor::Animate(RGB (&frame)[100]) UpdateTime(); UpdatePresses(); - for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; - for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { //Non pressed simply sets the RGB colour if(!isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) diff --git a/lib/AnimationStation/src/Effects/StaticColor.cpp b/lib/AnimationStation/src/Effects/StaticColor.cpp index 7b1d4b22d0..e58d4327b3 100644 --- a/lib/AnimationStation/src/Effects/StaticColor.cpp +++ b/lib/AnimationStation/src/Effects/StaticColor.cpp @@ -15,12 +15,12 @@ void StaticColor::Animate(RGB (&frame)[100]) UpdateTime(); UpdatePresses(); - for(int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; - for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { //Non pressed simply sets the RGB colour if(!isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) diff --git a/lib/AnimationStation/src/Pixel.hpp b/lib/AnimationStation/src/Pixel.hpp index 1892f1ff43..37cf1635e4 100644 --- a/lib/AnimationStation/src/Pixel.hpp +++ b/lib/AnimationStation/src/Pixel.hpp @@ -85,14 +85,14 @@ struct LightPosition //A single RGB light on the device. Replaced Pixel struct Light { - Light(uint8_t InFirstLedIndex, uint8_t InNumLedsPerLight, LightPosition InPosition, uint8_t GIPOPin, LightType InType) + Light(uint8_t InFirstLedIndex, uint8_t InNumLedsPerLight, LightPosition InPosition, uint8_t InGIPOPin, LightType InType) { FirstLedIndex = InFirstLedIndex; Position = InPosition; Type = InType; LedsPerLight = InNumLedsPerLight; //GamePadMask = GamePadMask; - GIPOPin = GIPOPin; + GIPOPin = InGIPOPin; } // index of first LED @@ -127,7 +127,7 @@ struct Lights inline uint8_t GetLedCount() const { - int count; + int count = 0; for(const Light& thisLight : AllLights ) { count += thisLight.LedsPerLight; diff --git a/proto/config.proto b/proto/config.proto index c377722691..1669d9ce2c 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -288,6 +288,9 @@ message LEDOptions optional int32 pledIndex2 = 33; optional int32 pledIndex3 = 34; optional int32 pledIndex4 = 35; + + optional bytes lightData = 36 [(nanopb).max_size = 600]; + optional int32 lightDataSize = 37; }; // This has to be kept in sync with AnimationOptions in AnimationStation.hpp @@ -300,8 +303,8 @@ message AnimationProfile_Proto optional int32 baseCycleTime = 4; - optional uint32 notPressedStaticColors[NUM_BANK0_GPIOS] = 5; - optional uint32 pressedStaticColors[NUM_BANK0_GPIOS] = 6; + repeated uint32 notPressedStaticColors = 5 [(nanopb).max_count = 30]; //NUM_BANK0_GPIOS from AnimationStation.hpp + repeated uint32 pressedStaticColors = 6 [(nanopb).max_count = 30]; //NUM_BANK0_GPIOS from AnimationStation.hpp optional uint32 buttonPressHoldTimeInMs = 7; optional uint32 buttonPressFadeOutTimeInMs = 8; @@ -310,9 +313,55 @@ message AnimationProfile_Proto // This has to be kept in sync with AnimationOptions in AnimationStation.hpp message AnimationOptions_Proto { - optional AnimationProfile profiles = 1; [(nanopb).max_count = 8]; //MAX_ANIMATION_PROFILES from AnimationStation.hpp + optional uint32 baseAnimationIndex = 1 [deprecated = true]; optional uint32 brightness = 2; - optional uint32 baseProfileIndex = 3; + optional uint32 staticColorIndex = 3 [deprecated = true]; + optional uint32 buttonColorIndex = 4 [deprecated = true]; + optional int32 chaseCycleTime = 5 [deprecated = true]; + optional int32 rainbowCycleTime = 6 [deprecated = true]; + optional uint32 themeIndex = 7 [deprecated = true]; + + optional bool hasCustomTheme = 8; + optional uint32 customThemeUp = 9 [deprecated = true]; + optional uint32 customThemeDown = 10 [deprecated = true]; + optional uint32 customThemeLeft = 11 [deprecated = true]; + optional uint32 customThemeRight = 12 [deprecated = true]; + optional uint32 customThemeB1 = 13 [deprecated = true]; + optional uint32 customThemeB2 = 14 [deprecated = true]; + optional uint32 customThemeB3 = 15 [deprecated = true]; + optional uint32 customThemeB4 = 16 [deprecated = true]; + optional uint32 customThemeL1 = 17 [deprecated = true]; + optional uint32 customThemeR1 = 18 [deprecated = true]; + optional uint32 customThemeL2 = 19 [deprecated = true]; + optional uint32 customThemeR2 = 20 [deprecated = true]; + optional uint32 customThemeS1 = 21 [deprecated = true]; + optional uint32 customThemeS2 = 22 [deprecated = true]; + optional uint32 customThemeL3 = 23 [deprecated = true]; + optional uint32 customThemeR3 = 24 [deprecated = true]; + optional uint32 customThemeA1 = 25 [deprecated = true]; + optional uint32 customThemeA2 = 26 [deprecated = true]; + optional uint32 customThemeUpPressed = 27 [deprecated = true]; + optional uint32 customThemeDownPressed = 28 [deprecated = true]; + optional uint32 customThemeLeftPressed = 29 [deprecated = true]; + optional uint32 customThemeRightPressed = 30 [deprecated = true]; + optional uint32 customThemeB1Pressed = 31 [deprecated = true]; + optional uint32 customThemeB2Pressed = 32 [deprecated = true]; + optional uint32 customThemeB3Pressed = 33 [deprecated = true]; + optional uint32 customThemeB4Pressed = 34 [deprecated = true]; + optional uint32 customThemeL1Pressed = 35 [deprecated = true]; + optional uint32 customThemeR1Pressed = 36 [deprecated = true]; + optional uint32 customThemeL2Pressed = 37 [deprecated = true]; + optional uint32 customThemeR2Pressed = 38 [deprecated = true]; + optional uint32 customThemeS1Pressed = 39 [deprecated = true]; + optional uint32 customThemeS2Pressed = 40 [deprecated = true]; + optional uint32 customThemeL3Pressed = 41 [deprecated = true]; + optional uint32 customThemeR3Pressed = 42 [deprecated = true]; + optional uint32 customThemeA1Pressed = 43 [deprecated = true]; + optional uint32 customThemeA2Pressed = 44 [deprecated = true]; + optional uint32 buttonPressColorCooldownTimeInMs = 45 [deprecated = true]; + + repeated AnimationProfile_Proto profiles = 46 [(nanopb).max_count = 4]; //MAX_ANIMATION_PROFILES from AnimationStation.hpp + optional uint32 baseProfileIndex = 47; } message BootselButtonOptions @@ -683,8 +732,8 @@ message MacroInput message Macro { optional MacroType macroType = 1; - optional string macroLabel = 2 [(nanopb).max_length = 64]; - repeated MacroInput macroInputs = 3 [(nanopb).max_count = 30]; + optional string macroLabel = 2 [(nanopb).max_length = 32]; + repeated MacroInput macroInputs = 3 [(nanopb).max_count = 10]; optional bool enabled = 4; optional bool useMacroTriggerButton = 5; optional int32 deprecatedMacroTriggerPin = 6 [deprecated = true]; diff --git a/proto/enums.proto b/proto/enums.proto index db76de54be..06ff32fec3 100644 --- a/proto/enums.proto +++ b/proto/enums.proto @@ -311,6 +311,31 @@ enum LEDFormat_Proto LED_FORMAT_RGBW = 3; } +/* This has to be kept in sync with AnimationNonPressedEffects in AnimationStation.hpp */ +enum AnimationNonPressedEffects_Proto +{ + EFFECT_STATIC_COLOR = 0; + EFFECT_RAINBOW_SYNCED = 1; + EFFECT_RAINBOW_ROTATE = 2; + EFFECT_CHASE = 3; +} + +/* This has to be kept in sync with AnimationPressedEffects in AnimationStation.hpp */ +enum AnimationPressedEffects_Proto +{ + EFFECT_HELD_STATIC_COLOR = 0; + EFFECT_RANDOM = 1; +} + +/* This has to be kept in sync with LightType in Pixel.hpp */ +enum LightType_Proto +{ + ActionButton = 0; + Case = 1; + Turbo = 2; + PlayerLight = 3; +} + enum ShmupMixMode { option (nanopb_enumopt).long_names = false; diff --git a/src/addons/neopicoleds.cpp b/src/addons/neopicoleds.cpp index bb3d4df6d4..47d6202a1c 100644 --- a/src/addons/neopicoleds.cpp +++ b/src/addons/neopicoleds.cpp @@ -282,7 +282,7 @@ void NeoPicoLEDAddon::process() vector pressedPins; for(auto thisLight : RGBLights.AllLights) { - if(values & 1 << thisLight.GIPOPin) + if(values & (1 << thisLight.GIPOPin)) { pressedPins.push_back(thisLight.GIPOPin); } @@ -581,9 +581,6 @@ void NeoPicoLEDAddon::configureLEDs() GenerateLights(lightData, lightDataSize); ledCount = RGBLights.GetLedCount(); - //matrix.setup(pixels, ledOptions.ledsPerButton); - //ledCount = matrix.getLedCount(); - if (ledOptions.pledType == PLED_TYPE_RGB && PLED_COUNT > 0) ledCount += PLED_COUNT; @@ -595,7 +592,6 @@ void NeoPicoLEDAddon::configureLEDs() Animation::format = static_cast(ledOptions.ledFormat); AnimStation.ConfigureBrightness(ledOptions.brightnessMaximum, ledOptions.brightnessSteps); AnimationOptions animationOptions = AnimationStore.getAnimationOptions(); - addStaticThemes(ledOptions, animationOptions); AnimStation.SetOptions(animationOptions); AnimStation.SetLights(RGBLights); AnimStation.SetMode(as.options.baseProfileIndex); @@ -617,7 +613,7 @@ void NeoPicoLEDAddon::GenerateLights(LEDOptions_lightData_t InLightData, uint32_ InLightData.bytes[arrayOffset+1], newLightPos, InLightData.bytes[arrayOffset+4], - InLightData.bytes[arrayOffset+5]); + (LightType)InLightData.bytes[arrayOffset+5]); generatedLights.push_back(newLight); } diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 64108a7244..0c88874c6f 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -476,24 +476,22 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY_BYTES(config.ledOptions, lightData, lightData); // animationOptions - if(config.animationOptions.has_profiles == false) + if(config.animationOptions.profiles_count == 0) { - config.animationOptions.has_profiles = true; - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], bIsValidProfile, true); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], baseNonPressedEffect, AnimationNonPressedEffects_Proto::NONPRESSED_Proto_EFFECT_RAINBOW_ROTATE); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], basePressedEffect, AnimationPressedEffects_Proto::PRESSED_Proto_EFFECT_RANDOM); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], baseCycleTime, 1); - for (int index = 0; index < NUM_BANK0_GPIOS; ++index) - { - if(!config.animationOptions.profiles[0].has_notPressedStaticColors) - config.animationOptions.profiles[0].notPressedStaticColors[index] = 0; - if(!config.animationOptions.profiles[0].has_pressedStaticColors) - config.animationOptions.profiles[0].pressedStaticColors[index] = 0; - } - config.animationOptions.profiles[0].has_notPressedStaticColors = true; - config.animationOptions.profiles[0].has_pressedStaticColors = true; - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], buttonPressHoldTimeInMs, 0); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], buttonPressFadeOutTimeInMs, 0); + config.animationOptions.profiles_count = 1; + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], bIsValidProfile, true); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], baseNonPressedEffect, AnimationNonPressedEffects_Proto::AnimationNonPressedEffects_Proto_EFFECT_RAINBOW_ROTATE); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], basePressedEffect, AnimationPressedEffects_Proto::AnimationPressedEffects_Proto_EFFECT_RANDOM); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], baseCycleTime, 1); + config.animationOptions.profiles[0].notPressedStaticColors_count = NUM_BANK0_GPIOS; + config.animationOptions.profiles[0].pressedStaticColors_count = NUM_BANK0_GPIOS; + for (unsigned int index = 0; index < NUM_BANK0_GPIOS; ++index) + { + config.animationOptions.profiles[0].notPressedStaticColors[index] = 0; + config.animationOptions.profiles[0].pressedStaticColors[index] = 0; + } + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], buttonPressHoldTimeInMs, 0); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], buttonPressFadeOutTimeInMs, 0); } //INIT_UNSET_PROPERTY(config.animationOptions, profiles[0], defaultProfile); INIT_UNSET_PROPERTY(config.animationOptions, brightness, LEDS_BRIGHTNESS); diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index a77fdae53e..29915b227b 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -962,7 +962,7 @@ std::string setCustomTheme() return result; }; - readDoc(options.hasCustomTheme, doc, "enabled"); + /*readDoc(options.hasCustomTheme, doc, "enabled"); options.customThemeUp = readDocDefaultToZero("Up", "u"); options.customThemeDown = readDocDefaultToZero("Down", "u"); options.customThemeLeft = readDocDefaultToZero("Left", "u"); @@ -1002,7 +1002,7 @@ std::string setCustomTheme() uint32_t pressCooldown = 0; readDoc(pressCooldown, doc, "buttonPressColorCooldownTimeInMs"); - options.buttonPressColorCooldownTimeInMs = pressCooldown; + options.buttonPressColorCooldownTimeInMs = pressCooldown;*/ AnimationStation::SetOptions(options); AnimationStore.save(); @@ -1015,7 +1015,7 @@ std::string getCustomTheme() DynamicJsonDocument doc(LWIP_HTTPD_POST_MAX_PAYLOAD_LEN); const AnimationOptions& options = AnimationStation::options; - writeDoc(doc, "enabled", options.hasCustomTheme); +/* writeDoc(doc, "enabled", options.hasCustomTheme); writeDoc(doc, "Up", "u", options.customThemeUp); writeDoc(doc, "Up", "d", options.customThemeUpPressed); writeDoc(doc, "Down", "u", options.customThemeDown); @@ -1052,7 +1052,7 @@ std::string getCustomTheme() writeDoc(doc, "L3", "d", options.customThemeL3Pressed); writeDoc(doc, "R3", "u", options.customThemeR3); writeDoc(doc, "R3", "d", options.customThemeR3Pressed); - writeDoc(doc, "buttonPressColorCooldownTimeInMs", options.buttonPressColorCooldownTimeInMs); + writeDoc(doc, "buttonPressColorCooldownTimeInMs", options.buttonPressColorCooldownTimeInMs);*/ return serialize_json(doc); } diff --git a/src/display/ui/screens/ButtonLayoutScreen.cpp b/src/display/ui/screens/ButtonLayoutScreen.cpp index 0a15acbf8a..e69ed1ccf9 100644 --- a/src/display/ui/screens/ButtonLayoutScreen.cpp +++ b/src/display/ui/screens/ButtonLayoutScreen.cpp @@ -117,7 +117,7 @@ void ButtonLayoutScreen::generateHeader() { statusBar.clear(); Storage& storage = Storage::getInstance(); - // Display Profile # banner + // Display Profile # banner if ( profileModeDisplay ) { if (((getMillis() - profileDelayStart) / 1000) < profileDelay) { statusBar.assign(storage.currentProfileLabel(), strlen(storage.currentProfileLabel())); @@ -210,13 +210,32 @@ void ButtonLayoutScreen::generateHeader() { } void ButtonLayoutScreen::drawScreen() { - if (profileModeDisplay) { +/* if (profileModeDisplay) { getRenderer()->drawRectangle(0, 0, 128, 7, true, true); getRenderer()->drawText(0, 0, statusBar, true); } else { getRenderer()->drawText(0, 0, statusBar); } getRenderer()->drawText(0, 7, footer); +*/ + + Storage& storage = Storage::getInstance(); +/* storage.printfs[0] = "Pods"; + storage.printfs[1] = "TEST1"; + storage.printfs[2] = "TEST2"; + storage.printfs[3] = "TEST3"; + storage.printfs[4] = "TEST4"; + storage.printfs[5] = "TEST5"; + storage.printfs[6] = "TEST6"; + storage.printfs[7] = "TEST7";*/ + getRenderer()->drawText(0, 0, AnimationStation::printfs[0]); + getRenderer()->drawText(0, 1, AnimationStation::printfs[1]); + getRenderer()->drawText(0, 2, AnimationStation::printfs[2]); + getRenderer()->drawText(0, 3, AnimationStation::printfs[3]); + getRenderer()->drawText(0, 4, storage.printfs[0]); + getRenderer()->drawText(0, 5, storage.printfs[1]); + getRenderer()->drawText(0, 6, storage.printfs[2]); + getRenderer()->drawText(0, 7, storage.printfs[3]); } GPLever* ButtonLayoutScreen::addLever(uint16_t startX, uint16_t startY, uint16_t sizeX, uint16_t sizeY, uint16_t strokeColor, uint16_t fillColor, uint16_t inputType) { diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index ea4aed161e..88cdd5771e 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -36,7 +36,7 @@ static void updateAnimationOptionsProto(const AnimationOptions& options) { AnimationOptions_Proto& optionsProto = Storage::getInstance().getAnimationOptions(); - for(int index = 0; index < 8; ++index) //MAX_ANIMATION_PROFILES from AnimationStation.hpp + for(int index = 0; index < 4; ++index) //MAX_ANIMATION_PROFILES from AnimationStation.hpp { optionsProto.profiles[index].bIsValidProfile = options.profiles[index].bIsValidProfile; optionsProto.profiles[index].baseNonPressedEffect = (AnimationNonPressedEffects_Proto)((int)options.profiles[index].baseNonPressedEffect); @@ -193,22 +193,9 @@ AnimationOptions AnimationStorage::getAnimationOptions() { AnimationOptions options; const AnimationOptions_Proto& optionsProto = Storage::getInstance().getAnimationOptions(); - - bool bIsValidProfile; - - AnimationNonPressedEffects baseNonPressedEffect; - AnimationPressedEffects basePressedEffect; - - int16_t baseCycleTime; - - uint32_t notPressedStaticColors[NUM_BANK0_GPIOS]; - uint32_t pressedStaticColors[NUM_BANK0_GPIOS]; - - uint32_t buttonPressHoldTimeInMs; - uint32_t buttonPressFadeOutTimeInMs; options.checksum = 0; - for(int index = 0; index < 8; ++index) //MAX_ANIMATION_PROFILES from AnimationStation.hpp + for(int index = 0; index < 4; ++index) //MAX_ANIMATION_PROFILES from AnimationStation.hpp { options.profiles[index].bIsValidProfile = optionsProto.profiles[index].bIsValidProfile; options.profiles[index].baseNonPressedEffect = (AnimationNonPressedEffects)((int)optionsProto.profiles[index].baseNonPressedEffect); From 0b5a6bb54bbc10aa33dd49d876d7522214b0d783 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Sat, 9 Nov 2024 00:03:56 +0000 Subject: [PATCH 006/121] Chase and static done Chase and static animations now done --- lib/AnimationStation/src/Animation.cpp | 65 ++- lib/AnimationStation/src/Animation.hpp | 3 +- lib/AnimationStation/src/AnimationStation.cpp | 37 +- lib/AnimationStation/src/AnimationStation.hpp | 14 +- lib/AnimationStation/src/Effects/Chase.cpp | 427 ++++++++++++++---- lib/AnimationStation/src/Effects/Chase.hpp | 55 ++- lib/AnimationStation/src/Effects/Rainbow.cpp | 19 +- .../src/Effects/RandomColor.cpp | 13 +- .../src/Effects/StaticColor.cpp | 17 +- proto/config.proto | 2 + proto/enums.proto | 10 +- src/config_utils.cpp | 37 +- src/display/ui/screens/ButtonLayoutScreen.cpp | 11 +- src/storagemanager.cpp | 2 + 14 files changed, 552 insertions(+), 160 deletions(-) diff --git a/lib/AnimationStation/src/Animation.cpp b/lib/AnimationStation/src/Animation.cpp index fa944716e9..e9d55642ff 100644 --- a/lib/AnimationStation/src/Animation.cpp +++ b/lib/AnimationStation/src/Animation.cpp @@ -46,14 +46,12 @@ void Animation::UpdatePresses() if(!isButtonAnimation) return; - //AnimationStation::printfs[0] = "UpdatePresses"; - //AnimationStation::printfs[1] = std::to_string(pressedPins.size()); - //if(pressedPins.size() > 0) - // AnimationStation::printfs[2] = std::to_string(pressedPins[0]); - //Set hold/fade time for all pressed buttons for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { + if(RGBLights->AllLights[lightIndex].Type != LightType_ActionButton) + continue; + for(unsigned int pressedPinIndex = 0; pressedPinIndex < pressedPins.size(); ++pressedPinIndex) { if(pressedPins[pressedPinIndex] == RGBLights->AllLights[lightIndex].GIPOPin) @@ -80,15 +78,56 @@ void Animation::UpdatePresses() void Animation::DecrementFadeCounters() { - for(unsigned int ledIndex = 0; ledIndex < RGBLights->GetLedCount(); ++ledIndex) + if(!isButtonAnimation) + return; + + //Set hold/fade time for all pressed buttons + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { - fadeTimes[ledIndex] -= updateTimeInMs; - if (fadeTimes[ledIndex] < 0) - fadeTimes[ledIndex] = 0; + //early out, save frames! + if(RGBLights->AllLights[lightIndex].Type != LightType_ActionButton || fadeTimes[RGBLights->AllLights[lightIndex].FirstLedIndex] <= 0) + continue; + + //is this button still pressed ? + bool wasPressed = false; + for(unsigned int pressedPinIndex = 0; pressedPinIndex < pressedPins.size(); ++pressedPinIndex) + { + if(pressedPins[pressedPinIndex] == RGBLights->AllLights[lightIndex].GIPOPin) + { + wasPressed = true; + } + } + + //if not then we can safely decrement the timer + if(!wasPressed) + { + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + for(int ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + fadeTimes[ledIndex] -= updateTimeInMs; + if (fadeTimes[ledIndex] < 0) + fadeTimes[ledIndex] = 0; + } + } } } -RGB Animation::BlendColor(RGB start, RGB end, uint32_t timeRemainingInMs) +RGB Animation::BlendColor(RGB start, RGB end, float alpha) +{ + RGB result = ColorBlack; + + if (alpha < 0.0f) alpha = 0.0f; + if (alpha > 1.0f) alpha = 1.0f; + + result.r = static_cast(static_cast(start.r) + ((static_cast(end.r) - static_cast(start.r)) * alpha)); + result.g = static_cast(static_cast(start.g) + ((static_cast(end.g) - static_cast(start.g)) * alpha)); + result.b = static_cast(static_cast(start.b) + ((static_cast(end.b) - static_cast(start.b)) * alpha)); + + return result; +} + +RGB Animation::FadeColor(RGB start, RGB end, uint32_t timeRemainingInMs) { RGB result = ColorBlack; @@ -104,9 +143,9 @@ RGB Animation::BlendColor(RGB start, RGB end, uint32_t timeRemainingInMs) if (progress < 0.0f) progress = 0.0f; if (progress > 1.0f) progress = 1.0f; - result.r = static_cast(static_cast(start.r + (end.r - start.r) * progress)); - result.g = static_cast(static_cast(start.g + (end.g - start.g) * progress)); - result.b = static_cast(static_cast(start.b + (end.b - start.b) * progress)); + result.r = static_cast(static_cast(start.r) + ((static_cast(end.r) - static_cast(start.r)) * progress)); + result.g = static_cast(static_cast(start.g) + ((static_cast(end.g) - static_cast(start.g)) * progress)); + result.b = static_cast(static_cast(start.b) + ((static_cast(end.b) - static_cast(start.b)) * progress)); return result; } diff --git a/lib/AnimationStation/src/Animation.hpp b/lib/AnimationStation/src/Animation.hpp index 94d050e135..8bba354c8a 100644 --- a/lib/AnimationStation/src/Animation.hpp +++ b/lib/AnimationStation/src/Animation.hpp @@ -132,7 +132,8 @@ class Animation { //notifies virtual void NewPressForPin(int lightIndex) {}; - RGB BlendColor(RGB start, RGB end, uint32_t frame); + RGB BlendColor(RGB start, RGB end, float alpha); + RGB FadeColor(RGB start, RGB end, uint32_t TimeLeft); //Type Helpers bool LightTypeIsForNonPressedAnimation(LightType Type); diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index 315ffc9bb5..914d428559 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -198,8 +198,11 @@ void AnimationStation::SetMode(int8_t mode) if(mode == -1) return; + //debug + //this->options.profiles[this->options.baseProfileIndex].baseNonPressedEffect = NONPRESSED_EFFECT_CHASE_RANDOM; + //set new profile nonpressed animation - switch ((AnimationNonPressedEffects)this->options.profiles[this->options.baseProfileIndex].baseNonPressedEffect) + switch (this->options.profiles[this->options.baseProfileIndex].baseNonPressedEffect) { case AnimationNonPressedEffects::NONPRESSED_EFFECT_RAINBOW_SYNCED: this->baseAnimation = new RainbowSynced(RGBLights); @@ -209,10 +212,34 @@ void AnimationStation::SetMode(int8_t mode) this->baseAnimation = new RainbowRotate(RGBLights); break; -/* case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE: - this->baseAnimation = new Chase(RGBLights); + case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE_SEQUENTIAL: + this->baseAnimation = new Chase(RGBLights, ChaseTypes::CHASETYPES_SEQUENTIAL); + break; + case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE_LEFT_TO_RIGHT: + this->baseAnimation = new Chase(RGBLights, ChaseTypes::CHASETYPES_LEFT_TO_RIGHT); + break; + case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE_RIGHT_TO_LEFT: + this->baseAnimation = new Chase(RGBLights, ChaseTypes::CHASETYPES_RIGHT_TO_LEFT); + break; + case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE_TOP_TO_BOTTOM: + this->baseAnimation = new Chase(RGBLights, ChaseTypes::CHASETYPES_TOP_TO_BOTTOM); + break; + case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE_BOTTOM_TO_TOP: + this->baseAnimation = new Chase(RGBLights, ChaseTypes::CHASETYPES_BOTTOM_TO_TOP); + break; + case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE_SEQUENTIAL_PINGPONG: + this->baseAnimation = new Chase(RGBLights, ChaseTypes::CHASETYPES_SEQUENTIAL_PINGPONG); + break; + case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE_HORIZONTAL_PINGPONG: + this->baseAnimation = new Chase(RGBLights, ChaseTypes::CHASETYPES_HORIZONTAL_PINGPONG); break; -*/ + case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE_VERTICAL_PINGPONG: + this->baseAnimation = new Chase(RGBLights, ChaseTypes::CHASETYPES_VERTICAL_PINGPONG); + break; + case AnimationNonPressedEffects::NONPRESSED_EFFECT_CHASE_RANDOM: + this->baseAnimation = new Chase(RGBLights, ChaseTypes::CHASETYPES_RANDOM); + break; + case AnimationNonPressedEffects::NONPRESSED_EFFECT_STATIC_COLOR: this->baseAnimation = new StaticColor(RGBLights); break; @@ -222,7 +249,7 @@ void AnimationStation::SetMode(int8_t mode) } //set new profile pressed animation - switch ((AnimationPressedEffects)this->options.profiles[this->options.baseProfileIndex].basePressedEffect) + switch (this->options.profiles[this->options.baseProfileIndex].basePressedEffect) { case AnimationPressedEffects::PRESSED_EFFECT_RANDOM: this->buttonAnimation = new RandomColor(RGBLights, lastPressed); diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index 8e58969667..9a8106b289 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -20,7 +20,15 @@ typedef enum NONPRESSED_EFFECT_STATIC_COLOR, NONPRESSED_EFFECT_RAINBOW_SYNCED, NONPRESSED_EFFECT_RAINBOW_ROTATE, - NONPRESSED_EFFECT_CHASE, + NONPRESSED_EFFECT_CHASE_SEQUENTIAL, + NONPRESSED_EFFECT_CHASE_LEFT_TO_RIGHT, + NONPRESSED_EFFECT_CHASE_RIGHT_TO_LEFT, + NONPRESSED_EFFECT_CHASE_TOP_TO_BOTTOM, + NONPRESSED_EFFECT_CHASE_BOTTOM_TO_TOP, + NONPRESSED_EFFECT_CHASE_SEQUENTIAL_PINGPONG, + NONPRESSED_EFFECT_CHASE_HORIZONTAL_PINGPONG, + NONPRESSED_EFFECT_CHASE_VERTICAL_PINGPONG, + NONPRESSED_EFFECT_CHASE_RANDOM, } AnimationNonPressedEffects; //List of non-pressed animation types @@ -51,12 +59,14 @@ struct __attribute__ ((__packed__)) AnimationProfile AnimationPressedEffects basePressedEffect; int16_t baseCycleTime; - + uint32_t notPressedStaticColors[NUM_BANK0_GPIOS]; uint32_t pressedStaticColors[NUM_BANK0_GPIOS]; uint32_t buttonPressHoldTimeInMs; uint32_t buttonPressFadeOutTimeInMs; + + uint32_t nonPressedSpecialColour; }; struct __attribute__ ((__packed__)) AnimationOptions diff --git a/lib/AnimationStation/src/Effects/Chase.cpp b/lib/AnimationStation/src/Effects/Chase.cpp index 40bc659209..b4c2199249 100644 --- a/lib/AnimationStation/src/Effects/Chase.cpp +++ b/lib/AnimationStation/src/Effects/Chase.cpp @@ -1,117 +1,378 @@ #include "Chase.hpp" +#include -#define CHASE_CYCLE_INCREMENT 10 -#define CHASE_CYCLE_MAX INT16_MAX/2 +#define CHASE_CYCLE_INCREMENT 50 +#define CHASE_CYCLE_MAX 500 #define CHASE_CYCLE_MIN 10 +#define CHASE_SECOND_LIGHT_OFFSET 0.5f -Chase::Chase(Lights& InRGBLights) : Animation(InRGBLights) { -} +Chase::Chase(Lights& InRGBLights, ChaseTypes InChaseType) : Animation(InRGBLights) +{ + ChaseTypeInUse = InChaseType; + + if(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime > CHASE_CYCLE_MAX) + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = CHASE_CYCLE_MAX; + if(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime < CHASE_CYCLE_MIN) + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = CHASE_CYCLE_MIN; + + ChaseTimes[0] = 1.0f; + ChaseTimes[1] = 1.0f + CHASE_SECOND_LIGHT_OFFSET; + + OrderedLights.clear(); + + //Get max x and y coords + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + if(LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type) == false) + continue; + + if(RGBLights->AllLights[lightIndex].Position.XPosition > MaxXCoord) + MaxXCoord = RGBLights->AllLights[lightIndex].Position.XPosition; + if(RGBLights->AllLights[lightIndex].Position.YPosition > MaxYCoord) + MaxYCoord = RGBLights->AllLights[lightIndex].Position.YPosition; -void Chase::Animate(RGB (&frame)[100]) { -/* if (!time_reached(this->nextRunTime)) { - return; + if(lightIndex == 0 || RGBLights->AllLights[lightIndex].Position.XPosition < MinXCoord) + MinXCoord = RGBLights->AllLights[lightIndex].Position.XPosition; + if(lightIndex == 0 || RGBLights->AllLights[lightIndex].Position.YPosition < MinYCoord) + MinYCoord = RGBLights->AllLights[lightIndex].Position.YPosition; } - UpdateTime(); - UpdatePresses(frame); - - for (auto &col : matrix->pixels) { - for (auto &pixel : col) { - if (pixel.index == NO_PIXEL.index) - continue; - - // Count down the timer - DecrementFadeCounter(pixel.index); - - if (this->IsChasePixel(pixel.index)) { - RGB color = RGB::wheel(this->WheelFrame(pixel.index)); - for (auto &pos : pixel.positions) - frame[pos] = BlendColor(hitColor[pixel.index], color, times[pixel.index]); - } else { - for (auto &pos : pixel.positions) - frame[pos] = BlendColor(hitColor[pixel.index], ColorBlack, times[pixel.index]); - } + //store off all lights in sequential order used on this animation + for(int yCoord = 0; yCoord <= MaxYCoord; ++yCoord) + { + for(int xCoord = 0; xCoord <= MaxXCoord; ++xCoord) + { + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + if(LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type) && + RGBLights->AllLights[lightIndex].Position.XPosition == xCoord && + RGBLights->AllLights[lightIndex].Position.YPosition == yCoord) + OrderedLights.push_back(lightIndex); + } } } - currentPixel++; + //pick starting type if using one of the multi types + switch(ChaseTypeInUse) + { + case ChaseTypes::CHASETYPES_RANDOM: + { + RandomChaseType = (SingleChaseTypes)(rand() % (int)SINGLECHASETYPES_MAX); + } break; - if (currentPixel > matrix->getPixelCount() - 1) { - currentPixel = 0; - } + case ChaseTypes::CHASETYPES_SEQUENTIAL_PINGPONG: + { + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_SEQUENTIAL; + } break; - if (reverse) { - currentFrame--; + case ChaseTypes::CHASETYPES_HORIZONTAL_PINGPONG: + { + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_LEFT_TO_RIGHT; + } break; + + case ChaseTypes::CHASETYPES_VERTICAL_PINGPONG: + { + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_TOP_TO_BOTTOM; + } break; - if (currentFrame < 0) { - currentFrame = 1; - reverse = false; - } - } else { - currentFrame++; + case ChaseTypes::CHASETYPES_TOP_TO_BOTTOM: + { + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_TOP_TO_BOTTOM; + } break; + + case ChaseTypes::CHASETYPES_BOTTOM_TO_TOP: + { + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_BOTTOM_TO_TOP; + } break; + + case ChaseTypes::CHASETYPES_LEFT_TO_RIGHT: + { + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_LEFT_TO_RIGHT; + } break; + + case ChaseTypes::CHASETYPES_RIGHT_TO_LEFT: + { + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_RIGHT_TO_LEFT; + } break; + + default: + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_SEQUENTIAL; + break; + } +} - if (currentFrame > 255) { - currentFrame = 254; - reverse = true; - } +void Chase::Animate(RGB (&frame)[100]) +{ + UpdateTime(); + + //update times and move to the next light(s) if required + ChaseTimes[0] -= (((float)AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime) / 1000.0f); + ChaseTimes[1] -= (((float)AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime) / 1000.0f); + if(ChaseTimes[0] < 0.0f) + { + ChaseTimes[0] = 0.0f; } - // this really shouldn't be nessecary, but something outside the param down might be changing this - if (AnimationStation::options.chaseCycleTime < CHASE_CYCLE_MIN) { - AnimationStation::options.chaseCycleTime = CHASE_CYCLE_MIN; - } else if (AnimationStation::options.chaseCycleTime > CHASE_CYCLE_MAX) { - AnimationStation::options.chaseCycleTime = CHASE_CYCLE_MAX; + //reset all lights first to ensure that if pressed lights are unpressed they can blend back to correct colour + for(unsigned int lightIndex = 0; lightIndex < OrderedLights.size(); ++lightIndex) + { + uint8_t firstLightIndex = RGBLights->AllLights[OrderedLights[lightIndex]].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[lightIndex]].LedsPerLight; + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + frame[ledIndex] = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[lightIndex]].GIPOPin]; + } } - this->nextRunTime = make_timeout_time_ms(AnimationStation::options.chaseCycleTime);*/ -} + //caclulate fade times here as these are used for all cases below + float fadeTimeOne = 0.0f; + if(ChaseTimes[0] < 1.0f && ChaseTimes[0] >= 0.8f) + fadeTimeOne = 1.0f - ((ChaseTimes[0] - 0.8f) / 0.2f); + else if(ChaseTimes[0] >= 0.2f && ChaseTimes[0] < 0.8f) + fadeTimeOne = 1.0f; + else if(ChaseTimes[0] < 0.2f && ChaseTimes[0] >= 0.0f) + fadeTimeOne = (ChaseTimes[0] / 0.2f); + float fadeTimeTwo = 0.0f; + if(ChaseTimes[1] < 1.0f && ChaseTimes[1] >= 0.8f) + fadeTimeTwo = 1.0f - ((ChaseTimes[1] - 0.8f) / 0.2f); + else if(ChaseTimes[1] >= 0.2f && ChaseTimes[1] < 0.8f) + fadeTimeTwo = 1.0f; + else if(ChaseTimes[1] < 0.2f && ChaseTimes[1] >= 0.0f) + fadeTimeTwo = (ChaseTimes[1] / 0.2f); + + //get this and next light + int currentLightReverseAdjusted = CurrentLight; + int nextLightReverseAdjusted = currentLightReverseAdjusted + 1; + + //now light the correct lights + switch(RandomChaseType) + { + case SingleChaseTypes::SINGLECHASETYPES_SEQUENTIAL: + { + //if we're on the way back then invert the index + if(Reversed) + { + currentLightReverseAdjusted = (OrderedLights.size()-1) - CurrentLight; + nextLightReverseAdjusted = currentLightReverseAdjusted - 1; + } + + uint8_t firstLightIndex = RGBLights->AllLights[OrderedLights[currentLightReverseAdjusted]].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[currentLightReverseAdjusted]].LedsPerLight; + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[currentLightReverseAdjusted]].GIPOPin], + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, + fadeTimeOne); + } + + if((unsigned int)(nextLightReverseAdjusted) < OrderedLights.size()) + { + uint8_t firstLightIndex = RGBLights->AllLights[OrderedLights[nextLightReverseAdjusted]].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[nextLightReverseAdjusted]].LedsPerLight; + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[nextLightReverseAdjusted]].GIPOPin], + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, + fadeTimeTwo); + } + } + } break; + + case SingleChaseTypes::SINGLECHASETYPES_RIGHT_TO_LEFT: + //reverse the order and fall through + currentLightReverseAdjusted = (MaxXCoord) - (CurrentLight - MinXCoord); + nextLightReverseAdjusted = currentLightReverseAdjusted - 1; + //Fall through (no break) + + case SingleChaseTypes::SINGLECHASETYPES_LEFT_TO_RIGHT: + { + for(unsigned int lightIndex = 0; lightIndex < OrderedLights.size(); ++lightIndex) + { + if(RGBLights->AllLights[OrderedLights[lightIndex]].Position.XPosition == currentLightReverseAdjusted) + { + uint8_t firstLightIndex = RGBLights->AllLights[OrderedLights[lightIndex]].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[lightIndex]].LedsPerLight; + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[lightIndex]].GIPOPin], + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, + fadeTimeOne); + } + } -bool Chase::IsChasePixel(int i) { - if (i == this->currentPixel || i == (this->currentPixel - 1) || - i == (this->currentPixel - 2)) { - return true; + if((CurrentLight+1) <= MaxXCoord) + { + if(RGBLights->AllLights[OrderedLights[lightIndex]].Position.XPosition == nextLightReverseAdjusted) + { + uint8_t firstLightIndex = RGBLights->AllLights[OrderedLights[lightIndex]].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[lightIndex]].LedsPerLight; + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[lightIndex]].GIPOPin], + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, + fadeTimeTwo); + } + } + } + } + } break; + + case SingleChaseTypes::SINGLECHASETYPES_BOTTOM_TO_TOP: + //reverse the order and fall through + currentLightReverseAdjusted = (MaxYCoord) - (CurrentLight - MinYCoord); + nextLightReverseAdjusted = currentLightReverseAdjusted - 1; + //Fall through (no break) + + case SingleChaseTypes::SINGLECHASETYPES_TOP_TO_BOTTOM: + { + for(unsigned int lightIndex = 0; lightIndex < OrderedLights.size(); ++lightIndex) + { + if(RGBLights->AllLights[OrderedLights[lightIndex]].Position.YPosition == currentLightReverseAdjusted) + { + uint8_t firstLightIndex = RGBLights->AllLights[OrderedLights[lightIndex]].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[lightIndex]].LedsPerLight; + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[lightIndex]].GIPOPin], + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, + fadeTimeOne); + } + } + + if((CurrentLight+1) <= MaxYCoord) + { + if(RGBLights->AllLights[OrderedLights[lightIndex]].Position.YPosition == nextLightReverseAdjusted) + { + uint8_t firstLightIndex = RGBLights->AllLights[OrderedLights[lightIndex]].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[lightIndex]].LedsPerLight; + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[lightIndex]].GIPOPin], + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, + fadeTimeTwo); + } + } + } + } + } break; + + default: + break; } - return false; + if(ChaseTimes[0] <= 0.0f) + { + CurrentLight++; + ChaseTimes[0] = ChaseTimes[1]; + ChaseTimes[1] += CHASE_SECOND_LIGHT_OFFSET; + CheckForEndOfSequence(); + } } -int Chase::WheelFrame(int i) { -/* int frame = this->currentFrame; - int pixelCount = matrix->getPixelCount(); - if (i == (this->currentPixel - 1) % pixelCount) { - if (this->reverse) { - frame = frame + 16; - } else { - frame = frame - 16; - } +void Chase::CheckForEndOfSequence() +{ + bool hasEnded = false; + + switch(RandomChaseType) + { + case SingleChaseTypes::SINGLECHASETYPES_SEQUENTIAL: + { + if((unsigned int)CurrentLight >= OrderedLights.size()) + { + hasEnded = true; + CurrentLight = 0; + ChaseTimes[0] = 1.0f; + ChaseTimes[1] = 1.0f + CHASE_SECOND_LIGHT_OFFSET; + } + } break; + + case SingleChaseTypes::SINGLECHASETYPES_LEFT_TO_RIGHT: + case SingleChaseTypes::SINGLECHASETYPES_RIGHT_TO_LEFT: + { + if(CurrentLight > MaxXCoord) + { + hasEnded = true; + CurrentLight = MinXCoord; + ChaseTimes[0] = 1.0f; + ChaseTimes[1] = 1.0f + CHASE_SECOND_LIGHT_OFFSET; + } + } break; + + case SingleChaseTypes::SINGLECHASETYPES_TOP_TO_BOTTOM: + case SingleChaseTypes::SINGLECHASETYPES_BOTTOM_TO_TOP: + { + if(CurrentLight > MaxYCoord) + { + hasEnded = true; + CurrentLight = MinYCoord; + ChaseTimes[0] = 1.0f; + ChaseTimes[1] = 1.0f + CHASE_SECOND_LIGHT_OFFSET; + } + } break; + + default: + break; } - if (i == (this->currentPixel - 2) % pixelCount) { - if (this->reverse) { - frame = frame + 32; - } else { - frame = frame - 32; + if(hasEnded) + { + //if a multi type then decide next type + switch(ChaseTypeInUse) + { + case ChaseTypes::CHASETYPES_SEQUENTIAL_PINGPONG: + { + Reversed = !Reversed; + } break; + + case ChaseTypes::CHASETYPES_HORIZONTAL_PINGPONG: + { + if(RandomChaseType == SingleChaseTypes::SINGLECHASETYPES_LEFT_TO_RIGHT) + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_RIGHT_TO_LEFT; + else + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_LEFT_TO_RIGHT; + } break; + + case ChaseTypes::CHASETYPES_VERTICAL_PINGPONG: + { + if(RandomChaseType == SingleChaseTypes::SINGLECHASETYPES_TOP_TO_BOTTOM) + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_BOTTOM_TO_TOP; + else + RandomChaseType = SingleChaseTypes::SINGLECHASETYPES_TOP_TO_BOTTOM; + } break; + + case ChaseTypes::CHASETYPES_RANDOM: + { + RandomChaseType = (SingleChaseTypes)(rand() % (int)SINGLECHASETYPES_MAX); + } break; + + default: + break; } } +} + +void Chase::ParameterUp() +{ + int32_t cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; + cycleTime = cycleTime + CHASE_CYCLE_INCREMENT; - if (frame < 0) { - return 0; + if (cycleTime > CHASE_CYCLE_MAX) + { + cycleTime = CHASE_CYCLE_MAX; } - return frame;*/ - return 0; + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = cycleTime; } -void Chase::ParameterUp() { -/* AnimationStation::options.chaseCycleTime = AnimationStation::options.chaseCycleTime + CHASE_CYCLE_INCREMENT; - if (AnimationStation::options.chaseCycleTime > CHASE_CYCLE_MAX) { - AnimationStation::options.chaseCycleTime = CHASE_CYCLE_MAX; - }*/ -} +void Chase::ParameterDown() +{ + int16_t cycleTime = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime; + cycleTime = cycleTime - CHASE_CYCLE_INCREMENT; + + if (cycleTime < CHASE_CYCLE_MIN) + { + cycleTime = CHASE_CYCLE_MIN; + } -void Chase::ParameterDown() { -/* AnimationStation::options.chaseCycleTime = AnimationStation::options.chaseCycleTime - CHASE_CYCLE_INCREMENT; - if (AnimationStation::options.chaseCycleTime < CHASE_CYCLE_MIN) { - AnimationStation::options.chaseCycleTime = CHASE_CYCLE_MIN; - }*/ + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = cycleTime; } diff --git a/lib/AnimationStation/src/Effects/Chase.hpp b/lib/AnimationStation/src/Effects/Chase.hpp index 54fe7af6d1..6f7dc08f18 100644 --- a/lib/AnimationStation/src/Effects/Chase.hpp +++ b/lib/AnimationStation/src/Effects/Chase.hpp @@ -8,22 +8,63 @@ #include #include "../AnimationStation.hpp" +//Chase lights the lights up in a specific order. 2 lights can be on at once as they overlaps on off times. There are multiple directions that can be used. + +//List of chase types +typedef enum +{ + CHASETYPES_SEQUENTIAL, + CHASETYPES_SEQUENTIAL_PINGPONG, + CHASETYPES_LEFT_TO_RIGHT, + CHASETYPES_RIGHT_TO_LEFT, + CHASETYPES_TOP_TO_BOTTOM, + CHASETYPES_BOTTOM_TO_TOP, + CHASETYPES_HORIZONTAL_PINGPONG, + CHASETYPES_VERTICAL_PINGPONG, + CHASETYPES_RANDOM, + CHASETYPES_MAX, +} ChaseTypes; + +typedef enum +{ + SINGLECHASETYPES_SEQUENTIAL, + SINGLECHASETYPES_LEFT_TO_RIGHT, + SINGLECHASETYPES_RIGHT_TO_LEFT, + SINGLECHASETYPES_TOP_TO_BOTTOM, + SINGLECHASETYPES_BOTTOM_TO_TOP, + SINGLECHASETYPES_MAX, +} SingleChaseTypes; + class Chase : public Animation { public: - Chase(Lights& InRGBLights); + Chase(Lights& InRGBLights, ChaseTypes InChaseType); ~Chase() {}; void Animate(RGB (&frame)[100]); void ParameterUp(); void ParameterDown(); + ChaseTypes ChaseTypeInUse = CHASETYPES_SEQUENTIAL; + protected: - bool IsChasePixel(int i); - int WheelFrame(int i); - int currentFrame = 0; - int currentPixel = 0; - bool reverse = false; - absolute_time_t nextRunTime = nil_time; + + void CheckForEndOfSequence(); + + float ChaseTimes[2]; + std::vector OrderedLights; + + int MinXCoord = 0; + int MinYCoord = 0; + int MaxXCoord = 0; + int MaxYCoord = 0; + + int CurrentLight = 0; + + bool Reversed = false; + + SingleChaseTypes RandomChaseType; + + absolute_time_t NextRunTime = nil_time; }; #endif diff --git a/lib/AnimationStation/src/Effects/Rainbow.cpp b/lib/AnimationStation/src/Effects/Rainbow.cpp index b2dd20bbc7..33797458b9 100644 --- a/lib/AnimationStation/src/Effects/Rainbow.cpp +++ b/lib/AnimationStation/src/Effects/Rainbow.cpp @@ -12,6 +12,10 @@ RainbowSynced::RainbowSynced(Lights& InRGBLights) : Animation(InRGBLights) { + if(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime > RAINBOW_CYCLE_MAX + RAINBOW_CYCLE_INCREMENT) + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = RAINBOW_CYCLE_MAX + RAINBOW_CYCLE_INCREMENT; + if(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime < RAINBOW_CYCLE_MIN - RAINBOW_CYCLE_INCREMENT) + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = RAINBOW_CYCLE_MIN - RAINBOW_CYCLE_INCREMENT; } void RainbowSynced::Animate(RGB (&frame)[100]) @@ -21,9 +25,6 @@ void RainbowSynced::Animate(RGB (&frame)[100]) return; } - //UpdateTime(); - //UpdatePresses(); - RGB color = RGB::wheel(this->currentFrame); for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { @@ -39,8 +40,6 @@ void RainbowSynced::Animate(RGB (&frame)[100]) } } - //DecrementFadeCounters(); - if (reverse) { currentFrame--; @@ -100,7 +99,10 @@ void RainbowSynced::ParameterDown() //////////////////////////////////////////////////////////////////////////////////////////// RainbowRotate::RainbowRotate(Lights& InRGBLights) : Animation(InRGBLights) { -} + if(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime > RAINBOW_CYCLE_MAX) + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = RAINBOW_CYCLE_MAX; + if(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime < RAINBOW_CYCLE_MIN) + AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].baseCycleTime = RAINBOW_CYCLE_MIN;} void RainbowRotate::Animate(RGB (&frame)[100]) { @@ -109,9 +111,6 @@ void RainbowRotate::Animate(RGB (&frame)[100]) return; } - //UpdateTime(); - //UpdatePresses(); - //the way this works is we offset the current frame by the distance from the top left of the grid int thisFrame = this->currentFrame; for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) @@ -132,8 +131,6 @@ void RainbowRotate::Animate(RGB (&frame)[100]) } } - //DecrementFadeCounters(); - currentFrame++; if (currentFrame >= 255) diff --git a/lib/AnimationStation/src/Effects/RandomColor.cpp b/lib/AnimationStation/src/Effects/RandomColor.cpp index 3cd9e7bf34..630cc9e4ca 100644 --- a/lib/AnimationStation/src/Effects/RandomColor.cpp +++ b/lib/AnimationStation/src/Effects/RandomColor.cpp @@ -18,9 +18,8 @@ RandomColor::RandomColor(Lights& InRGBLights, std::vector &InPressedPin void RandomColor::NewPressForPin(int lightIndex) { - savedPressedColour[lightIndex] = colors[rand() % colors.size()]; - - AnimationStation::printfs[3] = std::to_string(lightIndex); + //dont pick 0 as thats black + savedPressedColour[lightIndex] = colors[(rand() % (colors.size()-1)) + 1]; } void RandomColor::Animate(RGB (&frame)[100]) @@ -36,13 +35,9 @@ void RandomColor::Animate(RGB (&frame)[100]) for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { //Non pressed simply sets the RGB colour - if(!isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) - { - frame[ledIndex] = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin]; - } - else if (isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) + if (LightTypeIsForPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { - frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin], + frame[ledIndex] = FadeColor(savedPressedColour[lightIndex], frame[ledIndex], fadeTimes[ledIndex]); } diff --git a/lib/AnimationStation/src/Effects/StaticColor.cpp b/lib/AnimationStation/src/Effects/StaticColor.cpp index e58d4327b3..cc6eece422 100644 --- a/lib/AnimationStation/src/Effects/StaticColor.cpp +++ b/lib/AnimationStation/src/Effects/StaticColor.cpp @@ -27,11 +27,24 @@ void StaticColor::Animate(RGB (&frame)[100]) { frame[ledIndex] = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin]; } - else if (isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) + else if (isButtonAnimation && LightTypeIsForPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { - frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin], + if(fadeTimes[ledIndex] > 0) + { + RGB rgb = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].pressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin]; + AnimationStation::printfs[0] = std::to_string(rgb.r) + " " + std::to_string(rgb.g) + " " + std::to_string(rgb.b); + AnimationStation::printfs[1] = std::to_string(frame[ledIndex].r) + " " + std::to_string(frame[ledIndex].g) + " " + std::to_string(frame[ledIndex].b); + AnimationStation::printfs[2] = std::to_string(fadeTimes[ledIndex]); + } + + frame[ledIndex] = FadeColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].pressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin], frame[ledIndex], fadeTimes[ledIndex]); + + if(fadeTimes[ledIndex] > 0) + { + AnimationStation::printfs[3] = std::to_string(frame[ledIndex].r) + " " + std::to_string(frame[ledIndex].g) + " " + std::to_string(frame[ledIndex].b); + } } } } diff --git a/proto/config.proto b/proto/config.proto index 1669d9ce2c..2b0797c3f8 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -308,6 +308,8 @@ message AnimationProfile_Proto optional uint32 buttonPressHoldTimeInMs = 7; optional uint32 buttonPressFadeOutTimeInMs = 8; + + optional uint32 nonPressedSpecialColour = 9; }; // This has to be kept in sync with AnimationOptions in AnimationStation.hpp diff --git a/proto/enums.proto b/proto/enums.proto index 06ff32fec3..d2f9662053 100644 --- a/proto/enums.proto +++ b/proto/enums.proto @@ -317,7 +317,15 @@ enum AnimationNonPressedEffects_Proto EFFECT_STATIC_COLOR = 0; EFFECT_RAINBOW_SYNCED = 1; EFFECT_RAINBOW_ROTATE = 2; - EFFECT_CHASE = 3; + EFFECT_CHASE_SEQUENTIAL = 3; + EFFECT_CHASE_LEFT_TO_RIGHT = 4; + EFFECT_CHASE_RIGHT_TO_LEFT = 5; + EFFECT_CHASE_TOP_TO_BOTTOM = 6; + EFFECT_CHASE_BOTTOM_TO_TOP = 7; + EFFECT_CHASE_SEQUENTIAL_PINGPONG = 8; + EFFECT_CHASE_HORIZONTAL_PINGPONG = 9; + EFFECT_CHASE_VERTICAL_PINGPONG = 10; + EFFECT_CHASE_RANDOM = 11; } /* This has to be kept in sync with AnimationPressedEffects in AnimationStation.hpp */ diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 0c88874c6f..e064c33cb4 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -477,23 +477,28 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) // animationOptions if(config.animationOptions.profiles_count == 0) + config.animationOptions.profiles_count = 1; + for (unsigned int profileIndex = 0; profileIndex < 4; ++profileIndex) /* MAX_ANIMATION_PROFILES from AnimationStation.hpp */ { - config.animationOptions.profiles_count = 1; - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], bIsValidProfile, true); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], baseNonPressedEffect, AnimationNonPressedEffects_Proto::AnimationNonPressedEffects_Proto_EFFECT_RAINBOW_ROTATE); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], basePressedEffect, AnimationPressedEffects_Proto::AnimationPressedEffects_Proto_EFFECT_RANDOM); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], baseCycleTime, 1); - config.animationOptions.profiles[0].notPressedStaticColors_count = NUM_BANK0_GPIOS; - config.animationOptions.profiles[0].pressedStaticColors_count = NUM_BANK0_GPIOS; - for (unsigned int index = 0; index < NUM_BANK0_GPIOS; ++index) - { - config.animationOptions.profiles[0].notPressedStaticColors[index] = 0; - config.animationOptions.profiles[0].pressedStaticColors[index] = 0; - } - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], buttonPressHoldTimeInMs, 0); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[0], buttonPressFadeOutTimeInMs, 0); - } - //INIT_UNSET_PROPERTY(config.animationOptions, profiles[0], defaultProfile); + config.animationOptions.profiles[profileIndex].notPressedStaticColors_count = NUM_BANK0_GPIOS; + config.animationOptions.profiles[profileIndex].pressedStaticColors_count = NUM_BANK0_GPIOS; + if(config.animationOptions.profiles[profileIndex].has_bIsValidProfile || config.animationOptions.profiles[profileIndex].bIsValidProfile == false) + { + for (unsigned int lightIndex = 0; lightIndex < NUM_BANK0_GPIOS; ++lightIndex) + { + config.animationOptions.profiles[profileIndex].notPressedStaticColors[lightIndex] = 0; + config.animationOptions.profiles[profileIndex].pressedStaticColors[lightIndex] = 0; + } + } + + INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], bIsValidProfile, profileIndex == 0 ? true : false); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], baseNonPressedEffect, AnimationNonPressedEffects_Proto::AnimationNonPressedEffects_Proto_EFFECT_RAINBOW_SYNCED); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], basePressedEffect, AnimationPressedEffects_Proto::AnimationPressedEffects_Proto_EFFECT_HELD_STATIC_COLOR); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], baseCycleTime, 1); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], buttonPressHoldTimeInMs, 500); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], buttonPressFadeOutTimeInMs, 500); + INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], nonPressedSpecialColour, 255 << 16); //RED + } INIT_UNSET_PROPERTY(config.animationOptions, brightness, LEDS_BRIGHTNESS); INIT_UNSET_PROPERTY(config.animationOptions, baseProfileIndex, 0); diff --git a/src/display/ui/screens/ButtonLayoutScreen.cpp b/src/display/ui/screens/ButtonLayoutScreen.cpp index e69ed1ccf9..f9200490f3 100644 --- a/src/display/ui/screens/ButtonLayoutScreen.cpp +++ b/src/display/ui/screens/ButtonLayoutScreen.cpp @@ -210,24 +210,15 @@ void ButtonLayoutScreen::generateHeader() { } void ButtonLayoutScreen::drawScreen() { -/* if (profileModeDisplay) { + if (profileModeDisplay) { getRenderer()->drawRectangle(0, 0, 128, 7, true, true); getRenderer()->drawText(0, 0, statusBar, true); } else { getRenderer()->drawText(0, 0, statusBar); } getRenderer()->drawText(0, 7, footer); -*/ Storage& storage = Storage::getInstance(); -/* storage.printfs[0] = "Pods"; - storage.printfs[1] = "TEST1"; - storage.printfs[2] = "TEST2"; - storage.printfs[3] = "TEST3"; - storage.printfs[4] = "TEST4"; - storage.printfs[5] = "TEST5"; - storage.printfs[6] = "TEST6"; - storage.printfs[7] = "TEST7";*/ getRenderer()->drawText(0, 0, AnimationStation::printfs[0]); getRenderer()->drawText(0, 1, AnimationStation::printfs[1]); getRenderer()->drawText(0, 2, AnimationStation::printfs[2]); diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index 88cdd5771e..fdb0d6eac4 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -49,6 +49,7 @@ static void updateAnimationOptionsProto(const AnimationOptions& options) } optionsProto.profiles[index].buttonPressHoldTimeInMs = options.profiles[index].buttonPressHoldTimeInMs; optionsProto.profiles[index].buttonPressFadeOutTimeInMs = options.profiles[index].buttonPressFadeOutTimeInMs; + optionsProto.profiles[index].nonPressedSpecialColour = options.profiles[index].nonPressedSpecialColour; } optionsProto.brightness = options.brightness; optionsProto.baseProfileIndex = options.baseProfileIndex; @@ -208,6 +209,7 @@ AnimationOptions AnimationStorage::getAnimationOptions() } options.profiles[index].buttonPressHoldTimeInMs = optionsProto.profiles[index].buttonPressHoldTimeInMs; options.profiles[index].buttonPressFadeOutTimeInMs = optionsProto.profiles[index].buttonPressFadeOutTimeInMs; + options.profiles[index].nonPressedSpecialColour = optionsProto.profiles[index].nonPressedSpecialColour; } options.brightness = std::min(optionsProto.brightness, 255); options.baseProfileIndex = std::min(optionsProto.baseProfileIndex, 255); From a0cb96da888c0896847ee43e531c3208098311a6 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Sat, 16 Nov 2024 23:15:38 +0000 Subject: [PATCH 007/121] code dump --- headers/addons/neopicoleds.h | 2 +- headers/helper.h | 1 + headers/storagemanager.h | 6 + lib/AnimationStation/CMakeLists.txt | 1 + lib/AnimationStation/src/AnimationStation.cpp | 6 + lib/AnimationStation/src/AnimationStation.hpp | 9 ++ lib/AnimationStation/src/AnimationStorage.hpp | 2 + .../src/Effects/StaticColor.cpp | 13 -- .../src/SpecialMoveSystem.cpp | 83 +++++++++++ .../src/SpecialMoveSystem.hpp | 136 ++++++++++++++++++ lib/FlashPROM/src/FlashPROM.h | 4 +- proto/config.proto | 39 ++++- proto/enums.proto | 23 +++ src/addons/neopicoleds.cpp | 7 + src/config_utils.cpp | 39 +++++ src/storagemanager.cpp | 76 ++++++++-- 16 files changed, 416 insertions(+), 31 deletions(-) create mode 100644 lib/AnimationStation/src/SpecialMoveSystem.cpp create mode 100644 lib/AnimationStation/src/SpecialMoveSystem.hpp diff --git a/headers/addons/neopicoleds.h b/headers/addons/neopicoleds.h index 1453564ef5..840f7c856e 100644 --- a/headers/addons/neopicoleds.h +++ b/headers/addons/neopicoleds.h @@ -20,6 +20,7 @@ // MPGS #include "BoardConfig.h" #include "AnimationStation.hpp" +#include "SpecialMoveSystem.hpp" #include "NeoPico.hpp" #ifndef BOARD_LEDS_PIN @@ -222,7 +223,6 @@ class NeoPicoLEDAddon : public GPAddon { const uint32_t intervalMS = 10; absolute_time_t nextRunTime; uint8_t ledCount; - PixelMatrix matrix; InputMode inputMode; // HACK std::map buttonPositions; bool turnOffWhenSuspended; diff --git a/headers/helper.h b/headers/helper.h index 313948c464..564cca2bb3 100644 --- a/headers/helper.h +++ b/headers/helper.h @@ -7,6 +7,7 @@ #include "BoardConfig.h" #include #include "AnimationStation.hpp" +#include "SpecialMoveSystem.hpp" #include "PlayerLEDs.h" // GP2040-CE Board Config (64 character limit) diff --git a/headers/storagemanager.h b/headers/storagemanager.h index 191b2728d6..465e826d90 100644 --- a/headers/storagemanager.h +++ b/headers/storagemanager.h @@ -46,6 +46,7 @@ class Storage { ProfileOptions& getProfileOptions() { return config.profileOptions; } GpioMappingInfo* getProfilePinMappings() { return functionalPinMappings; } PeripheralOptions& getPeripheralOptions() { return config.peripheralOptions; } + SpecialMoveOptions_Proto& getSpecialMoveOptions() { return config.specialMoveOptions; } void init(); bool save(); @@ -54,6 +55,7 @@ class Storage { void performEnqueuedSaves(); void enqueueAnimationOptionsSave(const AnimationOptions& animationOptions); + void enqueueSpecialMoveOptionsSave(const SpecialMoveOptions& specialMoveOptions); void SetConfigMode(bool); // Config Mode (on-boot) bool GetConfigMode(); @@ -86,6 +88,10 @@ class Storage { critical_section_t animationOptionsCs; uint32_t animationOptionsCrc = 0; AnimationOptions animationOptionsToSave = {}; + std::atomic specialMoveOptionsSavePending; + critical_section_t specialMoveOptionsCs; + uint32_t specialMoveOptionsCrc = 0; + SpecialMoveOptions specialMoveOptionsToSave = {}; GpioMappingInfo functionalPinMappings[NUM_BANK0_GPIOS]; }; diff --git a/lib/AnimationStation/CMakeLists.txt b/lib/AnimationStation/CMakeLists.txt index bc9f428261..3a06162a40 100644 --- a/lib/AnimationStation/CMakeLists.txt +++ b/lib/AnimationStation/CMakeLists.txt @@ -5,6 +5,7 @@ src/Effects/StaticColor.cpp src/Effects/RandomColor.cpp src/AnimationStation.cpp src/Animation.cpp +src/SpecialMoveSystem.cpp ) target_include_directories(AnimationStation PUBLIC src diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index 914d428559..d8da26092a 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -9,6 +9,7 @@ #include "Effects/Rainbow.hpp" #include "Effects/StaticColor.hpp" #include "Effects/RandomColor.hpp" +#include "SpecialMoveSystem.hpp" #include "AnimationStation.hpp" @@ -153,6 +154,11 @@ void AnimationStation::HandlePressedPins(std::vector pressedPins) } } +void AnimationStation::HandlePressedButtons(uint32_t pressedButtons) +{ + specialMoveSystem.HandlePressedButtons(pressedButtons); +} + void AnimationStation::Animate() { //If no profiles running diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index 9a8106b289..b7d178b177 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -11,6 +11,7 @@ #include "NeoPico.hpp" #include "Animation.hpp" +#include "SpecialMoveSystem.hpp" #define MAX_ANIMATION_PROFILES 4 @@ -94,6 +95,9 @@ class AnimationStation //What buttons (physical gpio pins) are pressed this frame void HandlePressedPins(std::vector pressedPins); + //What buttons (logical ones) are pressed this frame + void HandlePressedButtons(uint32_t pressedButtons); + int8_t GetMode(); void SetMode(int8_t mode); void SetLights(Lights InRGBLights); @@ -109,6 +113,8 @@ class AnimationStation //passed in user options static void SetOptions(AnimationOptions InOptions); + + SpecialMoveSystem specialMoveSystem; //Running non-pressed animation Animation* baseAnimation; @@ -116,6 +122,9 @@ class AnimationStation //Running pressed animation Animation* buttonAnimation; + //Running special move animation + Animation* specialMoveAnimation; + //Buttons pressed (physical gipo pins) last frame, used when changing button theme so starts initialised std::vector lastPressed; diff --git a/lib/AnimationStation/src/AnimationStorage.hpp b/lib/AnimationStation/src/AnimationStorage.hpp index 23ba190074..b86472e220 100644 --- a/lib/AnimationStation/src/AnimationStorage.hpp +++ b/lib/AnimationStation/src/AnimationStorage.hpp @@ -2,12 +2,14 @@ #define _CONFIG_STORAGE_H_ #include "AnimationStation.hpp" +#include "SpecialMoveSystem.hpp" class AnimationStorage { public: void save(); AnimationOptions getAnimationOptions(); + SpecialMoveOptions getSpecialMoveOptions(); }; static AnimationStorage AnimationStore; diff --git a/lib/AnimationStation/src/Effects/StaticColor.cpp b/lib/AnimationStation/src/Effects/StaticColor.cpp index cc6eece422..61ce7ce3d8 100644 --- a/lib/AnimationStation/src/Effects/StaticColor.cpp +++ b/lib/AnimationStation/src/Effects/StaticColor.cpp @@ -29,22 +29,9 @@ void StaticColor::Animate(RGB (&frame)[100]) } else if (isButtonAnimation && LightTypeIsForPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { - if(fadeTimes[ledIndex] > 0) - { - RGB rgb = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].pressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin]; - AnimationStation::printfs[0] = std::to_string(rgb.r) + " " + std::to_string(rgb.g) + " " + std::to_string(rgb.b); - AnimationStation::printfs[1] = std::to_string(frame[ledIndex].r) + " " + std::to_string(frame[ledIndex].g) + " " + std::to_string(frame[ledIndex].b); - AnimationStation::printfs[2] = std::to_string(fadeTimes[ledIndex]); - } - frame[ledIndex] = FadeColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].pressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin], frame[ledIndex], fadeTimes[ledIndex]); - - if(fadeTimes[ledIndex] > 0) - { - AnimationStation::printfs[3] = std::to_string(frame[ledIndex].r) + " " + std::to_string(frame[ledIndex].g) + " " + std::to_string(frame[ledIndex].b); - } } } } diff --git a/lib/AnimationStation/src/SpecialMoveSystem.cpp b/lib/AnimationStation/src/SpecialMoveSystem.cpp new file mode 100644 index 0000000000..6093c5c561 --- /dev/null +++ b/lib/AnimationStation/src/SpecialMoveSystem.cpp @@ -0,0 +1,83 @@ +#include "SpecialMoveSystem.hpp" + +#include "AnimationStation.hpp" + +SpecialMoveOptions SpecialMoveSystem::Options = {}; + +SpecialMoveSystem::SpecialMoveSystem() +{ +} + +void SpecialMoveSystem::Update() +{ + thisFrameTime = get_absolute_time(); + + //trim history if required + while(SwitchHistory.size() > MAX_INPUT_HISTORY) + SwitchHistory.pop_front(); +} + +void SpecialMoveSystem::SetOptions(SpecialMoveOptions InOptions) +{ + Options = InOptions; +} + +void SpecialMoveSystem::HandlePressedButtons(uint32_t pressedButtons) +{ + //check each input and update history + for(int buttonMask = 1; buttonMask < (1 << 20); buttonMask = buttonMask << 1) + { + UpdateHistoryForInput(buttonMask, (pressedButtons & buttonMask) != 0); + } +} + +void SpecialMoveSystem::ClearHistory() +{ + SwitchHistory.clear(); +} + +void SpecialMoveSystem::UpdateHistoryForInput(uint32_t buttonMask, bool bIsPressed) +{ + //search history for recent instance of this button + for(unsigned int historyIndex = 0; historyIndex < SwitchHistory.size() ; ++historyIndex) + { + if(SwitchHistory[historyIndex].Input == buttonMask) + { + //found button. now check if its pressed state is correct + if(bIsPressed && SwitchHistory[historyIndex].bIsHeld == false) + { + //create new entry at start of history array + InputHistory newHistory; + newHistory.bIsHeld = true; + newHistory.TimeSet = thisFrameTime; + newHistory.Input = buttonMask; + SwitchHistory.push_front(newHistory); + } + else if(!bIsPressed && SwitchHistory[historyIndex].bIsHeld) + { + //button has been released. Store off when this happened + SwitchHistory[historyIndex].bIsHeld = false; + SwitchHistory[historyIndex].TimeReleased = thisFrameTime; + } + + return; + } + } + + //no previous entry found. Add new one + InputHistory newHistory; + newHistory.bIsHeld = true; + newHistory.TimeSet = thisFrameTime; + newHistory.Input = buttonMask; + SwitchHistory.push_front(newHistory); +} + +void SpecialMoveSystem::TestForActivatedSpecialMove() +{ + +} + +void SpecialMoveSystem::UpdateRunningSpecialMove() +{ + +} \ No newline at end of file diff --git a/lib/AnimationStation/src/SpecialMoveSystem.hpp b/lib/AnimationStation/src/SpecialMoveSystem.hpp new file mode 100644 index 0000000000..3ce46b6263 --- /dev/null +++ b/lib/AnimationStation/src/SpecialMoveSystem.hpp @@ -0,0 +1,136 @@ +#ifndef _SPECIALMOVE_H_ +#define _SPECIALMOVE_H_ + +#include +#include +#include +#include "pico/stdlib.h" +#include +#include +#include + +#define MAX_SPECIALMOVE_PROFILES 4 +#define MAX_SPECIALMOVES 20 +#define MAX_SPECIALMOVE_INPUTTYPES_PER_MOVE 4 +#define MAX_SPECIALMOVE_TRIGGERCOMBOS 3 +#define MAX_SPECIALMOVE_TRIGGERS_PER_MOVE 3 +#define MAX_INPUT_HISTORY 100 + +//List of specialMove animation +typedef enum +{ + SPECIALMOVE_SMEFFECT_WAVE, + SPECIALMOVE_SMEFFECT_SUPERWAVE, + SPECIALMOVE_SMEFFECT_PULSECOLOR, + SPECIALMOVE_SMEFFECT_CIRCLECOLOR, + SPECIALMOVE_SMEFFECT_FLASHCOLOR, + SPECIALMOVE_SMEFFECT_KNIGHTRIDER, + SPECIALMOVE_SMEFFECT_RANDOMFLASH, +} SpecialMoveEffects; + +// SpecialMove animation Duration Modifier +typedef enum +{ + SPECIALMOVE_DURATION_FAST, + SPECIALMOVE_DURATION_MEDIUM, + SPECIALMOVE_DURATION_LONG, +} SpecialMoveAnimationDuration; + +// SpecialMove animation Direction Modifier +typedef enum +{ + SPECIALMOVE_DIRECTION_UP, + SPECIALMOVE_DIRECTION_LEFT, + SPECIALMOVE_DIRECTION_RIGHT, + SPECIALMOVE_DIRECTION_DOWN, +} SpecialMoveAnimationDirection; + +// SpecialMove input types +typedef enum +{ + SPECIALMOVE_INPUT_QUARTER_DOWN_RIGHT, + SPECIALMOVE_INPUT_QUARTER_DOWN_LEFT, + SPECIALMOVE_INPUT_DP_RIGHT, + SPECIALMOVE_INPUT_DP_SHORTCUT_RIGHT, + SPECIALMOVE_INPUT_DP_LEFT, + SPECIALMOVE_INPUT_DP_SHORTCUT_LEFT, +} SpecialMoveInputTypes; + +// Input History structure. +struct InputHistory +{ + uint32_t Input; //button mask + absolute_time_t TimeSet; + absolute_time_t TimeReleased; + bool bIsHeld; +}; + +struct __attribute__ ((__packed__)) SpecialMoveInputTriggers +{ + uint32_t OptionalParams; //6 4byte params packed in here. Unique per effect type. See each effect for details + uint8_t RequiredTriggers; //buttonmasks +}; + +struct __attribute__ ((__packed__)) SpecialMoveDescription +{ + uint32_t NumRequiredInputCombos; + SpecialMoveInputTypes RequiredInputCombos[MAX_SPECIALMOVE_INPUTTYPES_PER_MOVE]; + uint32_t NumRequiredTriggerCombos; + SpecialMoveInputTriggers RequiredTriggerCombos[MAX_SPECIALMOVE_TRIGGERCOMBOS]; + + SpecialMoveEffects Animation; + bool bIsChargeMove; +}; + +struct __attribute__ ((__packed__)) SpecialMoveProfile +{ + uint32_t NumValidMoves; + SpecialMoveDescription AllSpecialMoves[MAX_SPECIALMOVES]; +}; + +struct __attribute__ ((__packed__)) SpecialMoveOptions +{ + uint32_t NumValidProfiles; + SpecialMoveProfile profiles[MAX_SPECIALMOVE_PROFILES]; + uint32_t ChargeTimeInMs; + uint8_t CurrentProfileIndex; +}; + +class SpecialMoveSystem { +public: + SpecialMoveSystem(); + virtual ~SpecialMoveSystem(){}; + + //Which buttons are held at the moment + void Update(); + + //passed in user options + static void SetOptions(SpecialMoveOptions InOptions); + + //What buttons (logical ones) are pressed this frame + void HandlePressedButtons(uint32_t pressedButtons); + +protected: + + void ClearHistory(); + void UpdateHistoryForInput(uint32_t buttonMask, bool bIsPressed); + + void TestForActivatedSpecialMove(); + void UpdateRunningSpecialMove(); + + static SpecialMoveOptions Options; + + //history of all buttons/directions held. (newest entries first) + std::deque SwitchHistory; + + // after a special move we need to wait for all inputs to be released before continuing to avoid repeats + bool SwitchClearAwaitingAllRelease = false; + + //Current running Special Move indexes + int RunnningSpecialMoveIndex; + int RunnningSpecialMoveAnimationIndex; + + absolute_time_t thisFrameTime = nil_time; +}; + +#endif diff --git a/lib/FlashPROM/src/FlashPROM.h b/lib/FlashPROM/src/FlashPROM.h index efc0c31106..b9be4262e3 100644 --- a/lib/FlashPROM/src/FlashPROM.h +++ b/lib/FlashPROM/src/FlashPROM.h @@ -13,8 +13,8 @@ #include #include -#define EEPROM_SIZE_BYTES 0x4000 // Reserve 16k of flash memory (ensure this value is divisible by 256) -#define EEPROM_ADDRESS_START _u(0x101FC000) // The arduino-pico EEPROM lib starts here, so we'll do the same +#define EEPROM_SIZE_BYTES 0x8000 // Reserve 32k of flash memory (ensure this value is divisible by 256) +#define EEPROM_ADDRESS_START _u(0x101F8000) // The arduino-pico EEPROM lib starts here, so we'll do the same // Warning: If the write wait is too long it can stall other processes #define EEPROM_WRITE_WAIT 50 // Amount of time in ms to wait before blocking core1 and committing to flash diff --git a/proto/config.proto b/proto/config.proto index 2b0797c3f8..1da9511c52 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -293,7 +293,38 @@ message LEDOptions optional int32 lightDataSize = 37; }; -// This has to be kept in sync with AnimationOptions in AnimationStation.hpp +// This has to be kept in sync with SpecialMoveAnimation in SpecialMoveSystem.hpp +message SpecialMoveInputTriggers_Proto +{ + optional uint32 OptionalParams = 1; //8 uint4's packed in here (assigned to custom enums later) + optional uint32 RequiredTriggers = 2; //buttonmasks +}; + +// This has to be kept in sync with SpecialMoveDescription in SpecialMoveSystem.hpp +message SpecialMoveDescription_Proto +{ + repeated SpecialMoveInputTypes_Proto RequiredInputCombos = 1 [(nanopb).max_count = 4]; //MAX_SPECIALMOVE_INPUTTYPES_PER_MOVE from SpecialMoveSystem.hpp + repeated SpecialMoveInputTriggers_Proto RequiredTriggerCombos = 2 [(nanopb).max_count = 3]; //MAX_SPECIALMOVE_TRIGGERCOMBOS from SpecialMoveSystem.hpp + + optional SpecialMoveEffects_Proto Animation = 3; + optional bool bIsChargeMove = 4; +}; + +// This has to be kept in sync with SpecialMoveProfile in SpecialMoveSystem.hpp +message SpecialMoveProfile_Proto +{ + repeated SpecialMoveDescription_Proto AllSpecialMoves = 1 [(nanopb).max_count = 20]; //MAX_SPECIALMOVES from SpecialMoveSystem.hpp +}; + +// This has to be kept in sync with SpecialMoveOptions in SpecialMoveSystem.hpp +message SpecialMoveOptions_Proto +{ + repeated SpecialMoveProfile_Proto profiles = 1 [(nanopb).max_count = 4]; //MAX_SPECIALMOVE_PROFILES from SpecialMoveSystem.hpp + optional uint32 ChargeTimeInMs = 2; + optional uint32 CurrentProfileIndex = 3; +}; + +// This has to be kept in sync with AnimationProfile in AnimationStation.hpp message AnimationProfile_Proto { optional bool bIsValidProfile = 1; @@ -734,8 +765,8 @@ message MacroInput message Macro { optional MacroType macroType = 1; - optional string macroLabel = 2 [(nanopb).max_length = 32]; - repeated MacroInput macroInputs = 3 [(nanopb).max_count = 10]; + optional string macroLabel = 2 [(nanopb).max_length = 64]; + repeated MacroInput macroInputs = 3 [(nanopb).max_count = 30]; optional bool enabled = 4; optional bool useMacroTriggerButton = 5; optional int32 deprecatedMacroTriggerPin = 6 [deprecated = true]; @@ -871,4 +902,6 @@ message Config optional GpioMappings gpioMappings = 13; optional MigrationHistory migrations = 14; optional PeripheralOptions peripheralOptions = 15; + + optional SpecialMoveOptions_Proto specialMoveOptions = 16; } diff --git a/proto/enums.proto b/proto/enums.proto index d2f9662053..b40116c5e4 100644 --- a/proto/enums.proto +++ b/proto/enums.proto @@ -311,6 +311,29 @@ enum LEDFormat_Proto LED_FORMAT_RGBW = 3; } +/* This has to be kept in sync with SpecialMoveEffects in SpecialMoveSystem.hpp */ +enum SpecialMoveEffects_Proto +{ + SMEFFECT_WAVE = 0; + SMEFFECT_SUPERWAVE = 1; + SMEFFECT_PULSECOLOR = 2; + SMEFFECT_CIRCLECOLOR = 3; + SMEFFECT_FLASHCOLOR = 4; + SMEFFECT_KNIGHTRIDER = 5; + SMEFFECT_RANDOMFLASH = 6; +} + +/* This has to be kept in sync with SpecialMoveInputTypes in SpecialMoveSystem.hpp */ +enum SpecialMoveInputTypes_Proto +{ + INPUT_QUARTER_DOWN_RIGHT = 0; + INPUT_QUARTER_DOWN_LEFT = 1; + INPUT_DP_RIGHT = 2; + INPUT_DP_SHORTCUT_RIGHT = 3; + INPUT_DP_LEFT = 4; + INPUT_DP_SHORTCUT_LEFT = 5; +} + /* This has to be kept in sync with AnimationNonPressedEffects in AnimationStation.hpp */ enum AnimationNonPressedEffects_Proto { diff --git a/src/addons/neopicoleds.cpp b/src/addons/neopicoleds.cpp index 47d6202a1c..6a1f6b567f 100644 --- a/src/addons/neopicoleds.cpp +++ b/src/addons/neopicoleds.cpp @@ -4,6 +4,7 @@ */ #include "AnimationStation.hpp" +#include "SpecialMoveSystem.hpp" #include "AnimationStorage.hpp" #include "NeoPico.hpp" #include "Pixel.hpp" @@ -289,6 +290,10 @@ void NeoPicoLEDAddon::process() } AnimStation.HandlePressedPins(pressedPins); + //Still need to check logical buttons so that we can trigger special moves + uint32_t buttonState = gamepad->state.dpad << 16 | gamepad->state.buttons; + AnimStation.HandlePressedButtons(buttonState); + //Update idle, button and special move animations AnimStation.Animate(); @@ -593,6 +598,8 @@ void NeoPicoLEDAddon::configureLEDs() AnimStation.ConfigureBrightness(ledOptions.brightnessMaximum, ledOptions.brightnessSteps); AnimationOptions animationOptions = AnimationStore.getAnimationOptions(); AnimStation.SetOptions(animationOptions); + SpecialMoveOptions specialMoveOptions = AnimationStore.getSpecialMoveOptions(); + AnimStation.specialMoveSystem.SetOptions(specialMoveOptions); AnimStation.SetLights(RGBLights); AnimStation.SetMode(as.options.baseProfileIndex); } diff --git a/src/config_utils.cpp b/src/config_utils.cpp index e064c33cb4..7163169bfa 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -475,6 +475,45 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) const unsigned char lightData[] = { LIGHT_DATA }; INIT_UNSET_PROPERTY_BYTES(config.ledOptions, lightData, lightData); + //SpecialMoveOptions + //TESTING + if(config.specialMoveOptions.profiles[0].AllSpecialMoves_count == 0) + { + config.specialMoveOptions.profiles[0].AllSpecialMoves_count = 2; + + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0], bIsChargeMove, false); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0], Animation, SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE); + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos_count = 1; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_QUARTER_DOWN_RIGHT; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], RequiredTriggers, GAMEPAD_MASK_B3); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], OptionalParams, 2 + (2 << 4) + (10 << 8)); //right //slow //colour blue + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], RequiredTriggers, GAMEPAD_MASK_B4); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], OptionalParams, 2 + (1 << 4) + (10 << 8)); //right //medium //colour blue + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], RequiredTriggers, GAMEPAD_MASK_R1); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], OptionalParams, 2 + (0 << 4) + (10 << 8)); //right //fast //colour blue + + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1], bIsChargeMove, false); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1], Animation, SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_PULSECOLOR); + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos_count = 2; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_RIGHT; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[1] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_SHORTCUT_RIGHT; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], RequiredTriggers, GAMEPAD_MASK_B3); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], OptionalParams, 2 + (1 << 8)); //fast //colour white + + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], RequiredTriggers, GAMEPAD_MASK_B4); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], OptionalParams, 1 + (1 << 8)); //med //colour white + + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], RequiredTriggers, GAMEPAD_MASK_R1); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], OptionalParams, 0 + (1 << 8)); //slow //colour white + } + + if(config.specialMoveOptions.profiles_count == 0) + config.specialMoveOptions.profiles_count = 1; + INIT_UNSET_PROPERTY(config.specialMoveOptions, ChargeTimeInMs, 750); + INIT_UNSET_PROPERTY(config.specialMoveOptions, CurrentProfileIndex, 0); + // animationOptions if(config.animationOptions.profiles_count == 0) config.animationOptions.profiles_count = 1; diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index fdb0d6eac4..d0a5d3212f 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -38,23 +38,18 @@ static void updateAnimationOptionsProto(const AnimationOptions& options) for(int index = 0; index < 4; ++index) //MAX_ANIMATION_PROFILES from AnimationStation.hpp { - optionsProto.profiles[index].bIsValidProfile = options.profiles[index].bIsValidProfile; - optionsProto.profiles[index].baseNonPressedEffect = (AnimationNonPressedEffects_Proto)((int)options.profiles[index].baseNonPressedEffect); - optionsProto.profiles[index].basePressedEffect = (AnimationPressedEffects_Proto)((int)options.profiles[index].basePressedEffect); optionsProto.profiles[index].baseCycleTime = options.profiles[index].baseCycleTime; - for(int pinIndex = 0; pinIndex < NUM_BANK0_GPIOS; ++pinIndex) - { - optionsProto.profiles[index].notPressedStaticColors[pinIndex] = options.profiles[index].notPressedStaticColors[pinIndex]; - optionsProto.profiles[index].pressedStaticColors[pinIndex] = options.profiles[index].pressedStaticColors[pinIndex]; - } - optionsProto.profiles[index].buttonPressHoldTimeInMs = options.profiles[index].buttonPressHoldTimeInMs; - optionsProto.profiles[index].buttonPressFadeOutTimeInMs = options.profiles[index].buttonPressFadeOutTimeInMs; - optionsProto.profiles[index].nonPressedSpecialColour = options.profiles[index].nonPressedSpecialColour; } optionsProto.brightness = options.brightness; optionsProto.baseProfileIndex = options.baseProfileIndex; } +static void updateSpecialMoveOptionsProto(const SpecialMoveOptions& options) +{ + SpecialMoveOptions_Proto& optionsProto = Storage::getInstance().getSpecialMoveOptions(); + optionsProto.CurrentProfileIndex = options.CurrentProfileIndex; +} + void Storage::performEnqueuedSaves() { if (animationOptionsSavePending.load()) @@ -65,6 +60,15 @@ void Storage::performEnqueuedSaves() animationOptionsSavePending.store(false); critical_section_exit(&animationOptionsCs); } + + if (specialMoveOptionsSavePending.load()) + { + critical_section_enter_blocking(&specialMoveOptionsCs); + updateSpecialMoveOptionsProto(specialMoveOptionsToSave); + save(); + specialMoveOptionsSavePending.store(false); + critical_section_exit(&specialMoveOptionsCs); + } } void Storage::enqueueAnimationOptionsSave(const AnimationOptions& animationOptions) @@ -80,6 +84,19 @@ void Storage::enqueueAnimationOptionsSave(const AnimationOptions& animationOptio critical_section_exit(&animationOptionsCs); } +void Storage::enqueueSpecialMoveOptionsSave(const SpecialMoveOptions& specialMoveOptions) +{ + const uint32_t crc = CRC32::calculate(&specialMoveOptions); + critical_section_enter_blocking(&specialMoveOptionsCs); + if (crc != specialMoveOptionsCrc) + { + specialMoveOptionsToSave = specialMoveOptions; + specialMoveOptionsCrc = crc; + specialMoveOptionsSavePending.store(true); + } + critical_section_exit(&specialMoveOptionsCs); +} + void Storage::ResetSettings() { EEPROM.reset(); @@ -202,7 +219,7 @@ AnimationOptions AnimationStorage::getAnimationOptions() options.profiles[index].baseNonPressedEffect = (AnimationNonPressedEffects)((int)optionsProto.profiles[index].baseNonPressedEffect); options.profiles[index].basePressedEffect = (AnimationPressedEffects)((int)optionsProto.profiles[index].basePressedEffect); options.profiles[index].baseCycleTime = optionsProto.profiles[index].baseCycleTime; - for(int pinIndex = 0; pinIndex < NUM_BANK0_GPIOS; ++pinIndex) + for(unsigned int pinIndex = 0; pinIndex < NUM_BANK0_GPIOS; ++pinIndex) { options.profiles[index].notPressedStaticColors[pinIndex] = optionsProto.profiles[index].notPressedStaticColors[pinIndex]; options.profiles[index].pressedStaticColors[pinIndex] = optionsProto.profiles[index].pressedStaticColors[pinIndex]; @@ -217,6 +234,41 @@ AnimationOptions AnimationStorage::getAnimationOptions() return options; } +SpecialMoveOptions AnimationStorage::getSpecialMoveOptions() +{ + SpecialMoveOptions options; + const SpecialMoveOptions_Proto& optionsProto = Storage::getInstance().getSpecialMoveOptions(); + + options.NumValidProfiles = optionsProto.profiles_count; + for(unsigned int profileIndex = 0; profileIndex < 4 && profileIndex < options.NumValidProfiles; ++profileIndex) //MAX_SPECIALMOVE_PROFILES from SpecialMoveSystem.hpp + { + options.profiles[profileIndex].NumValidMoves = optionsProto.profiles[profileIndex].AllSpecialMoves_count; + for(unsigned int moveIndex = 0; moveIndex < 20 && moveIndex < options.profiles[profileIndex].NumValidMoves; ++moveIndex) //MAX_SPECIALMOVES from SpecialMoveSystem.hpp + { + options.profiles[profileIndex].AllSpecialMoves[moveIndex].NumRequiredInputCombos = optionsProto.profiles[profileIndex].AllSpecialMoves[moveIndex].RequiredInputCombos_count; + for(unsigned int inputsIndex = 0; inputsIndex < 4 && inputsIndex < options.profiles[profileIndex].AllSpecialMoves[moveIndex].NumRequiredInputCombos; ++inputsIndex) //MAX_SPECIALMOVE_INPUTTYPES_PER_MOVE from SpecialMoveSystem.hpp + { + options.profiles[profileIndex].AllSpecialMoves[moveIndex].RequiredInputCombos[inputsIndex] = (SpecialMoveInputTypes)((int)optionsProto.profiles[profileIndex].AllSpecialMoves[moveIndex].RequiredInputCombos[inputsIndex]); + } + + options.profiles[profileIndex].AllSpecialMoves[moveIndex].NumRequiredTriggerCombos = optionsProto.profiles[profileIndex].AllSpecialMoves[moveIndex].RequiredTriggerCombos_count; + for(unsigned int triggersIndex = 0; triggersIndex < 3 && triggersIndex < options.profiles[profileIndex].AllSpecialMoves[moveIndex].NumRequiredTriggerCombos; ++triggersIndex) //MAX_SPECIALMOVE_TRIGGERS_PER_MOVE from SpecialMoveSystem.hpp + { + options.profiles[profileIndex].AllSpecialMoves[moveIndex].RequiredTriggerCombos[triggersIndex].OptionalParams = optionsProto.profiles[profileIndex].AllSpecialMoves[moveIndex].RequiredTriggerCombos[triggersIndex].OptionalParams; + options.profiles[profileIndex].AllSpecialMoves[moveIndex].RequiredTriggerCombos[triggersIndex].RequiredTriggers = optionsProto.profiles[profileIndex].AllSpecialMoves[moveIndex].RequiredTriggerCombos[triggersIndex].RequiredTriggers; + } + + options.profiles[profileIndex].AllSpecialMoves[moveIndex].Animation = (SpecialMoveEffects)((int)optionsProto.profiles[profileIndex].AllSpecialMoves[moveIndex].Animation); + options.profiles[profileIndex].AllSpecialMoves[moveIndex].bIsChargeMove = optionsProto.profiles[profileIndex].AllSpecialMoves[moveIndex].bIsChargeMove; + } + } + + options.ChargeTimeInMs = optionsProto.ChargeTimeInMs; + options.CurrentProfileIndex = optionsProto.CurrentProfileIndex; + + return options; +} + void AnimationStorage::save() { Storage::getInstance().enqueueAnimationOptionsSave(AnimationStation::options); From 9e3d2326cb897447f5107f3cbf81d328d92a8649 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Fri, 22 Nov 2024 14:42:59 +0000 Subject: [PATCH 008/121] code dump --- lib/AnimationStation/CMakeLists.txt | 1 + lib/AnimationStation/src/Animation.cpp | 8 + lib/AnimationStation/src/Animation.hpp | 5 + lib/AnimationStation/src/AnimationStation.cpp | 38 ++ lib/AnimationStation/src/AnimationStation.hpp | 3 + lib/AnimationStation/src/AnimationStorage.hpp | 2 +- .../src/Effects/SMPulseColour.cpp | 197 +++++++++++ .../src/Effects/SMPulseColour.hpp | 46 +++ .../src/SpecialMoveSystem.cpp | 334 +++++++++++++++++- .../src/SpecialMoveSystem.hpp | 99 ++++-- src/addons/neopicoleds.cpp | 5 +- src/config_utils.cpp | 20 +- src/storagemanager.cpp | 6 +- 13 files changed, 714 insertions(+), 50 deletions(-) create mode 100644 lib/AnimationStation/src/Effects/SMPulseColour.cpp create mode 100644 lib/AnimationStation/src/Effects/SMPulseColour.hpp diff --git a/lib/AnimationStation/CMakeLists.txt b/lib/AnimationStation/CMakeLists.txt index 3a06162a40..cf2785e250 100644 --- a/lib/AnimationStation/CMakeLists.txt +++ b/lib/AnimationStation/CMakeLists.txt @@ -3,6 +3,7 @@ src/Effects/Chase.cpp src/Effects/Rainbow.cpp src/Effects/StaticColor.cpp src/Effects/RandomColor.cpp +src/Effects/SMPulseColour.cpp src/AnimationStation.cpp src/Animation.cpp src/SpecialMoveSystem.cpp diff --git a/lib/AnimationStation/src/Animation.cpp b/lib/AnimationStation/src/Animation.cpp index e9d55642ff..99354d9e12 100644 --- a/lib/AnimationStation/src/Animation.cpp +++ b/lib/AnimationStation/src/Animation.cpp @@ -164,5 +164,13 @@ bool Animation::LightTypeIsForPressedAnimation(LightType Type) if(Type == LightType::LightType_ActionButton) return true; + return false; +} + +bool Animation::LightTypeIsForSpecialMoveAnimation(LightType Type) +{ + if(Type == LightType::LightType_ActionButton || Type == LightType::LightType_Case) + return true; + return false; } \ No newline at end of file diff --git a/lib/AnimationStation/src/Animation.hpp b/lib/AnimationStation/src/Animation.hpp index 8bba354c8a..a0c568886e 100644 --- a/lib/AnimationStation/src/Animation.hpp +++ b/lib/AnimationStation/src/Animation.hpp @@ -120,6 +120,10 @@ class Animation { virtual void ParameterUp() {}; virtual void ParameterDown() {}; + virtual void SetOptionalParams(uint32_t OptionalParams) {}; + + virtual bool IsFinished() { return false; } //ready for delete? Only applicable to special move anims really + protected: //gets current frame time @@ -138,6 +142,7 @@ class Animation { //Type Helpers bool LightTypeIsForNonPressedAnimation(LightType Type); bool LightTypeIsForPressedAnimation(LightType Type); + bool LightTypeIsForSpecialMoveAnimation(LightType Type); //Light data Lights* RGBLights; diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index d8da26092a..259612f889 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -9,6 +9,7 @@ #include "Effects/Rainbow.hpp" #include "Effects/StaticColor.hpp" #include "Effects/RandomColor.hpp" +#include "Effects/SMPulseColour.hpp" #include "SpecialMoveSystem.hpp" #include "AnimationStation.hpp" @@ -168,8 +169,21 @@ void AnimationStation::Animate() return; } + specialMoveSystem.Update(); + baseAnimation->Animate(this->frame); buttonAnimation->Animate(this->frame); + if(specialMoveAnimation) + { + specialMoveAnimation->Animate(this->frame); + //Special moves can end once their animation is over. Clean up if its finished + if(specialMoveAnimation->IsFinished()) + { + delete specialMoveAnimation; + specialMoveAnimation = nullptr; + specialMoveSystem.SetSpecialMoveAnimationOver(); + } + } } void AnimationStation::Clear() @@ -178,6 +192,28 @@ void AnimationStation::Clear() memset(frame, 0, sizeof(frame)); } +void AnimationStation::SetSpecialMoveAnimation(SpecialMoveEffects AnimationToPlay, uint32_t OptionalParams) +{ + switch(AnimationToPlay) + { + case SpecialMoveEffects::SPECIALMOVE_SMEFFECT_WAVE: + //this->specialMoveAnimation = new SMWaveEffect(RGBLights); + break; + + case SpecialMoveEffects::SPECIALMOVE_SMEFFECT_PULSECOLOR: + this->specialMoveAnimation = new SMPulseColour(RGBLights); + break; + + default: + break; + } + + if(this->specialMoveAnimation) + { + this->specialMoveAnimation->SetOptionalParams(OptionalParams); + } +} + int8_t AnimationStation::GetMode() { return this->options.baseProfileIndex; @@ -191,10 +227,12 @@ void AnimationStation::SetMode(int8_t mode) if (this->baseAnimation != nullptr) { delete this->baseAnimation; + this->baseAnimation = nullptr; } if (this->buttonAnimation != nullptr) { delete this->buttonAnimation; + this->buttonAnimation = nullptr; } //turn off all lights diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index b7d178b177..ac061ef776 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -114,6 +114,9 @@ class AnimationStation //passed in user options static void SetOptions(AnimationOptions InOptions); + //special move anim + void SetSpecialMoveAnimation(SpecialMoveEffects AnimationToPlay, uint32_t OptionalParams); + SpecialMoveSystem specialMoveSystem; //Running non-pressed animation diff --git a/lib/AnimationStation/src/AnimationStorage.hpp b/lib/AnimationStation/src/AnimationStorage.hpp index b86472e220..0010c639fb 100644 --- a/lib/AnimationStation/src/AnimationStorage.hpp +++ b/lib/AnimationStation/src/AnimationStorage.hpp @@ -9,7 +9,7 @@ class AnimationStorage public: void save(); AnimationOptions getAnimationOptions(); - SpecialMoveOptions getSpecialMoveOptions(); + void getSpecialMoveOptions(SpecialMoveOptions& options); }; static AnimationStorage AnimationStore; diff --git a/lib/AnimationStation/src/Effects/SMPulseColour.cpp b/lib/AnimationStation/src/Effects/SMPulseColour.cpp new file mode 100644 index 0000000000..4fa170412c --- /dev/null +++ b/lib/AnimationStation/src/Effects/SMPulseColour.cpp @@ -0,0 +1,197 @@ +#include "SMPulseColour.hpp" +#include "SpecialMoveSystem.hpp" + +#define PULSE_PREWAIT_MS 100 +#define PULSE_POSTWAIT_MS 250 + +SMPulseColour::SMPulseColour(Lights& InRGBLights) : Animation(InRGBLights) +{ +} + +void SMPulseColour::SetOptionalParams(uint32_t OptionalParams) +{ + //FORMAT + //4bit - SpecialMoveAnimationColourFadeSpeed - fade in speed + //4bit - SpecialMoveAnimationDuration - Hold colour time + //4bit - SpecialMoveAnimationColourFadeSpeed - fade out speed + //8bit - Animation::colors index - pulse colour + + FadeInSpeed = (SpecialMoveAnimationColourFadeSpeed)(OptionalParams & 0xF); + HoldColourTime = (SpecialMoveAnimationDuration)((OptionalParams >> 4) & 0xF); + FadeOutSpeed = (SpecialMoveAnimationColourFadeSpeed)((OptionalParams >> 8) & 0xF); + ColourIndex = (uint8_t)((OptionalParams >> 16) & 0xFF); + + CurrentState = SMPulseColourState::SM_PULSE_COLOUR_STATE_PREFRAMES; +} + +uint32_t SMPulseColour::GetFadeTimeFromEnum(SpecialMoveAnimationColourFadeSpeed FadeEnum) +{ + //in Ms + uint32_t fadeTime = 0; + switch(FadeEnum) + { + case SpecialMoveAnimationColourFadeSpeed::SPECIALMOVE_COLOURFADE_INSTANT: + { + fadeTime = 0; + } break; + case SpecialMoveAnimationColourFadeSpeed::SPECIALMOVE_COLOURFADE_VERYFAST: + { + fadeTime = 100; + } break; + case SpecialMoveAnimationColourFadeSpeed::SPECIALMOVE_COLOURFADE_FAST: + { + fadeTime = 200; + } break; + case SpecialMoveAnimationColourFadeSpeed::SPECIALMOVE_COLOURFADE_MEDIUM: + { + fadeTime = 500; + } break; + case SpecialMoveAnimationColourFadeSpeed::SPECIALMOVE_COLOURFADE_SLOW: + { + fadeTime = 750; + } break; + case SpecialMoveAnimationColourFadeSpeed::SPECIALMOVE_COLOURFADE_VERYSLOW: + { + fadeTime = 1000; + } break; + default: + { + fadeTime = 0; + } break; + } + + return fadeTime; +} + +uint32_t SMPulseColour::GetHoldTimeFromEnum(SpecialMoveAnimationDuration FadeEnum) +{ + //in Ms + uint32_t holdTime = 0; + switch(FadeEnum) + { + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_VERYSHORT: + { + holdTime = 250; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_SHORT: + { + holdTime = 500; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_MEDIUM: + { + holdTime = 750; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_LONG: + { + holdTime = 1000; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_VERYLONG: + { + holdTime = 1250; + } break; + default: + { + holdTime = 0; + } break; + } + + return holdTime; +} + +bool SMPulseColour::IsFinished() +{ + return CurrentState == SMPulseColourState::SM_PULSE_COLOUR_STATE_FINISHED; +} + +void SMPulseColour::Animate(RGB (&frame)[100]) +{ + UpdateTime(); + + CurrentStateTime += updateTimeInMs; + + float thisFrameFade; + switch(CurrentState) + { + case SMPulseColourState::SM_PULSE_COLOUR_STATE_PREFRAMES: + { + thisFrameFade = 0.0f; + if(CurrentStateTime > PULSE_PREWAIT_MS) + { + CurrentStateTime = 0.0f; + CurrentState = SMPulseColourState::SM_PULSE_COLOUR_STATE_FADEIN; + } + } break; + + case SMPulseColourState::SM_PULSE_COLOUR_STATE_FADEIN: + { + uint32_t fadeInTime = GetFadeTimeFromEnum(FadeInSpeed); + if(CurrentStateTime > fadeInTime) + { + thisFrameFade = 1.0f; + CurrentStateTime = 0.0f; + CurrentState = SMPulseColourState::SM_PULSE_COLOUR_STATE_HOLD; + } + else + { + thisFrameFade = (float)CurrentStateTime / (float)fadeInTime; + } + } break; + + case SMPulseColourState::SM_PULSE_COLOUR_STATE_HOLD: + { + thisFrameFade = 1.0f; + uint32_t holdTime = GetHoldTimeFromEnum(HoldColourTime); + if(CurrentStateTime > holdTime) + { + CurrentStateTime = 0.0f; + CurrentState = SMPulseColourState::SM_PULSE_COLOUR_STATE_FADEOUT; + } + } break; + + case SMPulseColourState::SM_PULSE_COLOUR_STATE_FADEOUT: + { + uint32_t fadeOutTime = GetFadeTimeFromEnum(FadeOutSpeed); + if(CurrentStateTime > fadeOutTime) + { + thisFrameFade = 0.0f; + CurrentStateTime = 0.0f; + CurrentState = SMPulseColourState::SM_PULSE_COLOUR_STATE_POSTFRAMES; + } + else + { + thisFrameFade = 1.0f - ((float)CurrentStateTime / (float)fadeOutTime); + } + } break; + + case SMPulseColourState::SM_PULSE_COLOUR_STATE_POSTFRAMES: + { + thisFrameFade = 0.0f; + if(CurrentStateTime > PULSE_POSTWAIT_MS) + { + CurrentStateTime = 0.0f; + CurrentState = SMPulseColourState::SM_PULSE_COLOUR_STATE_FINISHED; + } + } break; + + case SMPulseColourState::SM_PULSE_COLOUR_STATE_FINISHED: + case SMPulseColourState::SM_PULSE_COLOUR_STATE_NOTSTARTED: + default: + { + thisFrameFade = 0.0f; + } break; + } + + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + if (LightTypeIsForSpecialMoveAnimation(RGBLights->AllLights[lightIndex].Type)) + { + frame[ledIndex] = BlendColor(ColorBlack, colors[ColourIndex], thisFrameFade); + } + } + } +} \ No newline at end of file diff --git a/lib/AnimationStation/src/Effects/SMPulseColour.hpp b/lib/AnimationStation/src/Effects/SMPulseColour.hpp new file mode 100644 index 0000000000..62cb0c7633 --- /dev/null +++ b/lib/AnimationStation/src/Effects/SMPulseColour.hpp @@ -0,0 +1,46 @@ +#ifndef _SM_PULSE_COLOUR_H_ +#define _SM_PULSE_COLOUR_H_ + +#include "../Animation.hpp" +#include +#include +#include +#include "../AnimationStation.hpp" +#include "../SpecialMoveSystem.hpp" + +typedef enum +{ + SM_PULSE_COLOUR_STATE_NOTSTARTED, + SM_PULSE_COLOUR_STATE_PREFRAMES, + SM_PULSE_COLOUR_STATE_FADEIN, + SM_PULSE_COLOUR_STATE_HOLD, + SM_PULSE_COLOUR_STATE_FADEOUT, + SM_PULSE_COLOUR_STATE_POSTFRAMES, + SM_PULSE_COLOUR_STATE_FINISHED, +} SMPulseColourState; + +class SMPulseColour : public Animation { +public: + SMPulseColour(Lights& InRGBLights); + ~SMPulseColour() { }; + + void Animate(RGB (&frame)[100]); + + virtual void SetOptionalParams(uint32_t OptionalParams) override; + virtual bool IsFinished() override; + +protected: + + uint32_t GetFadeTimeFromEnum(SpecialMoveAnimationColourFadeSpeed FadeEnum); + uint32_t GetHoldTimeFromEnum(SpecialMoveAnimationDuration FadeEnum); + + SpecialMoveAnimationColourFadeSpeed FadeInSpeed; + SpecialMoveAnimationDuration HoldColourTime; + SpecialMoveAnimationColourFadeSpeed FadeOutSpeed; + uint8_t ColourIndex; + + uint32_t CurrentStateTime = 0; + SMPulseColourState CurrentState = SMPulseColourState::SM_PULSE_COLOUR_STATE_NOTSTARTED; +}; + +#endif diff --git a/lib/AnimationStation/src/SpecialMoveSystem.cpp b/lib/AnimationStation/src/SpecialMoveSystem.cpp index 6093c5c561..0c8cba6674 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.cpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.cpp @@ -8,40 +8,147 @@ SpecialMoveSystem::SpecialMoveSystem() { } +void SpecialMoveSystem::SetParentAnimationStation(class AnimationStation* InParentAnimationStation) +{ + ParentAnimationStation = InParentAnimationStation; + SwitchHistory.resize(0); +} + void SpecialMoveSystem::Update() { thisFrameTime = get_absolute_time(); //trim history if required - while(SwitchHistory.size() > MAX_INPUT_HISTORY) - SwitchHistory.pop_front(); +// if(SwitchHistory.size() > MAX_INPUT_HISTORY) +// SwitchHistory.resize(MAX_INPUT_HISTORY); + + //Debug + AnimationStation::printfs[0] = std::to_string(SwitchHistory.size()) + " "; + if(SwitchHistory.size() > 0) + { + AnimationStation::printfs[1] = (SwitchHistory[0].bIsHeld ? "true " : "false ") + std::to_string(SwitchHistory[0].ButtonMaskInput) + " "; + AnimationStation::printfs[2] = std::to_string(SwitchHistory[0].ButtonMaskInput) + " " + std::to_string(SwitchHistory[0].DirectionInput); + AnimationStation::printfs[3] = std::to_string(to_us_since_boot(SwitchHistory[0].TimeSet)) + " " + std::to_string(to_us_since_boot(SwitchHistory[0].TimeReleased)); + } + + if(bMoveIsRunning == false) + { + if(TestAllMoves()) + { + bMoveIsRunning = true; + } + } +} + +bool SpecialMoveSystem::TestAllMoves() +{ + //Test Each move + uint32_t numMoves = Options.profiles[Options.CurrentProfileIndex].NumValidMoves; + for(uint32_t moveIndex = 0; moveIndex < numMoves; ++moveIndex) + { + SpecialMoveDescription& thisMove = Options.profiles[Options.CurrentProfileIndex].AllSpecialMoves[moveIndex]; + uint32_t numCombos = thisMove.NumRequiredInputCombos; + uint32_t numTriggers = thisMove.NumRequiredTriggerCombos; + + for(uint32_t comboIndex = 0; comboIndex < numCombos; ++comboIndex) + { + for(uint32_t triggerIndex = 0; triggerIndex < numTriggers; ++triggerIndex) + { + bool bSucceeded = TestForActivatedSpecialMove(&thisMove, comboIndex, triggerIndex); + if(bSucceeded) + { + // Clear the history to prevent retrigger if animation is really quick + ClearHistory(); + if(ParentAnimationStation) + ParentAnimationStation->SetSpecialMoveAnimation(thisMove.Animation, thisMove.RequiredTriggerCombos[triggerIndex].OptionalParams); + SwitchClearAwaitingAllRelease = true; + + return true; + } + } + } + } + + return false; } -void SpecialMoveSystem::SetOptions(SpecialMoveOptions InOptions) +void SpecialMoveSystem::SetDirectionMasks(uint32_t UpMask, uint32_t DownMask, uint32_t LeftMask, uint32_t RightMask) { - Options = InOptions; + SPECIAL_MOVE_DIRECTION_MASK_UP = UpMask; + SPECIAL_MOVE_DIRECTION_MASK_DOWN = DownMask; + SPECIAL_MOVE_DIRECTION_MASK_LEFT = LeftMask; + SPECIAL_MOVE_DIRECTION_MASK_RIGHT = RightMask; +} + +bool SpecialMoveSystem::CheckJoystickDirection(SpecialMoveStickDirection& FoundDirection, SpecialMoveStickDirection TestDirection, uint32_t PressedButtons, uint32_t DirectionOne, uint32_t DirectionTwo) +{ + bool bWasPressed = false; + if(FoundDirection == SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID && ((PressedButtons & (DirectionOne | DirectionTwo)) == (DirectionOne | DirectionTwo))) + { + bWasPressed = true; + FoundDirection = TestDirection; + UpdateHistoryForInput(0, TestDirection, true); + } + else + { + UpdateHistoryForInput(0, TestDirection, false); + } + + return bWasPressed; } void SpecialMoveSystem::HandlePressedButtons(uint32_t pressedButtons) { - //check each input and update history - for(int buttonMask = 1; buttonMask < (1 << 20); buttonMask = buttonMask << 1) + bool bWasAnythingPressed = false; + + //do directions explicitly due to needing to do diagonals + SpecialMoveStickDirection FoundDirection = SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID; + bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_LEFT, SPECIAL_MOVE_DIRECTION_MASK_UP); + bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_RIGHT, SPECIAL_MOVE_DIRECTION_MASK_UP); + bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_LEFT, SPECIAL_MOVE_DIRECTION_MASK_DOWN); + bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_RIGHT, SPECIAL_MOVE_DIRECTION_MASK_DOWN); + bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_UP, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_UP, 0); + bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_DOWN, 0); + bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_LEFT, 0); + bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_RIGHT, 0); + + //check each button input and update history + for(uint32_t buttonMask = 1; buttonMask < (1 << 20); buttonMask = buttonMask << 1) { - UpdateHistoryForInput(buttonMask, (pressedButtons & buttonMask) != 0); + if(buttonMask == SPECIAL_MOVE_DIRECTION_MASK_UP || buttonMask == SPECIAL_MOVE_DIRECTION_MASK_DOWN || buttonMask == SPECIAL_MOVE_DIRECTION_MASK_LEFT || buttonMask == SPECIAL_MOVE_DIRECTION_MASK_RIGHT) + continue; + + bool bIsPressed = (pressedButtons & buttonMask) != 0; + bWasAnythingPressed |= bIsPressed; + UpdateHistoryForInput(buttonMask, SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID, bIsPressed); + } + + //After a special move we need to wait for all buttons to be released before we trigger another or we could potentially chain two together by accident. + //If nothing is pressed this frame then we can remove this block. + if(SwitchClearAwaitingAllRelease) + { + if(bWasAnythingPressed) + { + ClearHistory(); + } + else + { + SwitchClearAwaitingAllRelease = false; + } } } void SpecialMoveSystem::ClearHistory() { - SwitchHistory.clear(); + SwitchHistory.resize(0); } -void SpecialMoveSystem::UpdateHistoryForInput(uint32_t buttonMask, bool bIsPressed) +void SpecialMoveSystem::UpdateHistoryForInput(uint32_t buttonMask, SpecialMoveStickDirection directionHeld, bool bIsPressed) { //search history for recent instance of this button for(unsigned int historyIndex = 0; historyIndex < SwitchHistory.size() ; ++historyIndex) { - if(SwitchHistory[historyIndex].Input == buttonMask) + if(SwitchHistory[historyIndex].ButtonMaskInput == buttonMask && SwitchHistory[historyIndex].DirectionInput == directionHeld) { //found button. now check if its pressed state is correct if(bIsPressed && SwitchHistory[historyIndex].bIsHeld == false) @@ -50,7 +157,8 @@ void SpecialMoveSystem::UpdateHistoryForInput(uint32_t buttonMask, bool bIsPress InputHistory newHistory; newHistory.bIsHeld = true; newHistory.TimeSet = thisFrameTime; - newHistory.Input = buttonMask; + newHistory.ButtonMaskInput = buttonMask; + newHistory.DirectionInput = directionHeld; SwitchHistory.push_front(newHistory); } else if(!bIsPressed && SwitchHistory[historyIndex].bIsHeld) @@ -68,13 +176,213 @@ void SpecialMoveSystem::UpdateHistoryForInput(uint32_t buttonMask, bool bIsPress InputHistory newHistory; newHistory.bIsHeld = true; newHistory.TimeSet = thisFrameTime; - newHistory.Input = buttonMask; + newHistory.ButtonMaskInput = buttonMask; + newHistory.DirectionInput = directionHeld; SwitchHistory.push_front(newHistory); } -void SpecialMoveSystem::TestForActivatedSpecialMove() +void SpecialMoveSystem::GetComboArrayForMove(SpecialMoveInputTypes InputType, std::vector& comboArray) +{ + switch(InputType) + { + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_QUARTER_DOWN_LEFT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DP_RIGHT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DP_SHORTCUT_RIGHT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + } break; + + default: + break; + } +} + +bool SpecialMoveSystem::DoesInputMatch(int HistoryIndex, ComboEntry ComboInput, bool bIsChargeMove) { + if(ComboInput.DirectionInput != SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID) + { + //direction input check + if(bIsChargeMove) + { + //Charge moves allow the surrounding directions to also count + if(ComboInput.DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT) + { + return SwitchHistory[HistoryIndex].DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT || SwitchHistory[HistoryIndex].DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT; + } + else if(ComboInput.DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN) + { + return SwitchHistory[HistoryIndex].DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT || SwitchHistory[HistoryIndex].DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT; + } + else if(ComboInput.DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT) + { + return SwitchHistory[HistoryIndex].DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT || SwitchHistory[HistoryIndex].DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT; + } + else if(ComboInput.DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_UP) + { + return SwitchHistory[HistoryIndex].DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT || SwitchHistory[HistoryIndex].DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT; + } + } + + //other wise just an exact match will do + return SwitchHistory[HistoryIndex].DirectionInput == ComboInput.DirectionInput; + } + + //otherwise its button matching + return SwitchHistory[HistoryIndex].ButtonMaskInput == ComboInput.ButtonMaskInput; +} + +bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* MoveToTestFor, int ComboIndex, int TriggerIndex) +{ + int lastIndexComboInputWasFound = -1; + bool bHasFinishedDoingTriggerButtons = false; + absolute_time_t timeNow = thisFrameTime; + absolute_time_t timeLastInputSet = thisFrameTime; + int numMissed = 0; + bool bAllowMiss = MoveToTestFor->NumRequiredInputCombos >= COMBO_INPUT_COUNT_FOR_ONE_OUT_OF_TWO; + bool bIsChargeCombo = MoveToTestFor->bIsChargeMove; + int64_t OptionsChargeTime = Options.ChargeTimeInMs; + + // Get combo array + std::vector comboArray; + GetComboArrayForMove(MoveToTestFor->RequiredInputCombos[ComboIndex], comboArray); + int moveLength = comboArray.size(); + + // put triggers on the end for easier processing + int triggerLength = 0; + for(int triggerIndex = 0; triggerIndex < 3; ++triggerIndex) + { + int32_t thisTrigger = ((MoveToTestFor->RequiredTriggerCombos[TriggerIndex].RequiredTriggers) >> (4*triggerIndex)) & 0xFF; + if(thisTrigger != 0) + { + triggerLength++; + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID, thisTrigger)); + } + } + + int comboLength = moveLength + triggerLength; + if (comboLength > MAX_INPUT_HISTORY) + comboLength = MAX_INPUT_HISTORY; + + // Moves are specified in normal order. History is newest first. So start from the end of the combo and work back + int triggersFound = 0; + for (int comboIndex = comboLength - 1; comboIndex >= 0; --comboIndex) + { + // First see if the button(s) and the final movement that finish this combo routine have recently been pressed + if (bHasFinishedDoingTriggerButtons == false) + { + // Is this a trigger button + if (triggersFound == triggerLength) + { + bHasFinishedDoingTriggerButtons = true; + //we dont return here as the last movement is also counted as a trigger action. + } + + // In which case, we only care if it was pressed within the last COMBO_TRIGGER_INPUT_TIME_WINDOW + bool bFoundTrigger = false; + for (unsigned int historyIndex = 0; historyIndex < SwitchHistory.size(); ++historyIndex) + { + // are we past the time window? + if (absolute_time_diff_us(SwitchHistory[historyIndex].TimeSet, timeNow) > COMBO_TRIGGER_INPUT_TIME_WINDOW) + { + return false; // we havent managed to find this trigger in time + } + + if (DoesInputMatch(historyIndex, comboArray[comboIndex], bIsChargeCombo)) + { + // we found this trigger. Move onto the next one + bFoundTrigger = true; + triggersFound++; + break; + } + } + + if (bFoundTrigger == false) + { + return false; // we havent managed to find this trigger + } + + // found trigger so move onto next combo entry + continue; + } + + // search history for next input + bool bFoundInput = false; + for (int historyIndex = lastIndexComboInputWasFound + 1; historyIndex < MAX_INPUT_HISTORY; ++historyIndex) + { + if (DoesInputMatch(historyIndex, comboArray[comboIndex], bIsChargeCombo)) + { + bFoundInput = true; + + // Is this the last input and if so is it a charge input as they're special and + if (comboIndex == 0 && bIsChargeCombo) + { + // Its a charge move. In which case, this move must be held for CHARGE_COMBO_INPUT_TIME_WINDOW as well as released within COMBO_INPUT_TIME_WINDOW of the last one + if (SwitchHistory[historyIndex].bIsHeld == false && absolute_time_diff_us(SwitchHistory[historyIndex].TimeReleased, timeLastInputSet) < COMBO_INPUT_TIME_WINDOW && absolute_time_diff_us(SwitchHistory[historyIndex].TimeSet, SwitchHistory[historyIndex].TimeReleased) > OptionsChargeTime) + { + // Clear the history to prevent retrigger if animation is really quick + ClearHistory(); + return true; // success + } + else + { + return false; // released too early + } + } + + // regular input + absolute_time_t timeToUse = SwitchHistory[historyIndex].bIsHeld ? SwitchHistory[historyIndex].TimeSet : SwitchHistory[historyIndex].TimeReleased; + if (absolute_time_diff_us(timeToUse, timeLastInputSet) > COMBO_INPUT_TIME_WINDOW) + { + if (bAllowMiss) + { + // too long between inputs on this one. but might be ok to continue if this was an older input in the history + numMissed++; + if (numMissed == 2) + return false; // too many missing + } + else + return false; // too long between inputs + } + + // Store this time and location and move onto next input + timeLastInputSet = SwitchHistory[historyIndex].TimeSet; + lastIndexComboInputWasFound = historyIndex; + numMissed = 0; + + break; + } + } + + if (bFoundInput == false) + { + if (bAllowMiss) + { + // didnt find this one. but might be ok to continue + numMissed++; + if (numMissed == 2) + return false; // too many missing + } + else + return false; // we havent found the input at all + } + } + + // if we get here we've found every single input! Combo passed + return true; } void SpecialMoveSystem::UpdateRunningSpecialMove() diff --git a/lib/AnimationStation/src/SpecialMoveSystem.hpp b/lib/AnimationStation/src/SpecialMoveSystem.hpp index 3ce46b6263..1fe131c9a3 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.hpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.hpp @@ -16,6 +16,10 @@ #define MAX_SPECIALMOVE_TRIGGERS_PER_MOVE 3 #define MAX_INPUT_HISTORY 100 +#define COMBO_INPUT_TIME_WINDOW 200 //Maximum time between combo movements that arent a charge +#define COMBO_TRIGGER_INPUT_TIME_WINDOW 125 //Maximum time between combined button inputs eg PP, PPP, KK or PK etc +#define COMBO_INPUT_COUNT_FOR_ONE_OUT_OF_TWO 7 //if the combo input is 7 or more moves then the input system will allow you to succeed if you dont miss 2 in a row window. eg LDRU would be fine for a SPD + //List of specialMove animation typedef enum { @@ -23,7 +27,6 @@ typedef enum SPECIALMOVE_SMEFFECT_SUPERWAVE, SPECIALMOVE_SMEFFECT_PULSECOLOR, SPECIALMOVE_SMEFFECT_CIRCLECOLOR, - SPECIALMOVE_SMEFFECT_FLASHCOLOR, SPECIALMOVE_SMEFFECT_KNIGHTRIDER, SPECIALMOVE_SMEFFECT_RANDOMFLASH, } SpecialMoveEffects; @@ -31,11 +34,24 @@ typedef enum // SpecialMove animation Duration Modifier typedef enum { - SPECIALMOVE_DURATION_FAST, + SPECIALMOVE_DURATION_VERYSHORT, + SPECIALMOVE_DURATION_SHORT, SPECIALMOVE_DURATION_MEDIUM, SPECIALMOVE_DURATION_LONG, + SPECIALMOVE_DURATION_VERYLONG, } SpecialMoveAnimationDuration; +// SpecialMove colour fade Modifier +typedef enum +{ + SPECIALMOVE_COLOURFADE_INSTANT, + SPECIALMOVE_COLOURFADE_VERYFAST, + SPECIALMOVE_COLOURFADE_FAST, + SPECIALMOVE_COLOURFADE_MEDIUM, + SPECIALMOVE_COLOURFADE_SLOW, + SPECIALMOVE_COLOURFADE_VERYSLOW, +} SpecialMoveAnimationColourFadeSpeed; + // SpecialMove animation Direction Modifier typedef enum { @@ -56,10 +72,38 @@ typedef enum SPECIALMOVE_INPUT_DP_SHORTCUT_LEFT, } SpecialMoveInputTypes; +// SpecialMove joystick directions +typedef enum +{ + SPECIALMOVE_STICK_INVALID, + SPECIALMOVE_STICK_UP, + SPECIALMOVE_STICK_UPLEFT, + SPECIALMOVE_STICK_UPRIGHT, + SPECIALMOVE_STICK_LEFT, + SPECIALMOVE_STICK_DOWNLEFT, + SPECIALMOVE_STICK_DOWN, + SPECIALMOVE_STICK_DOWNRIGHT, + SPECIALMOVE_STICK_RIGHT, +} SpecialMoveStickDirection; + +struct ComboEntry +{ + SpecialMoveStickDirection DirectionInput; + uint32_t ButtonMaskInput; //button mask + + ComboEntry(SpecialMoveStickDirection InDirection, uint32_t InButton) + { + DirectionInput = InDirection; + ButtonMaskInput = InButton; + } +}; + // Input History structure. struct InputHistory { - uint32_t Input; //button mask + SpecialMoveStickDirection DirectionInput; + uint32_t ButtonMaskInput; //button mask + absolute_time_t TimeSet; absolute_time_t TimeReleased; bool bIsHeld; @@ -67,33 +111,34 @@ struct InputHistory struct __attribute__ ((__packed__)) SpecialMoveInputTriggers { - uint32_t OptionalParams; //6 4byte params packed in here. Unique per effect type. See each effect for details - uint8_t RequiredTriggers; //buttonmasks + uint32_t OptionalParams = 0; //6 4byte params packed in here. Unique per effect type. See each effect for details + uint32_t RequiredTriggers = 0; //buttonmasks }; struct __attribute__ ((__packed__)) SpecialMoveDescription { - uint32_t NumRequiredInputCombos; + uint32_t NumRequiredInputCombos = 0; SpecialMoveInputTypes RequiredInputCombos[MAX_SPECIALMOVE_INPUTTYPES_PER_MOVE]; - uint32_t NumRequiredTriggerCombos; + uint32_t NumRequiredTriggerCombos = 0; SpecialMoveInputTriggers RequiredTriggerCombos[MAX_SPECIALMOVE_TRIGGERCOMBOS]; SpecialMoveEffects Animation; - bool bIsChargeMove; + bool bIsChargeMove = false; }; struct __attribute__ ((__packed__)) SpecialMoveProfile { - uint32_t NumValidMoves; + uint32_t NumValidMoves = 0; SpecialMoveDescription AllSpecialMoves[MAX_SPECIALMOVES]; }; struct __attribute__ ((__packed__)) SpecialMoveOptions { - uint32_t NumValidProfiles; + uint32_t checksum; + uint32_t NumValidProfiles = 0; SpecialMoveProfile profiles[MAX_SPECIALMOVE_PROFILES]; - uint32_t ChargeTimeInMs; - uint8_t CurrentProfileIndex; + uint32_t ChargeTimeInMs = 0; + uint8_t CurrentProfileIndex = 0; }; class SpecialMoveSystem { @@ -105,20 +150,31 @@ class SpecialMoveSystem { void Update(); //passed in user options - static void SetOptions(SpecialMoveOptions InOptions); + void SetDirectionMasks(uint32_t UpMask, uint32_t DownMask, uint32_t LeftMask, uint32_t RightMask); //What buttons (logical ones) are pressed this frame void HandlePressedButtons(uint32_t pressedButtons); + void SetParentAnimationStation(class AnimationStation* InParentAnimationStation); + void SetSpecialMoveAnimationOver() { bMoveIsRunning = false; } + + static SpecialMoveOptions Options; + protected: void ClearHistory(); - void UpdateHistoryForInput(uint32_t buttonMask, bool bIsPressed); + void UpdateHistoryForInput(uint32_t buttonMask, SpecialMoveStickDirection directionHeld, bool bIsPressed); + bool CheckJoystickDirection(SpecialMoveStickDirection& FoundDirection, SpecialMoveStickDirection TestDirection, uint32_t PressedButtons, uint32_t DirectionOne, uint32_t DirectionTwo); + bool DoesInputMatch(int HistoryIndex, ComboEntry ComboInput, bool bIsChargeMove); - void TestForActivatedSpecialMove(); + bool TestAllMoves(); + bool TestForActivatedSpecialMove(SpecialMoveDescription* MoveToTestFor, int ComboIndex, int TriggerIndex); void UpdateRunningSpecialMove(); + void StartMoveAnimation(SpecialMoveEffects AnimationToPlay, uint32_t OptionalParams); - static SpecialMoveOptions Options; + void GetComboArrayForMove(SpecialMoveInputTypes InputType, std::vector& comboArray); + + class AnimationStation* ParentAnimationStation; //history of all buttons/directions held. (newest entries first) std::deque SwitchHistory; @@ -126,11 +182,14 @@ class SpecialMoveSystem { // after a special move we need to wait for all inputs to be released before continuing to avoid repeats bool SwitchClearAwaitingAllRelease = false; - //Current running Special Move indexes - int RunnningSpecialMoveIndex; - int RunnningSpecialMoveAnimationIndex; - absolute_time_t thisFrameTime = nil_time; + + uint32_t SPECIAL_MOVE_DIRECTION_MASK_UP; + uint32_t SPECIAL_MOVE_DIRECTION_MASK_DOWN; + uint32_t SPECIAL_MOVE_DIRECTION_MASK_LEFT; + uint32_t SPECIAL_MOVE_DIRECTION_MASK_RIGHT; + + bool bMoveIsRunning = false; }; #endif diff --git a/src/addons/neopicoleds.cpp b/src/addons/neopicoleds.cpp index 6a1f6b567f..6de0ba47fd 100644 --- a/src/addons/neopicoleds.cpp +++ b/src/addons/neopicoleds.cpp @@ -598,8 +598,9 @@ void NeoPicoLEDAddon::configureLEDs() AnimStation.ConfigureBrightness(ledOptions.brightnessMaximum, ledOptions.brightnessSteps); AnimationOptions animationOptions = AnimationStore.getAnimationOptions(); AnimStation.SetOptions(animationOptions); - SpecialMoveOptions specialMoveOptions = AnimationStore.getSpecialMoveOptions(); - AnimStation.specialMoveSystem.SetOptions(specialMoveOptions); + AnimationStore.getSpecialMoveOptions(AnimStation.specialMoveSystem.Options); + AnimStation.specialMoveSystem.SetParentAnimationStation(&AnimStation); + AnimStation.specialMoveSystem.SetDirectionMasks(GAMEPAD_MASK_DU, GAMEPAD_MASK_DD, GAMEPAD_MASK_DL, GAMEPAD_MASK_DR); AnimStation.SetLights(RGBLights); AnimStation.SetMode(as.options.baseProfileIndex); } diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 7163169bfa..a62ac9f8ad 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -495,18 +495,18 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1], bIsChargeMove, false); INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1], Animation, SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_PULSECOLOR); - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos_count = 2; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_RIGHT; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[1] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_SHORTCUT_RIGHT; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], RequiredTriggers, GAMEPAD_MASK_B3); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], OptionalParams, 2 + (1 << 8)); //fast //colour white + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos_count = 2; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_RIGHT; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos[1] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_SHORTCUT_RIGHT; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos_count = 3; + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[0], RequiredTriggers, GAMEPAD_MASK_B3); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[0], OptionalParams, 0 + (3 << 4) + (0 << 8) + (1 << 16)); //instant in //long duration //instant out //colour white - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], RequiredTriggers, GAMEPAD_MASK_B4); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], OptionalParams, 1 + (1 << 8)); //med //colour white + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[1], RequiredTriggers, GAMEPAD_MASK_B4); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[1], OptionalParams, 3 + (2 << 4) + (3 << 8) + (1 << 16)); //med in //med duration //med out //colour white - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], RequiredTriggers, GAMEPAD_MASK_R1); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], OptionalParams, 0 + (1 << 8)); //slow //colour white + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[2], RequiredTriggers, GAMEPAD_MASK_R1); + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[2], OptionalParams, 5 + (1 << 4) + (5 << 8) + (1 << 16)); //v.slow in //short duration //v.slow out //colour white } if(config.specialMoveOptions.profiles_count == 0) diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index d0a5d3212f..e873ec4b69 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -234,9 +234,8 @@ AnimationOptions AnimationStorage::getAnimationOptions() return options; } -SpecialMoveOptions AnimationStorage::getSpecialMoveOptions() +void AnimationStorage::getSpecialMoveOptions(SpecialMoveOptions& options) { - SpecialMoveOptions options; const SpecialMoveOptions_Proto& optionsProto = Storage::getInstance().getSpecialMoveOptions(); options.NumValidProfiles = optionsProto.profiles_count; @@ -265,11 +264,10 @@ SpecialMoveOptions AnimationStorage::getSpecialMoveOptions() options.ChargeTimeInMs = optionsProto.ChargeTimeInMs; options.CurrentProfileIndex = optionsProto.CurrentProfileIndex; - - return options; } void AnimationStorage::save() { Storage::getInstance().enqueueAnimationOptionsSave(AnimationStation::options); + Storage::getInstance().enqueueSpecialMoveOptionsSave(SpecialMoveSystem::Options); } From fef7e78ce91d9a3798a3524d35c55696c1a992a5 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Sat, 23 Nov 2024 00:07:18 +0000 Subject: [PATCH 009/121] code dump --- headers/addons/neopicoleds.h | 2 +- lib/AnimationStation/src/AnimationStorage.hpp | 2 +- .../src/SpecialMoveSystem.cpp | 83 ++++++++++++------- .../src/SpecialMoveSystem.hpp | 3 +- src/addons/neopicoleds.cpp | 8 +- src/storagemanager.cpp | 5 +- 6 files changed, 61 insertions(+), 42 deletions(-) diff --git a/headers/addons/neopicoleds.h b/headers/addons/neopicoleds.h index 840f7c856e..6a5540c1ed 100644 --- a/headers/addons/neopicoleds.h +++ b/headers/addons/neopicoleds.h @@ -204,7 +204,7 @@ class NeoPicoLEDAddon : public GPAddon { uint8_t setupButtonPositions(); //New co-ordinated setup - void GenerateLights(LEDOptions_lightData_t InLightData, uint32_t InLightDataSize); + void GenerateLights(const LEDOptions_lightData_t& InLightData, uint32_t InLightDataSize); //Controls the actual lights on the board. Writes out state each frame NeoPico *neopico; diff --git a/lib/AnimationStation/src/AnimationStorage.hpp b/lib/AnimationStation/src/AnimationStorage.hpp index 0010c639fb..1b1fac207e 100644 --- a/lib/AnimationStation/src/AnimationStorage.hpp +++ b/lib/AnimationStation/src/AnimationStorage.hpp @@ -8,7 +8,7 @@ class AnimationStorage { public: void save(); - AnimationOptions getAnimationOptions(); + void getAnimationOptions(AnimationOptions& options); void getSpecialMoveOptions(SpecialMoveOptions& options); }; diff --git a/lib/AnimationStation/src/SpecialMoveSystem.cpp b/lib/AnimationStation/src/SpecialMoveSystem.cpp index 0c8cba6674..b0f361b2be 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.cpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.cpp @@ -11,26 +11,13 @@ SpecialMoveSystem::SpecialMoveSystem() void SpecialMoveSystem::SetParentAnimationStation(class AnimationStation* InParentAnimationStation) { ParentAnimationStation = InParentAnimationStation; - SwitchHistory.resize(0); + ClearHistory(); } void SpecialMoveSystem::Update() { thisFrameTime = get_absolute_time(); - //trim history if required -// if(SwitchHistory.size() > MAX_INPUT_HISTORY) -// SwitchHistory.resize(MAX_INPUT_HISTORY); - - //Debug - AnimationStation::printfs[0] = std::to_string(SwitchHistory.size()) + " "; - if(SwitchHistory.size() > 0) - { - AnimationStation::printfs[1] = (SwitchHistory[0].bIsHeld ? "true " : "false ") + std::to_string(SwitchHistory[0].ButtonMaskInput) + " "; - AnimationStation::printfs[2] = std::to_string(SwitchHistory[0].ButtonMaskInput) + " " + std::to_string(SwitchHistory[0].DirectionInput); - AnimationStation::printfs[3] = std::to_string(to_us_since_boot(SwitchHistory[0].TimeSet)) + " " + std::to_string(to_us_since_boot(SwitchHistory[0].TimeReleased)); - } - if(bMoveIsRunning == false) { if(TestAllMoves()) @@ -97,12 +84,24 @@ bool SpecialMoveSystem::CheckJoystickDirection(SpecialMoveStickDirection& FoundD return bWasPressed; } +static uint64_t count = 0; +static bool halt = false; + void SpecialMoveSystem::HandlePressedButtons(uint32_t pressedButtons) { bool bWasAnythingPressed = false; + uint32_t oldButtonMask = SwitchHistory[0].ButtonMaskInput; + count++; + + if(halt) + { + while(true) + {} + } + //do directions explicitly due to needing to do diagonals - SpecialMoveStickDirection FoundDirection = SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID; +/* SpecialMoveStickDirection FoundDirection = SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID; bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_LEFT, SPECIAL_MOVE_DIRECTION_MASK_UP); bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_RIGHT, SPECIAL_MOVE_DIRECTION_MASK_UP); bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_LEFT, SPECIAL_MOVE_DIRECTION_MASK_DOWN); @@ -110,7 +109,7 @@ void SpecialMoveSystem::HandlePressedButtons(uint32_t pressedButtons) bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_UP, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_UP, 0); bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_DOWN, 0); bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_LEFT, 0); - bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_RIGHT, 0); + bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_RIGHT, 0);*/ //check each button input and update history for(uint32_t buttonMask = 1; buttonMask < (1 << 20); buttonMask = buttonMask << 1) @@ -123,6 +122,14 @@ void SpecialMoveSystem::HandlePressedButtons(uint32_t pressedButtons) UpdateHistoryForInput(buttonMask, SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID, bIsPressed); } + if(count > 300 && oldButtonMask <= 32 && SwitchHistory[0].ButtonMaskInput > 32) + { + halt = true; + } + AnimationStation::printfs[1] = std::to_string(pressedButtons) + " " + std::to_string(oldButtonMask); + AnimationStation::printfs[2] = std::to_string(SwitchHistory[0].ButtonMaskInput) + " " + std::to_string(SwitchHistory[0].DirectionInput); + AnimationStation::printfs[0] = std::to_string(count) + " "; + //After a special move we need to wait for all buttons to be released before we trigger another or we could potentially chain two together by accident. //If nothing is pressed this frame then we can remove this block. if(SwitchClearAwaitingAllRelease) @@ -140,13 +147,37 @@ void SpecialMoveSystem::HandlePressedButtons(uint32_t pressedButtons) void SpecialMoveSystem::ClearHistory() { - SwitchHistory.resize(0); + for(int historyIndex = 0; historyIndex < MAX_INPUT_HISTORY; ++historyIndex) + { + SwitchHistory[historyIndex].ButtonMaskInput = 0; + SwitchHistory[historyIndex].DirectionInput = SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID; + } +} + +void SpecialMoveSystem::SwitchHistoryCreateNew(uint32_t buttonMask, SpecialMoveStickDirection directionHeld) +{ + //Shift all entries up by 1 + for(int historyIndex = (MAX_INPUT_HISTORY-1) ; historyIndex > 0; --historyIndex) + { + SwitchHistory[historyIndex].ButtonMaskInput = SwitchHistory[historyIndex-1].ButtonMaskInput; + SwitchHistory[historyIndex].DirectionInput = SwitchHistory[historyIndex-1].DirectionInput; + SwitchHistory[historyIndex].TimeSet = SwitchHistory[historyIndex-1].TimeSet; + SwitchHistory[historyIndex].TimeReleased = SwitchHistory[historyIndex-1].TimeReleased; + SwitchHistory[historyIndex].bIsHeld = SwitchHistory[historyIndex-1].bIsHeld; + } + + //Stick new input onto front of array and set the held start time + SwitchHistory[0].ButtonMaskInput = buttonMask; + SwitchHistory[0].DirectionInput = directionHeld; + SwitchHistory[0].TimeSet = thisFrameTime; + //SwitchHistory[0].TimeReleased = (absolute_time_t)0; + SwitchHistory[0].bIsHeld = true; } void SpecialMoveSystem::UpdateHistoryForInput(uint32_t buttonMask, SpecialMoveStickDirection directionHeld, bool bIsPressed) { //search history for recent instance of this button - for(unsigned int historyIndex = 0; historyIndex < SwitchHistory.size() ; ++historyIndex) + for(unsigned int historyIndex = 0; historyIndex < MAX_INPUT_HISTORY; ++historyIndex) { if(SwitchHistory[historyIndex].ButtonMaskInput == buttonMask && SwitchHistory[historyIndex].DirectionInput == directionHeld) { @@ -154,12 +185,7 @@ void SpecialMoveSystem::UpdateHistoryForInput(uint32_t buttonMask, SpecialMoveSt if(bIsPressed && SwitchHistory[historyIndex].bIsHeld == false) { //create new entry at start of history array - InputHistory newHistory; - newHistory.bIsHeld = true; - newHistory.TimeSet = thisFrameTime; - newHistory.ButtonMaskInput = buttonMask; - newHistory.DirectionInput = directionHeld; - SwitchHistory.push_front(newHistory); + SwitchHistoryCreateNew(buttonMask, directionHeld); } else if(!bIsPressed && SwitchHistory[historyIndex].bIsHeld) { @@ -173,12 +199,7 @@ void SpecialMoveSystem::UpdateHistoryForInput(uint32_t buttonMask, SpecialMoveSt } //no previous entry found. Add new one - InputHistory newHistory; - newHistory.bIsHeld = true; - newHistory.TimeSet = thisFrameTime; - newHistory.ButtonMaskInput = buttonMask; - newHistory.DirectionInput = directionHeld; - SwitchHistory.push_front(newHistory); + SwitchHistoryCreateNew(buttonMask, directionHeld); } void SpecialMoveSystem::GetComboArrayForMove(SpecialMoveInputTypes InputType, std::vector& comboArray) @@ -292,7 +313,7 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move // In which case, we only care if it was pressed within the last COMBO_TRIGGER_INPUT_TIME_WINDOW bool bFoundTrigger = false; - for (unsigned int historyIndex = 0; historyIndex < SwitchHistory.size(); ++historyIndex) + for (unsigned int historyIndex = 0; historyIndex < MAX_INPUT_HISTORY; ++historyIndex) { // are we past the time window? if (absolute_time_diff_us(SwitchHistory[historyIndex].TimeSet, timeNow) > COMBO_TRIGGER_INPUT_TIME_WINDOW) diff --git a/lib/AnimationStation/src/SpecialMoveSystem.hpp b/lib/AnimationStation/src/SpecialMoveSystem.hpp index 1fe131c9a3..20472149e2 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.hpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.hpp @@ -166,6 +166,7 @@ class SpecialMoveSystem { void UpdateHistoryForInput(uint32_t buttonMask, SpecialMoveStickDirection directionHeld, bool bIsPressed); bool CheckJoystickDirection(SpecialMoveStickDirection& FoundDirection, SpecialMoveStickDirection TestDirection, uint32_t PressedButtons, uint32_t DirectionOne, uint32_t DirectionTwo); bool DoesInputMatch(int HistoryIndex, ComboEntry ComboInput, bool bIsChargeMove); + void SwitchHistoryCreateNew(uint32_t buttonMask, SpecialMoveStickDirection directionHeld); bool TestAllMoves(); bool TestForActivatedSpecialMove(SpecialMoveDescription* MoveToTestFor, int ComboIndex, int TriggerIndex); @@ -177,7 +178,7 @@ class SpecialMoveSystem { class AnimationStation* ParentAnimationStation; //history of all buttons/directions held. (newest entries first) - std::deque SwitchHistory; + InputHistory SwitchHistory[MAX_INPUT_HISTORY]; // after a special move we need to wait for all inputs to be released before continuing to avoid repeats bool SwitchClearAwaitingAllRelease = false; diff --git a/src/addons/neopicoleds.cpp b/src/addons/neopicoleds.cpp index 6de0ba47fd..a892d8e1e0 100644 --- a/src/addons/neopicoleds.cpp +++ b/src/addons/neopicoleds.cpp @@ -574,7 +574,7 @@ void NeoPicoLEDAddon::configureLEDs() const LEDOptions& ledOptions = Storage::getInstance().getLedOptions(); //New grid based setup - LEDOptions_lightData_t lightData = ledOptions.lightData; + LEDOptions_lightData_t lightData = ledOptions.lightData; //todo make this const ref if we remove the legacy version int32_t lightDataSize = ledOptions.lightDataSize; if(lightDataSize == 0) { @@ -596,9 +596,9 @@ void NeoPicoLEDAddon::configureLEDs() Animation::format = static_cast(ledOptions.ledFormat); AnimStation.ConfigureBrightness(ledOptions.brightnessMaximum, ledOptions.brightnessSteps); - AnimationOptions animationOptions = AnimationStore.getAnimationOptions(); - AnimStation.SetOptions(animationOptions); + AnimationStore.getAnimationOptions(AnimStation.options); AnimationStore.getSpecialMoveOptions(AnimStation.specialMoveSystem.Options); + AnimStation.SetBrightness(AnimStation.options.brightness); AnimStation.specialMoveSystem.SetParentAnimationStation(&AnimStation); AnimStation.specialMoveSystem.SetDirectionMasks(GAMEPAD_MASK_DU, GAMEPAD_MASK_DD, GAMEPAD_MASK_DL, GAMEPAD_MASK_DR); AnimStation.SetLights(RGBLights); @@ -609,7 +609,7 @@ void NeoPicoLEDAddon::configureLEDs() //New RGBLight setups //////////////////////////////////////////// -void NeoPicoLEDAddon::GenerateLights(LEDOptions_lightData_t InLightData, uint32_t InLightDataSize) +void NeoPicoLEDAddon::GenerateLights(const LEDOptions_lightData_t& InLightData, uint32_t InLightDataSize) { std::vector generatedLights; for(int index = 0; index < (int)InLightDataSize; ++index) diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index e873ec4b69..55b574e5bb 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -207,9 +207,8 @@ Gamepad * Storage::GetProcessedGamepad() } /* Animation stuffs */ -AnimationOptions AnimationStorage::getAnimationOptions() +void AnimationStorage::getAnimationOptions(AnimationOptions& options) { - AnimationOptions options; const AnimationOptions_Proto& optionsProto = Storage::getInstance().getAnimationOptions(); options.checksum = 0; @@ -230,8 +229,6 @@ AnimationOptions AnimationStorage::getAnimationOptions() } options.brightness = std::min(optionsProto.brightness, 255); options.baseProfileIndex = std::min(optionsProto.baseProfileIndex, 255); - - return options; } void AnimationStorage::getSpecialMoveOptions(SpecialMoveOptions& options) From 96c516ccda87096b5ae8967c0e35dd6721893fd3 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Mon, 25 Nov 2024 23:11:11 +0000 Subject: [PATCH 010/121] Wave animation --- lib/AnimationStation/CMakeLists.txt | 1 + lib/AnimationStation/src/AnimationStation.cpp | 3 +- .../src/Effects/SMPulseColour.cpp | 14 +- lib/AnimationStation/src/Effects/SMWave.cpp | 265 ++++++++++++++++++ lib/AnimationStation/src/Effects/SMWave.hpp | 56 ++++ .../src/SpecialMoveSystem.cpp | 102 ++++--- .../src/SpecialMoveSystem.hpp | 17 +- src/config_utils.cpp | 6 +- 8 files changed, 405 insertions(+), 59 deletions(-) create mode 100644 lib/AnimationStation/src/Effects/SMWave.cpp create mode 100644 lib/AnimationStation/src/Effects/SMWave.hpp diff --git a/lib/AnimationStation/CMakeLists.txt b/lib/AnimationStation/CMakeLists.txt index cf2785e250..657b3af429 100644 --- a/lib/AnimationStation/CMakeLists.txt +++ b/lib/AnimationStation/CMakeLists.txt @@ -4,6 +4,7 @@ src/Effects/Rainbow.cpp src/Effects/StaticColor.cpp src/Effects/RandomColor.cpp src/Effects/SMPulseColour.cpp +src/Effects/SMWave.cpp src/AnimationStation.cpp src/Animation.cpp src/SpecialMoveSystem.cpp diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index 259612f889..de5823bdd3 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -10,6 +10,7 @@ #include "Effects/StaticColor.hpp" #include "Effects/RandomColor.hpp" #include "Effects/SMPulseColour.hpp" +#include "Effects/SMWave.hpp" #include "SpecialMoveSystem.hpp" #include "AnimationStation.hpp" @@ -197,7 +198,7 @@ void AnimationStation::SetSpecialMoveAnimation(SpecialMoveEffects AnimationToPla switch(AnimationToPlay) { case SpecialMoveEffects::SPECIALMOVE_SMEFFECT_WAVE: - //this->specialMoveAnimation = new SMWaveEffect(RGBLights); + this->specialMoveAnimation = new SMWave(RGBLights); break; case SpecialMoveEffects::SPECIALMOVE_SMEFFECT_PULSECOLOR: diff --git a/lib/AnimationStation/src/Effects/SMPulseColour.cpp b/lib/AnimationStation/src/Effects/SMPulseColour.cpp index 4fa170412c..49bd7b2610 100644 --- a/lib/AnimationStation/src/Effects/SMPulseColour.cpp +++ b/lib/AnimationStation/src/Effects/SMPulseColour.cpp @@ -1,8 +1,8 @@ #include "SMPulseColour.hpp" #include "SpecialMoveSystem.hpp" -#define PULSE_PREWAIT_MS 100 -#define PULSE_POSTWAIT_MS 250 +#define PULSE_PREWAIT_MS 150 +#define PULSE_POSTWAIT_MS 150 SMPulseColour::SMPulseColour(Lights& InRGBLights) : Animation(InRGBLights) { @@ -183,12 +183,12 @@ void SMPulseColour::Animate(RGB (&frame)[100]) for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) { - uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; - uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; - - for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + if (LightTypeIsForSpecialMoveAnimation(RGBLights->AllLights[lightIndex].Type)) { - if (LightTypeIsForSpecialMoveAnimation(RGBLights->AllLights[lightIndex].Type)) + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { frame[ledIndex] = BlendColor(ColorBlack, colors[ColourIndex], thisFrameFade); } diff --git a/lib/AnimationStation/src/Effects/SMWave.cpp b/lib/AnimationStation/src/Effects/SMWave.cpp new file mode 100644 index 0000000000..44057e345f --- /dev/null +++ b/lib/AnimationStation/src/Effects/SMWave.cpp @@ -0,0 +1,265 @@ +#include "SMWave.hpp" +#include "SpecialMoveSystem.hpp" + +#define WAVE_PREWAIT_MS 150 +#define WAVE_POSTWAIT_MS 150 +#define WAVE_OFFSET_PER_COORD 0.1f +#define WAVE_LENGTH 1.0f +#define WAVE_HOLDLOOPS 2 + +SMWave::SMWave(Lights& InRGBLights) : Animation(InRGBLights) +{ + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + if(LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type) == false) + continue; + if(RGBLights->AllLights[lightIndex].Position.XPosition > MaxXCoord) + MaxXCoord = RGBLights->AllLights[lightIndex].Position.XPosition; + if(RGBLights->AllLights[lightIndex].Position.YPosition > MaxYCoord) + MaxYCoord = RGBLights->AllLights[lightIndex].Position.YPosition; + + if(lightIndex == 0 || RGBLights->AllLights[lightIndex].Position.XPosition < MinXCoord) + MinXCoord = RGBLights->AllLights[lightIndex].Position.XPosition; + if(lightIndex == 0 || RGBLights->AllLights[lightIndex].Position.YPosition < MinYCoord) + MinYCoord = RGBLights->AllLights[lightIndex].Position.YPosition; + } + + MidXCoord = MinXCoord + ((MaxXCoord - MinXCoord) / 2); + MidYCoord = MinYCoord + ((MaxYCoord - MinYCoord) / 2); +} + +void SMWave::SetOptionalParams(uint32_t OptionalParams) +{ + //FORMAT + //4bit - SpecialMoveAnimationDirection - Wave direction + //4bit - SpecialMoveAnimationDuration - Wave animation time + //4bit - int - Num wave loops + //4bit - SpecialMoveAnimationDivider - divides lights into sections and only plays on that section + //8bit - Animation::colors index - wave colour + + WaveDirection = (SpecialMoveAnimationDirection)(OptionalParams & 0xF); + WaveSpeed = (SpecialMoveAnimationDuration)((OptionalParams >> 4) & 0xF); + WaveLoops = ((OptionalParams >> 8) & 0xF); + WaveDivider = (SpecialMoveAnimationDivider)((OptionalParams >> 12) & 0xF); + ColourIndex = (uint8_t)((OptionalParams >> 16) & 0xFF); + +WaveLoops = 5; +WaveDirection = SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_RIGHT; + + CurrentState = SMWaveState::SM_WAVE_STATE_PREFRAMES; +} + +float SMWave::GetWaveSpeedFromEnum() +{ + //rads per frame + float speed = 0; + switch(WaveSpeed) + { + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_VERYSHORT: + { + speed = 0.1; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_SHORT: + { + speed = 0.15; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_MEDIUM: + { + speed = 0.2; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_LONG: + { + speed = 0.25; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_VERYLONG: + { + speed = 0.3; + } break; + default: + { + speed = 0.1; + } break; + } + + return speed; +} + +bool SMWave::IsFinished() +{ + return CurrentState == SMWaveState::SM_WAVE_STATE_FINISHED; +} + +void SMWave::Animate(RGB (&frame)[100]) +{ + UpdateTime(); + + CurrentStateTime += updateTimeInMs; + + switch(CurrentState) + { + case SMWaveState::SM_WAVE_STATE_PREFRAMES: + { + UpdateWave(frame); + if(CurrentStateTime > WAVE_PREWAIT_MS) + { + CurrentStateTime = 0.0f; + CurrentState = SMWaveState::SM_WAVE_STATE_RUNNING; + } + } break; + + case SMWaveState::SM_WAVE_STATE_RUNNING: + { + if(UpdateWave(frame)) + { + CurrentStateTime = 0.0f; + CurrentState = SMWaveState::SM_WAVE_STATE_POSTFRAMES; + } + } break; + + case SMWaveState::SM_WAVE_STATE_POSTFRAMES: + { + UpdateWave(frame); + if(CurrentStateTime > WAVE_POSTWAIT_MS) + { + CurrentStateTime = 0.0f; + CurrentState = SMWaveState::SM_WAVE_STATE_FINISHED; + } + } break; + + case SMWaveState::SM_WAVE_STATE_FINISHED: + case SMWaveState::SM_WAVE_STATE_NOTSTARTED: + default: + { + } break; + } +} + +bool SMWave::UpdateWave(RGB (&frame)[100]) +{ + bool bFinished = true; + + WaveValue += GetWaveSpeedFromEnum(); + + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + if (LightTypeIsForSpecialMoveAnimation(RGBLights->AllLights[lightIndex].Type)) + { + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + //default all to black if not running + if(CurrentState != SMWaveState::SM_WAVE_STATE_RUNNING) + { + frame[ledIndex] = ColorBlack; + continue; + } + + bool bShouldUseLight = CheckDividerForLight(lightIndex); + if(!bShouldUseLight) + { + frame[ledIndex] = ColorBlack; + continue; + } + + //This light is in use. Get the strength + float lightStr = GetStrengthForLight(RGBLights->AllLights[lightIndex].Position.XPosition, RGBLights->AllLights[lightIndex].Position.YPosition); + if(lightStr < 0) + lightStr = 0.0f; + else + bFinished = false; + + frame[ledIndex] = BlendColor(ColorBlack, colors[ColourIndex], lightStr); + } + } + } + + return bFinished; +} + +bool SMWave::CheckDividerForLight(unsigned int lightIndex) +{ + if(WaveDivider == SpecialMoveAnimationDivider::SPECIALMOVE_DIVIDER_FIRSTHALF_LIGHTS) + { + if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_LEFT || WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_RIGHT) + { + if(RGBLights->AllLights[lightIndex].Position.YPosition >= MidYCoord) + return false; + } + else if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_UP || WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_DOWN) + { + if(RGBLights->AllLights[lightIndex].Position.XPosition >= MidXCoord) + return false; + } + } + else if(WaveDivider == SpecialMoveAnimationDivider::SPECIALMOVE_DIVIDER_SECONDHALF_LIGHTS) + { + if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_LEFT || WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_RIGHT) + { + if(RGBLights->AllLights[lightIndex].Position.YPosition < MidYCoord) + return false; + } + else if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_UP || WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_DOWN) + { + if(RGBLights->AllLights[lightIndex].Position.XPosition < MidXCoord) + return false; + } + } + + return true; +} + +float SMWave::GetStrengthForLight(int XPos, int YPos) +{ + float thisWaveVal = WaveValue; + if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_RIGHT) + { + int xOffset = XPos - MinXCoord; + thisWaveVal -= (WAVE_OFFSET_PER_COORD * xOffset); + } + else if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_LEFT) + { + int xOffset = MaxXCoord - XPos; + thisWaveVal -= (WAVE_OFFSET_PER_COORD * xOffset); + } + else if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_UP) + { + int yOffset = MaxYCoord - YPos; + thisWaveVal -= (WAVE_OFFSET_PER_COORD * yOffset); + } + else// if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_DOWN) + { + int yOffset = YPos - MinYCoord; + thisWaveVal -= (WAVE_OFFSET_PER_COORD * yOffset); + } + + int holdLoopsToUse = WaveLoops <= 1 ? WAVE_HOLDLOOPS : 0; + int pulseLoopsToUse = WaveLoops - 1; + int totalLoops = holdLoopsToUse + pulseLoopsToUse; + float halfWaveLength = (WAVE_LENGTH / 2.0f); + if(thisWaveVal < 0) + return 0.0f; //not ready yet + else if(thisWaveVal < WAVE_LENGTH) + return thisWaveVal / WAVE_LENGTH; //fade in + else if (thisWaveVal < (WAVE_LENGTH * (holdLoopsToUse))) + return 1.0f; + else if (thisWaveVal < (WAVE_LENGTH * totalLoops)) + { + thisWaveVal -= WAVE_LENGTH; + while(thisWaveVal > WAVE_LENGTH) + thisWaveVal -= WAVE_LENGTH; + float mul; + if(thisWaveVal < halfWaveLength) + mul = 1.0f - ((thisWaveVal / halfWaveLength) * 0.5f); + else + mul = 0.5f + (((thisWaveVal - halfWaveLength) / halfWaveLength) * 0.5f); + + return mul; + } + else if (thisWaveVal < (WAVE_LENGTH * (totalLoops + 1))) + return 1.0 - ((thisWaveVal - (WAVE_LENGTH * totalLoops)) / WAVE_LENGTH);//in fade down + + //finished this light + return -1.0f; +} \ No newline at end of file diff --git a/lib/AnimationStation/src/Effects/SMWave.hpp b/lib/AnimationStation/src/Effects/SMWave.hpp new file mode 100644 index 0000000000..81e7b33666 --- /dev/null +++ b/lib/AnimationStation/src/Effects/SMWave.hpp @@ -0,0 +1,56 @@ +#ifndef _SM_WAVE_H_ +#define _SM_WAVE_H_ + +#include "../Animation.hpp" +#include +#include +#include +#include "../AnimationStation.hpp" +#include "../SpecialMoveSystem.hpp" + +typedef enum +{ + SM_WAVE_STATE_NOTSTARTED, + SM_WAVE_STATE_PREFRAMES, + SM_WAVE_STATE_RUNNING, + SM_WAVE_STATE_POSTFRAMES, + SM_WAVE_STATE_FINISHED, +} SMWaveState; + +class SMWave : public Animation { +public: + SMWave(Lights& InRGBLights); + ~SMWave() { }; + + void Animate(RGB (&frame)[100]); + + virtual void SetOptionalParams(uint32_t OptionalParams) override; + virtual bool IsFinished() override; + +protected: + + float GetWaveSpeedFromEnum(); + bool CheckDividerForLight(unsigned int lightIndex); + bool UpdateWave(RGB (&frame)[100]); + float GetStrengthForLight(int XPos, int YPos); + + SpecialMoveAnimationDirection WaveDirection; + SpecialMoveAnimationDuration WaveSpeed; + SpecialMoveAnimationDivider WaveDivider; + int WaveLoops = 0; + uint8_t ColourIndex; + + int MinXCoord = 0; + int MinYCoord = 0; + int MaxXCoord = 0; + int MaxYCoord = 0; + int MidXCoord = 0; + int MidYCoord = 0; + + float WaveValue = 0.0f; + + uint32_t CurrentStateTime = 0; + SMWaveState CurrentState = SMWaveState::SM_WAVE_STATE_NOTSTARTED; +}; + +#endif diff --git a/lib/AnimationStation/src/SpecialMoveSystem.cpp b/lib/AnimationStation/src/SpecialMoveSystem.cpp index b0f361b2be..35756cf333 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.cpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.cpp @@ -67,6 +67,28 @@ void SpecialMoveSystem::SetDirectionMasks(uint32_t UpMask, uint32_t DownMask, ui SPECIAL_MOVE_DIRECTION_MASK_RIGHT = RightMask; } +SpecialMoveStickDirection SpecialMoveSystem::GetDirectionPressed(uint32_t PressedButtons) +{ + if((PressedButtons & (SPECIAL_MOVE_DIRECTION_MASK_LEFT | SPECIAL_MOVE_DIRECTION_MASK_UP)) == (SPECIAL_MOVE_DIRECTION_MASK_LEFT | SPECIAL_MOVE_DIRECTION_MASK_UP)) + return SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT; + else if((PressedButtons & (SPECIAL_MOVE_DIRECTION_MASK_RIGHT | SPECIAL_MOVE_DIRECTION_MASK_UP)) == (SPECIAL_MOVE_DIRECTION_MASK_RIGHT | SPECIAL_MOVE_DIRECTION_MASK_UP)) + return SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT; + else if((PressedButtons & (SPECIAL_MOVE_DIRECTION_MASK_LEFT | SPECIAL_MOVE_DIRECTION_MASK_DOWN)) == (SPECIAL_MOVE_DIRECTION_MASK_LEFT | SPECIAL_MOVE_DIRECTION_MASK_DOWN)) + return SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT; + else if((PressedButtons & (SPECIAL_MOVE_DIRECTION_MASK_RIGHT | SPECIAL_MOVE_DIRECTION_MASK_DOWN)) == (SPECIAL_MOVE_DIRECTION_MASK_RIGHT | SPECIAL_MOVE_DIRECTION_MASK_DOWN)) + return SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT; + else if((PressedButtons & SPECIAL_MOVE_DIRECTION_MASK_UP) == SPECIAL_MOVE_DIRECTION_MASK_UP) + return SpecialMoveStickDirection::SPECIALMOVE_STICK_UP; + else if((PressedButtons & SPECIAL_MOVE_DIRECTION_MASK_DOWN) == SPECIAL_MOVE_DIRECTION_MASK_DOWN) + return SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN; + else if((PressedButtons & SPECIAL_MOVE_DIRECTION_MASK_LEFT) == SPECIAL_MOVE_DIRECTION_MASK_LEFT) + return SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT; + else if((PressedButtons & SPECIAL_MOVE_DIRECTION_MASK_RIGHT) == SPECIAL_MOVE_DIRECTION_MASK_RIGHT) + return SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT; + + return SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID; +} + bool SpecialMoveSystem::CheckJoystickDirection(SpecialMoveStickDirection& FoundDirection, SpecialMoveStickDirection TestDirection, uint32_t PressedButtons, uint32_t DirectionOne, uint32_t DirectionTwo) { bool bWasPressed = false; @@ -84,24 +106,12 @@ bool SpecialMoveSystem::CheckJoystickDirection(SpecialMoveStickDirection& FoundD return bWasPressed; } -static uint64_t count = 0; -static bool halt = false; - void SpecialMoveSystem::HandlePressedButtons(uint32_t pressedButtons) { bool bWasAnythingPressed = false; - uint32_t oldButtonMask = SwitchHistory[0].ButtonMaskInput; - count++; - - if(halt) - { - while(true) - {} - } - //do directions explicitly due to needing to do diagonals -/* SpecialMoveStickDirection FoundDirection = SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID; + SpecialMoveStickDirection FoundDirection = SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID; bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_LEFT, SPECIAL_MOVE_DIRECTION_MASK_UP); bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_RIGHT, SPECIAL_MOVE_DIRECTION_MASK_UP); bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_LEFT, SPECIAL_MOVE_DIRECTION_MASK_DOWN); @@ -109,7 +119,7 @@ void SpecialMoveSystem::HandlePressedButtons(uint32_t pressedButtons) bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_UP, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_UP, 0); bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_DOWN, 0); bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_LEFT, 0); - bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_RIGHT, 0);*/ + bWasAnythingPressed |= CheckJoystickDirection(FoundDirection, SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, pressedButtons, SPECIAL_MOVE_DIRECTION_MASK_RIGHT, 0); //check each button input and update history for(uint32_t buttonMask = 1; buttonMask < (1 << 20); buttonMask = buttonMask << 1) @@ -122,14 +132,6 @@ void SpecialMoveSystem::HandlePressedButtons(uint32_t pressedButtons) UpdateHistoryForInput(buttonMask, SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID, bIsPressed); } - if(count > 300 && oldButtonMask <= 32 && SwitchHistory[0].ButtonMaskInput > 32) - { - halt = true; - } - AnimationStation::printfs[1] = std::to_string(pressedButtons) + " " + std::to_string(oldButtonMask); - AnimationStation::printfs[2] = std::to_string(SwitchHistory[0].ButtonMaskInput) + " " + std::to_string(SwitchHistory[0].DirectionInput); - AnimationStation::printfs[0] = std::to_string(count) + " "; - //After a special move we need to wait for all buttons to be released before we trigger another or we could potentially chain two together by accident. //If nothing is pressed this frame then we can remove this block. if(SwitchClearAwaitingAllRelease) @@ -198,15 +200,16 @@ void SpecialMoveSystem::UpdateHistoryForInput(uint32_t buttonMask, SpecialMoveSt } } - //no previous entry found. Add new one - SwitchHistoryCreateNew(buttonMask, directionHeld); + //no previous entry found. Add new one if its being held + if(bIsPressed) + SwitchHistoryCreateNew(buttonMask, directionHeld); } void SpecialMoveSystem::GetComboArrayForMove(SpecialMoveInputTypes InputType, std::vector& comboArray) { switch(InputType) { - case SpecialMoveInputTypes::SPECIALMOVE_INPUT_QUARTER_DOWN_LEFT: + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_QUARTER_DOWN_RIGHT: { comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); @@ -231,7 +234,7 @@ void SpecialMoveSystem::GetComboArrayForMove(SpecialMoveInputTypes InputType, st } } -bool SpecialMoveSystem::DoesInputMatch(int HistoryIndex, ComboEntry ComboInput, bool bIsChargeMove) +bool SpecialMoveSystem::DoesInputMatch(int HistoryIndex, ComboEntry& ComboInput, bool bIsChargeMove) { if(ComboInput.DirectionInput != SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID) { @@ -265,6 +268,11 @@ bool SpecialMoveSystem::DoesInputMatch(int HistoryIndex, ComboEntry ComboInput, return SwitchHistory[HistoryIndex].ButtonMaskInput == ComboInput.ButtonMaskInput; } +int64_t SpecialMoveSystem::GetMsBetweenTimes(absolute_time_t start, absolute_time_t end) +{ + return absolute_time_diff_us(start, end) / 1000; +} + bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* MoveToTestFor, int ComboIndex, int TriggerIndex) { int lastIndexComboInputWasFound = -1; @@ -272,7 +280,6 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move absolute_time_t timeNow = thisFrameTime; absolute_time_t timeLastInputSet = thisFrameTime; int numMissed = 0; - bool bAllowMiss = MoveToTestFor->NumRequiredInputCombos >= COMBO_INPUT_COUNT_FOR_ONE_OUT_OF_TWO; bool bIsChargeCombo = MoveToTestFor->bIsChargeMove; int64_t OptionsChargeTime = Options.ChargeTimeInMs; @@ -280,18 +287,30 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move std::vector comboArray; GetComboArrayForMove(MoveToTestFor->RequiredInputCombos[ComboIndex], comboArray); int moveLength = comboArray.size(); + bool bAllowMiss = moveLength >= COMBO_INPUT_COUNT_FOR_ONE_OUT_OF_TWO; // put triggers on the end for easier processing int triggerLength = 0; - for(int triggerIndex = 0; triggerIndex < 3; ++triggerIndex) + uint32_t thisCombinedTrigger = MoveToTestFor->RequiredTriggerCombos[TriggerIndex].RequiredTriggers; + SpecialMoveStickDirection triggerDirection = GetDirectionPressed(thisCombinedTrigger); + if(triggerDirection != SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID) + { + comboArray.push_back(ComboEntry(triggerDirection, 0)); + triggerLength++; + } + for(uint32_t buttonMask = 1; buttonMask < (1 << 20); buttonMask = buttonMask << 1) { - int32_t thisTrigger = ((MoveToTestFor->RequiredTriggerCombos[TriggerIndex].RequiredTriggers) >> (4*triggerIndex)) & 0xFF; - if(thisTrigger != 0) + if(buttonMask == SPECIAL_MOVE_DIRECTION_MASK_UP || buttonMask == SPECIAL_MOVE_DIRECTION_MASK_DOWN || buttonMask == SPECIAL_MOVE_DIRECTION_MASK_LEFT || buttonMask == SPECIAL_MOVE_DIRECTION_MASK_RIGHT) + continue; + + if((thisCombinedTrigger & buttonMask) != 0) { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID, buttonMask)); triggerLength++; - comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID, thisTrigger)); } } + if(triggerLength == 0) + return false; int comboLength = moveLength + triggerLength; if (comboLength > MAX_INPUT_HISTORY) @@ -299,7 +318,7 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move // Moves are specified in normal order. History is newest first. So start from the end of the combo and work back int triggersFound = 0; - for (int comboIndex = comboLength - 1; comboIndex >= 0; --comboIndex) + for (int comboSearchIndex = comboLength - 1; comboSearchIndex >= 0; --comboSearchIndex) { // First see if the button(s) and the final movement that finish this combo routine have recently been pressed if (bHasFinishedDoingTriggerButtons == false) @@ -316,16 +335,17 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move for (unsigned int historyIndex = 0; historyIndex < MAX_INPUT_HISTORY; ++historyIndex) { // are we past the time window? - if (absolute_time_diff_us(SwitchHistory[historyIndex].TimeSet, timeNow) > COMBO_TRIGGER_INPUT_TIME_WINDOW) + if (GetMsBetweenTimes(SwitchHistory[historyIndex].TimeSet, timeNow) > (bHasFinishedDoingTriggerButtons ? COMBO_INPUT_TIME_WINDOW : COMBO_TRIGGER_INPUT_TIME_WINDOW)) { return false; // we havent managed to find this trigger in time } - if (DoesInputMatch(historyIndex, comboArray[comboIndex], bIsChargeCombo)) + if (DoesInputMatch(historyIndex, comboArray[comboSearchIndex], bIsChargeCombo)) { // we found this trigger. Move onto the next one bFoundTrigger = true; triggersFound++; + lastIndexComboInputWasFound = historyIndex; break; } } @@ -343,15 +363,15 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move bool bFoundInput = false; for (int historyIndex = lastIndexComboInputWasFound + 1; historyIndex < MAX_INPUT_HISTORY; ++historyIndex) { - if (DoesInputMatch(historyIndex, comboArray[comboIndex], bIsChargeCombo)) + if (DoesInputMatch(historyIndex, comboArray[comboSearchIndex], bIsChargeCombo)) { bFoundInput = true; // Is this the last input and if so is it a charge input as they're special and - if (comboIndex == 0 && bIsChargeCombo) + if (comboSearchIndex == 0 && bIsChargeCombo) { // Its a charge move. In which case, this move must be held for CHARGE_COMBO_INPUT_TIME_WINDOW as well as released within COMBO_INPUT_TIME_WINDOW of the last one - if (SwitchHistory[historyIndex].bIsHeld == false && absolute_time_diff_us(SwitchHistory[historyIndex].TimeReleased, timeLastInputSet) < COMBO_INPUT_TIME_WINDOW && absolute_time_diff_us(SwitchHistory[historyIndex].TimeSet, SwitchHistory[historyIndex].TimeReleased) > OptionsChargeTime) + if (SwitchHistory[historyIndex].bIsHeld == false && GetMsBetweenTimes(SwitchHistory[historyIndex].TimeReleased, timeLastInputSet) < COMBO_INPUT_TIME_WINDOW && GetMsBetweenTimes(SwitchHistory[historyIndex].TimeSet, SwitchHistory[historyIndex].TimeReleased) > OptionsChargeTime) { // Clear the history to prevent retrigger if animation is really quick ClearHistory(); @@ -365,7 +385,7 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move // regular input absolute_time_t timeToUse = SwitchHistory[historyIndex].bIsHeld ? SwitchHistory[historyIndex].TimeSet : SwitchHistory[historyIndex].TimeReleased; - if (absolute_time_diff_us(timeToUse, timeLastInputSet) > COMBO_INPUT_TIME_WINDOW) + if (GetMsBetweenTimes(timeToUse, timeLastInputSet) > COMBO_INPUT_TIME_WINDOW) { if (bAllowMiss) { @@ -402,11 +422,5 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move } // if we get here we've found every single input! Combo passed - return true; } - -void SpecialMoveSystem::UpdateRunningSpecialMove() -{ - -} \ No newline at end of file diff --git a/lib/AnimationStation/src/SpecialMoveSystem.hpp b/lib/AnimationStation/src/SpecialMoveSystem.hpp index 20472149e2..496e347955 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.hpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.hpp @@ -16,8 +16,8 @@ #define MAX_SPECIALMOVE_TRIGGERS_PER_MOVE 3 #define MAX_INPUT_HISTORY 100 -#define COMBO_INPUT_TIME_WINDOW 200 //Maximum time between combo movements that arent a charge -#define COMBO_TRIGGER_INPUT_TIME_WINDOW 125 //Maximum time between combined button inputs eg PP, PPP, KK or PK etc +#define COMBO_INPUT_TIME_WINDOW 250 //Maximum time between combo movements that arent a charge +#define COMBO_TRIGGER_INPUT_TIME_WINDOW 200 //Maximum time between combined button inputs eg PP, PPP, KK or PK etc #define COMBO_INPUT_COUNT_FOR_ONE_OUT_OF_TWO 7 //if the combo input is 7 or more moves then the input system will allow you to succeed if you dont miss 2 in a row window. eg LDRU would be fine for a SPD //List of specialMove animation @@ -61,6 +61,14 @@ typedef enum SPECIALMOVE_DIRECTION_DOWN, } SpecialMoveAnimationDirection; +// SpecialMove animation Divider Modifier +typedef enum +{ + SPECIALMOVE_DIVIDER_ALL_LIGHTS, + SPECIALMOVE_DIVIDER_FIRSTHALF_LIGHTS, + SPECIALMOVE_DIVIDER_SECONDHALF_LIGHTS, +} SpecialMoveAnimationDivider; + // SpecialMove input types typedef enum { @@ -163,14 +171,15 @@ class SpecialMoveSystem { protected: void ClearHistory(); + int64_t GetMsBetweenTimes(absolute_time_t start, absolute_time_t end); void UpdateHistoryForInput(uint32_t buttonMask, SpecialMoveStickDirection directionHeld, bool bIsPressed); bool CheckJoystickDirection(SpecialMoveStickDirection& FoundDirection, SpecialMoveStickDirection TestDirection, uint32_t PressedButtons, uint32_t DirectionOne, uint32_t DirectionTwo); - bool DoesInputMatch(int HistoryIndex, ComboEntry ComboInput, bool bIsChargeMove); + SpecialMoveStickDirection GetDirectionPressed(uint32_t PressedButtons); + bool DoesInputMatch(int HistoryIndex, ComboEntry& ComboInput, bool bIsChargeMove); void SwitchHistoryCreateNew(uint32_t buttonMask, SpecialMoveStickDirection directionHeld); bool TestAllMoves(); bool TestForActivatedSpecialMove(SpecialMoveDescription* MoveToTestFor, int ComboIndex, int TriggerIndex); - void UpdateRunningSpecialMove(); void StartMoveAnimation(SpecialMoveEffects AnimationToPlay, uint32_t OptionalParams); void GetComboArrayForMove(SpecialMoveInputTypes InputType, std::vector& comboArray); diff --git a/src/config_utils.cpp b/src/config_utils.cpp index a62ac9f8ad..ac30e4e389 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -487,11 +487,11 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_QUARTER_DOWN_RIGHT; config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], RequiredTriggers, GAMEPAD_MASK_B3); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], OptionalParams, 2 + (2 << 4) + (10 << 8)); //right //slow //colour blue + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], OptionalParams, 2 + (2 << 4) + (1 << 8) + (0 << 12) + (10 << 16)); //right //slow //1 loop //all lights //colour blue INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], RequiredTriggers, GAMEPAD_MASK_B4); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], OptionalParams, 2 + (1 << 4) + (10 << 8)); //right //medium //colour blue + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], OptionalParams, 2 + (1 << 4) + (1 << 8) + (1 << 12) + (10 << 16)); //right //medium //1 loop //top lights //colour blue INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], RequiredTriggers, GAMEPAD_MASK_R1); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], OptionalParams, 2 + (0 << 4) + (10 << 8)); //right //fast //colour blue + INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], OptionalParams, 2 + (0 << 4) + (1 << 8) + (2 << 12) + (10 << 16)); //right //fast //1 loop //bottom lights //colour blue INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1], bIsChargeMove, false); INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1], Animation, SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_PULSECOLOR); From aaa6a9060cb1189b0c978c1789c8848221cc7609 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Thu, 12 Dec 2024 23:53:40 +0000 Subject: [PATCH 011/121] Move types done Verified move types. Added new allowance for 1 missing input in middle sized roll moves --- lib/AnimationStation/CMakeLists.txt | 1 + lib/AnimationStation/src/AnimationStation.cpp | 13 + .../src/Effects/SMCircleColour.cpp | 205 ++++++++ .../src/Effects/SMCircleColour.hpp | 56 +++ lib/AnimationStation/src/Effects/SMWave.cpp | 3 - .../src/SpecialMoveSystem.cpp | 441 +++++++++++++++--- .../src/SpecialMoveSystem.hpp | 39 +- proto/enums.proto | 25 +- src/addons/neopicoleds.cpp | 1 + src/config_utils.cpp | 40 +- 10 files changed, 725 insertions(+), 99 deletions(-) create mode 100644 lib/AnimationStation/src/Effects/SMCircleColour.cpp create mode 100644 lib/AnimationStation/src/Effects/SMCircleColour.hpp diff --git a/lib/AnimationStation/CMakeLists.txt b/lib/AnimationStation/CMakeLists.txt index 657b3af429..d9306ae0e6 100644 --- a/lib/AnimationStation/CMakeLists.txt +++ b/lib/AnimationStation/CMakeLists.txt @@ -5,6 +5,7 @@ src/Effects/StaticColor.cpp src/Effects/RandomColor.cpp src/Effects/SMPulseColour.cpp src/Effects/SMWave.cpp +src/Effects/SMCircleColour.cpp src/AnimationStation.cpp src/Animation.cpp src/SpecialMoveSystem.cpp diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index de5823bdd3..4fc4bcf207 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -10,6 +10,7 @@ #include "Effects/StaticColor.hpp" #include "Effects/RandomColor.hpp" #include "Effects/SMPulseColour.hpp" +#include "Effects/SMCircleColour.hpp" #include "Effects/SMWave.hpp" #include "SpecialMoveSystem.hpp" @@ -205,6 +206,18 @@ void AnimationStation::SetSpecialMoveAnimation(SpecialMoveEffects AnimationToPla this->specialMoveAnimation = new SMPulseColour(RGBLights); break; + case SpecialMoveEffects::SPECIALMOVE_SMEFFECT_CIRCLECOLOR: + this->specialMoveAnimation = new SMCircleColour(RGBLights); + break; + + case SpecialMoveEffects::SPECIALMOVE_SMEFFECT_KNIGHTRIDER: + //this->specialMoveAnimation = new SMKnightRider(RGBLights); + break; + + case SpecialMoveEffects::SPECIALMOVE_SMEFFECT_RANDOMFLASH: + //this->specialMoveAnimation = new SMRandomFlash(RGBLights); + break; + default: break; } diff --git a/lib/AnimationStation/src/Effects/SMCircleColour.cpp b/lib/AnimationStation/src/Effects/SMCircleColour.cpp new file mode 100644 index 0000000000..1962335bf6 --- /dev/null +++ b/lib/AnimationStation/src/Effects/SMCircleColour.cpp @@ -0,0 +1,205 @@ +#include "SMCircleColour.hpp" +#include "SpecialMoveSystem.hpp" +#include + +#define CIRCLE_PREWAIT_MS 150 +#define CIRCLE_POSTWAIT_MS 150 +#define TWOCIRCLES 12.5666 +#define ONECIRCLE (TWOCIRCLES / 2.0f) + +SMCircleColour::SMCircleColour(Lights& InRGBLights) : Animation(InRGBLights) +{ + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + if(LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type) == false) + continue; + if(RGBLights->AllLights[lightIndex].Position.XPosition > MaxXCoord) + MaxXCoord = RGBLights->AllLights[lightIndex].Position.XPosition; + if(RGBLights->AllLights[lightIndex].Position.YPosition > MaxYCoord) + MaxYCoord = RGBLights->AllLights[lightIndex].Position.YPosition; + + if(lightIndex == 0 || RGBLights->AllLights[lightIndex].Position.XPosition < MinXCoord) + MinXCoord = RGBLights->AllLights[lightIndex].Position.XPosition; + if(lightIndex == 0 || RGBLights->AllLights[lightIndex].Position.YPosition < MinYCoord) + MinYCoord = RGBLights->AllLights[lightIndex].Position.YPosition; + } + + MidXCoord = MinXCoord + ((MaxXCoord - MinXCoord) / 2); + MidYCoord = MinYCoord + ((MaxYCoord - MinYCoord) / 2); +} + +void SMCircleColour::SetOptionalParams(uint32_t OptionalParams) +{ + //FORMAT + //4bit - bool - Clockwise + //4bit - SpecialMoveAnimationDuration - Circle animation time + //4bit - int - Num circle loops + //8bit - Animation::colors index - Circle colour + //8bit - Animation::colors index - Second Circle colour + + bClockwise = (OptionalParams & 0xF) != 0; + CircleSpeed = (SpecialMoveAnimationDuration)((OptionalParams >> 4) & 0xF); + CircleLoops = ((OptionalParams >> 8) & 0xF); + ColourIndex = (uint8_t)((OptionalParams >> 12) & 0xFF); + SecondColourIndex = (uint8_t)((OptionalParams >> 20) & 0xFF); + + CurrentState = SMCircleColourState::SM_CIRCLE_STATE_PREFRAMES; +} + +float SMCircleColour::GetCircleSpeedFromEnum() +{ + //rads per frame + float speed = 0; + switch(CircleSpeed) + { + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_VERYSHORT: + { + speed = 0.8; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_SHORT: + { + speed = 0.6; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_MEDIUM: + { + speed = 0.4; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_LONG: + { + speed = 0.2; + } break; + case SpecialMoveAnimationDuration::SPECIALMOVE_DURATION_VERYLONG: + { + speed = 0.1; + } break; + default: + { + speed = 0.1; + } break; + } + + return speed; +} + +bool SMCircleColour::IsFinished() +{ + return CurrentState == SMCircleColourState::SM_CIRCLE_STATE_FINISHED; +} + +void SMCircleColour::Animate(RGB (&frame)[100]) +{ + UpdateTime(); + + CurrentStateTime += updateTimeInMs; + + switch(CurrentState) + { + case SMCircleColourState::SM_CIRCLE_STATE_PREFRAMES: + { + UpdateCircle(frame); + if(CurrentStateTime > CIRCLE_PREWAIT_MS) + { + CurrentStateTime = 0.0f; + CurrentState = SMCircleColourState::SM_CIRCLE_STATE_RUNNING; + } + } break; + + case SMCircleColourState::SM_CIRCLE_STATE_RUNNING: + { + if(UpdateCircle(frame)) + { + CurrentStateTime = 0.0f; + CurrentState = SMCircleColourState::SM_CIRCLE_STATE_POSTFRAMES; + } + } break; + + case SMCircleColourState::SM_CIRCLE_STATE_POSTFRAMES: + { + UpdateCircle(frame); + if(CurrentStateTime > CIRCLE_POSTWAIT_MS) + { + CurrentStateTime = 0.0f; + CurrentState = SMCircleColourState::SM_CIRCLE_STATE_FINISHED; + } + } break; + + case SMCircleColourState::SM_CIRCLE_STATE_FINISHED: + case SMCircleColourState::SM_CIRCLE_STATE_NOTSTARTED: + default: + { + } break; + } +} + +bool SMCircleColour::UpdateCircle(RGB (&frame)[100]) +{ + if(CurrentState == SMCircleColourState::SM_CIRCLE_STATE_RUNNING) + CurrentAngle += GetCircleSpeedFromEnum(); + + bool inSecondCircle = CurrentAngle > ONECIRCLE; + float currentAngleModOneCircle = inSecondCircle ? CurrentAngle - ONECIRCLE : CurrentAngle; + + for(unsigned int lightIndex = 0; lightIndex < RGBLights->AllLights.size(); ++lightIndex) + { + if (LightTypeIsForSpecialMoveAnimation(RGBLights->AllLights[lightIndex].Type)) + { + uint8_t firstLightIndex = RGBLights->AllLights[lightIndex].FirstLedIndex; + uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[lightIndex].LedsPerLight; + + //Work out angle to light + bool useSecondColour; + float xToLight = RGBLights->AllLights[lightIndex].Position.XPosition - MidXCoord; + float yToLight = RGBLights->AllLights[lightIndex].Position.YPosition - MidYCoord; + float magnitude = std::sqrt((xToLight * xToLight) + (yToLight * yToLight)); + float angleBetweenUpAndLight = std::acos(-yToLight / magnitude); //negate Y here as the button coords are 0,0 in the top left + if(xToLight < 0) + { + //its on left side of center + angleBetweenUpAndLight = ONECIRCLE - angleBetweenUpAndLight; + } + + //should we light this light or turn it to the "off" colour? + useSecondColour = inSecondCircle ? false : true; + if(bClockwise) + { + if(angleBetweenUpAndLight < currentAngleModOneCircle) + useSecondColour = !useSecondColour; + } + else + { + if(angleBetweenUpAndLight > ONECIRCLE - currentAngleModOneCircle) + useSecondColour = !useSecondColour; + } + + RGB colToUse = ColorBlack; //black + if(NumLoopsDone == 0 && !inSecondCircle && useSecondColour) + colToUse = ColorBlack; + else if(NumLoopsDone == (CircleLoops-1) && inSecondCircle && useSecondColour) + colToUse = ColorBlack; + else if(useSecondColour) + colToUse = colors[SecondColourIndex]; + else + colToUse = colors[ColourIndex]; + + for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) + { + //default all to black if not running + if(CurrentState != SMCircleColourState::SM_CIRCLE_STATE_RUNNING) + { + frame[ledIndex] = ColorBlack; + continue; + } + + frame[ledIndex] = colToUse; + } + } + } + + if(CurrentAngle > TWOCIRCLES) + { + CurrentAngle = 0; + NumLoopsDone++; + } + + return NumLoopsDone == CircleLoops; +} \ No newline at end of file diff --git a/lib/AnimationStation/src/Effects/SMCircleColour.hpp b/lib/AnimationStation/src/Effects/SMCircleColour.hpp new file mode 100644 index 0000000000..468d7e95bb --- /dev/null +++ b/lib/AnimationStation/src/Effects/SMCircleColour.hpp @@ -0,0 +1,56 @@ +#ifndef _SM_CIRCLECOLOUR_H_ +#define _SM_CIRCLECOLOUR_H_ + +#include "../Animation.hpp" +#include +#include +#include +#include "../AnimationStation.hpp" +#include "../SpecialMoveSystem.hpp" + +typedef enum +{ + SM_CIRCLE_STATE_NOTSTARTED, + SM_CIRCLE_STATE_PREFRAMES, + SM_CIRCLE_STATE_RUNNING, + SM_CIRCLE_STATE_POSTFRAMES, + SM_CIRCLE_STATE_FINISHED, +} SMCircleColourState; + +class SMCircleColour : public Animation { +public: + SMCircleColour(Lights& InRGBLights); + ~SMCircleColour() { }; + + void Animate(RGB (&frame)[100]); + + virtual void SetOptionalParams(uint32_t OptionalParams) override; + virtual bool IsFinished() override; + +protected: + + float GetCircleSpeedFromEnum(); + bool UpdateCircle(RGB (&frame)[100]); + + bool bClockwise; + SpecialMoveAnimationDuration CircleSpeed; + int CircleLoops = 0; + uint8_t ColourIndex; + uint8_t SecondColourIndex; + + int MinXCoord = 0; + int MinYCoord = 0; + int MaxXCoord = 0; + int MaxYCoord = 0; + int MidXCoord = 0; + int MidYCoord = 0; + + float CurrentAngle = 0.0f; + + int NumLoopsDone = 0; + + uint32_t CurrentStateTime = 0; + SMCircleColourState CurrentState = SMCircleColourState::SM_CIRCLE_STATE_NOTSTARTED; +}; + +#endif diff --git a/lib/AnimationStation/src/Effects/SMWave.cpp b/lib/AnimationStation/src/Effects/SMWave.cpp index 44057e345f..ef3cc0279c 100644 --- a/lib/AnimationStation/src/Effects/SMWave.cpp +++ b/lib/AnimationStation/src/Effects/SMWave.cpp @@ -43,9 +43,6 @@ void SMWave::SetOptionalParams(uint32_t OptionalParams) WaveDivider = (SpecialMoveAnimationDivider)((OptionalParams >> 12) & 0xF); ColourIndex = (uint8_t)((OptionalParams >> 16) & 0xFF); -WaveLoops = 5; -WaveDirection = SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_RIGHT; - CurrentState = SMWaveState::SM_WAVE_STATE_PREFRAMES; } diff --git a/lib/AnimationStation/src/SpecialMoveSystem.cpp b/lib/AnimationStation/src/SpecialMoveSystem.cpp index 35756cf333..05006837b7 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.cpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.cpp @@ -41,16 +41,27 @@ bool SpecialMoveSystem::TestAllMoves() { for(uint32_t triggerIndex = 0; triggerIndex < numTriggers; ++triggerIndex) { - bool bSucceeded = TestForActivatedSpecialMove(&thisMove, comboIndex, triggerIndex); - if(bSucceeded) + //360/720 inputs require us to try all possible start locations (although we only bother with cardinals as an optimisation) + bool doCircleLoop = false; + if(thisMove.RequiredInputCombos[comboIndex] == SpecialMoveInputTypes::SPECIALMOVE_INPUT_360 || thisMove.RequiredInputCombos[comboIndex] == SpecialMoveInputTypes::SPECIALMOVE_INPUT_720) { - // Clear the history to prevent retrigger if animation is really quick - ClearHistory(); - if(ParentAnimationStation) - ParentAnimationStation->SetSpecialMoveAnimation(thisMove.Animation, thisMove.RequiredTriggerCombos[triggerIndex].OptionalParams); - SwitchClearAwaitingAllRelease = true; + doCircleLoop = true; + } - return true; + for(int circleLoops = 0; circleLoops < (doCircleLoop ? (int)SPECIALMOVE_CIRCLETYPE_MAX : 1); ++circleLoops) + { + bool bSucceeded = TestForActivatedSpecialMove(&thisMove, comboIndex, triggerIndex, (SpecialMoveCircleType)circleLoops); + + if(bSucceeded) + { + // Clear the history to prevent retrigger if animation is really quick + ClearHistory(); + if(ParentAnimationStation) + ParentAnimationStation->SetSpecialMoveAnimation(thisMove.Animation, thisMove.RequiredTriggerCombos[triggerIndex].OptionalParams); + SwitchClearAwaitingAllRelease = true; + + return true; + } } } } @@ -67,6 +78,11 @@ void SpecialMoveSystem::SetDirectionMasks(uint32_t UpMask, uint32_t DownMask, ui SPECIAL_MOVE_DIRECTION_MASK_RIGHT = RightMask; } +void SpecialMoveSystem::SetButtonMasks(uint32_t P1Mask) +{ + SPECIAL_MOVE_BUTTON_MASK_P1 = P1Mask; +} + SpecialMoveStickDirection SpecialMoveSystem::GetDirectionPressed(uint32_t PressedButtons) { if((PressedButtons & (SPECIAL_MOVE_DIRECTION_MASK_LEFT | SPECIAL_MOVE_DIRECTION_MASK_UP)) == (SPECIAL_MOVE_DIRECTION_MASK_LEFT | SPECIAL_MOVE_DIRECTION_MASK_UP)) @@ -205,43 +221,18 @@ void SpecialMoveSystem::UpdateHistoryForInput(uint32_t buttonMask, SpecialMoveSt SwitchHistoryCreateNew(buttonMask, directionHeld); } -void SpecialMoveSystem::GetComboArrayForMove(SpecialMoveInputTypes InputType, std::vector& comboArray) -{ - switch(InputType) - { - case SpecialMoveInputTypes::SPECIALMOVE_INPUT_QUARTER_DOWN_RIGHT: - { - comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); - comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); - comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); - } break; - - case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DP_RIGHT: - { - comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); - comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); - comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); - } break; - - case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DP_SHORTCUT_RIGHT: - { - comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); - comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); - } break; - - default: - break; - } -} - bool SpecialMoveSystem::DoesInputMatch(int HistoryIndex, ComboEntry& ComboInput, bool bIsChargeMove) { if(ComboInput.DirectionInput != SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID) { - //direction input check + //exact match always true + if(SwitchHistory[HistoryIndex].DirectionInput == ComboInput.DirectionInput) + return true; + + //charge moves are allowed to use diagonals if(bIsChargeMove) { - //Charge moves allow the surrounding directions to also count + //Charge moves allow the surrounding directions to also count if(ComboInput.DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT) { return SwitchHistory[HistoryIndex].DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT || SwitchHistory[HistoryIndex].DirectionInput == SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT; @@ -260,8 +251,8 @@ bool SpecialMoveSystem::DoesInputMatch(int HistoryIndex, ComboEntry& ComboInput, } } - //other wise just an exact match will do - return SwitchHistory[HistoryIndex].DirectionInput == ComboInput.DirectionInput; + //other wise we didnt find a match + return false; } //otherwise its button matching @@ -273,21 +264,23 @@ int64_t SpecialMoveSystem::GetMsBetweenTimes(absolute_time_t start, absolute_tim return absolute_time_diff_us(start, end) / 1000; } -bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* MoveToTestFor, int ComboIndex, int TriggerIndex) +bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* MoveToTestFor, int ComboIndex, int TriggerIndex, SpecialMoveCircleType CircleStartDirection) { int lastIndexComboInputWasFound = -1; bool bHasFinishedDoingTriggerButtons = false; absolute_time_t timeNow = thisFrameTime; absolute_time_t timeLastInputSet = thisFrameTime; - int numMissed = 0; + int numMissedConsecutive = 0; + int numMissedMiddle = 0; bool bIsChargeCombo = MoveToTestFor->bIsChargeMove; int64_t OptionsChargeTime = Options.ChargeTimeInMs; // Get combo array std::vector comboArray; - GetComboArrayForMove(MoveToTestFor->RequiredInputCombos[ComboIndex], comboArray); + GetComboArrayForMove(MoveToTestFor->RequiredInputCombos[ComboIndex], comboArray, CircleStartDirection); int moveLength = comboArray.size(); - bool bAllowMiss = moveLength >= COMBO_INPUT_COUNT_FOR_ONE_OUT_OF_TWO; + bool bAllowNoConsecutiveMiss = moveLength >= COMBO_INPUT_COUNT_FOR_ONE_OUT_OF_TWO; + bool bAllowMissInMiddle = moveLength >= COMBO_INPUT_COUNT_FOR_ONE_MISSING_IN_MIDDLE; // put triggers on the end for easier processing int triggerLength = 0; @@ -363,8 +356,14 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move bool bFoundInput = false; for (int historyIndex = lastIndexComboInputWasFound + 1; historyIndex < MAX_INPUT_HISTORY; ++historyIndex) { + AnimationStation::printfs[0] = "LastTested = " + std::to_string(comboSearchIndex); if (DoesInputMatch(historyIndex, comboArray[comboSearchIndex], bIsChargeCombo)) - { + { + if(comboSearchIndex == 0 || comboSearchIndex == 1) + { + AnimationStation::printfs[1] = "passed = " + std::to_string(comboSearchIndex); + } + bFoundInput = true; // Is this the last input and if so is it a charge input as they're special and @@ -387,13 +386,20 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move absolute_time_t timeToUse = SwitchHistory[historyIndex].bIsHeld ? SwitchHistory[historyIndex].TimeSet : SwitchHistory[historyIndex].TimeReleased; if (GetMsBetweenTimes(timeToUse, timeLastInputSet) > COMBO_INPUT_TIME_WINDOW) { - if (bAllowMiss) + if (bAllowNoConsecutiveMiss) { // too long between inputs on this one. but might be ok to continue if this was an older input in the history - numMissed++; - if (numMissed == 2) + numMissedConsecutive++; + if (numMissedConsecutive == 2) return false; // too many missing } + else if(bAllowMissInMiddle) + { + if(comboSearchIndex != 0 &&numMissedMiddle == 0) + numMissedMiddle++; + else + return false; + } else return false; // too long between inputs } @@ -401,7 +407,7 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move // Store this time and location and move onto next input timeLastInputSet = SwitchHistory[historyIndex].TimeSet; lastIndexComboInputWasFound = historyIndex; - numMissed = 0; + numMissedConsecutive = 0; break; } @@ -409,18 +415,335 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move if (bFoundInput == false) { - if (bAllowMiss) - { - // didnt find this one. but might be ok to continue - numMissed++; - if (numMissed == 2) - return false; // too many missing - } - else - return false; // we havent found the input at all + if (bAllowNoConsecutiveMiss) + { + // too long between inputs on this one. but might be ok to continue if this was an older input in the history + numMissedConsecutive++; + if (numMissedConsecutive == 2) + return false; // too many missing + } + else if(bAllowMissInMiddle) + { + if(comboSearchIndex != 0 &&numMissedMiddle == 0) + numMissedMiddle++; + else + return false; + } + else + return false; // we havent found the input at all } } // if we get here we've found every single input! Combo passed return true; } + +void SpecialMoveSystem::GetComboArrayForMove(SpecialMoveInputTypes InputType, std::vector& comboArray, SpecialMoveCircleType CircleStartDirection) +{ + switch(InputType) + { + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_QUARTER_DOWN_RIGHT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_QUARTER_DOWN_LEFT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DP_RIGHT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DP_LEFT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DP_SHORTCUT_RIGHT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DP_SHORTCUT_LEFT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_HALFCIRCLE_LEFT_RIGHT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_HALFCIRCLE_RIGHT_LEFT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DOUBLE_DOWN: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DOUBLE_QUARTER_DOWN_RIGHT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_DOUBLE_QUARTER_DOWN_LEFT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_CHARGE_LEFT_RIGHT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_CHARGE_RIGHT_LEFT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_CHARGE_DOWN_UP: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UP, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_SUPERCHARGE_LEFT_RIGHT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_SUPERCHARGE_RIGHT_LEFT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_RAGING_DEMON_RIGHT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID, SPECIAL_MOVE_BUTTON_MASK_P1)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID, SPECIAL_MOVE_BUTTON_MASK_P1)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_RAGING_DEMON_LEFT: + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID, SPECIAL_MOVE_BUTTON_MASK_P1)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_INVALID, SPECIAL_MOVE_BUTTON_MASK_P1)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_360: + { + if(CircleStartDirection == SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT || CircleStartDirection == SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN ||CircleStartDirection == SPECIALMOVE_CIRCLETYPE_RIGHT_UP ||CircleStartDirection == SPECIALMOVE_CIRCLETYPE_RIGHT_RIGHT) + { + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + } + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + } + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_RIGHT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT, 0)); + } + + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UP, 0)); + + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + } + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + } + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_RIGHT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } + } + else + { + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + } + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_DOWN) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + } + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_DOWN || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_LEFT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT, 0)); + } + + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UP, 0)); + + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_DOWN) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + } + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_DOWN && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_LEFT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + } + } + } break; + + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_720: + { + if(CircleStartDirection == SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT || CircleStartDirection == SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN ||CircleStartDirection == SPECIALMOVE_CIRCLETYPE_RIGHT_UP ||CircleStartDirection == SPECIALMOVE_CIRCLETYPE_RIGHT_RIGHT) + { + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + } + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + } + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_RIGHT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT, 0)); + } + + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UP, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UP, 0)); + + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + } + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + } + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_RIGHT_RIGHT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } + } + else + { + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + } + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_DOWN) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + } + if(CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_DOWN || CircleStartDirection == SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_LEFT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT, 0)); + } + + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UP, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UP, 0)); + + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_UPRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_RIGHT, 0)); + } + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_DOWN) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNRIGHT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); + } + if(CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_DOWN && CircleStartDirection != SpecialMoveCircleType::SPECIALMOVE_CIRCLETYPE_LEFT_LEFT) + { + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWNLEFT, 0)); + comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_LEFT, 0)); + } + } + } break; + + default: + break; + } +} \ No newline at end of file diff --git a/lib/AnimationStation/src/SpecialMoveSystem.hpp b/lib/AnimationStation/src/SpecialMoveSystem.hpp index 496e347955..dd0b1fca88 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.hpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.hpp @@ -18,13 +18,13 @@ #define COMBO_INPUT_TIME_WINDOW 250 //Maximum time between combo movements that arent a charge #define COMBO_TRIGGER_INPUT_TIME_WINDOW 200 //Maximum time between combined button inputs eg PP, PPP, KK or PK etc -#define COMBO_INPUT_COUNT_FOR_ONE_OUT_OF_TWO 7 //if the combo input is 7 or more moves then the input system will allow you to succeed if you dont miss 2 in a row window. eg LDRU would be fine for a SPD +#define COMBO_INPUT_COUNT_FOR_ONE_OUT_OF_TWO 7 //if the combo input is 7 or more moves then the input system will allow you to succeed if you dont miss 2 in a row window. eg LDRU would be fine for a SPD +#define COMBO_INPUT_COUNT_FOR_ONE_MISSING_IN_MIDDLE 5 //if the combo input is 5 (HCF) or more moves then the input system will allow you to succeed if you dont miss more than 1 in the middle //List of specialMove animation typedef enum { SPECIALMOVE_SMEFFECT_WAVE, - SPECIALMOVE_SMEFFECT_SUPERWAVE, SPECIALMOVE_SMEFFECT_PULSECOLOR, SPECIALMOVE_SMEFFECT_CIRCLECOLOR, SPECIALMOVE_SMEFFECT_KNIGHTRIDER, @@ -78,6 +78,20 @@ typedef enum SPECIALMOVE_INPUT_DP_SHORTCUT_RIGHT, SPECIALMOVE_INPUT_DP_LEFT, SPECIALMOVE_INPUT_DP_SHORTCUT_LEFT, + SPECIALMOVE_INPUT_HALFCIRCLE_LEFT_RIGHT, + SPECIALMOVE_INPUT_HALFCIRCLE_RIGHT_LEFT, + SPECIALMOVE_INPUT_DOUBLE_DOWN, + SPECIALMOVE_INPUT_DOUBLE_QUARTER_DOWN_RIGHT, + SPECIALMOVE_INPUT_DOUBLE_QUARTER_DOWN_LEFT, + SPECIALMOVE_INPUT_CHARGE_LEFT_RIGHT, + SPECIALMOVE_INPUT_CHARGE_RIGHT_LEFT, + SPECIALMOVE_INPUT_CHARGE_DOWN_UP, + SPECIALMOVE_INPUT_SUPERCHARGE_LEFT_RIGHT, + SPECIALMOVE_INPUT_SUPERCHARGE_RIGHT_LEFT, + SPECIALMOVE_INPUT_360, + SPECIALMOVE_INPUT_720, + SPECIALMOVE_INPUT_RAGING_DEMON_RIGHT, + SPECIALMOVE_INPUT_RAGING_DEMON_LEFT, } SpecialMoveInputTypes; // SpecialMove joystick directions @@ -94,6 +108,20 @@ typedef enum SPECIALMOVE_STICK_RIGHT, } SpecialMoveStickDirection; +// CircleType +typedef enum +{ + SPECIALMOVE_CIRCLETYPE_LEFT_LEFT, + SPECIALMOVE_CIRCLETYPE_LEFT_DOWN, + SPECIALMOVE_CIRCLETYPE_LEFT_RIGHT, + SPECIALMOVE_CIRCLETYPE_LEFT_UP, + SPECIALMOVE_CIRCLETYPE_RIGHT_LEFT, + SPECIALMOVE_CIRCLETYPE_RIGHT_DOWN, + SPECIALMOVE_CIRCLETYPE_RIGHT_RIGHT, + SPECIALMOVE_CIRCLETYPE_RIGHT_UP, + SPECIALMOVE_CIRCLETYPE_MAX, +} SpecialMoveCircleType; + struct ComboEntry { SpecialMoveStickDirection DirectionInput; @@ -159,6 +187,7 @@ class SpecialMoveSystem { //passed in user options void SetDirectionMasks(uint32_t UpMask, uint32_t DownMask, uint32_t LeftMask, uint32_t RightMask); + void SetButtonMasks(uint32_t P1Mask); //What buttons (logical ones) are pressed this frame void HandlePressedButtons(uint32_t pressedButtons); @@ -179,10 +208,10 @@ class SpecialMoveSystem { void SwitchHistoryCreateNew(uint32_t buttonMask, SpecialMoveStickDirection directionHeld); bool TestAllMoves(); - bool TestForActivatedSpecialMove(SpecialMoveDescription* MoveToTestFor, int ComboIndex, int TriggerIndex); + bool TestForActivatedSpecialMove(SpecialMoveDescription* MoveToTestFor, int ComboIndex, int TriggerIndex, SpecialMoveCircleType CircleStartDirection); void StartMoveAnimation(SpecialMoveEffects AnimationToPlay, uint32_t OptionalParams); - void GetComboArrayForMove(SpecialMoveInputTypes InputType, std::vector& comboArray); + void GetComboArrayForMove(SpecialMoveInputTypes InputType, std::vector& comboArray, SpecialMoveCircleType CircleStartDirection); class AnimationStation* ParentAnimationStation; @@ -199,6 +228,8 @@ class SpecialMoveSystem { uint32_t SPECIAL_MOVE_DIRECTION_MASK_LEFT; uint32_t SPECIAL_MOVE_DIRECTION_MASK_RIGHT; + uint32_t SPECIAL_MOVE_BUTTON_MASK_P1; + bool bMoveIsRunning = false; }; diff --git a/proto/enums.proto b/proto/enums.proto index b40116c5e4..78644b0612 100644 --- a/proto/enums.proto +++ b/proto/enums.proto @@ -315,12 +315,11 @@ enum LEDFormat_Proto enum SpecialMoveEffects_Proto { SMEFFECT_WAVE = 0; - SMEFFECT_SUPERWAVE = 1; - SMEFFECT_PULSECOLOR = 2; - SMEFFECT_CIRCLECOLOR = 3; - SMEFFECT_FLASHCOLOR = 4; - SMEFFECT_KNIGHTRIDER = 5; - SMEFFECT_RANDOMFLASH = 6; + SMEFFECT_PULSECOLOR = 1; + SMEFFECT_CIRCLECOLOR = 2; + SMEFFECT_FLASHCOLOR = 3; + SMEFFECT_KNIGHTRIDER = 4; + SMEFFECT_RANDOMFLASH = 5; } /* This has to be kept in sync with SpecialMoveInputTypes in SpecialMoveSystem.hpp */ @@ -332,6 +331,20 @@ enum SpecialMoveInputTypes_Proto INPUT_DP_SHORTCUT_RIGHT = 3; INPUT_DP_LEFT = 4; INPUT_DP_SHORTCUT_LEFT = 5; + INPUT_HALFCIRCLE_LEFT_RIGHT = 6; + INPUT_HALFCIRCLE_RIGHT_LEFT = 7; + INPUT_DOUBLE_DOWN = 8; + INPUT_DOUBLE_QUARTER_DOWN_RIGHT = 9; + INPUT_DOUBLE_QUARTER_DOWN_LEFT = 10; + INPUT_CHARGE_LEFT_RIGHT = 11; + INPUT_CHARGE_RIGHT_LEFT = 12; + INPUT_CHARGE_DOWN_UP = 13; + INPUT_SUPERCHARGE_LEFT_RIGHT = 14; + INPUT_SUPERCHARGE_RIGHT_LEFT = 15; + INPUT_360 = 16; + INPUT_720 = 17; + INPUT_RAGING_DEMON_RIGHT = 18; + INPUT_RAGING_DEMON_LEFT = 19; } /* This has to be kept in sync with AnimationNonPressedEffects in AnimationStation.hpp */ diff --git a/src/addons/neopicoleds.cpp b/src/addons/neopicoleds.cpp index a892d8e1e0..876bb20b40 100644 --- a/src/addons/neopicoleds.cpp +++ b/src/addons/neopicoleds.cpp @@ -601,6 +601,7 @@ void NeoPicoLEDAddon::configureLEDs() AnimStation.SetBrightness(AnimStation.options.brightness); AnimStation.specialMoveSystem.SetParentAnimationStation(&AnimStation); AnimStation.specialMoveSystem.SetDirectionMasks(GAMEPAD_MASK_DU, GAMEPAD_MASK_DD, GAMEPAD_MASK_DL, GAMEPAD_MASK_DR); + AnimStation.specialMoveSystem.SetButtonMasks(GAMEPAD_MASK_B3); AnimStation.SetLights(RGBLights); AnimStation.SetMode(as.options.baseProfileIndex); } diff --git a/src/config_utils.cpp b/src/config_utils.cpp index ac30e4e389..3d449bea37 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -477,36 +477,22 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) //SpecialMoveOptions //TESTING - if(config.specialMoveOptions.profiles[0].AllSpecialMoves_count == 0) + if(/*config.specialMoveOptions.profiles[0].AllSpecialMoves_count == 0*/true) { - config.specialMoveOptions.profiles[0].AllSpecialMoves_count = 2; + config.specialMoveOptions.profiles[0].AllSpecialMoves_count = 1; - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0], bIsChargeMove, false); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0], Animation, SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE); + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].bIsChargeMove = false; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_CIRCLECOLOR; config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos_count = 1; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_QUARTER_DOWN_RIGHT; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], RequiredTriggers, GAMEPAD_MASK_B3); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0], OptionalParams, 2 + (2 << 4) + (1 << 8) + (0 << 12) + (10 << 16)); //right //slow //1 loop //all lights //colour blue - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], RequiredTriggers, GAMEPAD_MASK_B4); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1], OptionalParams, 2 + (1 << 4) + (1 << 8) + (1 << 12) + (10 << 16)); //right //medium //1 loop //top lights //colour blue - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], RequiredTriggers, GAMEPAD_MASK_R1); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2], OptionalParams, 2 + (0 << 4) + (1 << 8) + (2 << 12) + (10 << 16)); //right //fast //1 loop //bottom lights //colour blue - - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1], bIsChargeMove, false); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1], Animation, SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_PULSECOLOR); - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos_count = 2; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_RIGHT; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos[1] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_SHORTCUT_RIGHT; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos_count = 3; - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[0], RequiredTriggers, GAMEPAD_MASK_B3); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[0], OptionalParams, 0 + (3 << 4) + (0 << 8) + (1 << 16)); //instant in //long duration //instant out //colour white - - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[1], RequiredTriggers, GAMEPAD_MASK_B4); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[1], OptionalParams, 3 + (2 << 4) + (3 << 8) + (1 << 16)); //med in //med duration //med out //colour white - - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[2], RequiredTriggers, GAMEPAD_MASK_R1); - INIT_UNSET_PROPERTY(config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[2], OptionalParams, 5 + (1 << 4) + (5 << 8) + (1 << 16)); //v.slow in //short duration //v.slow out //colour white + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_720; + //config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[1] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_RAGING_DEMON_LEFT; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 1; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 0 + (1 << 4) + (1 << 8) + (11 << 12) + (0 << 20); //anti //slow //1 loop //colour blue //colour black + //config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4; + //config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 0 + (2 << 4) + (4 << 8) + (11 << 12) + (2 << 20); //anti //medium //4 loop //colour blue //colour Red + //config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_R1; + //config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2].OptionalParams = 1 + (3 << 4) + (4 << 8) + (11 << 12) + (2 << 20); //clock //fast //4 loop //colour blue //colour Red } if(config.specialMoveOptions.profiles_count == 0) From 867b45a3b337f695b7ca548fdb1d34fa596c374f Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Mon, 16 Dec 2024 22:56:43 +0000 Subject: [PATCH 012/121] beta? Fixed crash if no light data set. Added SM profile label. Added LCD screen popups when changing LED or SM profile. --- configs/Haute42COSMOX/BoardConfig.h | 4 +- .../display/ui/screens/ButtonLayoutScreen.h | 13 +- lib/AnimationStation/src/Animation.cpp | 2 +- lib/AnimationStation/src/AnimationStation.cpp | 29 +++- lib/AnimationStation/src/AnimationStation.hpp | 9 +- .../src/SpecialMoveSystem.cpp | 77 ++++++++- .../src/SpecialMoveSystem.hpp | 5 + proto/config.proto | 8 +- src/addons/neopicoleds.cpp | 161 ++++++++++-------- src/config_utils.cpp | 133 ++++++++++----- src/configs/webconfig.cpp | 4 +- src/display/ui/screens/ButtonLayoutScreen.cpp | 100 ++++++++--- src/storagemanager.cpp | 7 +- 13 files changed, 390 insertions(+), 162 deletions(-) diff --git a/configs/Haute42COSMOX/BoardConfig.h b/configs/Haute42COSMOX/BoardConfig.h index 3089f66dac..be4492cf9c 100644 --- a/configs/Haute42COSMOX/BoardConfig.h +++ b/configs/Haute42COSMOX/BoardConfig.h @@ -119,7 +119,7 @@ //l3 //r3 //m2 (extra button 2) -#define LIGHT_DATA_SIZE 16 //number of sets in the below data +/*#define LIGHT_DATA_SIZE 16 //number of sets in the below data #define LIGHT_DATA \ 0, 1, 0, 2, 5, LightType_Proto::LightType_Proto_ActionButton, \ 1, 1, 2, 2, 3, LightType_Proto::LightType_Proto_ActionButton, \ @@ -136,7 +136,7 @@ 12, 1, 3, 0, 27, LightType_Proto::LightType_Proto_ActionButton, \ 13, 1, 6, 0, 18, LightType_Proto::LightType_Proto_ActionButton, \ 14, 1, 8, 5, 19, LightType_Proto::LightType_Proto_ActionButton, \ -15, 1, 3, 6, 26, LightType_Proto::LightType_Proto_ActionButton +15, 1, 3, 6, 26, LightType_Proto::LightType_Proto_ActionButton*/ #define HAS_I2C_DISPLAY 1 #define I2C0_ENABLED 1 diff --git a/headers/display/ui/screens/ButtonLayoutScreen.h b/headers/display/ui/screens/ButtonLayoutScreen.h index ce1a42fc67..4b01c1f7bc 100644 --- a/headers/display/ui/screens/ButtonLayoutScreen.h +++ b/headers/display/ui/screens/ButtonLayoutScreen.h @@ -102,6 +102,7 @@ class ButtonLayoutScreen : public GPScreen { virtual int8_t update(); virtual void init(); virtual void shutdown(); + protected: virtual void drawScreen(); private: @@ -113,6 +114,9 @@ class ButtonLayoutScreen : public GPScreen { GPWidget* pushElement(GPButtonLayout element); void generateHeader(); + void updateCustomHeaders(); + void addCustomHeader(std::string newStr); + const std::map displayModeLookup = { {INPUT_MODE_PS3, 0}, {INPUT_MODE_GENERIC, 0}, @@ -144,13 +148,20 @@ class ButtonLayoutScreen : public GPScreen { std::deque inputHistory; std::array lastInput; + bool gamepadProfileModeDisplay; + bool ledAnimationProfileModeDisplay; + bool specialMoveProfileModeDisplay; bool profileModeDisplay; uint8_t profileDelay = 2; int profileDelayStart = 0; + std::string profileModeString; + uint8_t prevGamepadProfileNumber = 0; + uint8_t prevLEDAnimationProfileNumber = 0; + uint8_t prevSpecialMoveProfileNumber = 0; + uint16_t prevButtonState = 0; uint8_t prevLayoutLeft = 0; uint8_t prevLayoutRight = 0; - uint8_t prevProfileNumber = 0; ButtonLayoutParamsLeft prevLeftOptions; ButtonLayoutParamsRight prevRightOptions; diff --git a/lib/AnimationStation/src/Animation.cpp b/lib/AnimationStation/src/Animation.cpp index 99354d9e12..640a5e0ba4 100644 --- a/lib/AnimationStation/src/Animation.cpp +++ b/lib/AnimationStation/src/Animation.cpp @@ -169,7 +169,7 @@ bool Animation::LightTypeIsForPressedAnimation(LightType Type) bool Animation::LightTypeIsForSpecialMoveAnimation(LightType Type) { - if(Type == LightType::LightType_ActionButton || Type == LightType::LightType_Case) + if(Type == LightType::LightType_ActionButton || (Type == LightType::LightType_Case && AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].bUseCaseLightsInSpecialMoves)) return true; return false; diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index 4fc4bcf207..2db8782d5f 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -70,6 +70,16 @@ void AnimationStation::HandleEvent(AnimationHotkey action) ChangeProfile(-1); } + //Switch to new profile + if (action == HOTKEY_LEDS_SPECIALMOVE_PROFILE_UP) + { + specialMoveSystem.ChangeSpecialMoveProfile(1); + } + if (action == HOTKEY_LEDS_SPECIALMOVE_PROFILE_DOWN) + { + specialMoveSystem.ChangeSpecialMoveProfile(-1); + } + //Adjust existing profile hotkeys if (this->baseAnimation == nullptr || this->buttonAnimation == nullptr) { @@ -104,17 +114,20 @@ uint16_t AnimationStation::AdjustIndex(int changeSize) std::vector validIndexes; //if no profiles defined then return -1 to turn everything off + if(options.NumValidProfiles == 0) + return -1; + + //Check to see which ones are enabled. If none then return -1 to turn everything off for(int index = 0; index < MAX_ANIMATION_PROFILES; ++index) { - if(options.profiles[index].bIsValidProfile) + if(options.profiles[index].bEnabled) validIndexes.push_back(index); } - if(validIndexes.size() == 0) return -1; //find index of current profile - int indexOfCurrentProfile = 0; + int indexOfCurrentProfile = -1; for(unsigned int index = 0; index < validIndexes.size(); ++index) { if(validIndexes[index] == (int)this->options.baseProfileIndex) @@ -148,12 +161,14 @@ void AnimationStation::HandlePressedPins(std::vector pressedPins) if(pressedPins.size()) { this->lastPressed = pressedPins; - this->buttonAnimation->UpdatePressed(pressedPins); + if(this->buttonAnimation) + this->buttonAnimation->UpdatePressed(pressedPins); } else { this->lastPressed.clear(); - this->buttonAnimation->ClearPressed(); + if(this->buttonAnimation) + this->buttonAnimation->ClearPressed(); } } @@ -322,11 +337,11 @@ void AnimationStation::SetMode(int8_t mode) } } -void AnimationStation::SetOptions(AnimationOptions InOptions) +/*void AnimationStation::SetOptions(AnimationOptions InOptions) { options = InOptions; AnimationStation::SetBrightness(options.brightness); -} +}*/ /////////////////////////////////// // Brightness functions diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index ac061ef776..9595f2673c 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -50,11 +50,13 @@ typedef enum HOTKEY_LEDS_PARAMETER_DOWN, HOTKEY_LEDS_BRIGHTNESS_UP, HOTKEY_LEDS_BRIGHTNESS_DOWN, + HOTKEY_LEDS_SPECIALMOVE_PROFILE_UP, + HOTKEY_LEDS_SPECIALMOVE_PROFILE_DOWN, } AnimationHotkey; struct __attribute__ ((__packed__)) AnimationProfile { - bool bIsValidProfile; + bool bEnabled = false; AnimationNonPressedEffects baseNonPressedEffect; AnimationPressedEffects basePressedEffect; @@ -68,11 +70,14 @@ struct __attribute__ ((__packed__)) AnimationProfile uint32_t buttonPressFadeOutTimeInMs; uint32_t nonPressedSpecialColour; + + bool bUseCaseLightsInSpecialMoves; }; struct __attribute__ ((__packed__)) AnimationOptions { uint32_t checksum; + uint8_t NumValidProfiles; AnimationProfile profiles[MAX_ANIMATION_PROFILES]; uint8_t brightness; uint8_t baseProfileIndex; @@ -112,7 +117,7 @@ class AnimationStation static void DimBrightnessTo0(); //passed in user options - static void SetOptions(AnimationOptions InOptions); + //static void SetOptions(AnimationOptions InOptions); //special move anim void SetSpecialMoveAnimation(SpecialMoveEffects AnimationToPlay, uint32_t OptionalParams); diff --git a/lib/AnimationStation/src/SpecialMoveSystem.cpp b/lib/AnimationStation/src/SpecialMoveSystem.cpp index 05006837b7..60be558e67 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.cpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.cpp @@ -14,6 +14,73 @@ void SpecialMoveSystem::SetParentAnimationStation(class AnimationStation* InPare ClearHistory(); } +void SpecialMoveSystem::Init() +{ + AdjustSpecialMoveProfileIndex(0); +} + +void SpecialMoveSystem::ChangeSpecialMoveProfile(int changeSize) +{ + AdjustSpecialMoveProfileIndex(changeSize); +} + +void SpecialMoveSystem::AdjustSpecialMoveProfileIndex(int changeSize) +{ + std::vector validIndexes; + + //if no profiles defined then return -1 to turn everything off + if(Options.NumValidProfiles == 0) + { + this->Options.CurrentProfileIndex = 0; + return; + } + + for(int index = 0; index < MAX_SPECIALMOVE_PROFILES; ++index) + { + if(Options.profiles[index].bEnabled) + validIndexes.push_back(index); + } + + if(validIndexes.size() == 0) + { + this->Options.CurrentProfileIndex = 0; + return; + } + + //find index of current profile + int indexOfCurrentProfile = -1; + for(unsigned int index = 0; index < validIndexes.size(); ++index) + { + if(validIndexes[index] == (int)this->Options.CurrentProfileIndex) + { + indexOfCurrentProfile = index; + break; + } + } + + //if we cant find it then this is probably the first call and the first profile isnt valid. Just return whichever is the first valid profile + if(indexOfCurrentProfile == -1) + { + this->Options.CurrentProfileIndex = 0; + return; + } + + int newProfileIndex = indexOfCurrentProfile + changeSize; + + if (newProfileIndex >= (int)validIndexes.size()) + { + this->Options.CurrentProfileIndex = validIndexes[0]; + } + else if (newProfileIndex < 0) + { + this->Options.CurrentProfileIndex = validIndexes[validIndexes.size() - 1]; + } + else + { + this->Options.CurrentProfileIndex = validIndexes[newProfileIndex]; + } +} + void SpecialMoveSystem::Update() { thisFrameTime = get_absolute_time(); @@ -29,6 +96,10 @@ void SpecialMoveSystem::Update() bool SpecialMoveSystem::TestAllMoves() { + //Do we have any valid profiles? + if(Options.NumValidProfiles == 0 || Options.CurrentProfileIndex > Options.NumValidProfiles || Options.profiles[Options.CurrentProfileIndex].bEnabled == false) + return false; + //Test Each move uint32_t numMoves = Options.profiles[Options.CurrentProfileIndex].NumValidMoves; for(uint32_t moveIndex = 0; moveIndex < numMoves; ++moveIndex) @@ -356,14 +427,8 @@ bool SpecialMoveSystem::TestForActivatedSpecialMove(SpecialMoveDescription* Move bool bFoundInput = false; for (int historyIndex = lastIndexComboInputWasFound + 1; historyIndex < MAX_INPUT_HISTORY; ++historyIndex) { - AnimationStation::printfs[0] = "LastTested = " + std::to_string(comboSearchIndex); if (DoesInputMatch(historyIndex, comboArray[comboSearchIndex], bIsChargeCombo)) { - if(comboSearchIndex == 0 || comboSearchIndex == 1) - { - AnimationStation::printfs[1] = "passed = " + std::to_string(comboSearchIndex); - } - bFoundInput = true; // Is this the last input and if so is it a charge input as they're special and diff --git a/lib/AnimationStation/src/SpecialMoveSystem.hpp b/lib/AnimationStation/src/SpecialMoveSystem.hpp index dd0b1fca88..46d2c70bc0 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.hpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.hpp @@ -164,6 +164,7 @@ struct __attribute__ ((__packed__)) SpecialMoveDescription struct __attribute__ ((__packed__)) SpecialMoveProfile { + bool bEnabled = false; uint32_t NumValidMoves = 0; SpecialMoveDescription AllSpecialMoves[MAX_SPECIALMOVES]; }; @@ -182,6 +183,9 @@ class SpecialMoveSystem { SpecialMoveSystem(); virtual ~SpecialMoveSystem(){}; + void Init(); + void ChangeSpecialMoveProfile(int changeSize); + //Which buttons are held at the moment void Update(); @@ -199,6 +203,7 @@ class SpecialMoveSystem { protected: + void AdjustSpecialMoveProfileIndex(int changeSize); void ClearHistory(); int64_t GetMsBetweenTimes(absolute_time_t start, absolute_time_t end); void UpdateHistoryForInput(uint32_t buttonMask, SpecialMoveStickDirection directionHeld, bool bIsPressed); diff --git a/proto/config.proto b/proto/config.proto index 1da9511c52..11b37f156b 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -313,7 +313,9 @@ message SpecialMoveDescription_Proto // This has to be kept in sync with SpecialMoveProfile in SpecialMoveSystem.hpp message SpecialMoveProfile_Proto { - repeated SpecialMoveDescription_Proto AllSpecialMoves = 1 [(nanopb).max_count = 20]; //MAX_SPECIALMOVES from SpecialMoveSystem.hpp + optional bool bEnabled = 1; + repeated SpecialMoveDescription_Proto AllSpecialMoves = 2 [(nanopb).max_count = 20]; //MAX_SPECIALMOVES from SpecialMoveSystem.hpp + optional string Label = 3 [(nanopb).max_length = 12]; }; // This has to be kept in sync with SpecialMoveOptions in SpecialMoveSystem.hpp @@ -327,7 +329,7 @@ message SpecialMoveOptions_Proto // This has to be kept in sync with AnimationProfile in AnimationStation.hpp message AnimationProfile_Proto { - optional bool bIsValidProfile = 1; + optional bool bEnabled = 1; optional AnimationNonPressedEffects_Proto baseNonPressedEffect = 2; optional AnimationPressedEffects_Proto basePressedEffect = 3; @@ -341,6 +343,8 @@ message AnimationProfile_Proto optional uint32 buttonPressFadeOutTimeInMs = 8; optional uint32 nonPressedSpecialColour = 9; + + optional bool bUseCaseLightsInSpecialMoves = 10; }; // This has to be kept in sync with AnimationOptions in AnimationStation.hpp diff --git a/src/addons/neopicoleds.cpp b/src/addons/neopicoleds.cpp index 876bb20b40..c8ba6a927e 100644 --- a/src/addons/neopicoleds.cpp +++ b/src/addons/neopicoleds.cpp @@ -368,29 +368,29 @@ void NeoPicoLEDAddon::generatedLEDButtons(std::vector> *pos out_lightDataSize = 18; //8 action buttons in 2x4 array - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B3], ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 0, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B1], ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 0, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); + generateLegacyIndividualLight(0, ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 0, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); + generateLegacyIndividualLight(1, ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 0, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B4], ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B2], ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 1, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); + generateLegacyIndividualLight(2, ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); + generateLegacyIndividualLight(3, ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 1, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R1], ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 2, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R2], ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 2, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); + generateLegacyIndividualLight(4, ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 2, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); + generateLegacyIndividualLight(5, ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 2, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L1], ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L2], ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 3, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); + generateLegacyIndividualLight(6, ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); + generateLegacyIndividualLight(7, ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 3, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); //extras - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_LEFT], ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 4, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_DOWN], ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_RIGHT], ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 4, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_UP], ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 4, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S1], ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 4, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S2], ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 4, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L3], ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 4, 6, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R3], ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 4, 7, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A1], ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 4, 8, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A2], ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 4, 9, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); + generateLegacyIndividualLight(8, ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 4, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); + generateLegacyIndividualLight(9, ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); + generateLegacyIndividualLight(10, ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 4, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); + generateLegacyIndividualLight(11, ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 4, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); + generateLegacyIndividualLight(12, ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 4, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); + generateLegacyIndividualLight(13, ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 4, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); + generateLegacyIndividualLight(14, ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 4, 6, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); + generateLegacyIndividualLight(15, ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 4, 7, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); + generateLegacyIndividualLight(16, ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 4, 8, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); + generateLegacyIndividualLight(17, ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 4, 9, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); } /** @@ -400,33 +400,33 @@ void NeoPicoLEDAddon::generatedLEDStickless(vector> *positions, { out_lightDataSize = 18; - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_LEFT], ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 0, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); + generateLegacyIndividualLight(0, ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 0, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_DOWN], ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); + generateLegacyIndividualLight(1, ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_RIGHT], ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 2, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); + generateLegacyIndividualLight(2, ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 2, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_UP], ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); + generateLegacyIndividualLight(3, ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B3], ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 4, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B1], ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); + generateLegacyIndividualLight(4, ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 4, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); + generateLegacyIndividualLight(5, ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B4], ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 5, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B2], ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 5, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); + generateLegacyIndividualLight(6, ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 5, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); + generateLegacyIndividualLight(7, ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 5, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R1], ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 6, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R2], ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 6, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); + generateLegacyIndividualLight(8, ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 6, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); + generateLegacyIndividualLight(9, ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 6, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L1], ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 7, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L2], ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 7, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); + generateLegacyIndividualLight(10, ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 7, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); + generateLegacyIndividualLight(11, ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 7, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); //extras - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S1], ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 8, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S2], ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 8, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L3], ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 8, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R3], ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 8, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A1], ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 8, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A2], ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 8, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); + generateLegacyIndividualLight(12, ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 8, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); + generateLegacyIndividualLight(13, ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 8, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); + generateLegacyIndividualLight(14, ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 8, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); + generateLegacyIndividualLight(15, ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 8, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); + generateLegacyIndividualLight(16, ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 8, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); + generateLegacyIndividualLight(17, ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 8, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); } /** @@ -436,32 +436,32 @@ void NeoPicoLEDAddon::generatedLEDWasd(std::vector> *positi { out_lightDataSize = 18; - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_LEFT], ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 0, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); + generateLegacyIndividualLight(0, ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 0, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_UP], ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_DOWN], ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 1, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); + generateLegacyIndividualLight(1, ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); + generateLegacyIndividualLight(2, ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 1, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_RIGHT], ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 2, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); + generateLegacyIndividualLight(3, ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 2, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B3], ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B1], ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 3, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); + generateLegacyIndividualLight(4, ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); + generateLegacyIndividualLight(5, ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 3, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B4], ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 4, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B2], ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); + generateLegacyIndividualLight(6, ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 4, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); + generateLegacyIndividualLight(7, ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R1], ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 5, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R2], ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 5, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); + generateLegacyIndividualLight(8, ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 5, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); + generateLegacyIndividualLight(9, ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 5, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L1], ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 6, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L2], ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 6, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); + generateLegacyIndividualLight(10, ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 6, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); + generateLegacyIndividualLight(11, ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 6, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); //extras - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S1], ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 7, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S2], ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 7, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L3], ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 7, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R3], ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 7, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A1], ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 7, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A2], ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 7, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); + generateLegacyIndividualLight(12, ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 7, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); + generateLegacyIndividualLight(13, ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 7, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); + generateLegacyIndividualLight(14, ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 7, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); + generateLegacyIndividualLight(15, ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 7, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); + generateLegacyIndividualLight(16, ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 7, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); + generateLegacyIndividualLight(17, ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 7, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); } /** @@ -469,34 +469,34 @@ void NeoPicoLEDAddon::generatedLEDWasd(std::vector> *positi */ void NeoPicoLEDAddon::generatedLEDWasdFBM(std::vector> *positions, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize) { - out_lightDataSize = 18; + out_lightDataSize = 18; - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L1], ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 0, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L2], ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 0, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); + generateLegacyIndividualLight(0, ledsPerPixel * buttonPositions[BUTTON_LABEL_L1], 0, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_L1); + generateLegacyIndividualLight(1, ledsPerPixel * buttonPositions[BUTTON_LABEL_L2], 0, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_L2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R1], ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R2], ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 1, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); + generateLegacyIndividualLight(2, ledsPerPixel * buttonPositions[BUTTON_LABEL_R1], 1, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_R1); + generateLegacyIndividualLight(3, ledsPerPixel * buttonPositions[BUTTON_LABEL_R2], 1, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_R2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B4], ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 2, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B2], ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 2, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); + generateLegacyIndividualLight(4, ledsPerPixel * buttonPositions[BUTTON_LABEL_B4], 2, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B4); + generateLegacyIndividualLight(5, ledsPerPixel * buttonPositions[BUTTON_LABEL_B2], 2, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B3], ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_B1], ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 3, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); + generateLegacyIndividualLight(6, ledsPerPixel * buttonPositions[BUTTON_LABEL_B3], 3, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_B3); + generateLegacyIndividualLight(7, ledsPerPixel * buttonPositions[BUTTON_LABEL_B1], 3, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_B1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_LEFT], ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); + generateLegacyIndividualLight(8, ledsPerPixel * buttonPositions[BUTTON_LABEL_LEFT], 4, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_LEFT); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_UP], ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 5, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_DOWN], ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 5, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); + generateLegacyIndividualLight(9, ledsPerPixel * buttonPositions[BUTTON_LABEL_UP], 5, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_UP); + generateLegacyIndividualLight(10, ledsPerPixel * buttonPositions[BUTTON_LABEL_DOWN], 5, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_DOWN); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_RIGHT], ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 6, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); + generateLegacyIndividualLight(11, ledsPerPixel * buttonPositions[BUTTON_LABEL_RIGHT], 6, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_RIGHT); //extras - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S1], ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 7, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_S2], ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 7, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_L3], ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 7, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_R3], ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 7, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A1], ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 7, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); - generateLegacyIndividualLight(buttonPositions[BUTTON_LABEL_A2], ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 7, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); + generateLegacyIndividualLight(12, ledsPerPixel * buttonPositions[BUTTON_LABEL_S1], 7, 0, ledsPerPixel, out_lightData, BUTTON_PRESS_S1); + generateLegacyIndividualLight(13, ledsPerPixel * buttonPositions[BUTTON_LABEL_S2], 7, 1, ledsPerPixel, out_lightData, BUTTON_PRESS_S2); + generateLegacyIndividualLight(14, ledsPerPixel * buttonPositions[BUTTON_LABEL_L3], 7, 2, ledsPerPixel, out_lightData, BUTTON_PRESS_L3); + generateLegacyIndividualLight(15, ledsPerPixel * buttonPositions[BUTTON_LABEL_R3], 7, 3, ledsPerPixel, out_lightData, BUTTON_PRESS_R3); + generateLegacyIndividualLight(16, ledsPerPixel * buttonPositions[BUTTON_LABEL_A1], 7, 4, ledsPerPixel, out_lightData, BUTTON_PRESS_A1); + generateLegacyIndividualLight(17, ledsPerPixel * buttonPositions[BUTTON_LABEL_A2], 7, 5, ledsPerPixel, out_lightData, BUTTON_PRESS_A2); } void NeoPicoLEDAddon::createLEDLayout(ButtonLayout layout, uint8_t ledsPerPixel, uint8_t ledButtonCount, LEDOptions_lightData_t& out_lightData, int32_t& out_lightDataSize) @@ -519,11 +519,14 @@ void NeoPicoLEDAddon::createLEDLayout(ButtonLayout layout, uint8_t ledsPerPixel, case BUTTON_LAYOUT_STICKLESS_R16: case BUTTON_LAYOUT_BOARD_DEFINED_A: generatedLEDStickless(&positions, ledsPerPixel, out_lightData, out_lightDataSize); + break; case BUTTON_LAYOUT_FIGHTBOARD_MIRRORED: generatedLEDWasdFBM(&positions, ledsPerPixel, out_lightData, out_lightDataSize); + break; case BUTTON_LAYOUT_BUTTONS_ANGLED: case BUTTON_LAYOUT_FIGHTBOARD_STICK: generatedLEDWasd(&positions, ledsPerPixel, out_lightData, out_lightDataSize); + break; case BUTTON_LAYOUT_BLANKA: case BUTTON_LAYOUT_BUTTONS_BASIC: case BUTTON_LAYOUT_KEYBOARD_ANGLED: @@ -534,6 +537,7 @@ void NeoPicoLEDAddon::createLEDLayout(ButtonLayout layout, uint8_t ledsPerPixel, case BUTTON_LAYOUT_VLXA: default: generatedLEDButtons(&positions, ledsPerPixel, out_lightData, out_lightDataSize); + break; } } @@ -602,6 +606,7 @@ void NeoPicoLEDAddon::configureLEDs() AnimStation.specialMoveSystem.SetParentAnimationStation(&AnimStation); AnimStation.specialMoveSystem.SetDirectionMasks(GAMEPAD_MASK_DU, GAMEPAD_MASK_DD, GAMEPAD_MASK_DL, GAMEPAD_MASK_DR); AnimStation.specialMoveSystem.SetButtonMasks(GAMEPAD_MASK_B3); + AnimStation.specialMoveSystem.Init(); AnimStation.SetLights(RGBLights); AnimStation.SetMode(as.options.baseProfileIndex); } @@ -680,6 +685,16 @@ AnimationHotkey NeoPicoLEDAddon::ProcessAnimationHotkeys(Gamepad *gamepad) action = HOTKEY_LEDS_PRESS_PARAMETER_DOWN; gamepad->state.buttons &= ~(GAMEPAD_MASK_L2 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); } + else if (gamepad->pressedL3()) + { + action = HOTKEY_LEDS_SPECIALMOVE_PROFILE_UP; + gamepad->state.buttons &= ~(GAMEPAD_MASK_L3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } + else if (gamepad->pressedR3()) + { + action = HOTKEY_LEDS_SPECIALMOVE_PROFILE_DOWN; + gamepad->state.buttons &= ~(GAMEPAD_MASK_R3 | GAMEPAD_MASK_S1 | GAMEPAD_MASK_S2); + } } return action; diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 3d449bea37..ae6daf0da0 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -476,57 +476,102 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY_BYTES(config.ledOptions, lightData, lightData); //SpecialMoveOptions - //TESTING - if(/*config.specialMoveOptions.profiles[0].AllSpecialMoves_count == 0*/true) - { - config.specialMoveOptions.profiles[0].AllSpecialMoves_count = 1; - - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].bIsChargeMove = false; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_CIRCLECOLOR; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos_count = 1; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_720; - //config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[1] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_RAGING_DEMON_LEFT; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 1; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 0 + (1 << 4) + (1 << 8) + (11 << 12) + (0 << 20); //anti //slow //1 loop //colour blue //colour black - //config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4; - //config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 0 + (2 << 4) + (4 << 8) + (11 << 12) + (2 << 20); //anti //medium //4 loop //colour blue //colour Red - //config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_R1; - //config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2].OptionalParams = 1 + (3 << 4) + (4 << 8) + (11 << 12) + (2 << 20); //clock //fast //4 loop //colour blue //colour Red - } - - if(config.specialMoveOptions.profiles_count == 0) - config.specialMoveOptions.profiles_count = 1; INIT_UNSET_PROPERTY(config.specialMoveOptions, ChargeTimeInMs, 750); INIT_UNSET_PROPERTY(config.specialMoveOptions, CurrentProfileIndex, 0); // animationOptions - if(config.animationOptions.profiles_count == 0) - config.animationOptions.profiles_count = 1; - for (unsigned int profileIndex = 0; profileIndex < 4; ++profileIndex) /* MAX_ANIMATION_PROFILES from AnimationStation.hpp */ - { - config.animationOptions.profiles[profileIndex].notPressedStaticColors_count = NUM_BANK0_GPIOS; - config.animationOptions.profiles[profileIndex].pressedStaticColors_count = NUM_BANK0_GPIOS; - if(config.animationOptions.profiles[profileIndex].has_bIsValidProfile || config.animationOptions.profiles[profileIndex].bIsValidProfile == false) - { - for (unsigned int lightIndex = 0; lightIndex < NUM_BANK0_GPIOS; ++lightIndex) - { - config.animationOptions.profiles[profileIndex].notPressedStaticColors[lightIndex] = 0; - config.animationOptions.profiles[profileIndex].pressedStaticColors[lightIndex] = 0; - } - } - - INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], bIsValidProfile, profileIndex == 0 ? true : false); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], baseNonPressedEffect, AnimationNonPressedEffects_Proto::AnimationNonPressedEffects_Proto_EFFECT_RAINBOW_SYNCED); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], basePressedEffect, AnimationPressedEffects_Proto::AnimationPressedEffects_Proto_EFFECT_HELD_STATIC_COLOR); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], baseCycleTime, 1); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], buttonPressHoldTimeInMs, 500); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], buttonPressFadeOutTimeInMs, 500); - INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], nonPressedSpecialColour, 255 << 16); //RED - } INIT_UNSET_PROPERTY(config.animationOptions, brightness, LEDS_BRIGHTNESS); INIT_UNSET_PROPERTY(config.animationOptions, baseProfileIndex, 0); + //TESTING + config.specialMoveOptions.profiles_count = 0; + config.animationOptions.profiles_count = 0; + if(true) + { + config.specialMoveOptions.profiles_count = 2; + + config.specialMoveOptions.profiles[0].bEnabled = true; + config.specialMoveOptions.profiles[0].AllSpecialMoves_count = 2; + strncpy(config.specialMoveOptions.profiles[0].Label, "Ryu", sizeof(config.specialMoveOptions.profiles[0].Label) - 1); + + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].bIsChargeMove = false; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos_count = 1; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_QUARTER_DOWN_LEFT; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 1 + (1 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //Left //slow //1 loop //all lights //colour skyblue + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 1 + (2 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //Left //medium //1 loop //all lights //colour skyblue + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_R1; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2].OptionalParams = 1 + (3 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //Left //fast //1 loop //all lights //colour skyblue + + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].bIsChargeMove = false; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos_count = 1; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_QUARTER_DOWN_RIGHT; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos_count = 3; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[0].OptionalParams = 2 + (1 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //right //slow //1 loop //all lights //colour skyblue + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[1].OptionalParams = 2 + (2 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //right //medium //1 loop //all lights //colour skyblue + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_R1; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[2].OptionalParams = 2 + (3 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //right //fast //1 loop //all lights //colour skyblue + + + config.specialMoveOptions.profiles[1].bEnabled = true; + config.specialMoveOptions.profiles[1].AllSpecialMoves_count = 1; + strncpy(config.specialMoveOptions.profiles[1].Label, "Ken Masters", sizeof(config.specialMoveOptions.profiles[0].Label) - 1); + + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].bIsChargeMove = false; + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE; + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredInputCombos_count = 2; + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_LEFT; + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredInputCombos[1] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_RIGHT; + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3; + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 0 + (3 << 4) + (1 << 8) + (0 << 12) + (1 << 16); //up //fast //1 loop //all lights //colour white + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4; + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 0 + (2 << 4) + (1 << 8) + (0 << 12) + (1 << 16); //up //medium //1 loop //all lights //colour white + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_R1; + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[2].OptionalParams = 0 + (1 << 4) + (1 << 8) + (0 << 12) + (1 << 16); //up //slow //1 loop //all lights //colour white + + + config.animationOptions.profiles_count = 2; + + config.animationOptions.profiles[0].bEnabled = true; + config.animationOptions.profiles[0].notPressedStaticColors_count = NUM_BANK0_GPIOS; + config.animationOptions.profiles[0].pressedStaticColors_count = NUM_BANK0_GPIOS; + for (unsigned int lightIndex = 0; lightIndex < NUM_BANK0_GPIOS; ++lightIndex) + { + config.animationOptions.profiles[0].notPressedStaticColors[lightIndex] = 0; //Black + config.animationOptions.profiles[0].pressedStaticColors[lightIndex] = 0; //Black + } + config.animationOptions.profiles[0].baseNonPressedEffect = AnimationNonPressedEffects_Proto::AnimationNonPressedEffects_Proto_EFFECT_RAINBOW_SYNCED; + config.animationOptions.profiles[0].basePressedEffect = AnimationPressedEffects_Proto::AnimationPressedEffects_Proto_EFFECT_HELD_STATIC_COLOR; + config.animationOptions.profiles[0].baseCycleTime = 1; + config.animationOptions.profiles[0].buttonPressHoldTimeInMs = 500; + config.animationOptions.profiles[0].buttonPressFadeOutTimeInMs = 500; + config.animationOptions.profiles[0].nonPressedSpecialColour = 255 << 16; //RED + config.animationOptions.profiles[0].bUseCaseLightsInSpecialMoves = false; + + config.animationOptions.profiles[1].bEnabled = true; + config.animationOptions.profiles[1].notPressedStaticColors_count = NUM_BANK0_GPIOS; + config.animationOptions.profiles[1].pressedStaticColors_count = NUM_BANK0_GPIOS; + for (unsigned int lightIndex = 0; lightIndex < NUM_BANK0_GPIOS; ++lightIndex) + { + config.animationOptions.profiles[1].notPressedStaticColors[lightIndex] = 255 << 8; //Green + config.animationOptions.profiles[1].pressedStaticColors[lightIndex] = 0; //Black + } + config.animationOptions.profiles[1].baseNonPressedEffect = AnimationNonPressedEffects_Proto::AnimationNonPressedEffects_Proto_EFFECT_CHASE_SEQUENTIAL; + config.animationOptions.profiles[1].basePressedEffect = AnimationPressedEffects_Proto::AnimationPressedEffects_Proto_EFFECT_RANDOM; + config.animationOptions.profiles[1].baseCycleTime = 1; + config.animationOptions.profiles[1].buttonPressHoldTimeInMs = 500; + config.animationOptions.profiles[1].buttonPressFadeOutTimeInMs = 500; + config.animationOptions.profiles[1].nonPressedSpecialColour = 255 << 16; //RED + config.animationOptions.profiles[1].bUseCaseLightsInSpecialMoves = true; + } + // addonOptions.bootselButtonOptions INIT_UNSET_PROPERTY(config.addonOptions.bootselButtonOptions, enabled, !!BOOTSEL_BUTTON_ENABLED); INIT_UNSET_PROPERTY(config.addonOptions.bootselButtonOptions, buttonMap, BOOTSEL_BUTTON_MASK); diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index 29915b227b..a9d22e2080 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -1004,8 +1004,8 @@ std::string setCustomTheme() readDoc(pressCooldown, doc, "buttonPressColorCooldownTimeInMs"); options.buttonPressColorCooldownTimeInMs = pressCooldown;*/ - AnimationStation::SetOptions(options); - AnimationStore.save(); + //AnimationStation::SetOptions(options); + //AnimationStore.save(); return serialize_json(doc); } diff --git a/src/display/ui/screens/ButtonLayoutScreen.cpp b/src/display/ui/screens/ButtonLayoutScreen.cpp index f9200490f3..6a2e4ba162 100644 --- a/src/display/ui/screens/ButtonLayoutScreen.cpp +++ b/src/display/ui/screens/ButtonLayoutScreen.cpp @@ -33,8 +33,9 @@ void ButtonLayoutScreen::init() { } // start with profile mode displayed - profileModeDisplay = true; - prevProfileNumber = -1; + prevGamepadProfileNumber = -1; + prevLEDAnimationProfileNumber = -1; + prevSpecialMoveProfileNumber = -1; prevLayoutLeft = Storage::getInstance().getDisplayOptions().buttonLayout; prevLayoutRight = Storage::getInstance().getDisplayOptions().buttonLayoutRight; prevLeftOptions = Storage::getInstance().getDisplayOptions().buttonLayoutCustomOptions.paramsLeft; @@ -70,27 +71,89 @@ void ButtonLayoutScreen::shutdown() { clearElements(); } +void ButtonLayoutScreen::addCustomHeader(std::string newStr){ + profileDelayStart = getMillis(); + profileModeString = newStr; + profileModeDisplay = true; +} + +void ButtonLayoutScreen::updateCustomHeaders() +{ + Storage& storage = Storage::getInstance(); + + // Check to see if gamepad profile has changed + if(!ledAnimationProfileModeDisplay && !specialMoveProfileModeDisplay){ + uint8_t profileNumber = getGamepad()->getOptions().profileNumber; + if (prevGamepadProfileNumber != profileNumber) { + prevGamepadProfileNumber = profileNumber; + + std::string profileStr; + profileStr.assign(storage.currentProfileLabel(), strlen(storage.currentProfileLabel())); + if (profileStr.empty()) { + profileStr = " Profile #"; + profileStr += std::to_string(profileNumber); + } else { + profileStr.insert(profileStr.begin(), (21-profileStr.length())/2, ' '); + } + + gamepadProfileModeDisplay = true; + addCustomHeader(profileStr); + } + } + + // Check to see if LED animation profile has changed + if(!gamepadProfileModeDisplay && !specialMoveProfileModeDisplay){ + uint8_t profileNumber = AnimationStation::options.baseProfileIndex; + if (prevLEDAnimationProfileNumber != profileNumber) { + prevLEDAnimationProfileNumber = profileNumber; + + std::string profileStr; + profileStr = " LED Profile #"; + profileStr += std::to_string(profileNumber); + + ledAnimationProfileModeDisplay = true; + addCustomHeader(profileStr); + } + } + + // Check to see if special move profile has changed + if(!gamepadProfileModeDisplay && !ledAnimationProfileModeDisplay){ + uint8_t profileNumber = SpecialMoveSystem::Options.CurrentProfileIndex; + if (prevSpecialMoveProfileNumber != profileNumber) { + prevSpecialMoveProfileNumber = profileNumber; + + const SpecialMoveOptions_Proto& optionsProto = storage.getSpecialMoveOptions(); + std::string profileStr; + profileStr.assign(optionsProto.profiles[profileNumber].Label, strlen(optionsProto.profiles[profileNumber].Label)); + if (profileStr.empty()) { + profileStr = "Special Profile #"; + profileStr += std::to_string(profileNumber); + } else { + profileStr.insert(profileStr.begin(), (21-profileStr.length())/2, ' '); + } + + specialMoveProfileModeDisplay = true; + addCustomHeader(profileStr); + } + } +} + int8_t ButtonLayoutScreen::update() { - bool configMode = Storage::getInstance().GetConfigMode(); - uint8_t profileNumber = getGamepad()->getOptions().profileNumber; + Storage& storage = Storage::getInstance(); + bool configMode = storage.GetConfigMode(); // Check if we've updated button layouts while in config mode if (configMode) { - uint8_t layoutLeft = Storage::getInstance().getDisplayOptions().buttonLayout; - uint8_t layoutRight = Storage::getInstance().getDisplayOptions().buttonLayoutRight; - bool inputHistoryEnabled = Storage::getInstance().getAddonOptions().inputHistoryOptions.enabled; + uint8_t layoutLeft = storage.getDisplayOptions().buttonLayout; + uint8_t layoutRight = storage.getDisplayOptions().buttonLayoutRight; + bool inputHistoryEnabled = storage.getAddonOptions().inputHistoryOptions.enabled; if ((prevLayoutLeft != layoutLeft) || (prevLayoutRight != layoutRight) || (isInputHistoryEnabled != inputHistoryEnabled) || compareCustomLayouts()) { shutdown(); init(); } } - // main logic loop - if (prevProfileNumber != profileNumber) { - profileDelayStart = getMillis(); - prevProfileNumber = profileNumber; - profileModeDisplay = true; - } + updateCustomHeaders(); // main logic loop generateHeader(); @@ -120,16 +183,13 @@ void ButtonLayoutScreen::generateHeader() { // Display Profile # banner if ( profileModeDisplay ) { if (((getMillis() - profileDelayStart) / 1000) < profileDelay) { - statusBar.assign(storage.currentProfileLabel(), strlen(storage.currentProfileLabel())); - if (statusBar.empty()) { - statusBar = " Profile #"; - statusBar += std::to_string(getGamepad()->getOptions().profileNumber); - } else { - statusBar.insert(statusBar.begin(), (21-statusBar.length())/2, ' '); - } + statusBar = profileModeString; return; } else { profileModeDisplay = false; + gamepadProfileModeDisplay = false; + ledAnimationProfileModeDisplay = false; + specialMoveProfileModeDisplay = false; } } diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index 55b574e5bb..c2a6a52b58 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -212,9 +212,10 @@ void AnimationStorage::getAnimationOptions(AnimationOptions& options) const AnimationOptions_Proto& optionsProto = Storage::getInstance().getAnimationOptions(); options.checksum = 0; - for(int index = 0; index < 4; ++index) //MAX_ANIMATION_PROFILES from AnimationStation.hpp + options.NumValidProfiles = optionsProto.profiles_count; + for(int index = 0; index < options.NumValidProfiles && index < 4; ++index) //MAX_ANIMATION_PROFILES from AnimationStation.hpp { - options.profiles[index].bIsValidProfile = optionsProto.profiles[index].bIsValidProfile; + options.profiles[index].bEnabled = optionsProto.profiles[index].bEnabled; options.profiles[index].baseNonPressedEffect = (AnimationNonPressedEffects)((int)optionsProto.profiles[index].baseNonPressedEffect); options.profiles[index].basePressedEffect = (AnimationPressedEffects)((int)optionsProto.profiles[index].basePressedEffect); options.profiles[index].baseCycleTime = optionsProto.profiles[index].baseCycleTime; @@ -226,6 +227,7 @@ void AnimationStorage::getAnimationOptions(AnimationOptions& options) options.profiles[index].buttonPressHoldTimeInMs = optionsProto.profiles[index].buttonPressHoldTimeInMs; options.profiles[index].buttonPressFadeOutTimeInMs = optionsProto.profiles[index].buttonPressFadeOutTimeInMs; options.profiles[index].nonPressedSpecialColour = optionsProto.profiles[index].nonPressedSpecialColour; + options.profiles[index].bUseCaseLightsInSpecialMoves = optionsProto.profiles[index].bUseCaseLightsInSpecialMoves; } options.brightness = std::min(optionsProto.brightness, 255); options.baseProfileIndex = std::min(optionsProto.baseProfileIndex, 255); @@ -238,6 +240,7 @@ void AnimationStorage::getSpecialMoveOptions(SpecialMoveOptions& options) options.NumValidProfiles = optionsProto.profiles_count; for(unsigned int profileIndex = 0; profileIndex < 4 && profileIndex < options.NumValidProfiles; ++profileIndex) //MAX_SPECIALMOVE_PROFILES from SpecialMoveSystem.hpp { + options.profiles[profileIndex].bEnabled = optionsProto.profiles[profileIndex].bEnabled; options.profiles[profileIndex].NumValidMoves = optionsProto.profiles[profileIndex].AllSpecialMoves_count; for(unsigned int moveIndex = 0; moveIndex < 20 && moveIndex < options.profiles[profileIndex].NumValidMoves; ++moveIndex) //MAX_SPECIALMOVES from SpecialMoveSystem.hpp { From ca2f7be8633630f0e4a647402a6f8ec9aad065f4 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Tue, 17 Dec 2024 22:46:32 +0000 Subject: [PATCH 013/121] Added define for prototype haute --- configs/Haute42COSMOX/BoardConfig.h | 33 +++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/configs/Haute42COSMOX/BoardConfig.h b/configs/Haute42COSMOX/BoardConfig.h index be4492cf9c..0c13afc3cb 100644 --- a/configs/Haute42COSMOX/BoardConfig.h +++ b/configs/Haute42COSMOX/BoardConfig.h @@ -119,6 +119,8 @@ //l3 //r3 //m2 (extra button 2) + +//Defines for T16 /*#define LIGHT_DATA_SIZE 16 //number of sets in the below data #define LIGHT_DATA \ 0, 1, 0, 2, 5, LightType_Proto::LightType_Proto_ActionButton, \ @@ -138,6 +140,37 @@ 14, 1, 8, 5, 19, LightType_Proto::LightType_Proto_ActionButton, \ 15, 1, 3, 6, 26, LightType_Proto::LightType_Proto_ActionButton*/ +//define for prototype with rim lighting +#define LIGHT_DATA_SIZE 27 //number of sets in the below data +#define LIGHT_DATA \ +0, 1, 1, 3, 5, LightType_Proto::LightType_Proto_ActionButton, \ +1, 1, 3, 3, 3, LightType_Proto::LightType_Proto_ActionButton, \ +2, 1, 5, 4, 4, LightType_Proto::LightType_Proto_ActionButton, \ +3, 1, 7, 8, 2, LightType_Proto::LightType_Proto_ActionButton, \ +4, 1, 7, 3, 10, LightType_Proto::LightType_Proto_ActionButton, \ +5, 1, 9, 2, 11, LightType_Proto::LightType_Proto_ActionButton, \ +6, 1, 11, 2, 12, LightType_Proto::LightType_Proto_ActionButton, \ +7, 1, 13, 2, 13, LightType_Proto::LightType_Proto_ActionButton, \ +8, 1, 7, 5, 6, LightType_Proto::LightType_Proto_ActionButton, \ +9, 1, 9, 4, 7, LightType_Proto::LightType_Proto_ActionButton, \ +10, 1, 11, 4, 8, LightType_Proto::LightType_Proto_ActionButton, \ +11, 1, 13, 4, 9, LightType_Proto::LightType_Proto_ActionButton, \ +12, 1, 4, 1, 27, LightType_Proto::LightType_Proto_ActionButton, \ +13, 1, 7, 1, 18, LightType_Proto::LightType_Proto_ActionButton, \ +14, 1, 9, 6, 19, LightType_Proto::LightType_Proto_ActionButton, \ +15, 1, 4, 7, 26, LightType_Proto::LightType_Proto_ActionButton, \ +16, 1, 5, 0, 0, LightType_Proto::LightType_Proto_Case, \ +17, 1, 0, 0, 0, LightType_Proto::LightType_Proto_Case, \ +18, 1, 0, 4, 0, LightType_Proto::LightType_Proto_Case, \ +19, 1, 0, 9, 0, LightType_Proto::LightType_Proto_Case, \ +20, 1, 4, 9, 0, LightType_Proto::LightType_Proto_Case, \ +21, 1, 8, 9, 0, LightType_Proto::LightType_Proto_Case, \ +22, 1, 12, 9, 0, LightType_Proto::LightType_Proto_Case, \ +23, 1, 15, 9, 0, LightType_Proto::LightType_Proto_Case, \ +24, 1, 15, 4, 0, LightType_Proto::LightType_Proto_Case, \ +25, 1, 15, 0, 0, LightType_Proto::LightType_Proto_Case, \ +26, 1, 10, 0, 0, LightType_Proto::LightType_Proto_Case + #define HAS_I2C_DISPLAY 1 #define I2C0_ENABLED 1 #define I2C0_PIN_SDA 0 From f624a0b892781293a4c0c4c8fb684dd66833fac9 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Thu, 9 Jan 2025 14:42:21 +0000 Subject: [PATCH 014/121] Knight Rider effect Added Knight rider effect and changed button colours to be indexed from preset colours to save config space --- configs/Haute42COSMOX/BoardConfig.h | 44 ++++++++---- lib/AnimationStation/CMakeLists.txt | 1 + lib/AnimationStation/src/Animation.cpp | 42 +++++++++++ lib/AnimationStation/src/Animation.hpp | 8 +++ lib/AnimationStation/src/AnimationStation.cpp | 3 +- lib/AnimationStation/src/AnimationStation.hpp | 4 ++ lib/AnimationStation/src/Effects/Chase.cpp | 14 ++-- lib/AnimationStation/src/Effects/Chase.hpp | 5 +- lib/AnimationStation/src/Effects/Rainbow.hpp | 2 +- .../src/Effects/RandomColor.hpp | 2 +- .../src/Effects/SMCircleColour.cpp | 4 +- .../src/Effects/SMCircleColour.hpp | 2 +- .../src/Effects/SMKnightRider.cpp | 71 +++++++++++++++++++ .../src/Effects/SMKnightRider.hpp | 26 +++++++ .../src/Effects/SMPulseColour.cpp | 2 +- .../src/Effects/SMPulseColour.hpp | 2 +- lib/AnimationStation/src/Effects/SMWave.cpp | 2 +- lib/AnimationStation/src/Effects/SMWave.hpp | 2 +- .../src/Effects/StaticColor.cpp | 4 +- .../src/Effects/StaticColor.hpp | 2 +- lib/AnimationStation/src/Pixel.hpp | 8 ++- .../src/SpecialMoveSystem.cpp | 5 ++ .../src/SpecialMoveSystem.hpp | 1 + proto/config.proto | 10 ++- proto/enums.proto | 6 +- src/addons/neopicoleds.cpp | 5 +- src/config_utils.cpp | 44 +++++++++--- src/storagemanager.cpp | 28 +++++++- 28 files changed, 295 insertions(+), 54 deletions(-) create mode 100644 lib/AnimationStation/src/Effects/SMKnightRider.cpp create mode 100644 lib/AnimationStation/src/Effects/SMKnightRider.hpp diff --git a/configs/Haute42COSMOX/BoardConfig.h b/configs/Haute42COSMOX/BoardConfig.h index 0c13afc3cb..eb1db46162 100644 --- a/configs/Haute42COSMOX/BoardConfig.h +++ b/configs/Haute42COSMOX/BoardConfig.h @@ -97,7 +97,7 @@ #define LEDS_BUTTON_R3 14 #define LEDS_BUTTON_A2 15 -//Data format = {first led index, leds on this light, xcoord, ycoord, GPIO pin, Type} +//Data format = {first led index, leds on this light, xcoord, ycoord, GPIO pin/case light Index, Type} //Eg, your first light would be "first led index" = 0 and "leds on this light" = 2. // your second light would be "first led index" = 2 (as 0 and 1 were just taken by the first light) //T16 @@ -140,8 +140,28 @@ 14, 1, 8, 5, 19, LightType_Proto::LightType_Proto_ActionButton, \ 15, 1, 3, 6, 26, LightType_Proto::LightType_Proto_ActionButton*/ +//Test setup for making some of the buttons act as case lights +#define LIGHT_DATA_SIZE 16 //number of sets in the below data +#define LIGHT_DATA \ +0, 1, 0, 2, 5, LightType_Proto::LightType_Proto_ActionButton, \ +1, 1, 2, 2, 3, LightType_Proto::LightType_Proto_ActionButton, \ +2, 1, 4, 3, 4, LightType_Proto::LightType_Proto_ActionButton, \ +3, 1, 6, 7, 2, LightType_Proto::LightType_Proto_ActionButton, \ +4, 1, 6, 2, 10, LightType_Proto::LightType_Proto_ActionButton, \ +5, 1, 8, 1, 11, LightType_Proto::LightType_Proto_ActionButton, \ +6, 1, 10, 1, 12, LightType_Proto::LightType_Proto_ActionButton, \ +7, 1, 12, 1, 13, LightType_Proto::LightType_Proto_ActionButton, \ +8, 1, 6, 4, 6, LightType_Proto::LightType_Proto_ActionButton, \ +9, 1, 8, 3, 7, LightType_Proto::LightType_Proto_ActionButton, \ +10, 1, 10, 3, 8, LightType_Proto::LightType_Proto_ActionButton, \ +11, 1, 12, 3, 9, LightType_Proto::LightType_Proto_ActionButton, \ +12, 1, 3, 0, 0, LightType_Proto::LightType_Proto_Case, \ +13, 1, 6, 0, 1, LightType_Proto::LightType_Proto_Case, \ +14, 1, 8, 5, 2, LightType_Proto::LightType_Proto_Case, \ +15, 1, 3, 6, 3, LightType_Proto::LightType_Proto_Case + //define for prototype with rim lighting -#define LIGHT_DATA_SIZE 27 //number of sets in the below data +/*#define LIGHT_DATA_SIZE 27 //number of sets in the below data #define LIGHT_DATA \ 0, 1, 1, 3, 5, LightType_Proto::LightType_Proto_ActionButton, \ 1, 1, 3, 3, 3, LightType_Proto::LightType_Proto_ActionButton, \ @@ -160,16 +180,16 @@ 14, 1, 9, 6, 19, LightType_Proto::LightType_Proto_ActionButton, \ 15, 1, 4, 7, 26, LightType_Proto::LightType_Proto_ActionButton, \ 16, 1, 5, 0, 0, LightType_Proto::LightType_Proto_Case, \ -17, 1, 0, 0, 0, LightType_Proto::LightType_Proto_Case, \ -18, 1, 0, 4, 0, LightType_Proto::LightType_Proto_Case, \ -19, 1, 0, 9, 0, LightType_Proto::LightType_Proto_Case, \ -20, 1, 4, 9, 0, LightType_Proto::LightType_Proto_Case, \ -21, 1, 8, 9, 0, LightType_Proto::LightType_Proto_Case, \ -22, 1, 12, 9, 0, LightType_Proto::LightType_Proto_Case, \ -23, 1, 15, 9, 0, LightType_Proto::LightType_Proto_Case, \ -24, 1, 15, 4, 0, LightType_Proto::LightType_Proto_Case, \ -25, 1, 15, 0, 0, LightType_Proto::LightType_Proto_Case, \ -26, 1, 10, 0, 0, LightType_Proto::LightType_Proto_Case +17, 1, 0, 0, 1, LightType_Proto::LightType_Proto_Case, \ +18, 1, 0, 4, 2, LightType_Proto::LightType_Proto_Case, \ +19, 1, 0, 9, 3, LightType_Proto::LightType_Proto_Case, \ +20, 1, 4, 9, 4, LightType_Proto::LightType_Proto_Case, \ +21, 1, 8, 9, 5, LightType_Proto::LightType_Proto_Case, \ +22, 1, 12, 9, 6, LightType_Proto::LightType_Proto_Case, \ +23, 1, 15, 9, 7, LightType_Proto::LightType_Proto_Case, \ +24, 1, 15, 4, 8, LightType_Proto::LightType_Proto_Case, \ +25, 1, 15, 0, 9, LightType_Proto::LightType_Proto_Case, \ +26, 1, 10, 0, 10, LightType_Proto::LightType_Proto_Case*/ #define HAS_I2C_DISPLAY 1 #define I2C0_ENABLED 1 diff --git a/lib/AnimationStation/CMakeLists.txt b/lib/AnimationStation/CMakeLists.txt index d9306ae0e6..308ae5bc86 100644 --- a/lib/AnimationStation/CMakeLists.txt +++ b/lib/AnimationStation/CMakeLists.txt @@ -5,6 +5,7 @@ src/Effects/StaticColor.cpp src/Effects/RandomColor.cpp src/Effects/SMPulseColour.cpp src/Effects/SMWave.cpp +src/Effects/SMKnightRider.cpp src/Effects/SMCircleColour.cpp src/AnimationStation.cpp src/Animation.cpp diff --git a/lib/AnimationStation/src/Animation.cpp b/lib/AnimationStation/src/Animation.cpp index 640a5e0ba4..0234879cee 100644 --- a/lib/AnimationStation/src/Animation.cpp +++ b/lib/AnimationStation/src/Animation.cpp @@ -173,4 +173,46 @@ bool Animation::LightTypeIsForSpecialMoveAnimation(LightType Type) return true; return false; +} + +//Get correct colour for light index +RGB Animation::GetNonPressedColorForLight(uint32_t LightIndex) +{ + int colIndex = 0; + Light* thisLight = &(RGBLights->AllLights[LightIndex]); + if(thisLight->Type == LightType::LightType_ActionButton) + { + //button + colIndex = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[thisLight->GIPOPin]; + } + else + { + //case light + colIndex = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].caseStaticColors[thisLight->CaseLightIndex]; + } + + return GetColorForIndex(colIndex); +} + +RGB Animation::GetPressedColorForLight(uint32_t LightIndex) +{ + Light* thisLight = &(RGBLights->AllLights[LightIndex]); + int colIndex = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].pressedStaticColors[thisLight->GIPOPin]; + return GetColorForIndex(colIndex); +} + +RGB Animation::GetColorForIndex(uint32_t ColorIndex) +{ + //pre defined color? + if(ColorIndex < (int)colors.size()) + return colors[ColorIndex]; + + //must be custom color + ColorIndex -= colors.size(); + if(ColorIndex > customColors.size()) + { + //error, no such color + return colors[0]; + } + return customColors[ColorIndex]; } \ No newline at end of file diff --git a/lib/AnimationStation/src/Animation.hpp b/lib/AnimationStation/src/Animation.hpp index a0c568886e..27842efac3 100644 --- a/lib/AnimationStation/src/Animation.hpp +++ b/lib/AnimationStation/src/Animation.hpp @@ -103,6 +103,9 @@ inline const std::vector colors { ColorLimeGreen, ColorGreen, ColorSeafoam, ColorAqua, ColorSkyBlue, ColorBlue, ColorPurple, ColorPink, ColorMagenta }; +#define MAX_CUSTOM_COLORS 16 +inline std::vector customColors { }; + class Animation { public: Animation(Lights& InRGBLights); @@ -144,6 +147,11 @@ class Animation { bool LightTypeIsForPressedAnimation(LightType Type); bool LightTypeIsForSpecialMoveAnimation(LightType Type); + //Get colour helpers + RGB GetNonPressedColorForLight(uint32_t LightIndex); + RGB GetPressedColorForLight(uint32_t LightIndex); + RGB GetColorForIndex(uint32_t ColorIndex); + //Light data Lights* RGBLights; diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index 2db8782d5f..c2abd96d12 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -12,6 +12,7 @@ #include "Effects/SMPulseColour.hpp" #include "Effects/SMCircleColour.hpp" #include "Effects/SMWave.hpp" +#include "Effects/SMKnightRider.hpp" #include "SpecialMoveSystem.hpp" #include "AnimationStation.hpp" @@ -226,7 +227,7 @@ void AnimationStation::SetSpecialMoveAnimation(SpecialMoveEffects AnimationToPla break; case SpecialMoveEffects::SPECIALMOVE_SMEFFECT_KNIGHTRIDER: - //this->specialMoveAnimation = new SMKnightRider(RGBLights); + this->specialMoveAnimation = new SMKnightRider(RGBLights); break; case SpecialMoveEffects::SPECIALMOVE_SMEFFECT_RANDOMFLASH: diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index 9595f2673c..b6258eaa81 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -14,6 +14,7 @@ #include "SpecialMoveSystem.hpp" #define MAX_ANIMATION_PROFILES 4 +#define MAX_CASE_LIGHTS 40 //this should be divisible by 4 as we pack 4 indexes into one config int32 //List of non-pressed animation types typedef enum @@ -60,12 +61,15 @@ struct __attribute__ ((__packed__)) AnimationProfile AnimationNonPressedEffects baseNonPressedEffect; AnimationPressedEffects basePressedEffect; + AnimationNonPressedEffects baseCaseEffect; int16_t baseCycleTime; uint32_t notPressedStaticColors[NUM_BANK0_GPIOS]; uint32_t pressedStaticColors[NUM_BANK0_GPIOS]; + uint32_t caseStaticColors[MAX_CASE_LIGHTS]; + uint32_t buttonPressHoldTimeInMs; uint32_t buttonPressFadeOutTimeInMs; diff --git a/lib/AnimationStation/src/Effects/Chase.cpp b/lib/AnimationStation/src/Effects/Chase.cpp index b4c2199249..f92fa8f3ad 100644 --- a/lib/AnimationStation/src/Effects/Chase.cpp +++ b/lib/AnimationStation/src/Effects/Chase.cpp @@ -120,7 +120,7 @@ void Chase::Animate(RGB (&frame)[100]) uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[lightIndex]].LedsPerLight; for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { - frame[ledIndex] = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[lightIndex]].GIPOPin]; + frame[ledIndex] = GetNonPressedColorForLight(OrderedLights[lightIndex]); } } @@ -160,7 +160,7 @@ void Chase::Animate(RGB (&frame)[100]) uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[currentLightReverseAdjusted]].LedsPerLight; for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { - frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[currentLightReverseAdjusted]].GIPOPin], + frame[ledIndex] = BlendColor(GetNonPressedColorForLight(OrderedLights[currentLightReverseAdjusted]), AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, fadeTimeOne); } @@ -171,7 +171,7 @@ void Chase::Animate(RGB (&frame)[100]) uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[nextLightReverseAdjusted]].LedsPerLight; for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { - frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[nextLightReverseAdjusted]].GIPOPin], + frame[ledIndex] = BlendColor(GetNonPressedColorForLight(OrderedLights[nextLightReverseAdjusted]), AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, fadeTimeTwo); } @@ -194,7 +194,7 @@ void Chase::Animate(RGB (&frame)[100]) uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[lightIndex]].LedsPerLight; for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { - frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[lightIndex]].GIPOPin], + frame[ledIndex] = BlendColor(GetNonPressedColorForLight(OrderedLights[lightIndex]), AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, fadeTimeOne); } @@ -208,7 +208,7 @@ void Chase::Animate(RGB (&frame)[100]) uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[lightIndex]].LedsPerLight; for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { - frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[lightIndex]].GIPOPin], + frame[ledIndex] = BlendColor(GetNonPressedColorForLight(OrderedLights[lightIndex]), AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, fadeTimeTwo); } @@ -233,7 +233,7 @@ void Chase::Animate(RGB (&frame)[100]) uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[lightIndex]].LedsPerLight; for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { - frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[lightIndex]].GIPOPin], + frame[ledIndex] = BlendColor(GetNonPressedColorForLight(OrderedLights[lightIndex]), AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, fadeTimeOne); } @@ -247,7 +247,7 @@ void Chase::Animate(RGB (&frame)[100]) uint8_t lastLightIndex = firstLightIndex + RGBLights->AllLights[OrderedLights[lightIndex]].LedsPerLight; for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { - frame[ledIndex] = BlendColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[OrderedLights[lightIndex]].GIPOPin], + frame[ledIndex] = BlendColor(GetNonPressedColorForLight(OrderedLights[lightIndex]), AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour, fadeTimeTwo); } diff --git a/lib/AnimationStation/src/Effects/Chase.hpp b/lib/AnimationStation/src/Effects/Chase.hpp index 6f7dc08f18..de53ec7a0c 100644 --- a/lib/AnimationStation/src/Effects/Chase.hpp +++ b/lib/AnimationStation/src/Effects/Chase.hpp @@ -40,7 +40,8 @@ class Chase : public Animation { Chase(Lights& InRGBLights, ChaseTypes InChaseType); ~Chase() {}; - void Animate(RGB (&frame)[100]); + virtual void Animate(RGB (&frame)[100]) override; + void ParameterUp(); void ParameterDown(); @@ -51,7 +52,7 @@ class Chase : public Animation { void CheckForEndOfSequence(); float ChaseTimes[2]; - std::vector OrderedLights; + std::vector OrderedLights; int MinXCoord = 0; int MinYCoord = 0; diff --git a/lib/AnimationStation/src/Effects/Rainbow.hpp b/lib/AnimationStation/src/Effects/Rainbow.hpp index a9f6a68ea5..2f171e971e 100644 --- a/lib/AnimationStation/src/Effects/Rainbow.hpp +++ b/lib/AnimationStation/src/Effects/Rainbow.hpp @@ -14,7 +14,7 @@ class RainbowSynced : public Animation RainbowSynced(Lights& InRGBLights); ~RainbowSynced() {}; - void Animate(RGB (&frame)[100]); + virtual void Animate(RGB (&frame)[100]) override; //These change the speed of the rainbow changing color void ParameterUp(); diff --git a/lib/AnimationStation/src/Effects/RandomColor.hpp b/lib/AnimationStation/src/Effects/RandomColor.hpp index f804530a4d..837ca4ae14 100644 --- a/lib/AnimationStation/src/Effects/RandomColor.hpp +++ b/lib/AnimationStation/src/Effects/RandomColor.hpp @@ -13,7 +13,7 @@ class RandomColor : public Animation { RandomColor(Lights& InRGBLights, std::vector &InPressedPins); ~RandomColor() { }; - void Animate(RGB (&frame)[100]); + virtual void Animate(RGB (&frame)[100]) override; protected: diff --git a/lib/AnimationStation/src/Effects/SMCircleColour.cpp b/lib/AnimationStation/src/Effects/SMCircleColour.cpp index 1962335bf6..ee5d49ef30 100644 --- a/lib/AnimationStation/src/Effects/SMCircleColour.cpp +++ b/lib/AnimationStation/src/Effects/SMCircleColour.cpp @@ -177,9 +177,9 @@ bool SMCircleColour::UpdateCircle(RGB (&frame)[100]) else if(NumLoopsDone == (CircleLoops-1) && inSecondCircle && useSecondColour) colToUse = ColorBlack; else if(useSecondColour) - colToUse = colors[SecondColourIndex]; + colToUse = GetColorForIndex(SecondColourIndex); else - colToUse = colors[ColourIndex]; + colToUse = GetColorForIndex(ColourIndex); for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { diff --git a/lib/AnimationStation/src/Effects/SMCircleColour.hpp b/lib/AnimationStation/src/Effects/SMCircleColour.hpp index 468d7e95bb..524d363abe 100644 --- a/lib/AnimationStation/src/Effects/SMCircleColour.hpp +++ b/lib/AnimationStation/src/Effects/SMCircleColour.hpp @@ -22,7 +22,7 @@ class SMCircleColour : public Animation { SMCircleColour(Lights& InRGBLights); ~SMCircleColour() { }; - void Animate(RGB (&frame)[100]); + virtual void Animate(RGB (&frame)[100]) override; virtual void SetOptionalParams(uint32_t OptionalParams) override; virtual bool IsFinished() override; diff --git a/lib/AnimationStation/src/Effects/SMKnightRider.cpp b/lib/AnimationStation/src/Effects/SMKnightRider.cpp new file mode 100644 index 0000000000..5aaee23c62 --- /dev/null +++ b/lib/AnimationStation/src/Effects/SMKnightRider.cpp @@ -0,0 +1,71 @@ +#include "SMWave.hpp" +#include "SMKnightRider.hpp" +#include "SpecialMoveSystem.hpp" + +SMKnightRider::SMKnightRider(Lights& InRGBLights) : SMWave(InRGBLights) +{ +} + +void SMKnightRider::SetOptionalParams(uint32_t OptionalParams) +{ + //FORMAT + //4bit - SpecialMoveAnimationDirection - Wave direction + //4bit - SpecialMoveAnimationDuration - Wave animation time + //4bit - int - Num wave loops + //4bit - SpecialMoveAnimationDivider - divides lights into sections and only plays on that section + //8bit - Animation::colors index - wave colour + + WaveDirection = (SpecialMoveAnimationDirection)(OptionalParams & 0xF); + WaveSpeed = (SpecialMoveAnimationDuration)((OptionalParams >> 4) & 0xF); + WaveLoops = 1; + KRLoops = ((OptionalParams >> 8) & 0xF); + WaveDivider = (SpecialMoveAnimationDivider)((OptionalParams >> 12) & 0xF); + ColourIndex = (uint8_t)((OptionalParams >> 16) & 0xFF); + + CurrentState = SMWaveState::SM_WAVE_STATE_PREFRAMES; +} + +void SMKnightRider::Animate(RGB (&frame)[100]) +{ + switch(CurrentState) + { + case SMWaveState::SM_WAVE_STATE_POSTFRAMES: + { + //flip direction + if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_LEFT) + WaveDirection = SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_RIGHT; + else if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_RIGHT) + WaveDirection = SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_LEFT; + else if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_UP) + WaveDirection = SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_DOWN; + else if(WaveDirection == SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_DOWN) + WaveDirection = SpecialMoveAnimationDirection::SPECIALMOVE_DIRECTION_UP; + + if(bOnReturnLeg == true) + { + KRLoops--; + } + bOnReturnLeg = !bOnReturnLeg; + + //restart wave if not finished + if(KRLoops > 0) + { + //must call update wave here to make sure we put black on all the leds + UpdateWave(frame); + + CurrentStateTime = 0.0f; + CurrentState = SMWaveState::SM_WAVE_STATE_RUNNING; + WaveValue = 0.0f; + + //dont fall through to super + return; + } + } break; + + default: + { + } break; + } + + SMWave::Animate(frame); +} \ No newline at end of file diff --git a/lib/AnimationStation/src/Effects/SMKnightRider.hpp b/lib/AnimationStation/src/Effects/SMKnightRider.hpp new file mode 100644 index 0000000000..adaa161da2 --- /dev/null +++ b/lib/AnimationStation/src/Effects/SMKnightRider.hpp @@ -0,0 +1,26 @@ +#ifndef _SM_KNIGHTRIDER_H_ +#define _SM_KNIGHTRIDER_H_ + +#include "../Animation.hpp" +#include +#include +#include +#include "../AnimationStation.hpp" +#include "../SpecialMoveSystem.hpp" +#include "SMWave.hpp" + +class SMKnightRider : public SMWave { +public: + SMKnightRider(Lights& InRGBLights); + ~SMKnightRider() { }; + + virtual void Animate(RGB (&frame)[100]) override; + virtual void SetOptionalParams(uint32_t OptionalParams) override; + +protected: + + int KRLoops = 0; + bool bOnReturnLeg = false; +}; + +#endif diff --git a/lib/AnimationStation/src/Effects/SMPulseColour.cpp b/lib/AnimationStation/src/Effects/SMPulseColour.cpp index 49bd7b2610..2cdb262ff9 100644 --- a/lib/AnimationStation/src/Effects/SMPulseColour.cpp +++ b/lib/AnimationStation/src/Effects/SMPulseColour.cpp @@ -190,7 +190,7 @@ void SMPulseColour::Animate(RGB (&frame)[100]) for(uint8_t ledIndex = firstLightIndex; ledIndex < lastLightIndex; ++ledIndex) { - frame[ledIndex] = BlendColor(ColorBlack, colors[ColourIndex], thisFrameFade); + frame[ledIndex] = BlendColor(ColorBlack, GetColorForIndex(ColourIndex), thisFrameFade); } } } diff --git a/lib/AnimationStation/src/Effects/SMPulseColour.hpp b/lib/AnimationStation/src/Effects/SMPulseColour.hpp index 62cb0c7633..0b25f3d931 100644 --- a/lib/AnimationStation/src/Effects/SMPulseColour.hpp +++ b/lib/AnimationStation/src/Effects/SMPulseColour.hpp @@ -24,7 +24,7 @@ class SMPulseColour : public Animation { SMPulseColour(Lights& InRGBLights); ~SMPulseColour() { }; - void Animate(RGB (&frame)[100]); + virtual void Animate(RGB (&frame)[100]) override; virtual void SetOptionalParams(uint32_t OptionalParams) override; virtual bool IsFinished() override; diff --git a/lib/AnimationStation/src/Effects/SMWave.cpp b/lib/AnimationStation/src/Effects/SMWave.cpp index ef3cc0279c..957c4fec6d 100644 --- a/lib/AnimationStation/src/Effects/SMWave.cpp +++ b/lib/AnimationStation/src/Effects/SMWave.cpp @@ -167,7 +167,7 @@ bool SMWave::UpdateWave(RGB (&frame)[100]) else bFinished = false; - frame[ledIndex] = BlendColor(ColorBlack, colors[ColourIndex], lightStr); + frame[ledIndex] = BlendColor(ColorBlack, GetColorForIndex(ColourIndex), lightStr); } } } diff --git a/lib/AnimationStation/src/Effects/SMWave.hpp b/lib/AnimationStation/src/Effects/SMWave.hpp index 81e7b33666..46da10076b 100644 --- a/lib/AnimationStation/src/Effects/SMWave.hpp +++ b/lib/AnimationStation/src/Effects/SMWave.hpp @@ -22,7 +22,7 @@ class SMWave : public Animation { SMWave(Lights& InRGBLights); ~SMWave() { }; - void Animate(RGB (&frame)[100]); + virtual void Animate(RGB (&frame)[100]) override; virtual void SetOptionalParams(uint32_t OptionalParams) override; virtual bool IsFinished() override; diff --git a/lib/AnimationStation/src/Effects/StaticColor.cpp b/lib/AnimationStation/src/Effects/StaticColor.cpp index 61ce7ce3d8..c083dd023c 100644 --- a/lib/AnimationStation/src/Effects/StaticColor.cpp +++ b/lib/AnimationStation/src/Effects/StaticColor.cpp @@ -25,11 +25,11 @@ void StaticColor::Animate(RGB (&frame)[100]) //Non pressed simply sets the RGB colour if(!isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { - frame[ledIndex] = AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].notPressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin]; + frame[ledIndex] = GetNonPressedColorForLight(lightIndex); } else if (isButtonAnimation && LightTypeIsForPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { - frame[ledIndex] = FadeColor(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].pressedStaticColors[RGBLights->AllLights[lightIndex].GIPOPin], + frame[ledIndex] = FadeColor(GetPressedColorForLight(lightIndex), frame[ledIndex], fadeTimes[ledIndex]); } diff --git a/lib/AnimationStation/src/Effects/StaticColor.hpp b/lib/AnimationStation/src/Effects/StaticColor.hpp index 4e5c1c829f..8772cb40a5 100644 --- a/lib/AnimationStation/src/Effects/StaticColor.hpp +++ b/lib/AnimationStation/src/Effects/StaticColor.hpp @@ -13,7 +13,7 @@ class StaticColor : public Animation { StaticColor(Lights& InRGBLights, std::vector &InPressedPins); ~StaticColor() { }; - void Animate(RGB (&frame)[100]); + virtual void Animate(RGB (&frame)[100]) override; protected: }; diff --git a/lib/AnimationStation/src/Pixel.hpp b/lib/AnimationStation/src/Pixel.hpp index 37cf1635e4..72a9fa4f97 100644 --- a/lib/AnimationStation/src/Pixel.hpp +++ b/lib/AnimationStation/src/Pixel.hpp @@ -92,7 +92,10 @@ struct Light Type = InType; LedsPerLight = InNumLedsPerLight; //GamePadMask = GamePadMask; - GIPOPin = InGIPOPin; + if(InType != LightType::LightType_Case) + GIPOPin = InGIPOPin; + else + CaseLightIndex = InGIPOPin; } // index of first LED @@ -112,6 +115,9 @@ struct Light //GIPO pin this action (if applicaple) is on int32_t GIPOPin = -1; + + //Sequential index of this case light + int32_t CaseLightIndex = -1; }; //All RGB lights on the device. Replaced PixelMatrix diff --git a/lib/AnimationStation/src/SpecialMoveSystem.cpp b/lib/AnimationStation/src/SpecialMoveSystem.cpp index 60be558e67..3ac11fcfb2 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.cpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.cpp @@ -507,6 +507,11 @@ void SpecialMoveSystem::GetComboArrayForMove(SpecialMoveInputTypes InputType, st { switch(InputType) { + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_NONE: + { + //Nothing. Used for stuff like Giefs Lariat + } break; + case SpecialMoveInputTypes::SPECIALMOVE_INPUT_QUARTER_DOWN_RIGHT: { comboArray.push_back(ComboEntry(SpecialMoveStickDirection::SPECIALMOVE_STICK_DOWN, 0)); diff --git a/lib/AnimationStation/src/SpecialMoveSystem.hpp b/lib/AnimationStation/src/SpecialMoveSystem.hpp index 46d2c70bc0..9712289f86 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.hpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.hpp @@ -92,6 +92,7 @@ typedef enum SPECIALMOVE_INPUT_720, SPECIALMOVE_INPUT_RAGING_DEMON_RIGHT, SPECIALMOVE_INPUT_RAGING_DEMON_LEFT, + SPECIALMOVE_INPUT_NONE, } SpecialMoveInputTypes; // SpecialMove joystick directions diff --git a/proto/config.proto b/proto/config.proto index 11b37f156b..2a5558f86c 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -336,8 +336,8 @@ message AnimationProfile_Proto optional int32 baseCycleTime = 4; - repeated uint32 notPressedStaticColors = 5 [(nanopb).max_count = 30]; //NUM_BANK0_GPIOS from AnimationStation.hpp - repeated uint32 pressedStaticColors = 6 [(nanopb).max_count = 30]; //NUM_BANK0_GPIOS from AnimationStation.hpp + repeated uint32 notPressedStaticColors = 5 [(nanopb).max_count = 8]; //NUM_BANK0_GPIOS/4 from platform_defs.h + repeated uint32 pressedStaticColors = 6 [(nanopb).max_count = 8]; //NUM_BANK0_GPIOS/4 from platform_defs.h optional uint32 buttonPressHoldTimeInMs = 7; optional uint32 buttonPressFadeOutTimeInMs = 8; @@ -345,6 +345,10 @@ message AnimationProfile_Proto optional uint32 nonPressedSpecialColour = 9; optional bool bUseCaseLightsInSpecialMoves = 10; + + optional AnimationNonPressedEffects_Proto baseCaseEffect = 11; + + repeated uint32 caseStaticColors = 12 [(nanopb).max_count = 10]; //(MAX_CASE_LIGHTS/4) from AnimationStation.hpp }; // This has to be kept in sync with AnimationOptions in AnimationStation.hpp @@ -399,6 +403,8 @@ message AnimationOptions_Proto repeated AnimationProfile_Proto profiles = 46 [(nanopb).max_count = 4]; //MAX_ANIMATION_PROFILES from AnimationStation.hpp optional uint32 baseProfileIndex = 47; + + repeated uint32 customColors = 48 [(nanopb).max_count = 16]; //MAX_CUSTOM_COLORS from Animation.hpp } message BootselButtonOptions diff --git a/proto/enums.proto b/proto/enums.proto index 78644b0612..8e8aa17bf1 100644 --- a/proto/enums.proto +++ b/proto/enums.proto @@ -317,9 +317,8 @@ enum SpecialMoveEffects_Proto SMEFFECT_WAVE = 0; SMEFFECT_PULSECOLOR = 1; SMEFFECT_CIRCLECOLOR = 2; - SMEFFECT_FLASHCOLOR = 3; - SMEFFECT_KNIGHTRIDER = 4; - SMEFFECT_RANDOMFLASH = 5; + SMEFFECT_KNIGHTRIDER = 3; + SMEFFECT_RANDOMFLASH = 4; } /* This has to be kept in sync with SpecialMoveInputTypes in SpecialMoveSystem.hpp */ @@ -345,6 +344,7 @@ enum SpecialMoveInputTypes_Proto INPUT_720 = 17; INPUT_RAGING_DEMON_RIGHT = 18; INPUT_RAGING_DEMON_LEFT = 19; + INPUT_NONE = 20; } /* This has to be kept in sync with AnimationNonPressedEffects in AnimationStation.hpp */ diff --git a/src/addons/neopicoleds.cpp b/src/addons/neopicoleds.cpp index c8ba6a927e..5c0a7b32cb 100644 --- a/src/addons/neopicoleds.cpp +++ b/src/addons/neopicoleds.cpp @@ -342,6 +342,10 @@ void NeoPicoLEDAddon::process() void NeoPicoLEDAddon::generateLegacyIndividualLight(int lightIndex, int firstLedIndex, int xCoord, int yCoord, uint8_t ledsPerPixel, LEDOptions_lightData_t& out_lightData, GpioAction actionButton) { + int arrayOffset = lightIndex * 6; + if(arrayOffset + 5 >= 600) //Max data array size (defined in config proto) + return; + const GpioMappings& pinMappings = Storage::getInstance().getGpioMappings(); int gpioPin = -1; @@ -351,7 +355,6 @@ void NeoPicoLEDAddon::generateLegacyIndividualLight(int lightIndex, int firstLed gpioPin = configIndex; } - int arrayOffset = lightIndex * 6; out_lightData.bytes[arrayOffset] = firstLedIndex; //first led index out_lightData.bytes[arrayOffset+1] = ledsPerPixel; //leds on this light out_lightData.bytes[arrayOffset+2] = xCoord; //xcoord diff --git a/src/config_utils.cpp b/src/config_utils.cpp index ae6daf0da0..6da443ace1 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -484,11 +484,13 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.animationOptions, baseProfileIndex, 0); //TESTING + config.animationOptions.customColors_count = 1; + config.animationOptions.customColors[0] = 255; config.specialMoveOptions.profiles_count = 0; config.animationOptions.profiles_count = 0; if(true) { - config.specialMoveOptions.profiles_count = 2; + config.specialMoveOptions.profiles_count = 3; config.specialMoveOptions.profiles[0].bEnabled = true; config.specialMoveOptions.profiles[0].AllSpecialMoves_count = 2; @@ -500,7 +502,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_QUARTER_DOWN_LEFT; config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 1 + (1 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //Left //slow //1 loop //all lights //colour skyblue + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 1 + (1 << 4) + (1 << 8) + (0 << 12) + (14 << 16); //Left //slow //1 loop //all lights //colour custom 1 config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4; config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 1 + (2 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //Left //medium //1 loop //all lights //colour skyblue config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_R1; @@ -521,7 +523,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) config.specialMoveOptions.profiles[1].bEnabled = true; config.specialMoveOptions.profiles[1].AllSpecialMoves_count = 1; - strncpy(config.specialMoveOptions.profiles[1].Label, "Ken Masters", sizeof(config.specialMoveOptions.profiles[0].Label) - 1); + strncpy(config.specialMoveOptions.profiles[1].Label, "Ken Masters", sizeof(config.specialMoveOptions.profiles[1].Label) - 1); config.specialMoveOptions.profiles[1].AllSpecialMoves[0].bIsChargeMove = false; config.specialMoveOptions.profiles[1].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE; @@ -536,13 +538,29 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_R1; config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[2].OptionalParams = 0 + (1 << 4) + (1 << 8) + (0 << 12) + (1 << 16); //up //slow //1 loop //all lights //colour white + config.specialMoveOptions.profiles[2].bEnabled = true; + config.specialMoveOptions.profiles[2].AllSpecialMoves_count = 1; + strncpy(config.specialMoveOptions.profiles[2].Label, "Gief", sizeof(config.specialMoveOptions.profiles[1].Label) - 1); + + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].bIsChargeMove = false; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_KNIGHTRIDER; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredInputCombos_count = 1; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_NONE; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B3 | GAMEPAD_MASK_B4; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 2 + (2 << 4) + (1 << 8) + (1 << 12) + (2 << 16); //Left //slow //1 loop //top lights //colour Red + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_B4 | GAMEPAD_MASK_R1; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[2].OptionalParams = 2 + (3 << 4) + (1 << 8) + (1 << 12) + (2 << 16); //Left //medium //1 loop //top lights //colour Red + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3 | GAMEPAD_MASK_B4 | GAMEPAD_MASK_R1; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 2 + (4 << 4) + (2 << 8) + (1 << 12) + (4 << 16); //Left //fast //1 loop //top lights //colour Yellow + config.animationOptions.profiles_count = 2; config.animationOptions.profiles[0].bEnabled = true; - config.animationOptions.profiles[0].notPressedStaticColors_count = NUM_BANK0_GPIOS; - config.animationOptions.profiles[0].pressedStaticColors_count = NUM_BANK0_GPIOS; - for (unsigned int lightIndex = 0; lightIndex < NUM_BANK0_GPIOS; ++lightIndex) + config.animationOptions.profiles[0].notPressedStaticColors_count = (NUM_BANK0_GPIOS/4)+1; + config.animationOptions.profiles[0].pressedStaticColors_count = (NUM_BANK0_GPIOS/4)+1; + for (unsigned int lightIndex = 0; lightIndex < (NUM_BANK0_GPIOS/4)+1; ++lightIndex) { config.animationOptions.profiles[0].notPressedStaticColors[lightIndex] = 0; //Black config.animationOptions.profiles[0].pressedStaticColors[lightIndex] = 0; //Black @@ -556,13 +574,19 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) config.animationOptions.profiles[0].bUseCaseLightsInSpecialMoves = false; config.animationOptions.profiles[1].bEnabled = true; - config.animationOptions.profiles[1].notPressedStaticColors_count = NUM_BANK0_GPIOS; - config.animationOptions.profiles[1].pressedStaticColors_count = NUM_BANK0_GPIOS; - for (unsigned int lightIndex = 0; lightIndex < NUM_BANK0_GPIOS; ++lightIndex) + config.animationOptions.profiles[1].notPressedStaticColors_count = (NUM_BANK0_GPIOS/4)+1; + config.animationOptions.profiles[1].pressedStaticColors_count = (NUM_BANK0_GPIOS/4)+1; + for (unsigned int lightIndex = 0; lightIndex < (NUM_BANK0_GPIOS/4)+1; ++lightIndex) { - config.animationOptions.profiles[1].notPressedStaticColors[lightIndex] = 255 << 8; //Green + config.animationOptions.profiles[1].notPressedStaticColors[lightIndex] = 6 + (6<<8) + (6<<16) + (6<<24); //Green config.animationOptions.profiles[1].pressedStaticColors[lightIndex] = 0; //Black } + config.animationOptions.profiles[1].caseStaticColors_count = MAX_CASE_LIGHTS/4; + for (unsigned int caseLightIndex = 0; caseLightIndex < MAX_CASE_LIGHTS/4; ++caseLightIndex) + { + config.animationOptions.profiles[1].caseStaticColors[caseLightIndex] = 14 + (1<<8) + (1<<16) + (1<<24); //custom 1, white, white, white + } + config.animationOptions.profiles[1].baseNonPressedEffect = AnimationNonPressedEffects_Proto::AnimationNonPressedEffects_Proto_EFFECT_CHASE_SEQUENTIAL; config.animationOptions.profiles[1].basePressedEffect = AnimationPressedEffects_Proto::AnimationPressedEffects_Proto_EFFECT_RANDOM; config.animationOptions.profiles[1].baseCycleTime = 1; diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index c2a6a52b58..dd4b0599a3 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -218,11 +218,27 @@ void AnimationStorage::getAnimationOptions(AnimationOptions& options) options.profiles[index].bEnabled = optionsProto.profiles[index].bEnabled; options.profiles[index].baseNonPressedEffect = (AnimationNonPressedEffects)((int)optionsProto.profiles[index].baseNonPressedEffect); options.profiles[index].basePressedEffect = (AnimationPressedEffects)((int)optionsProto.profiles[index].basePressedEffect); + options.profiles[index].baseCaseEffect = (AnimationNonPressedEffects)((int)optionsProto.profiles[index].baseCaseEffect); options.profiles[index].baseCycleTime = optionsProto.profiles[index].baseCycleTime; - for(unsigned int pinIndex = 0; pinIndex < NUM_BANK0_GPIOS; ++pinIndex) + for(unsigned int packedPinIndex = 0; packedPinIndex < (NUM_BANK0_GPIOS/4)+1; ++packedPinIndex) { - options.profiles[index].notPressedStaticColors[pinIndex] = optionsProto.profiles[index].notPressedStaticColors[pinIndex]; - options.profiles[index].pressedStaticColors[pinIndex] = optionsProto.profiles[index].pressedStaticColors[pinIndex]; + int pinIndex = packedPinIndex * 4; + options.profiles[index].notPressedStaticColors[pinIndex + 0] = optionsProto.profiles[index].notPressedStaticColors[packedPinIndex] & 0xFF; + options.profiles[index].notPressedStaticColors[pinIndex + 1] = (optionsProto.profiles[index].notPressedStaticColors[packedPinIndex] >> 8) & 0xFF; + options.profiles[index].notPressedStaticColors[pinIndex + 2] = (optionsProto.profiles[index].notPressedStaticColors[packedPinIndex] >> 16) & 0xFF; + options.profiles[index].notPressedStaticColors[pinIndex + 3] = (optionsProto.profiles[index].notPressedStaticColors[packedPinIndex] >> 24) & 0xFF; + options.profiles[index].pressedStaticColors[pinIndex + 0] = optionsProto.profiles[index].pressedStaticColors[packedPinIndex] & 0xFF; + options.profiles[index].pressedStaticColors[pinIndex + 1] = (optionsProto.profiles[index].pressedStaticColors[packedPinIndex] >> 8) & 0xFF; + options.profiles[index].pressedStaticColors[pinIndex + 2] = (optionsProto.profiles[index].pressedStaticColors[packedPinIndex] >> 16) & 0xFF; + options.profiles[index].pressedStaticColors[pinIndex + 3] = (optionsProto.profiles[index].pressedStaticColors[packedPinIndex] >> 24) & 0xFF; + } + for(unsigned int packedCaseIndex = 0; packedCaseIndex < MAX_CASE_LIGHTS / 4; ++packedCaseIndex) + { + int caseIndex = packedCaseIndex * 4; + options.profiles[index].caseStaticColors[caseIndex + 0] = optionsProto.profiles[index].caseStaticColors[packedCaseIndex] & 0xFF; + options.profiles[index].caseStaticColors[caseIndex + 1] = (optionsProto.profiles[index].caseStaticColors[packedCaseIndex] >> 8) & 0xFF; + options.profiles[index].caseStaticColors[caseIndex + 2] = (optionsProto.profiles[index].caseStaticColors[packedCaseIndex] >> 16) & 0xFF; + options.profiles[index].caseStaticColors[caseIndex + 3] = (optionsProto.profiles[index].caseStaticColors[packedCaseIndex] >> 24) & 0xFF; } options.profiles[index].buttonPressHoldTimeInMs = optionsProto.profiles[index].buttonPressHoldTimeInMs; options.profiles[index].buttonPressFadeOutTimeInMs = optionsProto.profiles[index].buttonPressFadeOutTimeInMs; @@ -231,6 +247,12 @@ void AnimationStorage::getAnimationOptions(AnimationOptions& options) } options.brightness = std::min(optionsProto.brightness, 255); options.baseProfileIndex = std::min(optionsProto.baseProfileIndex, 255); + + customColors.clear(); + for(unsigned int customColIndex = 0; customColIndex < MAX_CUSTOM_COLORS; ++customColIndex) + { + customColors.push_back(optionsProto.customColors[customColIndex]); + } } void AnimationStorage::getSpecialMoveOptions(SpecialMoveOptions& options) From 57d4128da4d8d21e0e1b0e6f01f5517c74f21de0 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Sun, 12 Jan 2025 13:03:06 +0000 Subject: [PATCH 015/121] Special moves priority and Jiggle effect Added priority so special moves with more inputs but similar to other moves can be prioritised (eg EX moves). Added new Jiggle effect to simulate fire/electricity. --- lib/AnimationStation/CMakeLists.txt | 2 + lib/AnimationStation/src/Animation.cpp | 2 +- lib/AnimationStation/src/AnimationStation.cpp | 14 ++++++ lib/AnimationStation/src/AnimationStation.hpp | 9 +++- .../src/Effects/JiggleStaticColor.cpp | 32 +++++++++++++ .../src/Effects/JiggleStaticColor.hpp | 22 +++++++++ .../src/Effects/JiggleTwoStaticColor.cpp | 48 +++++++++++++++++++ .../src/Effects/JiggleTwoStaticColor.hpp | 22 +++++++++ .../src/Effects/StaticColor.cpp | 4 +- .../src/Effects/StaticColor.hpp | 3 +- .../src/SpecialMoveSystem.cpp | 32 +++++++++---- .../src/SpecialMoveSystem.hpp | 8 ++++ proto/config.proto | 4 ++ proto/enums.proto | 4 ++ src/config_utils.cpp | 36 +++++++++----- src/storagemanager.cpp | 2 + 16 files changed, 218 insertions(+), 26 deletions(-) create mode 100644 lib/AnimationStation/src/Effects/JiggleStaticColor.cpp create mode 100644 lib/AnimationStation/src/Effects/JiggleStaticColor.hpp create mode 100644 lib/AnimationStation/src/Effects/JiggleTwoStaticColor.cpp create mode 100644 lib/AnimationStation/src/Effects/JiggleTwoStaticColor.hpp diff --git a/lib/AnimationStation/CMakeLists.txt b/lib/AnimationStation/CMakeLists.txt index 308ae5bc86..c37454bf4f 100644 --- a/lib/AnimationStation/CMakeLists.txt +++ b/lib/AnimationStation/CMakeLists.txt @@ -2,6 +2,8 @@ add_library(AnimationStation src/Effects/Chase.cpp src/Effects/Rainbow.cpp src/Effects/StaticColor.cpp +src/Effects/JiggleStaticColor.cpp +src/Effects/JiggleTwoStaticColor.cpp src/Effects/RandomColor.cpp src/Effects/SMPulseColour.cpp src/Effects/SMWave.cpp diff --git a/lib/AnimationStation/src/Animation.cpp b/lib/AnimationStation/src/Animation.cpp index 0234879cee..ea15905a95 100644 --- a/lib/AnimationStation/src/Animation.cpp +++ b/lib/AnimationStation/src/Animation.cpp @@ -204,7 +204,7 @@ RGB Animation::GetPressedColorForLight(uint32_t LightIndex) RGB Animation::GetColorForIndex(uint32_t ColorIndex) { //pre defined color? - if(ColorIndex < (int)colors.size()) + if(ColorIndex < (uint32_t)colors.size()) return colors[ColorIndex]; //must be custom color diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index c2abd96d12..7a00016643 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -8,6 +8,8 @@ #include "Effects/Chase.hpp" #include "Effects/Rainbow.hpp" #include "Effects/StaticColor.hpp" +#include "Effects/JiggleStaticColor.hpp" +#include "Effects/JiggleTwoStaticColor.hpp" #include "Effects/RandomColor.hpp" #include "Effects/SMPulseColour.hpp" #include "Effects/SMCircleColour.hpp" @@ -317,6 +319,12 @@ void AnimationStation::SetMode(int8_t mode) case AnimationNonPressedEffects::NONPRESSED_EFFECT_STATIC_COLOR: this->baseAnimation = new StaticColor(RGBLights); break; + case AnimationNonPressedEffects::NONPRESSED_EFFECT_JIGGLESTATIC: + this->baseAnimation = new JiggleStaticColor(RGBLights); + break; + case AnimationNonPressedEffects::NONPRESSED_EFFECT_JIGGLETWOSTATIC: + this->baseAnimation = new JiggleTwoStaticColor(RGBLights); + break; default: break; @@ -332,6 +340,12 @@ void AnimationStation::SetMode(int8_t mode) case AnimationPressedEffects::PRESSED_EFFECT_STATIC_COLOR: this->buttonAnimation = new StaticColor(RGBLights, lastPressed); break; + case AnimationPressedEffects::PRESSED_EFFECT_JIGGLESTATIC: + this->buttonAnimation = new JiggleStaticColor(RGBLights, lastPressed); + break; + case AnimationPressedEffects::PRESSED_EFFECT_JIGGLETWOSTATIC: + this->buttonAnimation = new JiggleTwoStaticColor(RGBLights, lastPressed); + break; default: break; diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index b6258eaa81..b90e0e52f8 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -31,6 +31,8 @@ typedef enum NONPRESSED_EFFECT_CHASE_HORIZONTAL_PINGPONG, NONPRESSED_EFFECT_CHASE_VERTICAL_PINGPONG, NONPRESSED_EFFECT_CHASE_RANDOM, + NONPRESSED_EFFECT_JIGGLESTATIC, + NONPRESSED_EFFECT_JIGGLETWOSTATIC, } AnimationNonPressedEffects; //List of non-pressed animation types @@ -38,6 +40,8 @@ typedef enum { PRESSED_EFFECT_STATIC_COLOR, PRESSED_EFFECT_RANDOM, + PRESSED_EFFECT_JIGGLESTATIC, + PRESSED_EFFECT_JIGGLETWOSTATIC, } AnimationPressedEffects; typedef enum @@ -65,8 +69,8 @@ struct __attribute__ ((__packed__)) AnimationProfile int16_t baseCycleTime; - uint32_t notPressedStaticColors[NUM_BANK0_GPIOS]; - uint32_t pressedStaticColors[NUM_BANK0_GPIOS]; + uint32_t notPressedStaticColors[NUM_BANK0_GPIOS + 3]; //since we pack 4 into each. Adding 3 ensures we have space for extra pading + uint32_t pressedStaticColors[NUM_BANK0_GPIOS + 3]; //since we pack 4 into each. Adding 3 ensures we have space for extra pading uint32_t caseStaticColors[MAX_CASE_LIGHTS]; @@ -74,6 +78,7 @@ struct __attribute__ ((__packed__)) AnimationProfile uint32_t buttonPressFadeOutTimeInMs; uint32_t nonPressedSpecialColour; + uint32_t pressedSpecialColour; bool bUseCaseLightsInSpecialMoves; }; diff --git a/lib/AnimationStation/src/Effects/JiggleStaticColor.cpp b/lib/AnimationStation/src/Effects/JiggleStaticColor.cpp new file mode 100644 index 0000000000..47f5f0c8c2 --- /dev/null +++ b/lib/AnimationStation/src/Effects/JiggleStaticColor.cpp @@ -0,0 +1,32 @@ +#include "JiggleStaticColor.hpp" +#include "StaticColor.hpp" + +JiggleStaticColor::JiggleStaticColor(Lights& InRGBLights) : StaticColor(InRGBLights) +{ +} + +JiggleStaticColor::JiggleStaticColor(Lights& InRGBLights, std::vector &InPressedPins) : StaticColor(InRGBLights, InPressedPins) +{ +} + +RGB JiggleStaticColor::AdjustColor(RGB InColor) +{ + RGB outColor; + float newR = (((float)InColor.r) * 0.85f) + (38 * (((float)(rand() % 100) / 100.0f))); + if(newR > 255.0f) + newR = 255; + outColor.r = (int)newR; + +float newG = (((float)InColor.g) * 0.85f) + (38 * (((float)(rand() % 100) / 100.0f))); + if(newG > 255.0f) + newG = 255; + outColor.g = (int)newG; + + float newB = (((float)InColor.b) * 0.85f) + (38 * (((float)(rand() % 100) / 100.0f))); + if(newB > 255.0f) + newB = 255; + outColor.b = (int)newB; + + return outColor; +} + \ No newline at end of file diff --git a/lib/AnimationStation/src/Effects/JiggleStaticColor.hpp b/lib/AnimationStation/src/Effects/JiggleStaticColor.hpp new file mode 100644 index 0000000000..689e5c4cb9 --- /dev/null +++ b/lib/AnimationStation/src/Effects/JiggleStaticColor.hpp @@ -0,0 +1,22 @@ +#ifndef _JIGGLE_STATIC_COLOR_H_ +#define _JIGGLE_STATIC_COLOR_H_ + +#include +#include +#include +#include "../Animation.hpp" +#include "../AnimationStation.hpp" +#include "StaticColor.hpp" + +class JiggleStaticColor : public StaticColor { +public: + JiggleStaticColor(Lights& InRGBLights); + JiggleStaticColor(Lights& InRGBLights, std::vector &InPressedPins); + ~JiggleStaticColor() { }; + + virtual RGB AdjustColor(RGB InColor) override; + +protected: +}; + +#endif diff --git a/lib/AnimationStation/src/Effects/JiggleTwoStaticColor.cpp b/lib/AnimationStation/src/Effects/JiggleTwoStaticColor.cpp new file mode 100644 index 0000000000..0f5a4c2b7c --- /dev/null +++ b/lib/AnimationStation/src/Effects/JiggleTwoStaticColor.cpp @@ -0,0 +1,48 @@ +#include "JiggleTwoStaticColor.hpp" +#include "StaticColor.hpp" + +JiggleTwoStaticColor::JiggleTwoStaticColor(Lights& InRGBLights) : StaticColor(InRGBLights) +{ +} + +JiggleTwoStaticColor::JiggleTwoStaticColor(Lights& InRGBLights, std::vector &InPressedPins) : StaticColor(InRGBLights, InPressedPins) +{ +} + +RGB JiggleTwoStaticColor::AdjustColor(RGB InColor) +{ + RGB otherColor; + + if(isButtonAnimation) + otherColor = RGB(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].pressedSpecialColour); + else + otherColor = RGB(AnimationStation::options.profiles[AnimationStation::options.baseProfileIndex].nonPressedSpecialColour); + + RGB outColor; + float rDiff = (float)otherColor.r - (float)InColor.r; + float newR = (float)InColor.r + (rDiff * (((float)(rand() % 100) / 100.0f))); + if(newR > 255.0f) + newR = 255; + if(newR < 0) + newR = 0; + outColor.r = (int)newR; + + float gDiff = (float)otherColor.g - (float)InColor.g; + float newG = (float)InColor.g + (gDiff * (((float)(rand() % 100) / 100.0f))); + if(newG > 255.0f) + newG = 255; + if(newG < 0) + newG = 0; + outColor.g = (int)newG; + + float bDiff = (float)otherColor.b - (float)InColor.b; + float newB = (float)InColor.b + (bDiff * (((float)(rand() % 100) / 100.0f))); + if(newB > 255.0f) + newB = 255; + if(newB < 0) + newB = 0; + outColor.b = (int)newB; + + return outColor; +} + \ No newline at end of file diff --git a/lib/AnimationStation/src/Effects/JiggleTwoStaticColor.hpp b/lib/AnimationStation/src/Effects/JiggleTwoStaticColor.hpp new file mode 100644 index 0000000000..0e027892f0 --- /dev/null +++ b/lib/AnimationStation/src/Effects/JiggleTwoStaticColor.hpp @@ -0,0 +1,22 @@ +#ifndef _JIGGLE_TWO_STATIC_COLOR_H_ +#define _JIGGLE_TWO_STATIC_COLOR_H_ + +#include +#include +#include +#include "../Animation.hpp" +#include "../AnimationStation.hpp" +#include "StaticColor.hpp" + +class JiggleTwoStaticColor : public StaticColor { +public: + JiggleTwoStaticColor(Lights& InRGBLights); + JiggleTwoStaticColor(Lights& InRGBLights, std::vector &InPressedPins); + ~JiggleTwoStaticColor() { }; + + virtual RGB AdjustColor(RGB InColor) override; + +protected: +}; + +#endif diff --git a/lib/AnimationStation/src/Effects/StaticColor.cpp b/lib/AnimationStation/src/Effects/StaticColor.cpp index c083dd023c..3a916df474 100644 --- a/lib/AnimationStation/src/Effects/StaticColor.cpp +++ b/lib/AnimationStation/src/Effects/StaticColor.cpp @@ -25,11 +25,11 @@ void StaticColor::Animate(RGB (&frame)[100]) //Non pressed simply sets the RGB colour if(!isButtonAnimation && LightTypeIsForNonPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { - frame[ledIndex] = GetNonPressedColorForLight(lightIndex); + frame[ledIndex] = AdjustColor(GetNonPressedColorForLight(lightIndex)); } else if (isButtonAnimation && LightTypeIsForPressedAnimation(RGBLights->AllLights[lightIndex].Type)) { - frame[ledIndex] = FadeColor(GetPressedColorForLight(lightIndex), + frame[ledIndex] = FadeColor(AdjustColor(GetPressedColorForLight(lightIndex)), frame[ledIndex], fadeTimes[ledIndex]); } diff --git a/lib/AnimationStation/src/Effects/StaticColor.hpp b/lib/AnimationStation/src/Effects/StaticColor.hpp index 8772cb40a5..773d517022 100644 --- a/lib/AnimationStation/src/Effects/StaticColor.hpp +++ b/lib/AnimationStation/src/Effects/StaticColor.hpp @@ -14,8 +14,9 @@ class StaticColor : public Animation { ~StaticColor() { }; virtual void Animate(RGB (&frame)[100]) override; - protected: + + virtual RGB AdjustColor(RGB InColor) { return InColor; } }; #endif diff --git a/lib/AnimationStation/src/SpecialMoveSystem.cpp b/lib/AnimationStation/src/SpecialMoveSystem.cpp index 3ac11fcfb2..f8bf7f4720 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.cpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.cpp @@ -100,7 +100,19 @@ bool SpecialMoveSystem::TestAllMoves() if(Options.NumValidProfiles == 0 || Options.CurrentProfileIndex > Options.NumValidProfiles || Options.profiles[Options.CurrentProfileIndex].bEnabled == false) return false; - //Test Each move + //Move is ready to fire + if(bHasCachedSucceededMove && GetMsBetweenTimes(cachedSucceededMoveTime, thisFrameTime) > PRIORITY_LEEWAY_TIME) + { + bHasCachedSucceededMove = false; + // Clear the history to prevent retrigger if animation is really quick + ClearHistory(); + if(ParentAnimationStation) + ParentAnimationStation->SetSpecialMoveAnimation(cachedSucceededMoveAnimation, cachedSucceededMoveParams); + SwitchClearAwaitingAllRelease = true; + return true; + } + + //Test Each move and cache successes so higher priority ones can take preferrence uint32_t numMoves = Options.profiles[Options.CurrentProfileIndex].NumValidMoves; for(uint32_t moveIndex = 0; moveIndex < numMoves; ++moveIndex) { @@ -125,13 +137,17 @@ bool SpecialMoveSystem::TestAllMoves() if(bSucceeded) { - // Clear the history to prevent retrigger if animation is really quick - ClearHistory(); - if(ParentAnimationStation) - ParentAnimationStation->SetSpecialMoveAnimation(thisMove.Animation, thisMove.RequiredTriggerCombos[triggerIndex].OptionalParams); - SwitchClearAwaitingAllRelease = true; - - return true; + if(!bHasCachedSucceededMove || thisMove.Priority > cachedSucceededMovePriority) + { + if(!bHasCachedSucceededMove) + { + bHasCachedSucceededMove = true; + cachedSucceededMoveTime = thisFrameTime; + } + cachedSucceededMovePriority = thisMove.Priority; + cachedSucceededMoveAnimation = thisMove.Animation; + cachedSucceededMoveParams = thisMove.RequiredTriggerCombos[triggerIndex].OptionalParams; + } } } } diff --git a/lib/AnimationStation/src/SpecialMoveSystem.hpp b/lib/AnimationStation/src/SpecialMoveSystem.hpp index 9712289f86..ca428e9d1b 100644 --- a/lib/AnimationStation/src/SpecialMoveSystem.hpp +++ b/lib/AnimationStation/src/SpecialMoveSystem.hpp @@ -20,6 +20,7 @@ #define COMBO_TRIGGER_INPUT_TIME_WINDOW 200 //Maximum time between combined button inputs eg PP, PPP, KK or PK etc #define COMBO_INPUT_COUNT_FOR_ONE_OUT_OF_TWO 7 //if the combo input is 7 or more moves then the input system will allow you to succeed if you dont miss 2 in a row window. eg LDRU would be fine for a SPD #define COMBO_INPUT_COUNT_FOR_ONE_MISSING_IN_MIDDLE 5 //if the combo input is 5 (HCF) or more moves then the input system will allow you to succeed if you dont miss more than 1 in the middle +#define PRIORITY_LEEWAY_TIME 75 //List of specialMove animation typedef enum @@ -161,6 +162,7 @@ struct __attribute__ ((__packed__)) SpecialMoveDescription SpecialMoveEffects Animation; bool bIsChargeMove = false; + int Priority; }; struct __attribute__ ((__packed__)) SpecialMoveProfile @@ -237,6 +239,12 @@ class SpecialMoveSystem { uint32_t SPECIAL_MOVE_BUTTON_MASK_P1; bool bMoveIsRunning = false; + + absolute_time_t cachedSucceededMoveTime; + int cachedSucceededMovePriority; + SpecialMoveEffects cachedSucceededMoveAnimation; + uint32_t cachedSucceededMoveParams; + bool bHasCachedSucceededMove = false; }; #endif diff --git a/proto/config.proto b/proto/config.proto index 2a5558f86c..d1f19452c4 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -308,6 +308,8 @@ message SpecialMoveDescription_Proto optional SpecialMoveEffects_Proto Animation = 3; optional bool bIsChargeMove = 4; + + optional int32 Priority = 5; }; // This has to be kept in sync with SpecialMoveProfile in SpecialMoveSystem.hpp @@ -349,6 +351,8 @@ message AnimationProfile_Proto optional AnimationNonPressedEffects_Proto baseCaseEffect = 11; repeated uint32 caseStaticColors = 12 [(nanopb).max_count = 10]; //(MAX_CASE_LIGHTS/4) from AnimationStation.hpp + + optional uint32 pressedSpecialColour = 13; }; // This has to be kept in sync with AnimationOptions in AnimationStation.hpp diff --git a/proto/enums.proto b/proto/enums.proto index 8e8aa17bf1..eb1602434d 100644 --- a/proto/enums.proto +++ b/proto/enums.proto @@ -362,6 +362,8 @@ enum AnimationNonPressedEffects_Proto EFFECT_CHASE_HORIZONTAL_PINGPONG = 9; EFFECT_CHASE_VERTICAL_PINGPONG = 10; EFFECT_CHASE_RANDOM = 11; + EFFECT_JIGGLESTATIC = 12; + EFFECT_JIGGLETWOSTATICS = 13; } /* This has to be kept in sync with AnimationPressedEffects in AnimationStation.hpp */ @@ -369,6 +371,8 @@ enum AnimationPressedEffects_Proto { EFFECT_HELD_STATIC_COLOR = 0; EFFECT_RANDOM = 1; + EFFECT_HELD_JIGGLESTATIC = 2; + EFFECT_HELD_JIGGLETWOSTATICS = 3; } /* This has to be kept in sync with LightType in Pixel.hpp */ diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 6da443ace1..07d815c179 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -498,6 +498,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) config.specialMoveOptions.profiles[0].AllSpecialMoves[0].bIsChargeMove = false; config.specialMoveOptions.profiles[0].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE; + config.specialMoveOptions.profiles[0].AllSpecialMoves[0].Priority = 0; config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos_count = 1; config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_QUARTER_DOWN_LEFT; config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; @@ -510,6 +511,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) config.specialMoveOptions.profiles[0].AllSpecialMoves[1].bIsChargeMove = false; config.specialMoveOptions.profiles[0].AllSpecialMoves[1].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE; + config.specialMoveOptions.profiles[0].AllSpecialMoves[1].Priority = 0; config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos_count = 1; config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_QUARTER_DOWN_RIGHT; config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos_count = 3; @@ -527,6 +529,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) config.specialMoveOptions.profiles[1].AllSpecialMoves[0].bIsChargeMove = false; config.specialMoveOptions.profiles[1].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE; + config.specialMoveOptions.profiles[1].AllSpecialMoves[0].Priority = 0; config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredInputCombos_count = 2; config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_LEFT; config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredInputCombos[1] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_RIGHT; @@ -539,20 +542,28 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[2].OptionalParams = 0 + (1 << 4) + (1 << 8) + (0 << 12) + (1 << 16); //up //slow //1 loop //all lights //colour white config.specialMoveOptions.profiles[2].bEnabled = true; - config.specialMoveOptions.profiles[2].AllSpecialMoves_count = 1; + config.specialMoveOptions.profiles[2].AllSpecialMoves_count = 2; strncpy(config.specialMoveOptions.profiles[2].Label, "Gief", sizeof(config.specialMoveOptions.profiles[1].Label) - 1); config.specialMoveOptions.profiles[2].AllSpecialMoves[0].bIsChargeMove = false; config.specialMoveOptions.profiles[2].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_KNIGHTRIDER; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].Priority = 0; config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredInputCombos_count = 1; config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_NONE; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B3 | GAMEPAD_MASK_B4; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 2 + (2 << 4) + (1 << 8) + (1 << 12) + (2 << 16); //Left //slow //1 loop //top lights //colour Red - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_B4 | GAMEPAD_MASK_R1; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[2].OptionalParams = 2 + (3 << 4) + (1 << 8) + (1 << 12) + (2 << 16); //Left //medium //1 loop //top lights //colour Red - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3 | GAMEPAD_MASK_B4 | GAMEPAD_MASK_R1; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 2 + (4 << 4) + (2 << 8) + (1 << 12) + (4 << 16); //Left //fast //1 loop //top lights //colour Yellow + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos_count = 2; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3 | GAMEPAD_MASK_B4; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 2 + (2 << 4) + (1 << 8) + (1 << 12) + (2 << 16); //Left //slow //1 loop //top lights //colour Red + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4 | GAMEPAD_MASK_R1; + config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 2 + (3 << 4) + (1 << 8) + (1 << 12) + (2 << 16); //Left //medium //1 loop //top lights //colour Red + + config.specialMoveOptions.profiles[2].AllSpecialMoves[1].bIsChargeMove = false; + config.specialMoveOptions.profiles[2].AllSpecialMoves[1].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_KNIGHTRIDER; + config.specialMoveOptions.profiles[2].AllSpecialMoves[1].Priority = 1; + config.specialMoveOptions.profiles[2].AllSpecialMoves[1].RequiredInputCombos_count = 1; + config.specialMoveOptions.profiles[2].AllSpecialMoves[1].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_NONE; + config.specialMoveOptions.profiles[2].AllSpecialMoves[1].RequiredTriggerCombos_count = 1; + config.specialMoveOptions.profiles[2].AllSpecialMoves[1].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3 | GAMEPAD_MASK_B4 | GAMEPAD_MASK_R1; + config.specialMoveOptions.profiles[2].AllSpecialMoves[1].RequiredTriggerCombos[0].OptionalParams = 2 + (4 << 4) + (2 << 8) + (1 << 12) + (4 << 16); //Left //fast //1 loop //top lights //colour Yellow config.animationOptions.profiles_count = 2; @@ -579,7 +590,7 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) for (unsigned int lightIndex = 0; lightIndex < (NUM_BANK0_GPIOS/4)+1; ++lightIndex) { config.animationOptions.profiles[1].notPressedStaticColors[lightIndex] = 6 + (6<<8) + (6<<16) + (6<<24); //Green - config.animationOptions.profiles[1].pressedStaticColors[lightIndex] = 0; //Black + config.animationOptions.profiles[1].pressedStaticColors[lightIndex] = 2 + (2<<8) + (2<<16) + (2<<24); //Black } config.animationOptions.profiles[1].caseStaticColors_count = MAX_CASE_LIGHTS/4; for (unsigned int caseLightIndex = 0; caseLightIndex < MAX_CASE_LIGHTS/4; ++caseLightIndex) @@ -587,12 +598,13 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) config.animationOptions.profiles[1].caseStaticColors[caseLightIndex] = 14 + (1<<8) + (1<<16) + (1<<24); //custom 1, white, white, white } - config.animationOptions.profiles[1].baseNonPressedEffect = AnimationNonPressedEffects_Proto::AnimationNonPressedEffects_Proto_EFFECT_CHASE_SEQUENTIAL; - config.animationOptions.profiles[1].basePressedEffect = AnimationPressedEffects_Proto::AnimationPressedEffects_Proto_EFFECT_RANDOM; + config.animationOptions.profiles[1].baseNonPressedEffect = AnimationNonPressedEffects_Proto::AnimationNonPressedEffects_Proto_EFFECT_STATIC_COLOR; + config.animationOptions.profiles[1].basePressedEffect = AnimationPressedEffects_Proto::AnimationPressedEffects_Proto_EFFECT_HELD_JIGGLETWOSTATICS; config.animationOptions.profiles[1].baseCycleTime = 1; config.animationOptions.profiles[1].buttonPressHoldTimeInMs = 500; config.animationOptions.profiles[1].buttonPressFadeOutTimeInMs = 500; - config.animationOptions.profiles[1].nonPressedSpecialColour = 255 << 16; //RED + config.animationOptions.profiles[1].nonPressedSpecialColour = 255; //BLUE + config.animationOptions.profiles[1].pressedSpecialColour = (255 << 16) + (50 << 8); //reddy YELLOW config.animationOptions.profiles[1].bUseCaseLightsInSpecialMoves = true; } diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index dd4b0599a3..59a1444dac 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -243,6 +243,7 @@ void AnimationStorage::getAnimationOptions(AnimationOptions& options) options.profiles[index].buttonPressHoldTimeInMs = optionsProto.profiles[index].buttonPressHoldTimeInMs; options.profiles[index].buttonPressFadeOutTimeInMs = optionsProto.profiles[index].buttonPressFadeOutTimeInMs; options.profiles[index].nonPressedSpecialColour = optionsProto.profiles[index].nonPressedSpecialColour; + options.profiles[index].pressedSpecialColour = optionsProto.profiles[index].pressedSpecialColour; options.profiles[index].bUseCaseLightsInSpecialMoves = optionsProto.profiles[index].bUseCaseLightsInSpecialMoves; } options.brightness = std::min(optionsProto.brightness, 255); @@ -281,6 +282,7 @@ void AnimationStorage::getSpecialMoveOptions(SpecialMoveOptions& options) options.profiles[profileIndex].AllSpecialMoves[moveIndex].Animation = (SpecialMoveEffects)((int)optionsProto.profiles[profileIndex].AllSpecialMoves[moveIndex].Animation); options.profiles[profileIndex].AllSpecialMoves[moveIndex].bIsChargeMove = optionsProto.profiles[profileIndex].AllSpecialMoves[moveIndex].bIsChargeMove; + options.profiles[profileIndex].AllSpecialMoves[moveIndex].Priority = optionsProto.profiles[profileIndex].AllSpecialMoves[moveIndex].Priority; } } From 1cc471ba359af55e80cf5123bbdd20605394f112 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Tue, 14 Jan 2025 08:00:39 +0000 Subject: [PATCH 016/121] Update config.proto --- proto/config.proto | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/proto/config.proto b/proto/config.proto index d1f19452c4..f3ba03795a 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -298,6 +298,11 @@ message SpecialMoveInputTriggers_Proto { optional uint32 OptionalParams = 1; //8 uint4's packed in here (assigned to custom enums later) optional uint32 RequiredTriggers = 2; //buttonmasks + + optional SpecialMoveEffects_Proto ChainedAnimation = 3; + optional uint32 ChainedOptionalParams = 4; + optional SpecialMoveEffects_Proto ChainedAnimationTwo = 5; + optional uint32 ChainedOptionalParamsTwo = 6; }; // This has to be kept in sync with SpecialMoveDescription in SpecialMoveSystem.hpp From fc3fb16564238a30b0773b12fa24a8371283e149 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Tue, 14 Jan 2025 18:14:25 +0000 Subject: [PATCH 017/121] Removed all SM stuff from ConvertToGIPOBranch --- headers/storagemanager.h | 2 +- proto/config.proto | 66 +++++++-------- src/config_utils.cpp | 81 ------------------- src/display/ui/screens/ButtonLayoutScreen.cpp | 4 +- src/storagemanager.cpp | 12 +-- 5 files changed, 43 insertions(+), 122 deletions(-) diff --git a/headers/storagemanager.h b/headers/storagemanager.h index 465e826d90..d5f2471707 100644 --- a/headers/storagemanager.h +++ b/headers/storagemanager.h @@ -46,7 +46,7 @@ class Storage { ProfileOptions& getProfileOptions() { return config.profileOptions; } GpioMappingInfo* getProfilePinMappings() { return functionalPinMappings; } PeripheralOptions& getPeripheralOptions() { return config.peripheralOptions; } - SpecialMoveOptions_Proto& getSpecialMoveOptions() { return config.specialMoveOptions; } + //SpecialMoveOptions_Proto& getSpecialMoveOptions() { return config.specialMoveOptions; } void init(); bool save(); diff --git a/proto/config.proto b/proto/config.proto index f3ba03795a..3b74588ed1 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -294,44 +294,44 @@ message LEDOptions }; // This has to be kept in sync with SpecialMoveAnimation in SpecialMoveSystem.hpp -message SpecialMoveInputTriggers_Proto -{ - optional uint32 OptionalParams = 1; //8 uint4's packed in here (assigned to custom enums later) - optional uint32 RequiredTriggers = 2; //buttonmasks - - optional SpecialMoveEffects_Proto ChainedAnimation = 3; - optional uint32 ChainedOptionalParams = 4; - optional SpecialMoveEffects_Proto ChainedAnimationTwo = 5; - optional uint32 ChainedOptionalParamsTwo = 6; -}; +//message SpecialMoveInputTriggers_Proto +//{ +// optional uint32 OptionalParams = 1; //8 uint4's packed in here (assigned to custom enums later) +// optional uint32 RequiredTriggers = 2; //buttonmasks +// +// optional SpecialMoveEffects_Proto ChainedAnimation = 3; +// optional uint32 ChainedOptionalParams = 4; +// optional SpecialMoveEffects_Proto ChainedAnimationTwo = 5; +// optional uint32 ChainedOptionalParamsTwo = 6; +//}; // This has to be kept in sync with SpecialMoveDescription in SpecialMoveSystem.hpp -message SpecialMoveDescription_Proto -{ - repeated SpecialMoveInputTypes_Proto RequiredInputCombos = 1 [(nanopb).max_count = 4]; //MAX_SPECIALMOVE_INPUTTYPES_PER_MOVE from SpecialMoveSystem.hpp - repeated SpecialMoveInputTriggers_Proto RequiredTriggerCombos = 2 [(nanopb).max_count = 3]; //MAX_SPECIALMOVE_TRIGGERCOMBOS from SpecialMoveSystem.hpp - - optional SpecialMoveEffects_Proto Animation = 3; - optional bool bIsChargeMove = 4; - - optional int32 Priority = 5; -}; +//message SpecialMoveDescription_Proto +//{ +// repeated SpecialMoveInputTypes_Proto RequiredInputCombos = 1 [(nanopb).max_count = 4]; //MAX_SPECIALMOVE_INPUTTYPES_PER_MOVE from SpecialMoveSystem.hpp +// repeated SpecialMoveInputTriggers_Proto RequiredTriggerCombos = 2 [(nanopb).max_count = 3]; //MAX_SPECIALMOVE_TRIGGERCOMBOS from SpecialMoveSystem.hpp +// +// optional SpecialMoveEffects_Proto Animation = 3; +// optional bool bIsChargeMove = 4; +// +// optional int32 Priority = 5; +//}; // This has to be kept in sync with SpecialMoveProfile in SpecialMoveSystem.hpp -message SpecialMoveProfile_Proto -{ - optional bool bEnabled = 1; - repeated SpecialMoveDescription_Proto AllSpecialMoves = 2 [(nanopb).max_count = 20]; //MAX_SPECIALMOVES from SpecialMoveSystem.hpp - optional string Label = 3 [(nanopb).max_length = 12]; -}; +//message SpecialMoveProfile_Proto +//{ +// optional bool bEnabled = 1; +// repeated SpecialMoveDescription_Proto AllSpecialMoves = 2 [(nanopb).max_count = 20]; //MAX_SPECIALMOVES from SpecialMoveSystem.hpp +// optional string Label = 3 [(nanopb).max_length = 12]; +//}; // This has to be kept in sync with SpecialMoveOptions in SpecialMoveSystem.hpp -message SpecialMoveOptions_Proto -{ - repeated SpecialMoveProfile_Proto profiles = 1 [(nanopb).max_count = 4]; //MAX_SPECIALMOVE_PROFILES from SpecialMoveSystem.hpp - optional uint32 ChargeTimeInMs = 2; - optional uint32 CurrentProfileIndex = 3; -}; +//message SpecialMoveOptions_Proto +//{ +// repeated SpecialMoveProfile_Proto profiles = 1 [(nanopb).max_count = 4]; //MAX_SPECIALMOVE_PROFILES from SpecialMoveSystem.hpp +// optional uint32 ChargeTimeInMs = 2; +// optional uint32 CurrentProfileIndex = 3; +//}; // This has to be kept in sync with AnimationProfile in AnimationStation.hpp message AnimationProfile_Proto @@ -922,5 +922,5 @@ message Config optional MigrationHistory migrations = 14; optional PeripheralOptions peripheralOptions = 15; - optional SpecialMoveOptions_Proto specialMoveOptions = 16; + //optional SpecialMoveOptions_Proto specialMoveOptions = 16; } diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 07d815c179..48ac7cef8b 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -474,10 +474,6 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.ledOptions, lightDataSize, LIGHT_DATA_SIZE); const unsigned char lightData[] = { LIGHT_DATA }; INIT_UNSET_PROPERTY_BYTES(config.ledOptions, lightData, lightData); - - //SpecialMoveOptions - INIT_UNSET_PROPERTY(config.specialMoveOptions, ChargeTimeInMs, 750); - INIT_UNSET_PROPERTY(config.specialMoveOptions, CurrentProfileIndex, 0); // animationOptions INIT_UNSET_PROPERTY(config.animationOptions, brightness, LEDS_BRIGHTNESS); @@ -486,86 +482,9 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) //TESTING config.animationOptions.customColors_count = 1; config.animationOptions.customColors[0] = 255; - config.specialMoveOptions.profiles_count = 0; config.animationOptions.profiles_count = 0; if(true) { - config.specialMoveOptions.profiles_count = 3; - - config.specialMoveOptions.profiles[0].bEnabled = true; - config.specialMoveOptions.profiles[0].AllSpecialMoves_count = 2; - strncpy(config.specialMoveOptions.profiles[0].Label, "Ryu", sizeof(config.specialMoveOptions.profiles[0].Label) - 1); - - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].bIsChargeMove = false; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].Priority = 0; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos_count = 1; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_QUARTER_DOWN_LEFT; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 1 + (1 << 4) + (1 << 8) + (0 << 12) + (14 << 16); //Left //slow //1 loop //all lights //colour custom 1 - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 1 + (2 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //Left //medium //1 loop //all lights //colour skyblue - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_R1; - config.specialMoveOptions.profiles[0].AllSpecialMoves[0].RequiredTriggerCombos[2].OptionalParams = 1 + (3 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //Left //fast //1 loop //all lights //colour skyblue - - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].bIsChargeMove = false; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].Priority = 0; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos_count = 1; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_QUARTER_DOWN_RIGHT; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos_count = 3; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[0].OptionalParams = 2 + (1 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //right //slow //1 loop //all lights //colour skyblue - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[1].OptionalParams = 2 + (2 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //right //medium //1 loop //all lights //colour skyblue - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_R1; - config.specialMoveOptions.profiles[0].AllSpecialMoves[1].RequiredTriggerCombos[2].OptionalParams = 2 + (3 << 4) + (1 << 8) + (0 << 12) + (9 << 16); //right //fast //1 loop //all lights //colour skyblue - - - config.specialMoveOptions.profiles[1].bEnabled = true; - config.specialMoveOptions.profiles[1].AllSpecialMoves_count = 1; - strncpy(config.specialMoveOptions.profiles[1].Label, "Ken Masters", sizeof(config.specialMoveOptions.profiles[1].Label) - 1); - - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].bIsChargeMove = false; - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_WAVE; - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].Priority = 0; - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredInputCombos_count = 2; - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_LEFT; - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredInputCombos[1] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_DP_RIGHT; - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos_count = 3; - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3; - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 0 + (3 << 4) + (1 << 8) + (0 << 12) + (1 << 16); //up //fast //1 loop //all lights //colour white - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4; - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 0 + (2 << 4) + (1 << 8) + (0 << 12) + (1 << 16); //up //medium //1 loop //all lights //colour white - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[2].RequiredTriggers = GAMEPAD_MASK_R1; - config.specialMoveOptions.profiles[1].AllSpecialMoves[0].RequiredTriggerCombos[2].OptionalParams = 0 + (1 << 4) + (1 << 8) + (0 << 12) + (1 << 16); //up //slow //1 loop //all lights //colour white - - config.specialMoveOptions.profiles[2].bEnabled = true; - config.specialMoveOptions.profiles[2].AllSpecialMoves_count = 2; - strncpy(config.specialMoveOptions.profiles[2].Label, "Gief", sizeof(config.specialMoveOptions.profiles[1].Label) - 1); - - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].bIsChargeMove = false; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_KNIGHTRIDER; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].Priority = 0; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredInputCombos_count = 1; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_NONE; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos_count = 2; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3 | GAMEPAD_MASK_B4; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[0].OptionalParams = 2 + (2 << 4) + (1 << 8) + (1 << 12) + (2 << 16); //Left //slow //1 loop //top lights //colour Red - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[1].RequiredTriggers = GAMEPAD_MASK_B4 | GAMEPAD_MASK_R1; - config.specialMoveOptions.profiles[2].AllSpecialMoves[0].RequiredTriggerCombos[1].OptionalParams = 2 + (3 << 4) + (1 << 8) + (1 << 12) + (2 << 16); //Left //medium //1 loop //top lights //colour Red - - config.specialMoveOptions.profiles[2].AllSpecialMoves[1].bIsChargeMove = false; - config.specialMoveOptions.profiles[2].AllSpecialMoves[1].Animation = SpecialMoveEffects_Proto::SpecialMoveEffects_Proto_SMEFFECT_KNIGHTRIDER; - config.specialMoveOptions.profiles[2].AllSpecialMoves[1].Priority = 1; - config.specialMoveOptions.profiles[2].AllSpecialMoves[1].RequiredInputCombos_count = 1; - config.specialMoveOptions.profiles[2].AllSpecialMoves[1].RequiredInputCombos[0] = SpecialMoveInputTypes_Proto::SpecialMoveInputTypes_Proto_INPUT_NONE; - config.specialMoveOptions.profiles[2].AllSpecialMoves[1].RequiredTriggerCombos_count = 1; - config.specialMoveOptions.profiles[2].AllSpecialMoves[1].RequiredTriggerCombos[0].RequiredTriggers = GAMEPAD_MASK_B3 | GAMEPAD_MASK_B4 | GAMEPAD_MASK_R1; - config.specialMoveOptions.profiles[2].AllSpecialMoves[1].RequiredTriggerCombos[0].OptionalParams = 2 + (4 << 4) + (2 << 8) + (1 << 12) + (4 << 16); //Left //fast //1 loop //top lights //colour Yellow - - config.animationOptions.profiles_count = 2; config.animationOptions.profiles[0].bEnabled = true; diff --git a/src/display/ui/screens/ButtonLayoutScreen.cpp b/src/display/ui/screens/ButtonLayoutScreen.cpp index 6a2e4ba162..a7a811738d 100644 --- a/src/display/ui/screens/ButtonLayoutScreen.cpp +++ b/src/display/ui/screens/ButtonLayoutScreen.cpp @@ -117,7 +117,7 @@ void ButtonLayoutScreen::updateCustomHeaders() } // Check to see if special move profile has changed - if(!gamepadProfileModeDisplay && !ledAnimationProfileModeDisplay){ + /*if(!gamepadProfileModeDisplay && !ledAnimationProfileModeDisplay){ uint8_t profileNumber = SpecialMoveSystem::Options.CurrentProfileIndex; if (prevSpecialMoveProfileNumber != profileNumber) { prevSpecialMoveProfileNumber = profileNumber; @@ -135,7 +135,7 @@ void ButtonLayoutScreen::updateCustomHeaders() specialMoveProfileModeDisplay = true; addCustomHeader(profileStr); } - } + }*/ } int8_t ButtonLayoutScreen::update() { diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index 59a1444dac..a9e78c5edf 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -46,8 +46,8 @@ static void updateAnimationOptionsProto(const AnimationOptions& options) static void updateSpecialMoveOptionsProto(const SpecialMoveOptions& options) { - SpecialMoveOptions_Proto& optionsProto = Storage::getInstance().getSpecialMoveOptions(); - optionsProto.CurrentProfileIndex = options.CurrentProfileIndex; + //SpecialMoveOptions_Proto& optionsProto = Storage::getInstance().getSpecialMoveOptions(); + //optionsProto.CurrentProfileIndex = options.CurrentProfileIndex; } void Storage::performEnqueuedSaves() @@ -258,7 +258,9 @@ void AnimationStorage::getAnimationOptions(AnimationOptions& options) void AnimationStorage::getSpecialMoveOptions(SpecialMoveOptions& options) { - const SpecialMoveOptions_Proto& optionsProto = Storage::getInstance().getSpecialMoveOptions(); + options.NumValidProfiles = 0; + + /*const SpecialMoveOptions_Proto& optionsProto = Storage::getInstance().getSpecialMoveOptions(); options.NumValidProfiles = optionsProto.profiles_count; for(unsigned int profileIndex = 0; profileIndex < 4 && profileIndex < options.NumValidProfiles; ++profileIndex) //MAX_SPECIALMOVE_PROFILES from SpecialMoveSystem.hpp @@ -287,11 +289,11 @@ void AnimationStorage::getSpecialMoveOptions(SpecialMoveOptions& options) } options.ChargeTimeInMs = optionsProto.ChargeTimeInMs; - options.CurrentProfileIndex = optionsProto.CurrentProfileIndex; + options.CurrentProfileIndex = optionsProto.CurrentProfileIndex;*/ } void AnimationStorage::save() { Storage::getInstance().enqueueAnimationOptionsSave(AnimationStation::options); - Storage::getInstance().enqueueSpecialMoveOptionsSave(SpecialMoveSystem::Options); + //Storage::getInstance().enqueueSpecialMoveOptionsSave(SpecialMoveSystem::Options); } From d0ee1c1212ea6ecdcc62a51fc06403c8b6ed44ed Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Tue, 14 Jan 2025 23:24:28 +0000 Subject: [PATCH 018/121] Legacy led removed. LED off state Removed old led config stuff to save space. Added new OFF state for LED profiles. Fixed lcd screen to not show blank bar on boot and to cope with Off state for LED profiles --- .../display/ui/screens/ButtonLayoutScreen.h | 14 ++--- lib/AnimationStation/src/AnimationStation.cpp | 17 +++--- lib/AnimationStation/src/AnimationStation.hpp | 2 +- proto/config.proto | 49 ++--------------- src/config_legacy.cpp | 53 ------------------- src/config_utils.cpp | 4 ++ src/display/ui/screens/ButtonLayoutScreen.cpp | 25 +++++---- src/storagemanager.cpp | 2 +- 8 files changed, 43 insertions(+), 123 deletions(-) diff --git a/headers/display/ui/screens/ButtonLayoutScreen.h b/headers/display/ui/screens/ButtonLayoutScreen.h index 4b01c1f7bc..82d81b5e4c 100644 --- a/headers/display/ui/screens/ButtonLayoutScreen.h +++ b/headers/display/ui/screens/ButtonLayoutScreen.h @@ -148,16 +148,16 @@ class ButtonLayoutScreen : public GPScreen { std::deque inputHistory; std::array lastInput; - bool gamepadProfileModeDisplay; - bool ledAnimationProfileModeDisplay; - bool specialMoveProfileModeDisplay; - bool profileModeDisplay; + bool gamepadProfileModeDisplay = false; + bool ledAnimationProfileModeDisplay = false; + bool specialMoveProfileModeDisplay = false; + bool profileModeDisplay = false; uint8_t profileDelay = 2; int profileDelayStart = 0; std::string profileModeString; - uint8_t prevGamepadProfileNumber = 0; - uint8_t prevLEDAnimationProfileNumber = 0; - uint8_t prevSpecialMoveProfileNumber = 0; + int8_t prevGamepadProfileNumber = -2; + int8_t prevLEDAnimationProfileNumber = -2; + int8_t prevSpecialMoveProfileNumber = -2; uint16_t prevButtonState = 0; uint8_t prevLayoutLeft = 0; diff --git a/lib/AnimationStation/src/AnimationStation.cpp b/lib/AnimationStation/src/AnimationStation.cpp index 7a00016643..c2a2cab631 100644 --- a/lib/AnimationStation/src/AnimationStation.cpp +++ b/lib/AnimationStation/src/AnimationStation.cpp @@ -140,20 +140,25 @@ uint16_t AnimationStation::AdjustIndex(int changeSize) } } - //if we cant find it then this is probably the first call and the first profile isnt valid. Just return whichever is the first valid profile + //if we cant find it then either we're in the off state or this is probably the first call and the first profile isnt valid. if(indexOfCurrentProfile == -1) - return validIndexes[0]; + { + if(changeSize >= 0) + return validIndexes[0]; + else + return validIndexes[validIndexes.size() - 1]; + } int newProfileIndex = indexOfCurrentProfile + changeSize; + //if we're going to wrap around then move to "OFF" profile if (newProfileIndex >= (int)validIndexes.size()) { - return validIndexes[0]; + return -1; } - - if (newProfileIndex < 0) + else if (newProfileIndex < 0) { - return validIndexes[validIndexes.size() - 1]; + return -1; } return (uint16_t)validIndexes[newProfileIndex]; diff --git a/lib/AnimationStation/src/AnimationStation.hpp b/lib/AnimationStation/src/AnimationStation.hpp index b90e0e52f8..67f51faf2e 100644 --- a/lib/AnimationStation/src/AnimationStation.hpp +++ b/lib/AnimationStation/src/AnimationStation.hpp @@ -89,7 +89,7 @@ struct __attribute__ ((__packed__)) AnimationOptions uint8_t NumValidProfiles; AnimationProfile profiles[MAX_ANIMATION_PROFILES]; uint8_t brightness; - uint8_t baseProfileIndex; + int8_t baseProfileIndex; }; class AnimationStation diff --git a/proto/config.proto b/proto/config.proto index 3b74588ed1..78261486ae 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -363,55 +363,12 @@ message AnimationProfile_Proto // This has to be kept in sync with AnimationOptions in AnimationStation.hpp message AnimationOptions_Proto { - optional uint32 baseAnimationIndex = 1 [deprecated = true]; + reserved 1, 3 to 45; + optional uint32 brightness = 2; - optional uint32 staticColorIndex = 3 [deprecated = true]; - optional uint32 buttonColorIndex = 4 [deprecated = true]; - optional int32 chaseCycleTime = 5 [deprecated = true]; - optional int32 rainbowCycleTime = 6 [deprecated = true]; - optional uint32 themeIndex = 7 [deprecated = true]; - - optional bool hasCustomTheme = 8; - optional uint32 customThemeUp = 9 [deprecated = true]; - optional uint32 customThemeDown = 10 [deprecated = true]; - optional uint32 customThemeLeft = 11 [deprecated = true]; - optional uint32 customThemeRight = 12 [deprecated = true]; - optional uint32 customThemeB1 = 13 [deprecated = true]; - optional uint32 customThemeB2 = 14 [deprecated = true]; - optional uint32 customThemeB3 = 15 [deprecated = true]; - optional uint32 customThemeB4 = 16 [deprecated = true]; - optional uint32 customThemeL1 = 17 [deprecated = true]; - optional uint32 customThemeR1 = 18 [deprecated = true]; - optional uint32 customThemeL2 = 19 [deprecated = true]; - optional uint32 customThemeR2 = 20 [deprecated = true]; - optional uint32 customThemeS1 = 21 [deprecated = true]; - optional uint32 customThemeS2 = 22 [deprecated = true]; - optional uint32 customThemeL3 = 23 [deprecated = true]; - optional uint32 customThemeR3 = 24 [deprecated = true]; - optional uint32 customThemeA1 = 25 [deprecated = true]; - optional uint32 customThemeA2 = 26 [deprecated = true]; - optional uint32 customThemeUpPressed = 27 [deprecated = true]; - optional uint32 customThemeDownPressed = 28 [deprecated = true]; - optional uint32 customThemeLeftPressed = 29 [deprecated = true]; - optional uint32 customThemeRightPressed = 30 [deprecated = true]; - optional uint32 customThemeB1Pressed = 31 [deprecated = true]; - optional uint32 customThemeB2Pressed = 32 [deprecated = true]; - optional uint32 customThemeB3Pressed = 33 [deprecated = true]; - optional uint32 customThemeB4Pressed = 34 [deprecated = true]; - optional uint32 customThemeL1Pressed = 35 [deprecated = true]; - optional uint32 customThemeR1Pressed = 36 [deprecated = true]; - optional uint32 customThemeL2Pressed = 37 [deprecated = true]; - optional uint32 customThemeR2Pressed = 38 [deprecated = true]; - optional uint32 customThemeS1Pressed = 39 [deprecated = true]; - optional uint32 customThemeS2Pressed = 40 [deprecated = true]; - optional uint32 customThemeL3Pressed = 41 [deprecated = true]; - optional uint32 customThemeR3Pressed = 42 [deprecated = true]; - optional uint32 customThemeA1Pressed = 43 [deprecated = true]; - optional uint32 customThemeA2Pressed = 44 [deprecated = true]; - optional uint32 buttonPressColorCooldownTimeInMs = 45 [deprecated = true]; repeated AnimationProfile_Proto profiles = 46 [(nanopb).max_count = 4]; //MAX_ANIMATION_PROFILES from AnimationStation.hpp - optional uint32 baseProfileIndex = 47; + optional int32 baseProfileIndex = 47; repeated uint32 customColors = 48 [(nanopb).max_count = 16]; //MAX_CUSTOM_COLORS from Animation.hpp } diff --git a/src/config_legacy.cpp b/src/config_legacy.cpp index d0af3ab2f6..68a605f3de 100644 --- a/src/config_legacy.cpp +++ b/src/config_legacy.cpp @@ -902,59 +902,6 @@ bool ConfigUtils::fromLegacyStorage(Config& config) SET_PROPERTY(ledOptions, pledColor, legacyLEDOptions.pledColor.value(LED_FORMAT_RGB)); } - const ConfigLegacy::AnimationOptions& legacyAnimationOptions = *reinterpret_cast(EEPROM_ADDRESS_START + ANIMATION_STORAGE_INDEX); - if (legacyAnimationOptions.checksum == computeChecksum(reinterpret_cast(&legacyAnimationOptions), sizeof(ConfigLegacy::AnimationOptions), offsetof(ConfigLegacy::AnimationOptions, checksum))) - { - legacyConfigFound = true; - - AnimationOptions_Proto& animationOptions = config.animationOptions; - config.has_animationOptions = true; - SET_PROPERTY(animationOptions, baseAnimationIndex, legacyAnimationOptions.baseAnimationIndex); - SET_PROPERTY(animationOptions, brightness, legacyAnimationOptions.brightness); - SET_PROPERTY(animationOptions, staticColorIndex, legacyAnimationOptions.staticColorIndex); - SET_PROPERTY(animationOptions, buttonColorIndex, legacyAnimationOptions.buttonColorIndex); - SET_PROPERTY(animationOptions, chaseCycleTime, legacyAnimationOptions.chaseCycleTime); - SET_PROPERTY(animationOptions, rainbowCycleTime, legacyAnimationOptions.rainbowCycleTime); - SET_PROPERTY(animationOptions, themeIndex, legacyAnimationOptions.themeIndex); - SET_PROPERTY(animationOptions, hasCustomTheme, legacyAnimationOptions.hasCustomTheme); - SET_PROPERTY(animationOptions, customThemeUp, legacyAnimationOptions.customThemeUp); - SET_PROPERTY(animationOptions, customThemeDown, legacyAnimationOptions.customThemeDown); - SET_PROPERTY(animationOptions, customThemeLeft, legacyAnimationOptions.customThemeLeft); - SET_PROPERTY(animationOptions, customThemeRight, legacyAnimationOptions.customThemeRight); - SET_PROPERTY(animationOptions, customThemeB1, legacyAnimationOptions.customThemeB1); - SET_PROPERTY(animationOptions, customThemeB2, legacyAnimationOptions.customThemeB2); - SET_PROPERTY(animationOptions, customThemeB3, legacyAnimationOptions.customThemeB3); - SET_PROPERTY(animationOptions, customThemeB4, legacyAnimationOptions.customThemeB4); - SET_PROPERTY(animationOptions, customThemeL1, legacyAnimationOptions.customThemeL1); - SET_PROPERTY(animationOptions, customThemeR1, legacyAnimationOptions.customThemeR1); - SET_PROPERTY(animationOptions, customThemeL2, legacyAnimationOptions.customThemeL2); - SET_PROPERTY(animationOptions, customThemeR2, legacyAnimationOptions.customThemeR2); - SET_PROPERTY(animationOptions, customThemeS1, legacyAnimationOptions.customThemeS1); - SET_PROPERTY(animationOptions, customThemeS2, legacyAnimationOptions.customThemeS2); - SET_PROPERTY(animationOptions, customThemeL3, legacyAnimationOptions.customThemeL3); - SET_PROPERTY(animationOptions, customThemeR3, legacyAnimationOptions.customThemeR3); - SET_PROPERTY(animationOptions, customThemeA1, legacyAnimationOptions.customThemeA1); - SET_PROPERTY(animationOptions, customThemeA2, legacyAnimationOptions.customThemeA2); - SET_PROPERTY(animationOptions, customThemeUpPressed, legacyAnimationOptions.customThemeUpPressed); - SET_PROPERTY(animationOptions, customThemeDownPressed, legacyAnimationOptions.customThemeDownPressed); - SET_PROPERTY(animationOptions, customThemeLeftPressed, legacyAnimationOptions.customThemeLeftPressed); - SET_PROPERTY(animationOptions, customThemeRightPressed, legacyAnimationOptions.customThemeRightPressed); - SET_PROPERTY(animationOptions, customThemeB1Pressed, legacyAnimationOptions.customThemeB1Pressed); - SET_PROPERTY(animationOptions, customThemeB2Pressed, legacyAnimationOptions.customThemeB2Pressed); - SET_PROPERTY(animationOptions, customThemeB3Pressed, legacyAnimationOptions.customThemeB3Pressed); - SET_PROPERTY(animationOptions, customThemeB4Pressed, legacyAnimationOptions.customThemeB4Pressed); - SET_PROPERTY(animationOptions, customThemeL1Pressed, legacyAnimationOptions.customThemeL1Pressed); - SET_PROPERTY(animationOptions, customThemeR1Pressed, legacyAnimationOptions.customThemeR1Pressed); - SET_PROPERTY(animationOptions, customThemeL2Pressed, legacyAnimationOptions.customThemeL2Pressed); - SET_PROPERTY(animationOptions, customThemeR2Pressed, legacyAnimationOptions.customThemeR2Pressed); - SET_PROPERTY(animationOptions, customThemeS1Pressed, legacyAnimationOptions.customThemeS1Pressed); - SET_PROPERTY(animationOptions, customThemeS2Pressed, legacyAnimationOptions.customThemeS2Pressed); - SET_PROPERTY(animationOptions, customThemeL3Pressed, legacyAnimationOptions.customThemeL3Pressed); - SET_PROPERTY(animationOptions, customThemeR3Pressed, legacyAnimationOptions.customThemeR3Pressed); - SET_PROPERTY(animationOptions, customThemeA1Pressed, legacyAnimationOptions.customThemeA1Pressed); - SET_PROPERTY(animationOptions, customThemeA2Pressed, legacyAnimationOptions.customThemeA2Pressed); - } - const ConfigLegacy::AddonOptions& legacyAddonOptions = *reinterpret_cast(EEPROM_ADDRESS_START + ADDON_STORAGE_INDEX); if (legacyAddonOptions.checksum == computeChecksum(reinterpret_cast(&legacyAddonOptions), sizeof(ConfigLegacy::AddonOptions), offsetof(ConfigLegacy::AddonOptions, checksum))) { diff --git a/src/config_utils.cpp b/src/config_utils.cpp index 48ac7cef8b..bb229f44e4 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -474,6 +474,10 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) INIT_UNSET_PROPERTY(config.ledOptions, lightDataSize, LIGHT_DATA_SIZE); const unsigned char lightData[] = { LIGHT_DATA }; INIT_UNSET_PROPERTY_BYTES(config.ledOptions, lightData, lightData); + + //SpecialMoveOptions + //INIT_UNSET_PROPERTY(config.specialMoveOptions, ChargeTimeInMs, 750); + //INIT_UNSET_PROPERTY(config.specialMoveOptions, CurrentProfileIndex, 0); // animationOptions INIT_UNSET_PROPERTY(config.animationOptions, brightness, LEDS_BRIGHTNESS); diff --git a/src/display/ui/screens/ButtonLayoutScreen.cpp b/src/display/ui/screens/ButtonLayoutScreen.cpp index a7a811738d..2e8170aeea 100644 --- a/src/display/ui/screens/ButtonLayoutScreen.cpp +++ b/src/display/ui/screens/ButtonLayoutScreen.cpp @@ -32,10 +32,10 @@ void ButtonLayoutScreen::init() { pushElement(currLayoutRight[elementCtr]); } - // start with profile mode displayed - prevGamepadProfileNumber = -1; - prevLEDAnimationProfileNumber = -1; - prevSpecialMoveProfileNumber = -1; + // start with profile modes displayed + prevGamepadProfileNumber = -2; + prevLEDAnimationProfileNumber = -2; + prevSpecialMoveProfileNumber = -2; prevLayoutLeft = Storage::getInstance().getDisplayOptions().buttonLayout; prevLayoutRight = Storage::getInstance().getDisplayOptions().buttonLayoutRight; prevLeftOptions = Storage::getInstance().getDisplayOptions().buttonLayoutCustomOptions.paramsLeft; @@ -83,7 +83,7 @@ void ButtonLayoutScreen::updateCustomHeaders() // Check to see if gamepad profile has changed if(!ledAnimationProfileModeDisplay && !specialMoveProfileModeDisplay){ - uint8_t profileNumber = getGamepad()->getOptions().profileNumber; + int16_t profileNumber = (int16_t)(getGamepad()->getOptions().profileNumber); if (prevGamepadProfileNumber != profileNumber) { prevGamepadProfileNumber = profileNumber; @@ -103,13 +103,20 @@ void ButtonLayoutScreen::updateCustomHeaders() // Check to see if LED animation profile has changed if(!gamepadProfileModeDisplay && !specialMoveProfileModeDisplay){ - uint8_t profileNumber = AnimationStation::options.baseProfileIndex; + int8_t profileNumber = AnimationStation::options.baseProfileIndex; if (prevLEDAnimationProfileNumber != profileNumber) { prevLEDAnimationProfileNumber = profileNumber; std::string profileStr; - profileStr = " LED Profile #"; - profileStr += std::to_string(profileNumber); + if(profileNumber != -1) + { + profileStr = " LED Profile #"; + profileStr += std::to_string(profileNumber+1); //add 1 so its from 1-x not from 0-x + } + else + { + profileStr = " LED Profile OFF"; + } ledAnimationProfileModeDisplay = true; addCustomHeader(profileStr); @@ -118,7 +125,7 @@ void ButtonLayoutScreen::updateCustomHeaders() // Check to see if special move profile has changed /*if(!gamepadProfileModeDisplay && !ledAnimationProfileModeDisplay){ - uint8_t profileNumber = SpecialMoveSystem::Options.CurrentProfileIndex; + int8_t profileNumber = SpecialMoveSystem::Options.CurrentProfileIndex; if (prevSpecialMoveProfileNumber != profileNumber) { prevSpecialMoveProfileNumber = profileNumber; diff --git a/src/storagemanager.cpp b/src/storagemanager.cpp index a9e78c5edf..d734efffe7 100644 --- a/src/storagemanager.cpp +++ b/src/storagemanager.cpp @@ -247,7 +247,7 @@ void AnimationStorage::getAnimationOptions(AnimationOptions& options) options.profiles[index].bUseCaseLightsInSpecialMoves = optionsProto.profiles[index].bUseCaseLightsInSpecialMoves; } options.brightness = std::min(optionsProto.brightness, 255); - options.baseProfileIndex = std::min(optionsProto.baseProfileIndex, 255); + options.baseProfileIndex = optionsProto.baseProfileIndex; customColors.clear(); for(unsigned int customColIndex = 0; customColIndex < MAX_CUSTOM_COLORS; ++customColIndex) From 3814e435861b98f97d1430b62fcf1b66a7f8dc91 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Fri, 17 Jan 2025 21:41:58 +0000 Subject: [PATCH 019/121] webconfig set/getAnimationProtoOptions Added get and set for AnimationProtoOptions to write and read the various settings for webconfig editing --- proto/config.proto | 8 +- src/configs/webconfig.cpp | 185 +++++++++++++++++++------------------- 2 files changed, 94 insertions(+), 99 deletions(-) diff --git a/proto/config.proto b/proto/config.proto index 78261486ae..e152ebc8b4 100644 --- a/proto/config.proto +++ b/proto/config.proto @@ -351,13 +351,13 @@ message AnimationProfile_Proto optional uint32 nonPressedSpecialColour = 9; - optional bool bUseCaseLightsInSpecialMoves = 10; + optional AnimationNonPressedEffects_Proto baseCaseEffect = 10; - optional AnimationNonPressedEffects_Proto baseCaseEffect = 11; + repeated uint32 caseStaticColors = 11 [(nanopb).max_count = 10]; //(MAX_CASE_LIGHTS/4) from AnimationStation.hpp - repeated uint32 caseStaticColors = 12 [(nanopb).max_count = 10]; //(MAX_CASE_LIGHTS/4) from AnimationStation.hpp + optional uint32 pressedSpecialColour = 12; - optional uint32 pressedSpecialColour = 13; + optional bool bUseCaseLightsInSpecialMoves = 13; }; // This has to be kept in sync with AnimationOptions in AnimationStation.hpp diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index a9d22e2080..fc7dd7834a 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -946,113 +946,108 @@ std::string getButtonLayouts() return serialize_json(doc); } -std::string setCustomTheme() +std::string setAnimationProtoOptions() { DynamicJsonDocument doc = get_post_data(); - AnimationOptions options = AnimationStation::options; + AnimationOptions_Proto& options = Storage::getInstance().getAnimationOptions(); + docToValue(options.brightness, doc, "brightness"); + docToValue(options.baseProfileIndex, doc, "baseProfileIndex"); - const auto readDocDefaultToZero = [&](const char* key0, const char* key1) -> uint32_t + JsonObject docOptions = doc.as(); + JsonArray customColorsList = docOptions["customColors"]; + for(unsigned int customColorsIndex = 0; customColorsIndex < customColorsList.size() && customColorsIndex < MAX_CUSTOM_COLORS; ++customColorsIndex) { - uint32_t result = 0; - if (hasValue(doc, key0, key1)) + options.customColors[customColorsIndex] = customColorsList[customColorsIndex]; + options.customColors_count = customColorsIndex; + } + + JsonArray profilesList = docOptions["profiles"]; + int profilesIndex = 0; + for (JsonObject profile : profilesList) + { + options.profiles[profilesIndex].bEnabled = profile["bEnabled"].as(); + options.profiles[profilesIndex].baseNonPressedEffect = (AnimationNonPressedEffects_Proto)(profile["baseNonPressedEffect"].as()); + options.profiles[profilesIndex].basePressedEffect = (AnimationPressedEffects_Proto)(profile["basePressedEffect"].as()); + options.profiles[profilesIndex].buttonPressHoldTimeInMs = profile["buttonPressHoldTimeInMs"].as(); + options.profiles[profilesIndex].buttonPressFadeOutTimeInMs = profile["buttonPressFadeOutTimeInMs"].as(); + options.profiles[profilesIndex].nonPressedSpecialColour = profile["nonPressedSpecialColour"].as(); + options.profiles[profilesIndex].bUseCaseLightsInSpecialMoves = profile["bUseCaseLightsInSpecialMoves"].as(); + options.profiles[profilesIndex].baseCaseEffect = (AnimationNonPressedEffects_Proto)(profile["baseCaseEffect"].as()); + options.profiles[profilesIndex].pressedSpecialColour = profile["pressedSpecialColour"].as(); + + JsonArray notPressedStaticColorsList = profile["notPressedStaticColors"]; + for(unsigned int notPressedStaticColorsIndex = 0; notPressedStaticColorsIndex < notPressedStaticColorsList.size() && notPressedStaticColorsIndex < 8/*((NUM_BANK0_GPIOS+3)/4)*/; ++notPressedStaticColorsIndex) { - readDoc(result, doc, key0, key1); + options.profiles[profilesIndex].notPressedStaticColors[notPressedStaticColorsIndex] = notPressedStaticColorsList[notPressedStaticColorsList]; + options.profiles[profilesIndex].notPressedStaticColors_count = notPressedStaticColorsIndex; + } + JsonArray pressedStaticColorsList = profile["pressedStaticColors"]; + for(unsigned int pressedStaticColorsIndex = 0; pressedStaticColorsIndex < pressedStaticColorsList.size() && pressedStaticColorsIndex < 8/*((NUM_BANK0_GPIOS+3)/4)*/; ++pressedStaticColorsIndex) + { + options.profiles[profilesIndex].pressedStaticColors[pressedStaticColorsIndex] = pressedStaticColorsList[pressedStaticColorsList]; + options.profiles[profilesIndex].pressedStaticColors_count = pressedStaticColorsIndex; + } + JsonArray caseStaticColorsList = profile["caseStaticColors"]; + for(unsigned int caseStaticColorsIndex = 0; caseStaticColorsIndex < caseStaticColorsList.size() && caseStaticColorsIndex < (MAX_CASE_LIGHTS/4); ++caseStaticColorsIndex) + { + options.profiles[profilesIndex].caseStaticColors[caseStaticColorsIndex] = caseStaticColorsList[caseStaticColorsList]; + options.profiles[profilesIndex].caseStaticColors_count = caseStaticColorsIndex; } - return result; - }; - /*readDoc(options.hasCustomTheme, doc, "enabled"); - options.customThemeUp = readDocDefaultToZero("Up", "u"); - options.customThemeDown = readDocDefaultToZero("Down", "u"); - options.customThemeLeft = readDocDefaultToZero("Left", "u"); - options.customThemeRight = readDocDefaultToZero("Right", "u"); - options.customThemeB1 = readDocDefaultToZero("B1", "u"); - options.customThemeB2 = readDocDefaultToZero("B2", "u"); - options.customThemeB3 = readDocDefaultToZero("B3", "u"); - options.customThemeB4 = readDocDefaultToZero("B4", "u"); - options.customThemeL1 = readDocDefaultToZero("L1", "u"); - options.customThemeR1 = readDocDefaultToZero("R1", "u"); - options.customThemeL2 = readDocDefaultToZero("L2", "u"); - options.customThemeR2 = readDocDefaultToZero("R2", "u"); - options.customThemeS1 = readDocDefaultToZero("S1", "u"); - options.customThemeS2 = readDocDefaultToZero("S2", "u"); - options.customThemeL3 = readDocDefaultToZero("L3", "u"); - options.customThemeR3 = readDocDefaultToZero("R3", "u"); - options.customThemeA1 = readDocDefaultToZero("A1", "u"); - options.customThemeA2 = readDocDefaultToZero("A2", "u"); - options.customThemeUpPressed = readDocDefaultToZero("Up", "d"); - options.customThemeDownPressed = readDocDefaultToZero("Down", "d"); - options.customThemeLeftPressed = readDocDefaultToZero("Left", "d"); - options.customThemeRightPressed = readDocDefaultToZero("Right", "d"); - options.customThemeB1Pressed = readDocDefaultToZero("B1", "d"); - options.customThemeB2Pressed = readDocDefaultToZero("B2", "d"); - options.customThemeB3Pressed = readDocDefaultToZero("B3", "d"); - options.customThemeB4Pressed = readDocDefaultToZero("B4", "d"); - options.customThemeL1Pressed = readDocDefaultToZero("L1", "d"); - options.customThemeR1Pressed = readDocDefaultToZero("R1", "d"); - options.customThemeL2Pressed = readDocDefaultToZero("L2", "d"); - options.customThemeR2Pressed = readDocDefaultToZero("R2", "d"); - options.customThemeS1Pressed = readDocDefaultToZero("S1", "d"); - options.customThemeS2Pressed = readDocDefaultToZero("S2", "d"); - options.customThemeL3Pressed = readDocDefaultToZero("L3", "d"); - options.customThemeR3Pressed = readDocDefaultToZero("R3", "d"); - options.customThemeA1Pressed = readDocDefaultToZero("A1", "d"); - options.customThemeA2Pressed = readDocDefaultToZero("A2", "d"); - - uint32_t pressCooldown = 0; - readDoc(pressCooldown, doc, "buttonPressColorCooldownTimeInMs"); - options.buttonPressColorCooldownTimeInMs = pressCooldown;*/ - - //AnimationStation::SetOptions(options); - //AnimationStore.save(); + options.profiles_count = profilesIndex; + + if (++profilesIndex >= MAX_ANIMATION_PROFILES) + break; + } + Storage::getInstance().save(); return serialize_json(doc); } -std::string getCustomTheme() +std::string getAnimationProtoOptions() { DynamicJsonDocument doc(LWIP_HTTPD_POST_MAX_PAYLOAD_LEN); - const AnimationOptions& options = AnimationStation::options; - -/* writeDoc(doc, "enabled", options.hasCustomTheme); - writeDoc(doc, "Up", "u", options.customThemeUp); - writeDoc(doc, "Up", "d", options.customThemeUpPressed); - writeDoc(doc, "Down", "u", options.customThemeDown); - writeDoc(doc, "Down", "d", options.customThemeDownPressed); - writeDoc(doc, "Left", "u", options.customThemeLeft); - writeDoc(doc, "Left", "d", options.customThemeLeftPressed); - writeDoc(doc, "Right", "u", options.customThemeRight); - writeDoc(doc, "Right", "d", options.customThemeRightPressed); - writeDoc(doc, "B1", "u", options.customThemeB1); - writeDoc(doc, "B1", "d", options.customThemeB1Pressed); - writeDoc(doc, "B2", "u", options.customThemeB2); - writeDoc(doc, "B2", "d", options.customThemeB2Pressed); - writeDoc(doc, "B3", "u", options.customThemeB3); - writeDoc(doc, "B3", "d", options.customThemeB3Pressed); - writeDoc(doc, "B4", "u", options.customThemeB4); - writeDoc(doc, "B4", "d", options.customThemeB4Pressed); - writeDoc(doc, "L1", "u", options.customThemeL1); - writeDoc(doc, "L1", "d", options.customThemeL1Pressed); - writeDoc(doc, "R1", "u", options.customThemeR1); - writeDoc(doc, "R1", "d", options.customThemeR1Pressed); - writeDoc(doc, "L2", "u", options.customThemeL2); - writeDoc(doc, "L2", "d", options.customThemeL2Pressed); - writeDoc(doc, "R2", "u", options.customThemeR2); - writeDoc(doc, "R2", "d", options.customThemeR2Pressed); - writeDoc(doc, "S1", "u", options.customThemeS1); - writeDoc(doc, "S1", "d", options.customThemeS1Pressed); - writeDoc(doc, "S2", "u", options.customThemeS2); - writeDoc(doc, "S2", "d", options.customThemeS2Pressed); - writeDoc(doc, "A1", "u", options.customThemeA1); - writeDoc(doc, "A1", "d", options.customThemeA1Pressed); - writeDoc(doc, "A2", "u", options.customThemeA2); - writeDoc(doc, "A2", "d", options.customThemeA2Pressed); - writeDoc(doc, "L3", "u", options.customThemeL3); - writeDoc(doc, "L3", "d", options.customThemeL3Pressed); - writeDoc(doc, "R3", "u", options.customThemeR3); - writeDoc(doc, "R3", "d", options.customThemeR3Pressed); - writeDoc(doc, "buttonPressColorCooldownTimeInMs", options.buttonPressColorCooldownTimeInMs);*/ + const AnimationOptions_Proto& options = Storage::getInstance().getAnimationOptions(); + + writeDoc(doc, "AnimationOptions", "brightness", options.brightness); + writeDoc(doc, "AnimationOptions", "baseProfileIndex", options.baseProfileIndex); + JsonArray customColorsList = doc.createNestedArray("customColors"); + for (int customColorsIndex = 0; customColorsIndex < options.customColors_count; ++customColorsIndex) + { + customColorsList.add(options.customColors[customColorsIndex]); + } + + JsonArray profileList = doc.createNestedArray("profiles"); + for (int profilesIndex = 0; profilesIndex < options.profiles_count; ++profilesIndex) + { + JsonObject profile = profileList.createNestedObject(); + profile["bEnabled"] = options.profiles[profilesIndex].bEnabled ? 1 : 0; + profile["baseNonPressedEffect"] = options.profiles[profilesIndex].baseNonPressedEffect; + profile["basePressedEffect"] = options.profiles[profilesIndex].basePressedEffect; + profile["buttonPressHoldTimeInMs"] = options.profiles[profilesIndex].buttonPressHoldTimeInMs; + profile["buttonPressFadeOutTimeInMs"] = options.profiles[profilesIndex].buttonPressFadeOutTimeInMs; + profile["nonPressedSpecialColour"] = options.profiles[profilesIndex].nonPressedSpecialColour; + profile["bUseCaseLightsInSpecialMoves"] = options.profiles[profilesIndex].bUseCaseLightsInSpecialMoves ? 1 : 0; + profile["baseCaseEffect"] = options.profiles[profilesIndex].baseCaseEffect; + profile["pressedSpecialColour"] = options.profiles[profilesIndex].pressedSpecialColour; + + JsonArray notPressedStaticColorsList = doc.createNestedArray("notPressedStaticColors"); + for (int notPressedStaticColorsIndex = 0; notPressedStaticColorsIndex < options.profiles[profilesIndex].notPressedStaticColors_count; ++notPressedStaticColorsIndex) + { + notPressedStaticColorsList.add(options.profiles[profilesIndex].notPressedStaticColors[notPressedStaticColorsIndex]); + } + JsonArray pressedStaticColorsList = doc.createNestedArray("pressedStaticColors"); + for (int pressedStaticColorsIndex = 0; pressedStaticColorsIndex < options.profiles[profilesIndex].pressedStaticColors_count; ++pressedStaticColorsIndex) + { + pressedStaticColorsList.add(options.profiles[profilesIndex].pressedStaticColors[pressedStaticColorsIndex]); + } + JsonArray caseStaticColorsList = doc.createNestedArray("caseStaticColors"); + for (int caseStaticColorsIndex = 0; caseStaticColorsIndex < options.profiles[profilesIndex].caseStaticColors_count; ++caseStaticColorsIndex) + { + caseStaticColorsList.add(options.profiles[profilesIndex].caseStaticColors[caseStaticColorsIndex]); + } + } return serialize_json(doc); } @@ -2316,8 +2311,8 @@ static const std::pair handlerFuncs[] = { "/api/setPreviewDisplayOptions", setPreviewDisplayOptions }, { "/api/setGamepadOptions", setGamepadOptions }, { "/api/setLedOptions", setLedOptions }, - { "/api/setCustomTheme", setCustomTheme }, - { "/api/getCustomTheme", getCustomTheme }, + { "/api/setAnimationProtoOptions", setAnimationProtoOptions }, + { "/api/getAnimationProtoOptions", getAnimationProtoOptions }, { "/api/setPinMappings", setPinMappings }, { "/api/setProfileOptions", setProfileOptions }, { "/api/setPeripheralOptions", setPeripheralOptions }, From fa124e1a5fcce47f9f3bf6a115c7dbc0c1ab88a6 Mon Sep 17 00:00:00 2001 From: Podbod12 Date: Sun, 19 Jan 2025 21:02:42 +0000 Subject: [PATCH 020/121] fixes for get/set anim options --- src/config_utils.cpp | 12 ++++++----- src/configs/webconfig.cpp | 42 +++++++++++++++++++++++---------------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/config_utils.cpp b/src/config_utils.cpp index bb229f44e4..ec58b89337 100644 --- a/src/config_utils.cpp +++ b/src/config_utils.cpp @@ -482,13 +482,15 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config) // animationOptions INIT_UNSET_PROPERTY(config.animationOptions, brightness, LEDS_BRIGHTNESS); INIT_UNSET_PROPERTY(config.animationOptions, baseProfileIndex, 0); - + + for (unsigned int profileIndex = 0; profileIndex < MAX_ANIMATION_PROFILES; ++profileIndex) + INIT_UNSET_PROPERTY(config.animationOptions.profiles[profileIndex], bEnabled, 0); + //TESTING - config.animationOptions.customColors_count = 1; - config.animationOptions.customColors[0] = 255; - config.animationOptions.profiles_count = 0; - if(true) + if(false) { + config.animationOptions.customColors_count = 1; + config.animationOptions.customColors[0] = 255; config.animationOptions.profiles_count = 2; config.animationOptions.profiles[0].bEnabled = true; diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index fc7dd7834a..bf039b797a 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -951,19 +951,23 @@ std::string setAnimationProtoOptions() DynamicJsonDocument doc = get_post_data(); AnimationOptions_Proto& options = Storage::getInstance().getAnimationOptions(); - docToValue(options.brightness, doc, "brightness"); - docToValue(options.baseProfileIndex, doc, "baseProfileIndex"); - JsonObject docOptions = doc.as(); - JsonArray customColorsList = docOptions["customColors"]; + JsonObject docJson = doc.as(); + JsonObject AnimOptions = docJson["AnimationOptions"]; + + options.brightness = AnimOptions["brightness"].as(); + options.baseProfileIndex = AnimOptions["baseProfileIndex"].as(); + JsonArray customColorsList = AnimOptions["customColors"]; + options.customColors_count = 0; for(unsigned int customColorsIndex = 0; customColorsIndex < customColorsList.size() && customColorsIndex < MAX_CUSTOM_COLORS; ++customColorsIndex) { options.customColors[customColorsIndex] = customColorsList[customColorsIndex]; - options.customColors_count = customColorsIndex; + options.customColors_count = customColorsIndex+1; } - JsonArray profilesList = docOptions["profiles"]; + JsonArray profilesList = AnimOptions["profiles"]; int profilesIndex = 0; + options.profiles_count = 0; for (JsonObject profile : profilesList) { options.profiles[profilesIndex].bEnabled = profile["bEnabled"].as(); @@ -977,25 +981,28 @@ std::string setAnimationProtoOptions() options.profiles[profilesIndex].pressedSpecialColour = profile["pressedSpecialColour"].as(); JsonArray notPressedStaticColorsList = profile["notPressedStaticColors"]; + options.profiles[profilesIndex].notPressedStaticColors_count = 0; for(unsigned int notPressedStaticColorsIndex = 0; notPressedStaticColorsIndex < notPressedStaticColorsList.size() && notPressedStaticColorsIndex < 8/*((NUM_BANK0_GPIOS+3)/4)*/; ++notPressedStaticColorsIndex) { options.profiles[profilesIndex].notPressedStaticColors[notPressedStaticColorsIndex] = notPressedStaticColorsList[notPressedStaticColorsList]; - options.profiles[profilesIndex].notPressedStaticColors_count = notPressedStaticColorsIndex; + options.profiles[profilesIndex].notPressedStaticColors_count = notPressedStaticColorsIndex+1; } JsonArray pressedStaticColorsList = profile["pressedStaticColors"]; + options.profiles[profilesIndex].pressedStaticColors_count = 0; for(unsigned int pressedStaticColorsIndex = 0; pressedStaticColorsIndex < pressedStaticColorsList.size() && pressedStaticColorsIndex < 8/*((NUM_BANK0_GPIOS+3)/4)*/; ++pressedStaticColorsIndex) { options.profiles[profilesIndex].pressedStaticColors[pressedStaticColorsIndex] = pressedStaticColorsList[pressedStaticColorsList]; - options.profiles[profilesIndex].pressedStaticColors_count = pressedStaticColorsIndex; + options.profiles[profilesIndex].pressedStaticColors_count = pressedStaticColorsIndex+1; } JsonArray caseStaticColorsList = profile["caseStaticColors"]; + options.profiles[profilesIndex].caseStaticColors_count = 0; for(unsigned int caseStaticColorsIndex = 0; caseStaticColorsIndex < caseStaticColorsList.size() && caseStaticColorsIndex < (MAX_CASE_LIGHTS/4); ++caseStaticColorsIndex) { options.profiles[profilesIndex].caseStaticColors[caseStaticColorsIndex] = caseStaticColorsList[caseStaticColorsList]; - options.profiles[profilesIndex].caseStaticColors_count = caseStaticColorsIndex; + options.profiles[profilesIndex].caseStaticColors_count = caseStaticColorsIndex+1; } - options.profiles_count = profilesIndex; + options.profiles_count = profilesIndex+1; if (++profilesIndex >= MAX_ANIMATION_PROFILES) break; @@ -1010,15 +1017,16 @@ std::string getAnimationProtoOptions() DynamicJsonDocument doc(LWIP_HTTPD_POST_MAX_PAYLOAD_LEN); const AnimationOptions_Proto& options = Storage::getInstance().getAnimationOptions(); - writeDoc(doc, "AnimationOptions", "brightness", options.brightness); - writeDoc(doc, "AnimationOptions", "baseProfileIndex", options.baseProfileIndex); - JsonArray customColorsList = doc.createNestedArray("customColors"); + JsonObject AnimOptions = doc.createNestedObject("AnimationOptions"); + AnimOptions["brightness"] = options.brightness; + AnimOptions["baseProfileIndex"] = options.baseProfileIndex; + JsonArray customColorsList = AnimOptions.createNestedArray("customColors"); for (int customColorsIndex = 0; customColorsIndex < options.customColors_count; ++customColorsIndex) { customColorsList.add(options.customColors[customColorsIndex]); } - JsonArray profileList = doc.createNestedArray("profiles"); + JsonArray profileList = AnimOptions.createNestedArray("profiles"); for (int profilesIndex = 0; profilesIndex < options.profiles_count; ++profilesIndex) { JsonObject profile = profileList.createNestedObject(); @@ -1032,17 +1040,17 @@ std::string getAnimationProtoOptions() profile["baseCaseEffect"] = options.profiles[profilesIndex].baseCaseEffect; profile["pressedSpecialColour"] = options.profiles[profilesIndex].pressedSpecialColour; - JsonArray notPressedStaticColorsList = doc.createNestedArray("notPressedStaticColors"); + JsonArray notPressedStaticColorsList = profile.createNestedArray("notPressedStaticColors"); for (int notPressedStaticColorsIndex = 0; notPressedStaticColorsIndex < options.profiles[profilesIndex].notPressedStaticColors_count; ++notPressedStaticColorsIndex) { notPressedStaticColorsList.add(options.profiles[profilesIndex].notPressedStaticColors[notPressedStaticColorsIndex]); } - JsonArray pressedStaticColorsList = doc.createNestedArray("pressedStaticColors"); + JsonArray pressedStaticColorsList = profile.createNestedArray("pressedStaticColors"); for (int pressedStaticColorsIndex = 0; pressedStaticColorsIndex < options.profiles[profilesIndex].pressedStaticColors_count; ++pressedStaticColorsIndex) { pressedStaticColorsList.add(options.profiles[profilesIndex].pressedStaticColors[pressedStaticColorsIndex]); } - JsonArray caseStaticColorsList = doc.createNestedArray("caseStaticColors"); + JsonArray caseStaticColorsList = profile.createNestedArray("caseStaticColors"); for (int caseStaticColorsIndex = 0; caseStaticColorsIndex < options.profiles[profilesIndex].caseStaticColors_count; ++caseStaticColorsIndex) { caseStaticColorsList.add(options.profiles[profilesIndex].caseStaticColors[caseStaticColorsIndex]); From 624da7aa06b71c6ad18fe24ea5f9bc03aa7c46d2 Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 19 Jan 2025 22:54:04 +0100 Subject: [PATCH 021/121] Add mock for animation options route in dev server --- www/server/app.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/www/server/app.js b/www/server/app.js index e31241fc64..5698338643 100644 --- a/www/server/app.js +++ b/www/server/app.js @@ -91,6 +91,55 @@ app.get('/api/getSplashImage', (req, res) => { return res.send(data); }); +app.get('/api/getAnimationOptions', (req, res) => { + return res.send({ + AnimationOptions: { + brightness: 5, + baseProfileIndex: 0, + customColors: [255], + profiles: [ + { + bEnabled: 1, + baseNonPressedEffect: 1, + basePressedEffect: 0, + buttonPressHoldTimeInMs: 500, + buttonPressFadeOutTimeInMs: 500, + nonPressedSpecialColour: 16711680, + bUseCaseLightsInSpecialMoves: 0, + baseCaseEffect: 0, + pressedSpecialColour: 0, + notPressedStaticColors: [0, 0, 0, 0, 0, 0, 0, 0], + pressedStaticColors: [0, 0, 0, 0, 0, 0, 0, 0], + caseStaticColors: [], + }, + { + bEnabled: 1, + baseNonPressedEffect: 0, + basePressedEffect: 3, + buttonPressHoldTimeInMs: 500, + buttonPressFadeOutTimeInMs: 500, + nonPressedSpecialColour: 255, + bUseCaseLightsInSpecialMoves: 1, + baseCaseEffect: 0, + pressedSpecialColour: 16724480, + notPressedStaticColors: [ + 101058054, 101058054, 101058054, 101058054, 101058054, 101058054, + 101058054, 101058054, + ], + pressedStaticColors: [ + 33686018, 33686018, 33686018, 33686018, 33686018, 33686018, + 33686018, 33686018, + ], + caseStaticColors: [ + 16843022, 16843022, 16843022, 16843022, 16843022, 16843022, + 16843022, 16843022, 16843022, 16843022, + ], + }, + ], + }, + }); +}); + app.get('/api/getGamepadOptions', (req, res) => { return res.send({ dpadMode: 0, From 7856281b7829057fa7fcf2159a9057b6dd184378 Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 19 Jan 2025 22:54:38 +0100 Subject: [PATCH 022/121] Add api fetcher for getAnimationOptions --- www/src/Services/WebApi.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/www/src/Services/WebApi.js b/www/src/Services/WebApi.js index 92416d1806..a82ce3eaad 100644 --- a/www/src/Services/WebApi.js +++ b/www/src/Services/WebApi.js @@ -392,6 +392,15 @@ async function getButtonLayoutDefs() { } } +async function getAnimationOptions() { + try { + const { data } = await Http.get(`${baseUrl}/api/getAnimationOptions`); + return data; + } catch (error) { + console.log(error); + } +} + async function getPinMappings() { try { const { data } = await Http.get(`${baseUrl}/api/getPinMappings`); @@ -701,6 +710,7 @@ function sanitizeRequest(request) { export default { resetSettings, + getAnimationOptions, getDisplayOptions, setDisplayOptions, getGamepadOptions, From 465343c4da09d3de3e422ecd2bef5b03d3185da5 Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 19 Jan 2025 22:56:39 +0100 Subject: [PATCH 023/121] Add route for animation options page --- www/src/App.jsx | 2 ++ www/src/Components/Navigation.jsx | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/www/src/App.jsx b/www/src/App.jsx index 378408ff47..b068541439 100644 --- a/www/src/App.jsx +++ b/www/src/App.jsx @@ -17,6 +17,7 @@ import AddonsConfigPage from './Pages/AddonsConfigPage'; import BackupPage from './Pages/BackupPage'; import PlaygroundPage from './Pages/PlaygroundPage'; import InputMacroAddonPage from './Pages/InputMacroAddonPage'; +import AnimationPage from './Pages/AnimationPage'; import './App.scss'; @@ -36,6 +37,7 @@ const App = () => { /> } /> } /> + } /> } /> } /> } /> diff --git a/www/src/Components/Navigation.jsx b/www/src/Components/Navigation.jsx index 2bc0929b79..a5a4525a27 100644 --- a/www/src/Components/Navigation.jsx +++ b/www/src/Components/Navigation.jsx @@ -85,6 +85,13 @@ const Navigation = () => { > {t('Navigation:peripheral-mapping-label')} + + Animation + Date: Sun, 19 Jan 2025 23:33:38 +0100 Subject: [PATCH 024/121] Add start of animation global state handler --- www/src/Store/useAnimationStore.ts | 59 ++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 www/src/Store/useAnimationStore.ts diff --git a/www/src/Store/useAnimationStore.ts b/www/src/Store/useAnimationStore.ts new file mode 100644 index 0000000000..11ce46713d --- /dev/null +++ b/www/src/Store/useAnimationStore.ts @@ -0,0 +1,59 @@ +import { create } from 'zustand'; +import WebApi from '../Services/WebApi'; + +export const MAX_ANIMATION_PROFILES = 4; + +type Profile = { + bEnabled: boolean; + baseCaseEffect: number; + baseNonPressedEffect: number; + basePressedEffect: number; + buttonPressFadeOutTimeInMs: number; + buttonPressHoldTimeInMs: number; + caseStaticColors: number[]; + nonPressedSpecialColour: number; + notPressedStaticColors: number[]; + pressedSpecialColour: number; + pressedStaticColors: number[]; +}; + +type AnimationOptions = { + brightness: number; + baseProfileIndex: number; + customColors: number[]; + profiles: Profile[]; +}; + +type State = { + animationOptions: AnimationOptions; + loadingAnimationOptions: boolean; +}; + +type Actions = { + fetchAnimationOptions: () => void; +}; + +const INITIAL_STATE: State = { + animationOptions: { + brightness: 0, + baseProfileIndex: 0, + customColors: [], + profiles: [], + }, + loadingAnimationOptions: false, +}; + +const useAnimationStore = create()((set, get) => ({ + ...INITIAL_STATE, + fetchAnimationOptions: async () => { + set({ loadingAnimationOptions: true }); + + const { AnimationOptions } = await WebApi.getAnimationOptions(); + set(() => ({ + animationOptions: AnimationOptions, + loadingAnimationOptions: false, + })); + }, +})); + +export default useAnimationStore; From 1263048d1ab27b775e1abb1f6d89a59169e89ba7 Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 19 Jan 2025 23:34:16 +0100 Subject: [PATCH 025/121] Start with profile select and brightness in animation page --- www/src/Pages/AnimationPage.jsx | 96 +++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 www/src/Pages/AnimationPage.jsx diff --git a/www/src/Pages/AnimationPage.jsx b/www/src/Pages/AnimationPage.jsx new file mode 100644 index 0000000000..eb71457077 --- /dev/null +++ b/www/src/Pages/AnimationPage.jsx @@ -0,0 +1,96 @@ +import React, { useEffect, useState } from 'react'; +import { Button, Row } from 'react-bootstrap'; +import Form from 'react-bootstrap/Form'; +import { Formik } from 'formik'; +import * as yup from 'yup'; + +import Section from '../Components/Section'; +import useAnimationStore from '../Store/useAnimationStore'; +import FormControl from '../Components/FormControl'; +import FormSelect from '../Components/FormSelect'; +import { useTranslation } from 'react-i18next'; + +const schema = yup.object().shape({ + baseProfileIndex: yup.number().required('Selecting a profile is required'), + brightness: yup + .number() + .min(0, 'Brightness must be at least 0') + .max(100, 'Brightness cannot be more than 100') + .required('Brightness is required'), + profiles: yup.array().of( + yup.object().shape({ + // TODO add schema for profile + }), + ), +}); + +export default function AnimationPage() { + const { animationOptions, fetchAnimationOptions } = useAnimationStore(); + + const { t } = useTranslation(''); + + const [saveMessage, setSaveMessage] = useState(''); + useEffect(() => { + fetchAnimationOptions(); + }, []); + + const onSuccess = async (values) => { + setSaveMessage('Saved'); + }; + + return ( +
+ + {({ handleSubmit, handleChange, values, errors, setFieldValue }) => + console.log(values, 'values') || ( +
+ + + setFieldValue('baseProfileIndex', parseInt(e.target.value)) + } + > + {values.profiles.map((_, i) => ( + + ))} + + + + + + + {saveMessage ? ( + {saveMessage} + ) : null} +
+ ) + } +
+
+ ); +} From b71e3b44b4b6b2ba8c385006dfe921df3fac587e Mon Sep 17 00:00:00 2001 From: ian Date: Mon, 20 Jan 2025 00:58:54 +0100 Subject: [PATCH 026/121] Convert to TS, add support for custom colors --- www/src/Components/FormControl.tsx | 4 +- www/src/Pages/AnimationPage.jsx | 96 --------------- www/src/Pages/AnimationPage.tsx | 180 +++++++++++++++++++++++++++++ www/src/Store/useAnimationStore.ts | 1 + 4 files changed, 183 insertions(+), 98 deletions(-) delete mode 100644 www/src/Pages/AnimationPage.jsx create mode 100644 www/src/Pages/AnimationPage.tsx diff --git a/www/src/Components/FormControl.tsx b/www/src/Components/FormControl.tsx index c3631bf9e3..619d728b0a 100644 --- a/www/src/Components/FormControl.tsx +++ b/www/src/Components/FormControl.tsx @@ -3,7 +3,7 @@ import { Form, FormControlProps } from 'react-bootstrap'; type formTypes = { onClick?: () => void; - label: string; + label?: string; error?: string; groupClassName?: string; hidden?: boolean; @@ -20,7 +20,7 @@ const FormControl = ({ }: formTypes) => { return ( diff --git a/www/src/Pages/AnimationPage.jsx b/www/src/Pages/AnimationPage.jsx deleted file mode 100644 index eb71457077..0000000000 --- a/www/src/Pages/AnimationPage.jsx +++ /dev/null @@ -1,96 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Button, Row } from 'react-bootstrap'; -import Form from 'react-bootstrap/Form'; -import { Formik } from 'formik'; -import * as yup from 'yup'; - -import Section from '../Components/Section'; -import useAnimationStore from '../Store/useAnimationStore'; -import FormControl from '../Components/FormControl'; -import FormSelect from '../Components/FormSelect'; -import { useTranslation } from 'react-i18next'; - -const schema = yup.object().shape({ - baseProfileIndex: yup.number().required('Selecting a profile is required'), - brightness: yup - .number() - .min(0, 'Brightness must be at least 0') - .max(100, 'Brightness cannot be more than 100') - .required('Brightness is required'), - profiles: yup.array().of( - yup.object().shape({ - // TODO add schema for profile - }), - ), -}); - -export default function AnimationPage() { - const { animationOptions, fetchAnimationOptions } = useAnimationStore(); - - const { t } = useTranslation(''); - - const [saveMessage, setSaveMessage] = useState(''); - useEffect(() => { - fetchAnimationOptions(); - }, []); - - const onSuccess = async (values) => { - setSaveMessage('Saved'); - }; - - return ( -
- - {({ handleSubmit, handleChange, values, errors, setFieldValue }) => - console.log(values, 'values') || ( -
- - - setFieldValue('baseProfileIndex', parseInt(e.target.value)) - } - > - {values.profiles.map((_, i) => ( - - ))} - - - - - - - {saveMessage ? ( - {saveMessage} - ) : null} -
- ) - } -
-
- ); -} diff --git a/www/src/Pages/AnimationPage.tsx b/www/src/Pages/AnimationPage.tsx new file mode 100644 index 0000000000..2b0987d474 --- /dev/null +++ b/www/src/Pages/AnimationPage.tsx @@ -0,0 +1,180 @@ +import React, { useEffect, useState } from 'react'; +import { Button, FormGroup, Row, Tab, Tabs } from 'react-bootstrap'; +import Form from 'react-bootstrap/Form'; +import { FieldArray, Formik } from 'formik'; +import * as yup from 'yup'; + +import Section from '../Components/Section'; +import useAnimationStore, { + MAX_CUSTOM_COLORS, +} from '../Store/useAnimationStore'; +import FormControl from '../Components/FormControl'; +import FormSelect from '../Components/FormSelect'; +import { useTranslation } from 'react-i18next'; + +const schema = yup.object().shape({ + baseProfileIndex: yup.number().required('Selecting a profile is required'), + brightness: yup + .number() + .min(0, 'Brightness must be at least 0') + .max(100, 'Brightness cannot be more than 100') + .required('Brightness is required'), + profiles: yup.array().of( + yup.object().shape({ + // TODO add schema for profile + }), + ), +}); + +const convertToHex = (color: number) => + `#${color.toString(16).padStart(6, '0')}`; + +const convertToDecimal = (hex: string) => parseInt(hex.replace('#', ''), 16); + +export default function AnimationPage() { + const { animationOptions, fetchAnimationOptions } = useAnimationStore(); + const [key, setKey] = useState( + `profile-${animationOptions.baseProfileIndex}`, + ); + const { t } = useTranslation(''); + + const [saveMessage, setSaveMessage] = useState(''); + useEffect(() => { + fetchAnimationOptions(); + }, []); + + const onSuccess = async (values) => { + setSaveMessage('Saved'); + }; + + return ( +
+ + {({ handleSubmit, handleChange, values, errors, setFieldValue }) => + console.log(values, 'values') || ( +
+ + + setFieldValue('baseProfileIndex', parseInt(e.target.value)) + } + > + {values.profiles.map((_, i) => ( + + ))} + + + + + + + Custom colors + ( +
+ {values.customColors.map((color, index) => ( +
+ + arrayHelpers.replace( + index, + convertToDecimal(e.target.value), + ) + } + /> + +
+ ))} + {values.customColors.length <= MAX_CUSTOM_COLORS && ( + + )} +
+ )} + /> +
+
+ + ( + { + if (!eventKey) return; + console.log('eventKey', eventKey); + setKey(eventKey); + }} + className="my-3" + > + {values.profiles.map((profile, index) => ( + + Tab content for Profile {index + 1} + + ))} + + )} + /> + + + {saveMessage ? ( + {saveMessage} + ) : null} + + ) + } +
+
+ ); +} diff --git a/www/src/Store/useAnimationStore.ts b/www/src/Store/useAnimationStore.ts index 11ce46713d..798d70d3c6 100644 --- a/www/src/Store/useAnimationStore.ts +++ b/www/src/Store/useAnimationStore.ts @@ -1,6 +1,7 @@ import { create } from 'zustand'; import WebApi from '../Services/WebApi'; +export const MAX_CUSTOM_COLORS = 8; export const MAX_ANIMATION_PROFILES = 4; type Profile = { From fe9b57d05f30c76afcd091067bf26384bb78cc35 Mon Sep 17 00:00:00 2001 From: ian Date: Mon, 20 Jan 2025 01:16:07 +0100 Subject: [PATCH 027/121] Add handling of custom colors --- www/src/Pages/AnimationPage.tsx | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/www/src/Pages/AnimationPage.tsx b/www/src/Pages/AnimationPage.tsx index 2b0987d474..7b149f4bb9 100644 --- a/www/src/Pages/AnimationPage.tsx +++ b/www/src/Pages/AnimationPage.tsx @@ -61,7 +61,7 @@ export default function AnimationPage() { ( -
+
{values.customColors.map((color, index) => ( -
+
arrayHelpers.replace( @@ -158,7 +154,7 @@ export default function AnimationPage() { eventKey={`profile-${index}`} title={`Profile ${index + 1}`} > - Tab content for Profile {index + 1} + {/* Tab content for Profile {index + 1} */} ))} From cdafa64c7505a97e1f2aa3f7438860657f466a02 Mon Sep 17 00:00:00 2001 From: ian Date: Mon, 20 Jan 2025 23:32:46 +0100 Subject: [PATCH 028/121] First crude version of config for animations --- src/configs/webconfig.cpp | 2 +- www/server/app.js | 21 +- www/src/Data/Animations.ts | 23 ++ www/src/Pages/AnimationPage.tsx | 629 +++++++++++++++++++++++------ www/src/Pages/PinMapping.tsx | 2 +- www/src/Services/WebApi.js | 5 + www/src/Store/useAnimationStore.ts | 22 +- 7 files changed, 567 insertions(+), 137 deletions(-) create mode 100644 www/src/Data/Animations.ts diff --git a/src/configs/webconfig.cpp b/src/configs/webconfig.cpp index bf039b797a..9a82d98749 100644 --- a/src/configs/webconfig.cpp +++ b/src/configs/webconfig.cpp @@ -41,7 +41,7 @@ using namespace std; extern struct fsdata_file file__index_html[]; -const static char* spaPaths[] = { "/backup", "/display-config", "/led-config", "/pin-mapping", "/settings", "/reset-settings", "/add-ons", "/custom-theme", "/macro", "/peripheral-mapping" }; +const static char* spaPaths[] = { "/animation", "/backup", "/display-config", "/led-config", "/pin-mapping", "/settings", "/reset-settings", "/add-ons", "/custom-theme", "/macro", "/peripheral-mapping" }; const static char* excludePaths[] = { "/css", "/images", "/js", "/static" }; const static uint32_t rebootDelayMs = 500; static string http_post_uri; diff --git a/www/server/app.js b/www/server/app.js index 5698338643..9a4ae815c6 100644 --- a/www/server/app.js +++ b/www/server/app.js @@ -108,9 +108,9 @@ app.get('/api/getAnimationOptions', (req, res) => { bUseCaseLightsInSpecialMoves: 0, baseCaseEffect: 0, pressedSpecialColour: 0, - notPressedStaticColors: [0, 0, 0, 0, 0, 0, 0, 0], - pressedStaticColors: [0, 0, 0, 0, 0, 0, 0, 0], - caseStaticColors: [], + notPressedStaticColors: [5052131, 11679800, 16765393], + pressedStaticColors: [16726072, 16777215, 6172977], + caseStaticColors: [11647771, 5847610, 2931246, 4589062], }, { bEnabled: 1, @@ -122,18 +122,9 @@ app.get('/api/getAnimationOptions', (req, res) => { bUseCaseLightsInSpecialMoves: 1, baseCaseEffect: 0, pressedSpecialColour: 16724480, - notPressedStaticColors: [ - 101058054, 101058054, 101058054, 101058054, 101058054, 101058054, - 101058054, 101058054, - ], - pressedStaticColors: [ - 33686018, 33686018, 33686018, 33686018, 33686018, 33686018, - 33686018, 33686018, - ], - caseStaticColors: [ - 16843022, 16843022, 16843022, 16843022, 16843022, 16843022, - 16843022, 16843022, 16843022, 16843022, - ], + notPressedStaticColors: [727914, 5052131, 11679800, 16765393], + pressedStaticColors: [637896, 16726072, 16777215, 6172977], + caseStaticColors: [11647771, 8196626, 5847610, 2931246, 4589062], }, ], }, diff --git a/www/src/Data/Animations.ts b/www/src/Data/Animations.ts new file mode 100644 index 0000000000..c14b3a77b5 --- /dev/null +++ b/www/src/Data/Animations.ts @@ -0,0 +1,23 @@ +export const ANIMATION_NON_PRESSED_EFFECTS = { + NONPRESSED_EFFECT_STATIC_COLOR: 0, + NONPRESSED_EFFECT_RAINBOW_SYNCED: 1, + NONPRESSED_EFFECT_RAINBOW_ROTATE: 2, + NONPRESSED_EFFECT_CHASE_SEQUENTIAL: 3, + NONPRESSED_EFFECT_CHASE_LEFT_TO_RIGHT: 4, + NONPRESSED_EFFECT_CHASE_RIGHT_TO_LEFT: 5, + NONPRESSED_EFFECT_CHASE_TOP_TO_BOTTOM: 6, + NONPRESSED_EFFECT_CHASE_BOTTOM_TO_TOP: 7, + NONPRESSED_EFFECT_CHASE_SEQUENTIAL_PINGPONG: 8, + NONPRESSED_EFFECT_CHASE_HORIZONTAL_PINGPONG: 9, + NONPRESSED_EFFECT_CHASE_VERTICAL_PINGPONG: 10, + NONPRESSED_EFFECT_CHASE_RANDOM: 11, + NONPRESSED_EFFECT_JIGGLESTATIC: 12, + NONPRESSED_EFFECT_JIGGLETWOSTATIC: 13, +} as const; + +export const ANIMATION_PRESSED_EFFECTS = { + PRESSED_EFFECT_STATIC_COLOR: 0, + PRESSED_EFFECT_RANDOM: 1, + PRESSED_EFFECT_JIGGLESTATIC: 2, + PRESSED_EFFECT_JIGGLETWOSTATIC: 3, +} as const; diff --git a/www/src/Pages/AnimationPage.tsx b/www/src/Pages/AnimationPage.tsx index 7b149f4bb9..c88746a55c 100644 --- a/www/src/Pages/AnimationPage.tsx +++ b/www/src/Pages/AnimationPage.tsx @@ -1,16 +1,35 @@ import React, { useEffect, useState } from 'react'; -import { Button, FormGroup, Row, Tab, Tabs } from 'react-bootstrap'; -import Form from 'react-bootstrap/Form'; -import { FieldArray, Formik } from 'formik'; +import { + Form, + Alert, + Button, + FormCheck, + FormGroup, + OverlayTrigger, + Row, + Tab, + Tabs, + Tooltip, +} from 'react-bootstrap'; +import { ErrorMessage, FieldArray, Formik } from 'formik'; import * as yup from 'yup'; import Section from '../Components/Section'; import useAnimationStore, { + MAX_ANIMATION_PROFILES, + MAX_CASE_LIGHTS, MAX_CUSTOM_COLORS, + MAX_PRESSED_COLORS, } from '../Store/useAnimationStore'; import FormControl from '../Components/FormControl'; import FormSelect from '../Components/FormSelect'; import { useTranslation } from 'react-i18next'; +import InfoCircle from '../Icons/InfoCircle'; +import { parseInt } from 'lodash'; +import { + ANIMATION_NON_PRESSED_EFFECTS, + ANIMATION_PRESSED_EFFECTS, +} from '../Data/Animations'; const schema = yup.object().shape({ baseProfileIndex: yup.number().required('Selecting a profile is required'), @@ -21,32 +40,95 @@ const schema = yup.object().shape({ .required('Brightness is required'), profiles: yup.array().of( yup.object().shape({ - // TODO add schema for profile + bEnabled: yup.number().required(), + baseCaseEffect: yup.number().required(), + baseNonPressedEffect: yup.number().required(), + basePressedEffect: yup.number().required(), + buttonPressFadeOutTimeInMs: yup.number().required(), + buttonPressHoldTimeInMs: yup.number().required(), + caseStaticColors: yup.array().of(yup.number()).required(), + nonPressedSpecialColour: yup.number().required(), + notPressedStaticColors: yup + .array() + .of(yup.number()) + .required() + .test( + 'same-length', + 'Not Pressed Static Colors and Pressed Static Colors must be the same length', + function (value) { + return value.length === this.parent.pressedStaticColors.length; + }, + ), + pressedSpecialColour: yup.number().required(), + pressedStaticColors: yup + .array() + .of(yup.number()) + .required() + .test( + 'same-length', + 'Pressed Static Colors and Not Pressed Static Colors must be the same length', + function (value) { + return value.length === this.parent.notPressedStaticColors.length; + }, + ), }), ), }); +const emptyAnimationProfile = { + bEnabled: 1, + baseCaseEffect: 0, + baseNonPressedEffect: 0, + basePressedEffect: 0, + buttonPressFadeOutTimeInMs: 0, + buttonPressHoldTimeInMs: 0, + caseStaticColors: [], + nonPressedSpecialColour: 0, + notPressedStaticColors: [], + pressedSpecialColour: 0, + pressedStaticColors: [], +}; + const convertToHex = (color: number) => `#${color.toString(16).padStart(6, '0')}`; const convertToDecimal = (hex: string) => parseInt(hex.replace('#', ''), 16); export default function AnimationPage() { - const { animationOptions, fetchAnimationOptions } = useAnimationStore(); + const { + animationOptions, + loadingAnimationOptions, + fetchAnimationOptions, + saveAnimationOptions, + } = useAnimationStore(); const [key, setKey] = useState( `profile-${animationOptions.baseProfileIndex}`, ); const { t } = useTranslation(''); const [saveMessage, setSaveMessage] = useState(''); + useEffect(() => { fetchAnimationOptions(); }, []); - const onSuccess = async (values) => { - setSaveMessage('Saved'); + const onSuccess = async () => { + try { + await saveAnimationOptions(); + setSaveMessage(t('Common:saved-success-message')); + } catch (error) { + console.error(error); + } }; + if (loadingAnimationOptions) { + return ( +
+ +
+ ); + } + return (
- {({ handleSubmit, handleChange, values, errors, setFieldValue }) => - console.log(values, 'values') || ( -
- - - setFieldValue('baseProfileIndex', parseInt(e.target.value)) - } - > - {values.profiles.map((_, i) => ( - - ))} - - - - - - - Custom colors - ( -
- {values.customColors.map((color, index) => ( -
- - arrayHelpers.replace( - index, - convertToDecimal(e.target.value), - ) - } - /> - -
- ))} - {values.customColors.length <= MAX_CUSTOM_COLORS && ( - - )} -
- )} - /> -
-
+ {({ handleSubmit, handleChange, values, errors, setFieldValue }) => ( + + + + setFieldValue('baseProfileIndex', parseInt(e.target.value)) + } + > + {values.profiles.map((_, i) => ( + + ))} + + + + + Custom colors ( - { - if (!eventKey) return; - console.log('eventKey', eventKey); - setKey(eventKey); - }} - className="my-3" - > - {values.profiles.map((profile, index) => ( - + {values.customColors.map((color, index) => ( +
- {/* Tab content for Profile {index + 1} */} - + + arrayHelpers.replace( + index, + convertToDecimal(e.target.value), + ) + } + /> + +
))} -
+ {values.customColors.length !== MAX_CUSTOM_COLORS && ( + <> +
+ + + )} +
)} /> + + + ( + { + if (!eventKey) return; + if ('profile-add' === eventKey) { + arrayHelpers.push(emptyAnimationProfile); + setKey(`profile-${values.profiles.length}`); + } else { + setKey(eventKey); + } + }} + className="my-3" + > + {values.profiles.map((profile, index) => ( + + Enabled does something} + > +
+ + +
+ + } + type="switch" + reverse + checked={Boolean(profile.bEnabled)} + onChange={() => + setFieldValue( + `profiles.${index}.bEnabled`, + Number(!profile.bEnabled), + ) + } + /> + + + setFieldValue( + `profiles.${index}.baseCaseEffect`, + parseInt(e.target.value), + ) + } + > + {Object.entries(ANIMATION_NON_PRESSED_EFFECTS).map( + ([key, value]) => ( + + ), + )} + + + setFieldValue( + `profiles.${index}.baseNonPressedEffect`, + parseInt(e.target.value), + ) + } + > + {Object.entries(ANIMATION_NON_PRESSED_EFFECTS).map( + ([key, value]) => ( + + ), + )} + + + setFieldValue( + `profiles.${index}.basePressedEffect`, + parseInt(e.target.value), + ) + } + > + {Object.entries(ANIMATION_PRESSED_EFFECTS).map( + ([key, value]) => ( + + ), + )} + + + + + + + + setFieldValue( + `profiles.${index}.pressedSpecialColour`, + convertToDecimal(e.target.value), + ) + } + /> + + setFieldValue( + `profiles.${index}.nonPressedSpecialColour`, + convertToDecimal(e.target.value), + ) + } + /> + + Case Static Colors + ( +
+ {profile.caseStaticColors.map((color, i) => ( +
+ + arrayHelpers.replace( + i, + convertToDecimal(e.target.value), + ) + } + /> + +
+ ))} + {profile.caseStaticColors.length !== + MAX_CASE_LIGHTS && ( + <> +
+ + + )} +
+ )} + /> +
+ + Pressed Static Colors + ( + <> +
+ {profile.pressedStaticColors.map((color, i) => ( +
+ + arrayHelpers.replace( + i, + convertToDecimal(e.target.value), + ) + } + /> + +
+ ))} + {profile.pressedStaticColors.length !== + MAX_PRESSED_COLORS && ( + <> +
+ + + )} +
+ ( +

{msg}

+ )} + /> + + )} + /> +
+ + Non Pressed Static Colors + ( + <> +
+ {profile.notPressedStaticColors.map( + (color, i) => ( +
+ + arrayHelpers.replace( + i, + convertToDecimal(e.target.value), + ) + } + /> + +
+ ), + )} + {profile.notPressedStaticColors.length !== + MAX_PRESSED_COLORS && ( + <> +
+ + + )} +
+ + ( +

{msg}

+ )} + /> + + )} + /> +
+
+ ))} + + {values.profiles.length !== MAX_ANIMATION_PROFILES && ( + + )} +
+ )} + /> - - {saveMessage ? ( - {saveMessage} - ) : null} - - ) - } + + {saveMessage && {saveMessage}} + + )} ); diff --git a/www/src/Pages/PinMapping.tsx b/www/src/Pages/PinMapping.tsx index d8f4ac8a72..1e1dad3459 100644 --- a/www/src/Pages/PinMapping.tsx +++ b/www/src/Pages/PinMapping.tsx @@ -396,7 +396,7 @@ export default function PinMapping() { {loadingProfiles && (
- +
)}