Display Updates and Mini Menu (#1254)
* Initial commit for mini config menu * Implemented menu options and prepared methods for save functionality. * Removed stdio init * Added screen saver mode in addition to display timeout. Default is Display Off (original behavior). Added "snow", "bounce", "pipes", and "toast" screen savers. drawSprite can now scale sprite data. * Added VLX and Sega 2P 6 button layout variants Added button layout orientation feature to switch layouts for handedness Updated Display config page to update enum definitions for i18n * Added menu navigation helper function in prep for event system Added layout and menu action locale strings * Adjustments to Arcade, Button Angled, and Capcom layouts to make them less likely to cut off on SH110X displays. * Improved screen autodetection and manual override * Adjusting conflicts * Conflicts part deux * Conflicts with enums * One more time with conflicts * Button layout screen conflicts with change between profile banner and generic banner * Remove profile variables * Mostly implemented menu navigation, config change storage, and reboot events * Full menu navigation implementation. Added timer for reboot cases. * Increased storage size to 32k * Added options to disable different components of the status bar on ButtonLayoutScreen. Removed & deprecated input history addon remnants and migrated to Display options proper. * Remove deprecated input history init * Set default Display tab to Hardware * _Actually_ set default Display tab to Hardware * Adjust bounce velocity
This commit is contained in:
@@ -186,6 +186,7 @@ src/display/ui/elements/GPWidget.cpp
|
||||
src/display/ui/elements/GPButton.cpp
|
||||
src/display/ui/elements/GPLever.cpp
|
||||
src/display/ui/elements/GPLabel.cpp
|
||||
src/display/ui/elements/GPMenu.cpp
|
||||
src/display/ui/elements/GPScreen.cpp
|
||||
src/display/ui/elements/GPShape.cpp
|
||||
src/display/ui/elements/GPSprite.cpp
|
||||
@@ -196,6 +197,7 @@ src/display/ui/screens/PinViewerScreen.cpp
|
||||
src/display/ui/screens/RestartScreen.cpp
|
||||
src/display/ui/screens/StatsScreen.cpp
|
||||
src/display/ui/screens/SplashScreen.cpp
|
||||
src/display/ui/screens/DisplaySaverScreen.cpp
|
||||
src/display/GPGFX.cpp
|
||||
src/display/GPGFX_UI.cpp
|
||||
src/drivermanager.cpp
|
||||
|
||||
@@ -106,6 +106,14 @@
|
||||
#define INPUT_HISTORY_ROW 7
|
||||
#endif
|
||||
|
||||
#ifndef DISPLAY_SAVER_MODE
|
||||
#define DISPLAY_SAVER_MODE DISPLAY_SAVER_DISPLAY_OFF
|
||||
#endif
|
||||
|
||||
#ifndef DISPLAY_LAYOUT_ORIENTATION
|
||||
#define DISPLAY_LAYOUT_ORIENTATION BUTTON_ORIENTATION_DEFAULT
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_SPLASH
|
||||
#define DEFAULT_SPLASH \
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, \
|
||||
@@ -188,8 +196,9 @@ public:
|
||||
virtual std::string name() { return DisplayName; }
|
||||
|
||||
void handleSystemRestart(GPEvent* e);
|
||||
void handleMenuNavigation(GPEvent* e);
|
||||
private:
|
||||
bool updateDisplayScreen();
|
||||
bool updateDisplayScreen();
|
||||
void drawStatusBar(Gamepad*);
|
||||
void initMenu(char**);
|
||||
bool pressedUp();
|
||||
@@ -209,11 +218,15 @@ private:
|
||||
GPGFX* gpDisplay;
|
||||
GPScreen* gpScreen;
|
||||
DisplayMode currDisplayMode;
|
||||
DisplayMode prevDisplayMode;
|
||||
DisplayMode prevDisplayMode;
|
||||
bool turnOffWhenSuspended;
|
||||
uint32_t bootMode;
|
||||
|
||||
GPGFX_DisplayTypeOptions gpOptions;
|
||||
DisplaySaverMode displaySaverMode;
|
||||
|
||||
GPGFX_DisplayTypeOptions gpOptions;
|
||||
|
||||
GamepadButtonMapping *mapMenuToggle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -129,20 +129,30 @@
|
||||
{GP_ELEMENT_BTN_BUTTON, {119,33, 5, 5, 1, 1, GAMEPAD_MASK_S2, GP_SHAPE_ELLIPSE}}\
|
||||
}
|
||||
|
||||
#define BUTTON_GROUP_VLXB_6B {\
|
||||
{GP_ELEMENT_BTN_BUTTON, {50, 31, 7, 7, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {66, 24, 7, 7, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {82, 24, 7, 7, 1, 1, GAMEPAD_MASK_R1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {45, 47, 7, 7, 1, 1, GAMEPAD_MASK_B1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {61, 40, 7, 7, 1, 1, GAMEPAD_MASK_B2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {77, 40, 7, 7, 1, 1, GAMEPAD_MASK_R2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {119,33, 5, 5, 1, 1, GAMEPAD_MASK_S2, GP_SHAPE_ELLIPSE}}\
|
||||
}
|
||||
|
||||
#define BUTTON_GROUP_FIGHTBOARD {\
|
||||
{GP_ELEMENT_BTN_BUTTON, {69, 27, 7, 7, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {86, 18, 7, 7, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {103,18, 7, 7, 1, 1, GAMEPAD_MASK_R1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {120,18, 7, 7, 1, 1, GAMEPAD_MASK_L1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {69, 43, 7, 7, 1, 1, GAMEPAD_MASK_B1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {86, 35, 7, 7, 1, 1, GAMEPAD_MASK_B2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {103,35, 7, 7, 1, 1, GAMEPAD_MASK_R2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {120,35, 7, 7, 1, 1, GAMEPAD_MASK_L2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {84, 47, 3, 3, 1, 1, GAMEPAD_MASK_L3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {94, 47, 3, 3, 1, 1, GAMEPAD_MASK_S1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {103,47, 3, 3, 1, 1, GAMEPAD_MASK_A1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {112,47, 3, 3, 1, 1, GAMEPAD_MASK_S2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {122,47, 3, 3, 1, 1, GAMEPAD_MASK_R3, GP_SHAPE_ELLIPSE}}\
|
||||
{GP_ELEMENT_BTN_BUTTON, {67, 27, 7, 7, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {84, 18, 7, 7, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {101,18, 7, 7, 1, 1, GAMEPAD_MASK_R1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {118,18, 7, 7, 1, 1, GAMEPAD_MASK_L1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {67, 43, 7, 7, 1, 1, GAMEPAD_MASK_B1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {84, 35, 7, 7, 1, 1, GAMEPAD_MASK_B2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {101,35, 7, 7, 1, 1, GAMEPAD_MASK_R2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {118,35, 7, 7, 1, 1, GAMEPAD_MASK_L2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {82, 47, 3, 3, 1, 1, GAMEPAD_MASK_L3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {92, 47, 3, 3, 1, 1, GAMEPAD_MASK_S1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {101,47, 3, 3, 1, 1, GAMEPAD_MASK_A1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {110,47, 3, 3, 1, 1, GAMEPAD_MASK_S2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {120,47, 3, 3, 1, 1, GAMEPAD_MASK_R3, GP_SHAPE_ELLIPSE}}\
|
||||
}
|
||||
|
||||
#define BUTTON_GROUP_VEWLIX7 {\
|
||||
@@ -166,6 +176,15 @@
|
||||
{GP_ELEMENT_BTN_BUTTON, {111,46, 8, 8, 1, 1, GAMEPAD_MASK_L2, GP_SHAPE_ELLIPSE}}\
|
||||
}
|
||||
|
||||
#define BUTTON_GROUP_SEGA_2P_6B {\
|
||||
{GP_ELEMENT_BTN_BUTTON, {57, 34, 8, 8, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {75, 24, 8, 8, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {93, 24, 8, 8, 1, 1, GAMEPAD_MASK_R1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {57, 52, 8, 8, 1, 1, GAMEPAD_MASK_B1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {75, 42, 8, 8, 1, 1, GAMEPAD_MASK_B2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {93, 42, 8, 8, 1, 1, GAMEPAD_MASK_R2, GP_SHAPE_ELLIPSE}}\
|
||||
}
|
||||
|
||||
#define BUTTON_GROUP_NOIR8 {\
|
||||
{GP_ELEMENT_BTN_BUTTON, {57, 33, 8, 8, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {75, 24, 8, 8, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
@@ -178,14 +197,14 @@
|
||||
}
|
||||
|
||||
#define BUTTON_GROUP_CAPCOM {\
|
||||
{GP_ELEMENT_BTN_BUTTON, {64, 28, 8, 8, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {82, 28, 8, 8, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {100,28, 8, 8, 1, 1, GAMEPAD_MASK_R1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {118,28, 8, 8, 1, 1, GAMEPAD_MASK_L1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {64, 46, 8, 8, 1, 1, GAMEPAD_MASK_B1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {82, 46, 8, 8, 1, 1, GAMEPAD_MASK_B2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {100,46, 8, 8, 1, 1, GAMEPAD_MASK_R2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {118,46, 8, 8, 1, 1, GAMEPAD_MASK_L2, GP_SHAPE_ELLIPSE}}\
|
||||
{GP_ELEMENT_BTN_BUTTON, {62, 28, 8, 8, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {80, 28, 8, 8, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {98, 28, 8, 8, 1, 1, GAMEPAD_MASK_R1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {116,28, 8, 8, 1, 1, GAMEPAD_MASK_L1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {62, 46, 8, 8, 1, 1, GAMEPAD_MASK_B1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {80, 46, 8, 8, 1, 1, GAMEPAD_MASK_B2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {98, 46, 8, 8, 1, 1, GAMEPAD_MASK_R2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {116,46, 8, 8, 1, 1, GAMEPAD_MASK_L2, GP_SHAPE_ELLIPSE}}\
|
||||
}
|
||||
|
||||
#define BUTTON_GROUP_CAPCOM6 {\
|
||||
@@ -209,25 +228,25 @@
|
||||
}
|
||||
|
||||
#define BUTTON_GROUP_WASD_BUTTONS {\
|
||||
{GP_ELEMENT_BTN_BUTTON, {69, 28, 7, 7, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {86, 24, 7, 7, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {103,24, 7, 7, 1, 1, GAMEPAD_MASK_R1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {120,28, 7, 7, 1, 1, GAMEPAD_MASK_L1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {63, 45, 7, 7, 1, 1, GAMEPAD_MASK_B1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {80, 41, 7, 7, 1, 1, GAMEPAD_MASK_B2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {97, 41, 7, 7, 1, 1, GAMEPAD_MASK_R2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {114,45, 7, 7, 1, 1, GAMEPAD_MASK_L2, GP_SHAPE_ELLIPSE}}\
|
||||
{GP_ELEMENT_BTN_BUTTON, {67, 28, 7, 7, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {84, 24, 7, 7, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {101,24, 7, 7, 1, 1, GAMEPAD_MASK_R1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {118,28, 7, 7, 1, 1, GAMEPAD_MASK_L1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {61, 45, 7, 7, 1, 1, GAMEPAD_MASK_B1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {78, 41, 7, 7, 1, 1, GAMEPAD_MASK_B2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {95, 41, 7, 7, 1, 1, GAMEPAD_MASK_R2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {112,45, 7, 7, 1, 1, GAMEPAD_MASK_L2, GP_SHAPE_ELLIPSE}}\
|
||||
}
|
||||
|
||||
#define BUTTON_GROUP_ARCADE_BUTTONS {\
|
||||
{GP_ELEMENT_BTN_BUTTON, {64, 28, 8, 8, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {82, 24, 8, 8, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {100,24, 8, 8, 1, 1, GAMEPAD_MASK_R1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {118,28, 8, 8, 1, 1, GAMEPAD_MASK_L1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {59, 46, 8, 8, 1, 1, GAMEPAD_MASK_B1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {77, 42, 8, 8, 1, 1, GAMEPAD_MASK_B2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {95, 42, 8, 8, 1, 1, GAMEPAD_MASK_R2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {113,46, 8, 8, 1, 1, GAMEPAD_MASK_L2, GP_SHAPE_ELLIPSE}}\
|
||||
{GP_ELEMENT_BTN_BUTTON, {62, 28, 8, 8, 1, 1, GAMEPAD_MASK_B3, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {80, 24, 8, 8, 1, 1, GAMEPAD_MASK_B4, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {98, 24, 8, 8, 1, 1, GAMEPAD_MASK_R1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {116,28, 8, 8, 1, 1, GAMEPAD_MASK_L1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {57, 46, 8, 8, 1, 1, GAMEPAD_MASK_B1, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {75, 42, 8, 8, 1, 1, GAMEPAD_MASK_B2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {93, 42, 8, 8, 1, 1, GAMEPAD_MASK_R2, GP_SHAPE_ELLIPSE}},\
|
||||
{GP_ELEMENT_BTN_BUTTON, {111,46, 8, 8, 1, 1, GAMEPAD_MASK_L2, GP_SHAPE_ELLIPSE}}\
|
||||
}
|
||||
|
||||
#define BUTTON_GROUP_STICKLESS13A {\
|
||||
|
||||
@@ -12,7 +12,7 @@ class GPGFX {
|
||||
|
||||
void init(GPGFX_DisplayTypeOptions options);
|
||||
|
||||
GPGFX_DisplayTypeOptions getAvailableDisplay();
|
||||
GPGFX_DisplayTypeOptions getAvailableDisplay(GPGFX_DisplayType displayType);
|
||||
|
||||
GPGFX_DisplayBase* getDriver() { return displayDriver; }
|
||||
|
||||
@@ -20,6 +20,7 @@ class GPGFX {
|
||||
void clearScreen();
|
||||
void render();
|
||||
|
||||
uint32_t getPixel(uint16_t x, uint16_t y);
|
||||
void drawPixel(uint16_t x, uint16_t y, uint32_t color);
|
||||
void drawText(uint16_t x, uint16_t y, std::string text, uint8_t invert = 0);
|
||||
void drawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint32_t color, uint8_t filled);
|
||||
@@ -27,9 +28,11 @@ class GPGFX {
|
||||
void drawEllipse(uint16_t x, uint16_t y, uint32_t radiusX, uint32_t radiusY, uint32_t color, uint8_t filled);
|
||||
void drawRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color, uint8_t filled, double rotationAngle = 0);
|
||||
void drawPolygon(uint16_t x, uint16_t y, uint16_t radius, uint16_t sides, uint32_t color, uint8_t filled, double rotation = 0);
|
||||
void drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority);
|
||||
void drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority, double scale = 1.0);
|
||||
private:
|
||||
GPGFX_DisplayBase* displayDriver = nullptr;
|
||||
|
||||
bool detectDisplay(GPGFX_DisplayTypeOptions* display, GPGFX_DisplayType displayType);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,7 @@ enum DisplayMode {
|
||||
BUTTONS,
|
||||
SPLASH,
|
||||
PIN_VIEWER,
|
||||
DISPLAY_SAVER,
|
||||
STATS,
|
||||
MAIN_MENU,
|
||||
RESTART
|
||||
@@ -13,6 +14,7 @@ enum DisplayMode {
|
||||
|
||||
#include "ui/screens/ButtonLayoutScreen.h"
|
||||
#include "ui/screens/ConfigScreen.h"
|
||||
#include "ui/screens/DisplaySaverScreen.h"
|
||||
#include "ui/screens/MainMenuScreen.h"
|
||||
#include "ui/screens/PinViewerScreen.h"
|
||||
#include "ui/screens/RestartScreen.h"
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
typedef struct {
|
||||
typedef struct MenuEntry {
|
||||
std::string label;
|
||||
uint8_t* icon;
|
||||
std::vector<MenuEntry>* submenu;
|
||||
std::function<int32_t()> currentValue;
|
||||
std::function<void()> action;
|
||||
int32_t optionValue = -1;
|
||||
} MenuEntry;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "ui/elements/GPScreen.h"
|
||||
#include "ui/elements/GPShape.h"
|
||||
#include "ui/elements/GPSprite.h"
|
||||
#include "ui/elements/GPMenu.h"
|
||||
|
||||
#include "GPGFX_UI_screens.h"
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class GPButton : public GPWidget {
|
||||
double _angle = 0;
|
||||
double _angleEnd = 0;
|
||||
bool _closed = false;
|
||||
int16_t _inputMask = -1;
|
||||
int32_t _inputMask = -1;
|
||||
bool _inputDirection = false;
|
||||
GPElement _inputType = GP_ELEMENT_BTN_BUTTON;
|
||||
GPShape_Type _shape = GP_SHAPE_ELLIPSE;
|
||||
|
||||
31
headers/display/ui/elements/GPMenu.h
Normal file
31
headers/display/ui/elements/GPMenu.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef _GPMENU_H_
|
||||
#define _GPMENU_H_
|
||||
|
||||
#include "GPWidget.h"
|
||||
#include "GPShape.h"
|
||||
#include "GPGFX_UI_types.h"
|
||||
|
||||
class GPMenu : public GPShape {
|
||||
public:
|
||||
void draw();
|
||||
GPMenu* setMenuSize(uint16_t sizeX, uint16_t sizeY) { this->menuSizeX = sizeX; this->menuSizeY = sizeY; return this; }
|
||||
|
||||
uint16_t getDataSize() { return this->menuEntryData->size(); };
|
||||
|
||||
void setIndex(uint16_t pos) { this->menuIndex = pos; };
|
||||
uint16_t getIndex() { return this->menuIndex; };
|
||||
|
||||
void setMenuData(std::vector<MenuEntry>* menu) { this->menuEntryData = menu; };
|
||||
void setMenuTitle(std::string title) { this->menuTitle = title; };
|
||||
private:
|
||||
uint16_t menuSizeX = 0;
|
||||
uint16_t menuSizeY = 0;
|
||||
|
||||
uint16_t menuLines = 15;
|
||||
uint16_t menuIndex = 0;
|
||||
|
||||
std::vector<MenuEntry>* menuEntryData;
|
||||
std::string menuTitle;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -28,6 +28,9 @@ class GPWidget : public GPGFX_UI {
|
||||
|
||||
double getScaleX() { return ((double)(this->getViewport().right - this->getViewport().left) / (double)(getRenderer()->getDriver()->getMetrics()->width)); }
|
||||
double getScaleY() { return ((double)(this->getViewport().bottom - this->getViewport().top) / (double)(getRenderer()->getDriver()->getMetrics()->height)); }
|
||||
|
||||
void setVisibility(bool visible) { this->_visibility = visible; }
|
||||
bool getVisibility() { return this->_visibility; }
|
||||
protected:
|
||||
uint16_t x = 0;
|
||||
uint16_t y = 0;
|
||||
@@ -36,6 +39,7 @@ class GPWidget : public GPGFX_UI {
|
||||
uint16_t fillColor = 0;
|
||||
uint16_t _ID;
|
||||
uint16_t _priority = 0;
|
||||
bool _visibility = true;
|
||||
|
||||
GPViewport _viewport;
|
||||
};
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <deque>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
#include "layoutmanager.h"
|
||||
#include "GPGFX_UI_widgets.h"
|
||||
#include "GPGFX_UI_layouts.h"
|
||||
@@ -158,9 +161,18 @@ class ButtonLayoutScreen : public GPScreen {
|
||||
uint8_t prevProfileNumber = 0;
|
||||
ButtonLayoutParamsLeft prevLeftOptions;
|
||||
ButtonLayoutParamsRight prevRightOptions;
|
||||
|
||||
ButtonLayoutOrientation prevOrientation;
|
||||
|
||||
bool macroEnabled;
|
||||
|
||||
bool showInputMode = true;
|
||||
bool showTurboMode = true;
|
||||
bool showDpadMode = true;
|
||||
bool showSocdMode = true;
|
||||
bool showMacroMode = true;
|
||||
bool showProfileMode = false;
|
||||
void trim(std::string &s);
|
||||
|
||||
uint16_t map(uint16_t x, uint16_t in_min, uint16_t in_max, uint16_t out_min, uint16_t out_max);
|
||||
void processInputHistory();
|
||||
bool compareCustomLayouts();
|
||||
|
||||
62
headers/display/ui/screens/DisplaySaverScreen.h
Normal file
62
headers/display/ui/screens/DisplaySaverScreen.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef _DISPLAYSAVERSCREEN_H_
|
||||
#define _DISPLAYSAVERSCREEN_H_
|
||||
|
||||
#include <vector>
|
||||
#include "GPGFX_UI_widgets.h"
|
||||
#include "bitmaps.h"
|
||||
|
||||
const uint8_t SCREEN_WIDTH = 128;
|
||||
const uint8_t SCREEN_HEIGHT = 64;
|
||||
|
||||
class DisplaySaverScreen : public GPScreen {
|
||||
public:
|
||||
DisplaySaverScreen() {}
|
||||
DisplaySaverScreen(GPGFX* renderer) { setRenderer(renderer); }
|
||||
virtual int8_t update();
|
||||
virtual void init();
|
||||
virtual void shutdown();
|
||||
protected:
|
||||
virtual void drawScreen();
|
||||
uint16_t prevButtonState = 0;
|
||||
DisplaySaverMode displaySaverMode;
|
||||
|
||||
// snow screen
|
||||
uint8_t snowflakeSpeeds[SCREEN_WIDTH][SCREEN_HEIGHT] = {};
|
||||
int8_t snowflakeDrift[SCREEN_WIDTH][SCREEN_HEIGHT] = {};
|
||||
void initSnowScene();
|
||||
void drawSnowScene();
|
||||
|
||||
// bounce
|
||||
uint16_t bounceSpriteX = 0;
|
||||
uint16_t bounceSpriteY = 0;
|
||||
uint16_t bounceSpriteWidth = 128;
|
||||
uint16_t bounceSpriteHeight = 35;
|
||||
double bounceSpriteVelocityX = 1;
|
||||
double bounceSpriteVelocityY = 1;
|
||||
double bounceScale = 0.5;
|
||||
void drawBounceScene();
|
||||
|
||||
// pipes
|
||||
void drawPipeScene();
|
||||
|
||||
// toaster
|
||||
struct ToastParams {
|
||||
uint8_t* image;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
double scale;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t dx;
|
||||
int16_t dy;
|
||||
};
|
||||
|
||||
std::vector<ToastParams> toasters;
|
||||
uint16_t numberOfToasters = 10;
|
||||
uint16_t toasterSpriteWidth = 43;
|
||||
uint16_t toasterSpriteHeight = 39;
|
||||
void initToasters();
|
||||
void drawToasterScene();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,38 @@
|
||||
|
||||
#include "GPGFX_UI_widgets.h"
|
||||
#include "GPGFX_UI_types.h"
|
||||
#include "enums.pb.h"
|
||||
#include "AnimationStation.hpp"
|
||||
#include "eventmanager.h"
|
||||
|
||||
#define INPUT_MODE_XINPUT_NAME "XInput"
|
||||
#define INPUT_MODE_SWITCH_NAME "Nintendo Switch"
|
||||
#define INPUT_MODE_PS3_NAME "PS3"
|
||||
#define INPUT_MODE_KEYBOARD_NAME "Keyboard"
|
||||
#define INPUT_MODE_PS4_NAME "PS4"
|
||||
#define INPUT_MODE_XBONE_NAME "Xbox One"
|
||||
#define INPUT_MODE_MDMINI_NAME "Sega Genesis Mini"
|
||||
#define INPUT_MODE_NEOGEO_NAME "NEOGEO mini"
|
||||
#define INPUT_MODE_PCEMINI_NAME "PC Engine Mini"
|
||||
#define INPUT_MODE_EGRET_NAME "EGRET II mini"
|
||||
#define INPUT_MODE_ASTRO_NAME "ASTROCITY Mini"
|
||||
#define INPUT_MODE_PSCLASSIC_NAME "Playstation Classic"
|
||||
#define INPUT_MODE_XBOXORIGINAL_NAME "Original Xbox"
|
||||
#define INPUT_MODE_PS5_NAME "PS5"
|
||||
#define INPUT_MODE_GENERIC_NAME "Generic HID"
|
||||
#define INPUT_MODE_CONFIG_NAME "Web Config"
|
||||
|
||||
#define SOCD_MODE_UP_PRIORITY_NAME "Up Priority"
|
||||
#define SOCD_MODE_NEUTRAL_NAME "Neutral"
|
||||
#define SOCD_MODE_SECOND_INPUT_PRIORITY_NAME "Last Win"
|
||||
#define SOCD_MODE_FIRST_INPUT_PRIORITY_NAME "First Win"
|
||||
#define SOCD_MODE_BYPASS_NAME "Off"
|
||||
|
||||
#define DPAD_MODE_DIGITAL_NAME "D-Pad"
|
||||
#define DPAD_MODE_LEFT_ANALOG_NAME "Left Analog"
|
||||
#define DPAD_MODE_RIGHT_ANALOG_NAME "Right Analog"
|
||||
|
||||
#define MAIN_MENU_NAME "GP2040-CE Mini Menu"
|
||||
|
||||
class MainMenuScreen : public GPScreen {
|
||||
public:
|
||||
@@ -12,6 +44,30 @@ class MainMenuScreen : public GPScreen {
|
||||
virtual int8_t update();
|
||||
virtual void init();
|
||||
virtual void shutdown();
|
||||
|
||||
void testMenu() {}
|
||||
void saveAndExit();
|
||||
int32_t modeValue();
|
||||
|
||||
void selectInputMode();
|
||||
int32_t currentInputMode();
|
||||
|
||||
void selectDPadMode();
|
||||
int32_t currentDpadMode();
|
||||
|
||||
void selectSOCDMode();
|
||||
int32_t currentSOCDMode();
|
||||
|
||||
void selectProfile();
|
||||
int32_t currentProfile();
|
||||
|
||||
void selectFocusMode();
|
||||
int32_t currentFocusMode();
|
||||
|
||||
void selectTurboMode();
|
||||
int32_t currentTurboMode();
|
||||
|
||||
void updateMenuNavigation(GpioAction action);
|
||||
protected:
|
||||
virtual void drawScreen();
|
||||
private:
|
||||
@@ -19,7 +75,84 @@ class MainMenuScreen : public GPScreen {
|
||||
bool isPressed = false;
|
||||
uint32_t checkDebounce;
|
||||
std::vector<MenuEntry>* currentMenu;
|
||||
std::vector<MenuEntry>* previousMenu;
|
||||
uint16_t prevButtonState = 0;
|
||||
Mask_t prevValues;
|
||||
GPMenu* gpMenu;
|
||||
|
||||
bool screenIsPrompting = false;
|
||||
bool promptChoice = false;
|
||||
|
||||
int8_t exitToScreenBeforePrompt = -1;
|
||||
int8_t exitToScreen = -1;
|
||||
|
||||
GamepadButtonMapping *mapMenuUp;
|
||||
GamepadButtonMapping *mapMenuDown;
|
||||
GamepadButtonMapping *mapMenuLeft;
|
||||
GamepadButtonMapping *mapMenuRight;
|
||||
GamepadButtonMapping *mapMenuSelect;
|
||||
GamepadButtonMapping *mapMenuBack;
|
||||
GamepadButtonMapping *mapMenuToggle;
|
||||
|
||||
void saveOptions();
|
||||
void resetOptions();
|
||||
bool changeRequiresReboot = false;
|
||||
bool changeRequiresSave = false;
|
||||
|
||||
#define INPUT_MODE_ENTRIES(name, value) {name##_NAME, NULL, nullptr, std::bind(&MainMenuScreen::currentInputMode, this), std::bind(&MainMenuScreen::selectInputMode, this), value},
|
||||
#define DPAD_MODE_ENTRIES(name, value) {name##_NAME, NULL, nullptr, std::bind(&MainMenuScreen::currentDpadMode, this), std::bind(&MainMenuScreen::selectDPadMode, this), value},
|
||||
#define SOCD_MODE_ENTRIES(name, value) {name##_NAME, NULL, nullptr, std::bind(&MainMenuScreen::currentSOCDMode, this), std::bind(&MainMenuScreen::selectSOCDMode, this), value},
|
||||
|
||||
std::vector<MenuEntry> inputModeMenu = {
|
||||
InputMode_VALUELIST(INPUT_MODE_ENTRIES)
|
||||
};
|
||||
InputMode prevInputMode;
|
||||
InputMode updateInputMode;
|
||||
|
||||
std::vector<MenuEntry> dpadModeMenu = {
|
||||
DpadMode_VALUELIST(DPAD_MODE_ENTRIES)
|
||||
};
|
||||
DpadMode prevDpadMode;
|
||||
DpadMode updateDpadMode;
|
||||
|
||||
std::vector<MenuEntry> socdModeMenu = {
|
||||
SOCDMode_VALUELIST(SOCD_MODE_ENTRIES)
|
||||
};
|
||||
SOCDMode prevSocdMode;
|
||||
SOCDMode updateSocdMode;
|
||||
|
||||
std::vector<MenuEntry> profilesMenu = {};
|
||||
uint8_t prevProfile;
|
||||
uint8_t updateProfile;
|
||||
|
||||
std::vector<MenuEntry> focusModeMenu = {
|
||||
{"Off", NULL, nullptr, std::bind(&MainMenuScreen::currentFocusMode, this), std::bind(&MainMenuScreen::selectFocusMode, this), 0},
|
||||
{"On", NULL, nullptr, std::bind(&MainMenuScreen::currentFocusMode, this), std::bind(&MainMenuScreen::selectFocusMode, this), 1},
|
||||
};
|
||||
bool prevFocus;
|
||||
bool updateFocus;
|
||||
|
||||
std::vector<MenuEntry> turboModeMenu = {
|
||||
{"Off", NULL, nullptr, std::bind(&MainMenuScreen::currentTurboMode, this), std::bind(&MainMenuScreen::selectTurboMode, this), 0},
|
||||
{"On", NULL, nullptr, std::bind(&MainMenuScreen::currentTurboMode, this), std::bind(&MainMenuScreen::selectTurboMode, this), 1},
|
||||
};
|
||||
bool prevTurbo;
|
||||
bool updateTurbo;
|
||||
|
||||
std::vector<MenuEntry> mainMenu = {
|
||||
{"Input Mode", NULL, &inputModeMenu, std::bind(&MainMenuScreen::modeValue, this), std::bind(&MainMenuScreen::testMenu, this)},
|
||||
{"D-Pad Mode", NULL, &dpadModeMenu, std::bind(&MainMenuScreen::modeValue, this), std::bind(&MainMenuScreen::testMenu, this)},
|
||||
{"SOCD Mode", NULL, &socdModeMenu, std::bind(&MainMenuScreen::modeValue, this), std::bind(&MainMenuScreen::testMenu, this)},
|
||||
{"Profile", NULL, &profilesMenu, std::bind(&MainMenuScreen::modeValue, this), std::bind(&MainMenuScreen::testMenu, this)},
|
||||
{"Focus Mode", NULL, &focusModeMenu, std::bind(&MainMenuScreen::modeValue, this), std::bind(&MainMenuScreen::testMenu, this)},
|
||||
{"Turbo", NULL, &turboModeMenu, std::bind(&MainMenuScreen::modeValue, this), std::bind(&MainMenuScreen::testMenu, this)},
|
||||
{"Save & Exit",NULL, &saveMenu, std::bind(&MainMenuScreen::modeValue, this), std::bind(&MainMenuScreen::testMenu, this)},
|
||||
};
|
||||
|
||||
std::vector<MenuEntry> saveMenu = {
|
||||
{"Yes", NULL, nullptr, std::bind(&MainMenuScreen::modeValue, this), std::bind(&MainMenuScreen::saveAndExit, this), 1},
|
||||
{"No", NULL, nullptr, std::bind(&MainMenuScreen::modeValue, this), std::bind(&MainMenuScreen::testMenu, this), 0},
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -14,8 +14,11 @@
|
||||
#include "GPEvent.h"
|
||||
#include "GPGamepadEvent.h"
|
||||
#include "GPEncoderEvent.h"
|
||||
#include "GPMenuNavigateEvent.h"
|
||||
#include "GPProfileEvent.h"
|
||||
#include "GPRestartEvent.h"
|
||||
#include "GPStorageSaveEvent.h"
|
||||
#include "GPSystemRebootEvent.h"
|
||||
#include "GPUSBHostEvent.h"
|
||||
|
||||
#define EVENTMGR EventManager::getInstance()
|
||||
@@ -33,6 +36,9 @@ class EventManager {
|
||||
return instance;
|
||||
}
|
||||
|
||||
void init();
|
||||
void clearEventHandlers();
|
||||
|
||||
void registerEventHandler(GPEventType eventType, EventFunction handler);
|
||||
void triggerEvent(GPEvent* event);
|
||||
private:
|
||||
|
||||
21
headers/events/GPMenuNavigateEvent.h
Normal file
21
headers/events/GPMenuNavigateEvent.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef _GPMENUNAVIGATEEVENT_H_
|
||||
#define _GPMENUNAVIGATEEVENT_H_
|
||||
|
||||
#include "system.h"
|
||||
|
||||
class GPMenuNavigateEvent : public GPEvent {
|
||||
public:
|
||||
GPMenuNavigateEvent() {}
|
||||
GPMenuNavigateEvent(GpioAction action) {
|
||||
this->menuAction = action;
|
||||
}
|
||||
~GPMenuNavigateEvent() {}
|
||||
|
||||
GPEventType eventType() { return this->_eventType; }
|
||||
|
||||
GpioAction menuAction;
|
||||
private:
|
||||
GPEventType _eventType = GP_EVENT_MENU_NAVIGATE;
|
||||
};
|
||||
|
||||
#endif
|
||||
23
headers/events/GPStorageSaveEvent.h
Normal file
23
headers/events/GPStorageSaveEvent.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef _GPSTORAGESAVEEVENT_H_
|
||||
#define _GPSTORAGESAVEEVENT_H_
|
||||
|
||||
#include "system.h"
|
||||
|
||||
class GPStorageSaveEvent : public GPEvent {
|
||||
public:
|
||||
GPStorageSaveEvent() {}
|
||||
GPStorageSaveEvent(bool force, bool restart = false) {
|
||||
this->forceSave = force;
|
||||
this->restartAfterSave = restart;
|
||||
}
|
||||
~GPStorageSaveEvent() {}
|
||||
|
||||
GPEventType eventType() { return this->_eventType; }
|
||||
|
||||
bool forceSave = false;
|
||||
bool restartAfterSave = false;
|
||||
private:
|
||||
GPEventType _eventType = GP_EVENT_STORAGE_SAVE;
|
||||
};
|
||||
|
||||
#endif
|
||||
21
headers/events/GPSystemRebootEvent.h
Normal file
21
headers/events/GPSystemRebootEvent.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef _GPSYSTEMREBOOTEVENT_H_
|
||||
#define _GPSYSTEMREBOOTEVENT_H_
|
||||
|
||||
#include "system.h"
|
||||
|
||||
class GPSystemRebootEvent : public GPEvent {
|
||||
public:
|
||||
GPSystemRebootEvent() {}
|
||||
GPSystemRebootEvent(System::BootMode mode) {
|
||||
this->bootMode = mode;
|
||||
}
|
||||
~GPSystemRebootEvent() {}
|
||||
|
||||
GPEventType eventType() { return this->_eventType; }
|
||||
|
||||
System::BootMode bootMode = System::BootMode::DEFAULT;
|
||||
private:
|
||||
GPEventType _eventType = GP_EVENT_SYSTEM_REBOOT;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -11,6 +11,7 @@
|
||||
// GP2040 Classes
|
||||
#include "gamepad.h"
|
||||
#include "addonmanager.h"
|
||||
#include "eventmanager.h"
|
||||
#include "gpdriver.h"
|
||||
|
||||
#include "pico/types.h"
|
||||
@@ -75,6 +76,13 @@ private:
|
||||
|
||||
// input mask, action
|
||||
std::map<uint32_t, int32_t> bootActions;
|
||||
|
||||
bool saveRequested = false;
|
||||
bool saveSuccessful = false;
|
||||
void handleStorageSave(GPEvent* e);
|
||||
|
||||
bool rebootRequested = false;
|
||||
void handleSystemReboot(GPEvent* e);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,8 @@ class GPGFX_DisplayBase : public I2CDeviceBase {
|
||||
|
||||
virtual void clear() {}
|
||||
|
||||
virtual uint32_t getPixel(uint8_t x, uint8_t y) {}
|
||||
|
||||
virtual void drawPixel(uint8_t x, uint8_t y, uint32_t color) {}
|
||||
|
||||
virtual void drawText(uint8_t x, uint8_t y, std::string text, uint8_t invert = 0) {}
|
||||
@@ -32,7 +34,7 @@ class GPGFX_DisplayBase : public I2CDeviceBase {
|
||||
|
||||
virtual void drawPolygon(uint16_t x, uint16_t y, uint16_t radius, uint16_t sides, uint32_t color, uint8_t filled, double rotation = 0) {}
|
||||
|
||||
virtual void drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority) {}
|
||||
virtual void drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority, double scale) {}
|
||||
|
||||
virtual void drawBuffer(uint8_t *pBuffer) {}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ class GPGFX_OBD_SSD1306 : public GPGFX_DisplayBase {
|
||||
|
||||
void clear();
|
||||
|
||||
uint32_t getPixel(uint8_t x, uint8_t y);
|
||||
|
||||
void drawPixel(uint8_t x, uint8_t y, uint32_t color);
|
||||
|
||||
void drawText(uint8_t x, uint8_t y, std::string text, uint8_t invert = 0);
|
||||
@@ -27,7 +29,7 @@ class GPGFX_OBD_SSD1306 : public GPGFX_DisplayBase {
|
||||
|
||||
void drawRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color, uint8_t filled, double rotationAngle = 0);
|
||||
|
||||
void drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority);
|
||||
void drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority, double scale = 1.0);
|
||||
|
||||
void drawBuffer(uint8_t *pBuffer);
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ class GPGFX_TinySSD1306 : public GPGFX_DisplayBase {
|
||||
|
||||
void clear();
|
||||
|
||||
uint32_t getPixel(uint8_t x, uint8_t y);
|
||||
|
||||
void drawPixel(uint8_t x, uint8_t y, uint32_t color);
|
||||
|
||||
void drawText(uint8_t x, uint8_t y, std::string text, uint8_t invert = 0);
|
||||
@@ -30,7 +32,7 @@ class GPGFX_TinySSD1306 : public GPGFX_DisplayBase {
|
||||
|
||||
void drawPolygon(uint16_t x, uint16_t y, uint16_t radius, uint16_t sides, uint32_t color, uint8_t filled, double rotation = 0);
|
||||
|
||||
void drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority);
|
||||
void drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority, double scale = 1.0);
|
||||
|
||||
void drawBuffer(uint8_t *pBuffer);
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ class LayoutManager {
|
||||
std::string getButtonLayoutRightName(ButtonLayoutRight layout);
|
||||
|
||||
LayoutList adjustByCustomSettings(LayoutList layout, ButtonLayoutParamsCommon common, uint16_t originX = 0, uint16_t originY = 0);
|
||||
LayoutList adjustByOffset(LayoutList layout, int16_t originX = 0, int16_t originY = 0);
|
||||
LayoutList flipHorizontally(LayoutList layout, int16_t startX = 0, int16_t startY = 0, int16_t endX = 0, int16_t endY = 0);
|
||||
|
||||
// old layout methods
|
||||
LayoutList drawStickless();
|
||||
@@ -71,6 +73,7 @@ class LayoutManager {
|
||||
LayoutList drawVewlix();
|
||||
LayoutList drawVewlix7();
|
||||
LayoutList drawSega2p();
|
||||
LayoutList drawSega2p6b();
|
||||
LayoutList drawNoir8();
|
||||
LayoutList drawCapcom();
|
||||
LayoutList drawCapcom6();
|
||||
@@ -85,6 +88,7 @@ class LayoutManager {
|
||||
LayoutList drawBlankB();
|
||||
LayoutList drawVLXA();
|
||||
LayoutList drawVLXB();
|
||||
LayoutList drawVLXB6B();
|
||||
LayoutList drawFightboard();
|
||||
LayoutList drawFightboardMirrored();
|
||||
LayoutList drawFightboardStick();
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "config.pb.h"
|
||||
#include <atomic>
|
||||
#include "pico/critical_section.h"
|
||||
#include "eventmanager.h"
|
||||
#include "GPStorageSaveEvent.h"
|
||||
|
||||
#define SI Storage::getInstance()
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
#include <hardware/flash.h>
|
||||
#include <hardware/timer.h>
|
||||
|
||||
#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
|
||||
|
||||
@@ -252,6 +252,21 @@ message DisplayOptions
|
||||
|
||||
optional int32 displaySaverTimeout = 17;
|
||||
optional bool turnOffWhenSuspended = 18;
|
||||
optional DisplaySaverMode displaySaverMode = 19;
|
||||
|
||||
optional ButtonLayoutOrientation buttonLayoutOrientation = 20;
|
||||
|
||||
optional bool inputMode = 21;
|
||||
optional bool turboMode = 22;
|
||||
optional bool dpadMode = 23;
|
||||
optional bool socdMode = 24;
|
||||
optional bool macroMode = 25;
|
||||
optional bool profileMode = 26;
|
||||
|
||||
optional bool inputHistoryEnabled = 27;
|
||||
optional uint32 inputHistoryLength = 28;
|
||||
optional uint32 inputHistoryCol = 29;
|
||||
optional uint32 inputHistoryRow = 30;
|
||||
}
|
||||
|
||||
message LEDOptions
|
||||
@@ -751,10 +766,10 @@ message MacroOptions
|
||||
|
||||
message InputHistoryOptions
|
||||
{
|
||||
optional bool enabled = 1;
|
||||
optional uint32 length = 2;
|
||||
optional uint32 col = 3;
|
||||
optional uint32 row = 4;
|
||||
optional bool deprecatedEnabled = 1 [deprecated = true];
|
||||
optional uint32 deprecatedLength = 2 [deprecated = true];
|
||||
optional uint32 deprecatedCol = 3 [deprecated = true];
|
||||
optional uint32 deprecatedRow = 4 [deprecated = true];
|
||||
}
|
||||
|
||||
message RotaryPinOptions
|
||||
@@ -831,7 +846,7 @@ message AddonOptions
|
||||
optional TiltOptions tiltOptions = 18;
|
||||
optional PSPassthroughOptions psPassthroughOptions = 19 [deprecated = true];
|
||||
optional MacroOptions macroOptions = 20;
|
||||
optional InputHistoryOptions inputHistoryOptions = 21;
|
||||
optional InputHistoryOptions inputHistoryOptions = 21 [deprecated = true];
|
||||
optional XBOnePassthroughOptions xbonePassthroughOptions = 22 [deprecated = true];
|
||||
optional AnalogADS1256Options analogADS1256Options = 23;
|
||||
optional RotaryOptions rotaryOptions = 24;
|
||||
|
||||
@@ -84,6 +84,8 @@ enum ButtonLayoutRight
|
||||
BUTTON_LAYOUT_6GAWD_ALLBUTTON_B = 35;
|
||||
BUTTON_LAYOUT_6GAWD_ALLBUTTONPLUS_B = 36;
|
||||
BUTTON_LAYOUT_STICKLESS_R16B = 37;
|
||||
BUTTON_LAYOUT_VLXB_6B = 38;
|
||||
BUTTON_LAYOUT_SEGA2P_6B = 39;
|
||||
}
|
||||
|
||||
enum SplashMode
|
||||
@@ -262,7 +264,15 @@ enum GpioAction
|
||||
BUTTON_PRESS_INPUT_REVERSE = 69;
|
||||
SUSTAIN_FOCUS_MODE = 70;
|
||||
|
||||
SUSTAIN_4_8_WAY_MODE = 71;
|
||||
SUSTAIN_4_8_WAY_MODE = 71;
|
||||
|
||||
MENU_NAVIGATION_UP = 72;
|
||||
MENU_NAVIGATION_DOWN = 73;
|
||||
MENU_NAVIGATION_LEFT = 74;
|
||||
MENU_NAVIGATION_RIGHT = 75;
|
||||
MENU_NAVIGATION_SELECT = 76;
|
||||
MENU_NAVIGATION_BACK = 77;
|
||||
MENU_NAVIGATION_TOGGLE = 78;
|
||||
}
|
||||
|
||||
enum GpioDirection
|
||||
@@ -321,6 +331,13 @@ enum GamepadHotkey
|
||||
HOTKEY_DPAD_RIGHT = 41;
|
||||
HOTKEY_PREVIOUS_PROFILE = 42;
|
||||
HOTKEY_SAVE_CONFIG = 43;
|
||||
HOTKEY_MENU_NAV_UP = 44;
|
||||
HOTKEY_MENU_NAV_DOWN = 45;
|
||||
HOTKEY_MENU_NAV_LEFT = 46;
|
||||
HOTKEY_MENU_NAV_RIGHT = 47;
|
||||
HOTKEY_MENU_NAV_SELECT = 48;
|
||||
HOTKEY_MENU_NAV_BACK = 49;
|
||||
HOTKEY_MENU_NAV_TOGGLE = 50;
|
||||
}
|
||||
|
||||
// This has to be kept in sync with LEDFormat in NeoPico.hpp
|
||||
@@ -453,6 +470,26 @@ enum PS4ControllerIDMode
|
||||
PS4_ID_EMULATION = 1;
|
||||
};
|
||||
|
||||
enum DisplaySaverMode
|
||||
{
|
||||
option (nanopb_enumopt).long_names = false;
|
||||
|
||||
DISPLAY_SAVER_DISPLAY_OFF = 0;
|
||||
DISPLAY_SAVER_SNOW = 1;
|
||||
DISPLAY_SAVER_BOUNCE = 2;
|
||||
DISPLAY_SAVER_PIPES = 3;
|
||||
DISPLAY_SAVER_TOAST = 4;
|
||||
};
|
||||
|
||||
enum ButtonLayoutOrientation
|
||||
{
|
||||
option (nanopb_enumopt).long_names = false;
|
||||
|
||||
BUTTON_ORIENTATION_DEFAULT = 0;
|
||||
BUTTON_ORIENTATION_SOUTHPAW = 1;
|
||||
BUTTON_ORIENTATION_SWITCHED = 2;
|
||||
};
|
||||
|
||||
enum GPEventType
|
||||
{
|
||||
option (nanopb_enumopt).long_names = false;
|
||||
@@ -469,4 +506,7 @@ enum GPEventType
|
||||
GP_EVENT_BUTTON_PROCESSED_DOWN = 9;
|
||||
GP_EVENT_ANALOG_MOVE = 10;
|
||||
GP_EVENT_ANALOG_PROCESSED_MOVE = 11;
|
||||
};
|
||||
GP_EVENT_STORAGE_SAVE = 12;
|
||||
GP_EVENT_SYSTEM_REBOOT = 13;
|
||||
GP_EVENT_MENU_NAVIGATE = 14;
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ bool DisplayAddon::available() {
|
||||
if (options.enabled) {
|
||||
// create the gfx interface
|
||||
gpDisplay = new GPGFX();
|
||||
gpOptions = gpDisplay->getAvailableDisplay();
|
||||
gpOptions = gpDisplay->getAvailableDisplay(GPGFX_DisplayType::DISPLAY_TYPE_NONE);
|
||||
result = (gpOptions.displayType != GPGFX_DisplayType::DISPLAY_TYPE_NONE);
|
||||
if (!result) delete gpDisplay;
|
||||
}
|
||||
@@ -53,6 +53,16 @@ void DisplayAddon::setup() {
|
||||
displaySaverTimeout = displaySaverTimer;
|
||||
configMode = Storage::getInstance().GetConfigMode();
|
||||
turnOffWhenSuspended = options.turnOffWhenSuspended;
|
||||
displaySaverMode = options.displaySaverMode;
|
||||
|
||||
mapMenuToggle = new GamepadButtonMapping(0);
|
||||
GpioMappingInfo* pinMappings = Storage::getInstance().getProfilePinMappings();
|
||||
for (Pin_t pin = 0; pin < (Pin_t)NUM_BANK0_GPIOS; pin++) {
|
||||
switch (pinMappings[pin].action) {
|
||||
case GpioAction::MENU_NAVIGATION_TOGGLE: mapMenuToggle->pinMask |= 1 << pin; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// set current display mode
|
||||
if (!configMode) {
|
||||
@@ -68,6 +78,7 @@ void DisplayAddon::setup() {
|
||||
updateDisplayScreen();
|
||||
|
||||
EventManager::getInstance().registerEventHandler(GP_EVENT_RESTART, GPEVENT_CALLBACK(this->handleSystemRestart(event)));
|
||||
EventManager::getInstance().registerEventHandler(GP_EVENT_MENU_NAVIGATE, GPEVENT_CALLBACK(this->handleMenuNavigation(event)));
|
||||
}
|
||||
|
||||
bool DisplayAddon::updateDisplayScreen() {
|
||||
@@ -81,7 +92,7 @@ bool DisplayAddon::updateDisplayScreen() {
|
||||
delete (SplashScreen*)gpScreen;
|
||||
break;
|
||||
case MAIN_MENU:
|
||||
delete (SplashScreen*)gpScreen;
|
||||
delete (MainMenuScreen*)gpScreen;
|
||||
break;
|
||||
case BUTTONS:
|
||||
delete (ButtonLayoutScreen*)gpScreen;
|
||||
@@ -89,6 +100,9 @@ bool DisplayAddon::updateDisplayScreen() {
|
||||
case PIN_VIEWER:
|
||||
delete (PinViewerScreen*)gpScreen;
|
||||
break;
|
||||
case DISPLAY_SAVER:
|
||||
delete (DisplaySaverScreen*)gpScreen;
|
||||
break;
|
||||
case STATS:
|
||||
delete (StatsScreen*)gpScreen;
|
||||
break;
|
||||
@@ -116,6 +130,9 @@ bool DisplayAddon::updateDisplayScreen() {
|
||||
case PIN_VIEWER:
|
||||
gpScreen = new PinViewerScreen(gpDisplay);
|
||||
break;
|
||||
case DISPLAY_SAVER:
|
||||
gpScreen = new DisplaySaverScreen(gpDisplay);
|
||||
break;
|
||||
case STATS:
|
||||
gpScreen = new StatsScreen(gpDisplay);
|
||||
break;
|
||||
@@ -153,12 +170,19 @@ bool DisplayAddon::isDisplayPowerOff()
|
||||
displaySaverTimer = displaySaverTimeout;
|
||||
setDisplayPower(1);
|
||||
} else if (!!displaySaverTimeout && displaySaverTimer <= 0) {
|
||||
setDisplayPower(0);
|
||||
if (displaySaverMode == DisplaySaverMode::DISPLAY_SAVER_DISPLAY_OFF) {
|
||||
setDisplayPower(0);
|
||||
} else {
|
||||
if (currDisplayMode != DISPLAY_SAVER) {
|
||||
currDisplayMode = DISPLAY_SAVER;
|
||||
updateDisplayScreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prevMillis = getMillis();
|
||||
|
||||
return (!!displaySaverTimeout && displaySaverTimer <= 0);
|
||||
return ((!!displaySaverTimeout && displaySaverTimer <= 0) && (displaySaverMode == DisplaySaverMode::DISPLAY_SAVER_DISPLAY_OFF));
|
||||
}
|
||||
|
||||
void DisplayAddon::setDisplayPower(uint8_t status)
|
||||
@@ -179,6 +203,15 @@ void DisplayAddon::process() {
|
||||
int8_t screenReturn = gpScreen->update();
|
||||
gpScreen->draw();
|
||||
|
||||
if (!configMode && screenReturn < 0) {
|
||||
Mask_t values = Storage::getInstance().GetGamepad()->debouncedGpio;
|
||||
if (values & mapMenuToggle->pinMask) {
|
||||
if (currDisplayMode != DisplayMode::MAIN_MENU) {
|
||||
screenReturn = DisplayMode::MAIN_MENU;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -1 = we do not change state
|
||||
if (screenReturn >= 0) {
|
||||
// Screen wants to change to something else
|
||||
@@ -199,4 +232,20 @@ void DisplayAddon::handleSystemRestart(GPEvent* e) {
|
||||
currDisplayMode = DisplayMode::RESTART;
|
||||
bootMode = (uint32_t)((GPRestartEvent*)e)->bootMode;
|
||||
updateDisplayScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayAddon::handleMenuNavigation(GPEvent* e) {
|
||||
if (currDisplayMode != MAIN_MENU) {
|
||||
if (((GPMenuNavigateEvent*)e)->menuAction == GpioAction::MENU_NAVIGATION_TOGGLE) {
|
||||
currDisplayMode = MAIN_MENU;
|
||||
updateDisplayScreen();
|
||||
}
|
||||
} else {
|
||||
if (((GPMenuNavigateEvent*)e)->menuAction != GpioAction::MENU_NAVIGATION_TOGGLE) {
|
||||
((MainMenuScreen*)gpScreen)->updateMenuNavigation(((GPMenuNavigateEvent*)e)->menuAction);
|
||||
} else {
|
||||
currDisplayMode = BUTTONS;
|
||||
updateDisplayScreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ void FocusModeAddon::setup() {
|
||||
void FocusModeAddon::process() {
|
||||
Gamepad * gamepad = Storage::getInstance().GetGamepad();
|
||||
Mask_t values = Storage::getInstance().GetGamepad()->debouncedGpio;
|
||||
|
||||
if (!Storage::getInstance().getAddonOptions().focusModeOptions.enabled) return;
|
||||
|
||||
if (values & mapFocusMode->pinMask) {
|
||||
if (buttonLockMask & GAMEPAD_MASK_DU) {
|
||||
gamepad->state.dpad &= ~GAMEPAD_MASK_UP;
|
||||
|
||||
@@ -134,6 +134,8 @@ void TurboInput::process()
|
||||
uint16_t buttonsPressed = gamepad->state.buttons & TURBO_BUTTON_MASK;
|
||||
uint8_t dpadPressed = gamepad->state.dpad & GAMEPAD_MASK_DPAD;
|
||||
|
||||
if (!options.enabled) return;
|
||||
|
||||
// Check for TURBO pin enabled
|
||||
if (gamepad->debouncedGpio & turboPinMask) {
|
||||
if (buttonsPressed && (lastPressed != buttonsPressed)) {
|
||||
|
||||
@@ -413,6 +413,16 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config)
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, buttonLayout, BUTTON_LAYOUT);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, buttonLayoutRight, BUTTON_LAYOUT_RIGHT);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, turnOffWhenSuspended, DISPLAY_TURN_OFF_WHEN_SUSPENDED);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, inputMode, 1);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, turboMode, 1);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, dpadMode, 1);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, socdMode, 1);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, macroMode, 1);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, profileMode, 0);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, inputHistoryEnabled, !!INPUT_HISTORY_ENABLED);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, inputHistoryLength, INPUT_HISTORY_LENGTH);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, inputHistoryCol, INPUT_HISTORY_COL);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, inputHistoryRow, INPUT_HISTORY_ROW);
|
||||
|
||||
ButtonLayoutParamsLeft& paramsLeft = config.displayOptions.buttonLayoutCustomOptions.paramsLeft;
|
||||
INIT_UNSET_PROPERTY(paramsLeft, layout, BUTTON_LAYOUT);
|
||||
@@ -437,6 +447,8 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config)
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, flip, DISPLAY_FLIP);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, invert, !!DISPLAY_INVERT);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, displaySaverTimeout, DISPLAY_SAVER_TIMEOUT);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, displaySaverMode, DISPLAY_SAVER_MODE);
|
||||
INIT_UNSET_PROPERTY(config.displayOptions, buttonLayoutOrientation, DISPLAY_LAYOUT_ORIENTATION);
|
||||
|
||||
// peripheralOptions
|
||||
PeripheralOptions& peripheralOptions = config.peripheralOptions;
|
||||
@@ -679,12 +691,6 @@ void ConfigUtils::initUnsetPropertiesWithDefaults(Config& config)
|
||||
INIT_UNSET_PROPERTY(config.addonOptions.buzzerOptions, volume, BUZZER_VOLUME);
|
||||
INIT_UNSET_PROPERTY(config.addonOptions.buzzerOptions, enablePin, BUZZER_ENABLE_PIN);
|
||||
|
||||
// addonOptions.inputHistoryOptions
|
||||
INIT_UNSET_PROPERTY(config.addonOptions.inputHistoryOptions, enabled, !!INPUT_HISTORY_ENABLED);
|
||||
INIT_UNSET_PROPERTY(config.addonOptions.inputHistoryOptions, length, INPUT_HISTORY_LENGTH);
|
||||
INIT_UNSET_PROPERTY(config.addonOptions.inputHistoryOptions, col, INPUT_HISTORY_COL);
|
||||
INIT_UNSET_PROPERTY(config.addonOptions.inputHistoryOptions, row, INPUT_HISTORY_ROW);
|
||||
|
||||
// addonOptions.playerNumberOptions
|
||||
INIT_UNSET_PROPERTY(config.addonOptions.playerNumberOptions, enabled, !!PLAYERNUM_ADDON_ENABLED);
|
||||
INIT_UNSET_PROPERTY(config.addonOptions.playerNumberOptions, number, PLAYER_NUMBER);
|
||||
|
||||
@@ -450,7 +450,19 @@ std::string setDisplayOptions(DisplayOptions& displayOptions)
|
||||
readDoc(displayOptions.splashChoice, doc, "splashChoice");
|
||||
readDoc(displayOptions.splashDuration, doc, "splashDuration");
|
||||
readDoc(displayOptions.displaySaverTimeout, doc, "displaySaverTimeout");
|
||||
readDoc(displayOptions.displaySaverMode, doc, "displaySaverMode");
|
||||
readDoc(displayOptions.buttonLayoutOrientation, doc, "buttonLayoutOrientation");
|
||||
readDoc(displayOptions.turnOffWhenSuspended, doc, "turnOffWhenSuspended");
|
||||
readDoc(displayOptions.inputMode, doc, "inputMode");
|
||||
readDoc(displayOptions.turboMode, doc, "turboMode");
|
||||
readDoc(displayOptions.dpadMode, doc, "dpadMode");
|
||||
readDoc(displayOptions.socdMode, doc, "socdMode");
|
||||
readDoc(displayOptions.macroMode, doc, "macroMode");
|
||||
readDoc(displayOptions.profileMode, doc, "profileMode");
|
||||
readDoc(displayOptions.inputHistoryEnabled, doc, "inputHistoryEnabled");
|
||||
readDoc(displayOptions.inputHistoryLength, doc, "inputHistoryLength");
|
||||
readDoc(displayOptions.inputHistoryCol, doc, "inputHistoryCol");
|
||||
readDoc(displayOptions.inputHistoryRow, doc, "inputHistoryRow");
|
||||
|
||||
readDoc(displayOptions.buttonLayoutCustomOptions.paramsLeft.layout, doc, "buttonLayoutCustomOptions", "params", "layout");
|
||||
readDoc(displayOptions.buttonLayoutCustomOptions.paramsLeft.common.startX, doc, "buttonLayoutCustomOptions", "params", "startX");
|
||||
@@ -492,7 +504,19 @@ std::string getDisplayOptions() // Manually set Document Attributes for the disp
|
||||
writeDoc(doc, "splashChoice", displayOptions.splashChoice);
|
||||
writeDoc(doc, "splashDuration", displayOptions.splashDuration);
|
||||
writeDoc(doc, "displaySaverTimeout", displayOptions.displaySaverTimeout);
|
||||
writeDoc(doc, "displaySaverMode", displayOptions.displaySaverMode);
|
||||
writeDoc(doc, "buttonLayoutOrientation", displayOptions.buttonLayoutOrientation);
|
||||
writeDoc(doc, "turnOffWhenSuspended", displayOptions.turnOffWhenSuspended);
|
||||
writeDoc(doc, "inputMode", displayOptions.inputMode);
|
||||
writeDoc(doc, "turboMode", displayOptions.turboMode);
|
||||
writeDoc(doc, "dpadMode", displayOptions.dpadMode);
|
||||
writeDoc(doc, "socdMode", displayOptions.socdMode);
|
||||
writeDoc(doc, "macroMode", displayOptions.macroMode);
|
||||
writeDoc(doc, "profileMode", displayOptions.profileMode);
|
||||
writeDoc(doc, "inputHistoryEnabled", displayOptions.inputHistoryEnabled);
|
||||
writeDoc(doc, "inputHistoryLength", displayOptions.inputHistoryLength);
|
||||
writeDoc(doc, "inputHistoryCol", displayOptions.inputHistoryCol);
|
||||
writeDoc(doc, "inputHistoryRow", displayOptions.inputHistoryRow);
|
||||
|
||||
writeDoc(doc, "buttonLayoutCustomOptions", "params", "layout", displayOptions.buttonLayoutCustomOptions.paramsLeft.layout);
|
||||
writeDoc(doc, "buttonLayoutCustomOptions", "params", "startX", displayOptions.buttonLayoutCustomOptions.paramsLeft.common.startX);
|
||||
@@ -1589,12 +1613,6 @@ std::string setAddonOptions()
|
||||
docToPin(snesOptions.latchPin, doc, "snesPadLatchPin");
|
||||
docToPin(snesOptions.dataPin, doc, "snesPadDataPin");
|
||||
|
||||
InputHistoryOptions& inputHistoryOptions = Storage::getInstance().getAddonOptions().inputHistoryOptions;
|
||||
docToValue(inputHistoryOptions.length, doc, "inputHistoryLength");
|
||||
docToValue(inputHistoryOptions.enabled, doc, "InputHistoryAddonEnabled");
|
||||
docToValue(inputHistoryOptions.col, doc, "inputHistoryCol");
|
||||
docToValue(inputHistoryOptions.row, doc, "inputHistoryRow");
|
||||
|
||||
KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions;
|
||||
docToValue(keyboardHostOptions.enabled, doc, "KeyboardHostAddonEnabled");
|
||||
docToValue(keyboardHostOptions.mapping.keyDpadUp, doc, "keyboardHostMap", "Up");
|
||||
@@ -2005,12 +2023,6 @@ std::string getAddonOptions()
|
||||
writeDoc(doc, "snesPadDataPin", cleanPin(snesOptions.dataPin));
|
||||
writeDoc(doc, "SNESpadAddonEnabled", snesOptions.enabled);
|
||||
|
||||
const InputHistoryOptions& inputHistoryOptions = Storage::getInstance().getAddonOptions().inputHistoryOptions;
|
||||
writeDoc(doc, "inputHistoryLength", inputHistoryOptions.length);
|
||||
writeDoc(doc, "InputHistoryAddonEnabled", inputHistoryOptions.enabled);
|
||||
writeDoc(doc, "inputHistoryCol", inputHistoryOptions.col);
|
||||
writeDoc(doc, "inputHistoryRow", inputHistoryOptions.row);
|
||||
|
||||
const KeyboardHostOptions& keyboardHostOptions = Storage::getInstance().getAddonOptions().keyboardHostOptions;
|
||||
writeDoc(doc, "KeyboardHostAddonEnabled", keyboardHostOptions.enabled);
|
||||
writeDoc(doc, "keyboardHostMap", "Up", keyboardHostOptions.mapping.keyDpadUp);
|
||||
|
||||
@@ -24,7 +24,6 @@ GPGFX::GPGFX() {
|
||||
void GPGFX::init(GPGFX_DisplayTypeOptions options) {
|
||||
switch (options.displayType) {
|
||||
case GPGFX_DisplayType::DISPLAY_TYPE_SSD1306:
|
||||
//this->displayDriver = new GPGFX_OBD_SSD1306();
|
||||
this->displayDriver = new GPGFX_TinySSD1306();
|
||||
break;
|
||||
default:
|
||||
@@ -37,38 +36,53 @@ void GPGFX::init(GPGFX_DisplayTypeOptions options) {
|
||||
}
|
||||
}
|
||||
|
||||
GPGFX_DisplayTypeOptions GPGFX::getAvailableDisplay() {
|
||||
GPGFX_DisplayBase* driver = nullptr;
|
||||
GPGFX_DisplayTypeOptions GPGFX::getAvailableDisplay(GPGFX_DisplayType displayType) {
|
||||
GPGFX_DisplayTypeOptions display;
|
||||
|
||||
display.displayType = GPGFX_DisplayType::DISPLAY_TYPE_NONE;
|
||||
display.displayType = displayType;
|
||||
|
||||
for (uint16_t i = GPGFX_DisplayType::DISPLAY_TYPE_NONE; i < GPGFX_DisplayType::DISPLAY_TYPE_COUNT; i++) {
|
||||
if (i == GPGFX_DisplayType::DISPLAY_TYPE_SSD1306) {
|
||||
driver = new GPGFX_TinySSD1306();
|
||||
} else {
|
||||
driver = nullptr;
|
||||
if (display.displayType == GPGFX_DisplayType::DISPLAY_TYPE_NONE) {
|
||||
// autoscan for device
|
||||
for (uint16_t i = GPGFX_DisplayType::DISPLAY_TYPE_NONE; i < GPGFX_DisplayType::DISPLAY_TYPE_COUNT; i++) {
|
||||
if (detectDisplay(&display, (GPGFX_DisplayType)i)) break;
|
||||
}
|
||||
if ((driver != nullptr) && (display.displayType == GPGFX_DisplayType::DISPLAY_TYPE_NONE)) {
|
||||
if (driver->isI2C()) {
|
||||
PeripheralI2CScanResult result = PeripheralManager::getInstance().scanForI2CDevice(driver->getDeviceAddresses());
|
||||
if (result.address > -1) {
|
||||
display.displayType = (GPGFX_DisplayType)i;
|
||||
display.address = result.address;
|
||||
display.i2c = PeripheralManager::getInstance().getI2C(result.block);
|
||||
display.i2c->setExclusiveUse(result.address);
|
||||
return display;
|
||||
}
|
||||
}
|
||||
if (driver->isSPI()) {
|
||||
// NYI: check if SPI display exists
|
||||
}
|
||||
delete driver;
|
||||
} else {
|
||||
if (!detectDisplay(&display, display.displayType)) {
|
||||
display.displayType = GPGFX_DisplayType::DISPLAY_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
return display;
|
||||
}
|
||||
|
||||
bool GPGFX::detectDisplay(GPGFX_DisplayTypeOptions* display, GPGFX_DisplayType displayType) {
|
||||
GPGFX_DisplayBase* driver = nullptr;
|
||||
|
||||
if (displayType == GPGFX_DisplayType::DISPLAY_TYPE_SSD1306) {
|
||||
driver = new GPGFX_TinySSD1306();
|
||||
} else {
|
||||
driver = nullptr;
|
||||
}
|
||||
|
||||
if (driver != nullptr) {
|
||||
if (driver->isI2C()) {
|
||||
PeripheralI2CScanResult result = PeripheralManager::getInstance().scanForI2CDevice(driver->getDeviceAddresses());
|
||||
if (result.address > -1) {
|
||||
display->displayType = displayType;
|
||||
display->address = result.address;
|
||||
display->i2c = PeripheralManager::getInstance().getI2C(result.block);
|
||||
display->i2c->setExclusiveUse(result.address);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (driver->isSPI()) {
|
||||
// NYI: check if SPI display exists
|
||||
}
|
||||
delete driver;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GPGFX::clearScreen() {
|
||||
this->displayDriver->clear();
|
||||
}
|
||||
@@ -77,6 +91,10 @@ void GPGFX::render() {
|
||||
this->displayDriver->drawBuffer(NULL);
|
||||
}
|
||||
|
||||
uint32_t GPGFX::getPixel(uint16_t x, uint16_t y) {
|
||||
return this->displayDriver->getPixel(x, y);
|
||||
}
|
||||
|
||||
void GPGFX::drawPixel(uint16_t x, uint16_t y, uint32_t color) {
|
||||
this->displayDriver->drawPixel(x, y, color);
|
||||
}
|
||||
@@ -105,6 +123,6 @@ void GPGFX::drawPolygon(uint16_t x, uint16_t y, uint16_t radius, uint16_t sides,
|
||||
this->displayDriver->drawPolygon(x, y, radius, sides, color, filled, rotation);
|
||||
}
|
||||
|
||||
void GPGFX::drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority) {
|
||||
this->displayDriver->drawSprite(spriteData, width, height, pitch, x, y, priority);
|
||||
void GPGFX::drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority, double scale) {
|
||||
this->displayDriver->drawSprite(spriteData, width, height, pitch, x, y, priority, scale);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,6 @@ void GPButton::draw() {
|
||||
|
||||
if (useMask && mapMask != NULL) {
|
||||
maskedPins = (pinValues & mapMask->pinMask);
|
||||
|
||||
for (Pin_t pin = 0; pin < (Pin_t)NUM_BANK0_GPIOS; pin++) {
|
||||
if ((maskedPins & (1 << pin)) == (1 << pin)) {
|
||||
setPin = pin;
|
||||
|
||||
@@ -43,13 +43,13 @@ void GPLever::draw() {
|
||||
bool leftState = (this->_leftMask > -1 ? getProcessedGamepad()->pressedButton((uint16_t)this->_leftMask) : getProcessedGamepad()->pressedLeft());
|
||||
bool downState = (this->_downMask > -1 ? getProcessedGamepad()->pressedButton((uint16_t)this->_downMask) : getProcessedGamepad()->pressedDown());
|
||||
bool rightState = (this->_rightMask > -1 ? getProcessedGamepad()->pressedButton((uint16_t)this->_rightMask) : getProcessedGamepad()->pressedRight());
|
||||
if (upState != downState) {
|
||||
leverY -= upState ? leverRadius : -leverRadius;
|
||||
if (upState != downState) {
|
||||
leverY -= upState ? leverRadius : -leverRadius;
|
||||
}
|
||||
if (leftState != rightState) {
|
||||
leverX -= leftState ? leverRadius : -leverRadius;
|
||||
}
|
||||
} else {
|
||||
if (leftState != rightState) {
|
||||
leverX -= leftState ? leverRadius : -leverRadius;
|
||||
}
|
||||
} else {
|
||||
// analog
|
||||
uint16_t analogX = map((this->_inputType == DPAD_MODE_LEFT_ANALOG ? getProcessedGamepad()->state.lx : getProcessedGamepad()->state.rx), 0, 0xFFFF, 0, 100);
|
||||
uint16_t analogY = map((this->_inputType == DPAD_MODE_LEFT_ANALOG ? getProcessedGamepad()->state.ly : getProcessedGamepad()->state.ry), 0, 0xFFFF, 0, 100);
|
||||
|
||||
45
src/display/ui/elements/GPMenu.cpp
Normal file
45
src/display/ui/elements/GPMenu.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "GPMenu.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
void GPMenu::draw() {
|
||||
if (this->getVisibility()) {
|
||||
uint16_t baseX = this->x;
|
||||
uint16_t baseY = this->y;
|
||||
|
||||
uint16_t menuWidth = this->menuSizeX * 6;
|
||||
uint16_t menuHeight = this->menuSizeY * 8;
|
||||
|
||||
uint16_t dataSize = this->getDataSize();
|
||||
uint16_t totalPages = (dataSize + this->menuSizeY - 1) / this->menuSizeY;
|
||||
uint16_t itemPage = (this->menuIndex / this->menuSizeY);
|
||||
|
||||
int16_t currPageItems = (dataSize - (itemPage * this->menuSizeY));
|
||||
if (currPageItems > this->menuSizeY) {
|
||||
currPageItems = this->menuSizeY;
|
||||
} else if (currPageItems <= 0) {
|
||||
currPageItems = 0;
|
||||
}
|
||||
|
||||
getRenderer()->drawText((21-this->menuTitle.length()) / 2, 0, this->menuTitle.c_str());
|
||||
|
||||
std::string pageDisplay = "";
|
||||
pageDisplay += "Page: " + std::to_string(itemPage+1) + "/" + std::to_string(totalPages);
|
||||
getRenderer()->drawText(11, 7, pageDisplay.c_str());
|
||||
|
||||
if (this->menuEntryData->size() > 0) {
|
||||
for (uint8_t menuLine = 0; menuLine < currPageItems; menuLine++) {
|
||||
uint8_t pageLine = (this->menuSizeY * itemPage) + menuLine;
|
||||
int32_t lineValue = this->menuEntryData->at(pageLine).optionValue;
|
||||
bool showCurrentOption = false;
|
||||
if (lineValue != -1) {
|
||||
showCurrentOption = (this->menuEntryData->at(pageLine).currentValue() == this->menuEntryData->at(pageLine).optionValue);
|
||||
}
|
||||
getRenderer()->drawText(2, 2+menuLine, this->menuEntryData->at(pageLine).label + (showCurrentOption ? " *" : ""));
|
||||
}
|
||||
}
|
||||
|
||||
// draw cursor
|
||||
getRenderer()->drawText(1, 2+(this->menuIndex % this->menuSizeY), CHAR_RIGHT);
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,10 @@
|
||||
#include "drivers/xinput/XInputDriver.h"
|
||||
|
||||
void ButtonLayoutScreen::init() {
|
||||
const InputHistoryOptions& inputHistoryOptions = Storage::getInstance().getAddonOptions().inputHistoryOptions;
|
||||
isInputHistoryEnabled = inputHistoryOptions.enabled;
|
||||
inputHistoryX = inputHistoryOptions.row;
|
||||
inputHistoryY = inputHistoryOptions.col;
|
||||
inputHistoryLength = inputHistoryOptions.length;
|
||||
isInputHistoryEnabled = Storage::getInstance().getDisplayOptions().inputHistoryEnabled;
|
||||
inputHistoryX = Storage::getInstance().getDisplayOptions().inputHistoryRow;
|
||||
inputHistoryY = Storage::getInstance().getDisplayOptions().inputHistoryCol;
|
||||
inputHistoryLength = Storage::getInstance().getDisplayOptions().inputHistoryLength;
|
||||
bannerDelayStart = getMillis();
|
||||
gamepad = Storage::getInstance().GetGamepad();
|
||||
inputMode = DriverManager::getInstance().getInputMode();
|
||||
@@ -44,6 +43,7 @@ void ButtonLayoutScreen::init() {
|
||||
prevLayoutRight = Storage::getInstance().getDisplayOptions().buttonLayoutRight;
|
||||
prevLeftOptions = Storage::getInstance().getDisplayOptions().buttonLayoutCustomOptions.paramsLeft;
|
||||
prevRightOptions = Storage::getInstance().getDisplayOptions().buttonLayoutCustomOptions.paramsRight;
|
||||
prevOrientation = Storage::getInstance().getDisplayOptions().buttonLayoutOrientation;
|
||||
|
||||
// we cannot look at macro options enabled, pull the pins
|
||||
|
||||
@@ -68,6 +68,14 @@ void ButtonLayoutScreen::init() {
|
||||
}
|
||||
}
|
||||
|
||||
// determine which fields will be displayed on the status bar
|
||||
showInputMode = Storage::getInstance().getDisplayOptions().inputMode;
|
||||
showTurboMode = Storage::getInstance().getDisplayOptions().turboMode;
|
||||
showDpadMode = Storage::getInstance().getDisplayOptions().dpadMode;
|
||||
showSocdMode = Storage::getInstance().getDisplayOptions().socdMode;
|
||||
showMacroMode = Storage::getInstance().getDisplayOptions().macroMode;
|
||||
showProfileMode = Storage::getInstance().getDisplayOptions().profileMode;
|
||||
|
||||
getRenderer()->clearScreen();
|
||||
}
|
||||
|
||||
@@ -83,8 +91,9 @@ int8_t ButtonLayoutScreen::update() {
|
||||
if (configMode) {
|
||||
uint8_t layoutLeft = Storage::getInstance().getDisplayOptions().buttonLayout;
|
||||
uint8_t layoutRight = Storage::getInstance().getDisplayOptions().buttonLayoutRight;
|
||||
bool inputHistoryEnabled = Storage::getInstance().getAddonOptions().inputHistoryOptions.enabled;
|
||||
if ((prevLayoutLeft != layoutLeft) || (prevLayoutRight != layoutRight) || (isInputHistoryEnabled != inputHistoryEnabled) || compareCustomLayouts()) {
|
||||
uint8_t buttonLayoutOrientation = Storage::getInstance().getDisplayOptions().buttonLayoutOrientation;
|
||||
bool inputHistoryEnabled = Storage::getInstance().getDisplayOptions().inputHistoryEnabled;
|
||||
if ((prevLayoutLeft != layoutLeft) || (prevLayoutRight != layoutRight) || (isInputHistoryEnabled != inputHistoryEnabled) || compareCustomLayouts() || (prevOrientation != buttonLayoutOrientation)) {
|
||||
shutdown();
|
||||
init();
|
||||
}
|
||||
@@ -143,80 +152,102 @@ void ButtonLayoutScreen::generateHeader() {
|
||||
}
|
||||
}
|
||||
|
||||
// Display standard header
|
||||
switch (inputMode)
|
||||
{
|
||||
case INPUT_MODE_PS3: statusBar += "PS3"; break;
|
||||
case INPUT_MODE_GENERIC: statusBar += "USBHID"; break;
|
||||
case INPUT_MODE_SWITCH: statusBar += "SWITCH"; break;
|
||||
case INPUT_MODE_MDMINI: statusBar += "GEN/MD"; break;
|
||||
case INPUT_MODE_NEOGEO: statusBar += "NGMINI"; break;
|
||||
case INPUT_MODE_PCEMINI: statusBar += "PCE/TG"; break;
|
||||
case INPUT_MODE_EGRET: statusBar += "EGRET"; break;
|
||||
case INPUT_MODE_ASTRO: statusBar += "ASTRO"; break;
|
||||
case INPUT_MODE_PSCLASSIC: statusBar += "PSC"; break;
|
||||
case INPUT_MODE_XBOXORIGINAL: statusBar += "OGXBOX"; break;
|
||||
case INPUT_MODE_PS4:
|
||||
statusBar += "PS4";
|
||||
if(((PS4Driver*)DriverManager::getInstance().getDriver())->getAuthSent() == true )
|
||||
statusBar += ":AS";
|
||||
else
|
||||
statusBar += " ";
|
||||
break;
|
||||
case INPUT_MODE_PS5:
|
||||
statusBar += "PS5";
|
||||
if(((PS4Driver*)DriverManager::getInstance().getDriver())->getAuthSent() == true )
|
||||
statusBar += ":AS";
|
||||
else
|
||||
statusBar += " ";
|
||||
break;
|
||||
case INPUT_MODE_XBONE:
|
||||
statusBar += "XBON";
|
||||
if(((XBOneDriver*)DriverManager::getInstance().getDriver())->getAuthSent() == true )
|
||||
statusBar += "E";
|
||||
else
|
||||
statusBar += "*";
|
||||
break;
|
||||
case INPUT_MODE_XINPUT:
|
||||
statusBar += "X";
|
||||
if(((XInputDriver*)DriverManager::getInstance().getDriver())->getAuthEnabled() == true )
|
||||
statusBar += "B360";
|
||||
else
|
||||
statusBar += "INPUT";
|
||||
break;
|
||||
case INPUT_MODE_KEYBOARD: statusBar += "HID-KB"; break;
|
||||
case INPUT_MODE_CONFIG: statusBar += "CONFIG"; break;
|
||||
}
|
||||
if (showInputMode) {
|
||||
// Display standard header
|
||||
switch (inputMode)
|
||||
{
|
||||
case INPUT_MODE_PS3: statusBar += "PS3"; break;
|
||||
case INPUT_MODE_GENERIC: statusBar += "USBHID"; break;
|
||||
case INPUT_MODE_SWITCH: statusBar += "SWITCH"; break;
|
||||
case INPUT_MODE_MDMINI: statusBar += "GEN/MD"; break;
|
||||
case INPUT_MODE_NEOGEO: statusBar += "NGMINI"; break;
|
||||
case INPUT_MODE_PCEMINI: statusBar += "PCE/TG"; break;
|
||||
case INPUT_MODE_EGRET: statusBar += "EGRET"; break;
|
||||
case INPUT_MODE_ASTRO: statusBar += "ASTRO"; break;
|
||||
case INPUT_MODE_PSCLASSIC: statusBar += "PSC"; break;
|
||||
case INPUT_MODE_XBOXORIGINAL: statusBar += "OGXBOX"; break;
|
||||
case INPUT_MODE_PS4:
|
||||
statusBar += "PS4";
|
||||
if(((PS4Driver*)DriverManager::getInstance().getDriver())->getAuthSent() == true )
|
||||
statusBar += ":AS";
|
||||
else
|
||||
statusBar += " ";
|
||||
break;
|
||||
case INPUT_MODE_PS5:
|
||||
statusBar += "PS5";
|
||||
if(((PS4Driver*)DriverManager::getInstance().getDriver())->getAuthSent() == true )
|
||||
statusBar += ":AS";
|
||||
else
|
||||
statusBar += " ";
|
||||
break;
|
||||
case INPUT_MODE_XBONE:
|
||||
statusBar += "XBON";
|
||||
if(((XBOneDriver*)DriverManager::getInstance().getDriver())->getAuthSent() == true )
|
||||
statusBar += "E";
|
||||
else
|
||||
statusBar += "*";
|
||||
break;
|
||||
case INPUT_MODE_XINPUT:
|
||||
statusBar += "X";
|
||||
if(((XInputDriver*)DriverManager::getInstance().getDriver())->getAuthEnabled() == true )
|
||||
statusBar += "B360";
|
||||
else
|
||||
statusBar += "INPUT";
|
||||
break;
|
||||
case INPUT_MODE_KEYBOARD: statusBar += "HID-KB"; break;
|
||||
case INPUT_MODE_CONFIG: statusBar += "CONFIG"; break;
|
||||
}
|
||||
}
|
||||
|
||||
const TurboOptions& turboOptions = storage.getAddonOptions().turboOptions;
|
||||
if ( turboOptions.enabled ) {
|
||||
statusBar += " T";
|
||||
if ( turboOptions.shotCount < 10 ) // padding
|
||||
statusBar += "0";
|
||||
statusBar += std::to_string(turboOptions.shotCount);
|
||||
} else {
|
||||
statusBar += " "; // no turbo, don't show Txx setting
|
||||
}
|
||||
if (showTurboMode) {
|
||||
const TurboOptions& turboOptions = storage.getAddonOptions().turboOptions;
|
||||
if ( turboOptions.enabled ) {
|
||||
statusBar += " T";
|
||||
if ( turboOptions.shotCount < 10 ) // padding
|
||||
statusBar += "0";
|
||||
statusBar += std::to_string(turboOptions.shotCount);
|
||||
} else {
|
||||
statusBar += " "; // no turbo, don't show Txx setting
|
||||
}
|
||||
}
|
||||
|
||||
const GamepadOptions & options = gamepad->getOptions();
|
||||
|
||||
switch (gamepad->getActiveDpadMode())
|
||||
{
|
||||
case DPAD_MODE_DIGITAL: statusBar += " D"; break;
|
||||
case DPAD_MODE_LEFT_ANALOG: statusBar += " L"; break;
|
||||
case DPAD_MODE_RIGHT_ANALOG: statusBar += " R"; break;
|
||||
}
|
||||
if (showDpadMode) {
|
||||
switch (gamepad->getActiveDpadMode())
|
||||
{
|
||||
case DPAD_MODE_DIGITAL: statusBar += " D"; break;
|
||||
case DPAD_MODE_LEFT_ANALOG: statusBar += " L"; break;
|
||||
case DPAD_MODE_RIGHT_ANALOG: statusBar += " R"; break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Gamepad::resolveSOCDMode(gamepad->getOptions()))
|
||||
{
|
||||
case SOCD_MODE_NEUTRAL: statusBar += " SOCD-N"; break;
|
||||
case SOCD_MODE_UP_PRIORITY: statusBar += " SOCD-U"; break;
|
||||
case SOCD_MODE_SECOND_INPUT_PRIORITY: statusBar += " SOCD-L"; break;
|
||||
case SOCD_MODE_FIRST_INPUT_PRIORITY: statusBar += " SOCD-F"; break;
|
||||
case SOCD_MODE_BYPASS: statusBar += " SOCD-X"; break;
|
||||
}
|
||||
if (macroEnabled)
|
||||
statusBar += " M";
|
||||
if (showSocdMode) {
|
||||
switch (Gamepad::resolveSOCDMode(gamepad->getOptions()))
|
||||
{
|
||||
case SOCD_MODE_NEUTRAL: statusBar += " SOCD-N"; break;
|
||||
case SOCD_MODE_UP_PRIORITY: statusBar += " SOCD-U"; break;
|
||||
case SOCD_MODE_SECOND_INPUT_PRIORITY: statusBar += " SOCD-L"; break;
|
||||
case SOCD_MODE_FIRST_INPUT_PRIORITY: statusBar += " SOCD-F"; break;
|
||||
case SOCD_MODE_BYPASS: statusBar += " SOCD-X"; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (showMacroMode && macroEnabled) statusBar += " M";
|
||||
|
||||
if (showProfileMode) {
|
||||
statusBar += " Pr:";
|
||||
|
||||
std::string profile;
|
||||
profile.assign(storage.currentProfileLabel(), strlen(storage.currentProfileLabel()));
|
||||
if (profile.empty()) {
|
||||
statusBar += std::to_string(getGamepad()->getOptions().profileNumber);
|
||||
} else {
|
||||
statusBar += profile;
|
||||
}
|
||||
}
|
||||
|
||||
trim(statusBar);
|
||||
}
|
||||
|
||||
void ButtonLayoutScreen::drawScreen() {
|
||||
@@ -514,3 +545,8 @@ void ButtonLayoutScreen::handleUSB(GPEvent* e) {
|
||||
}
|
||||
bannerDisplay = true;
|
||||
}
|
||||
|
||||
void ButtonLayoutScreen::trim(std::string &s) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
|
||||
std::not1(std::ptr_fun<int, int>(std::isspace))));
|
||||
}
|
||||
197
src/display/ui/screens/DisplaySaverScreen.cpp
Normal file
197
src/display/ui/screens/DisplaySaverScreen.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
#include "DisplaySaverScreen.h"
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "version.h"
|
||||
|
||||
void DisplaySaverScreen::init() {
|
||||
const DisplayOptions& options = Storage::getInstance().getDisplayOptions();
|
||||
displaySaverMode = options.displaySaverMode;
|
||||
|
||||
getRenderer()->clearScreen();
|
||||
|
||||
switch (displaySaverMode) {
|
||||
case DisplaySaverMode::DISPLAY_SAVER_SNOW:
|
||||
initSnowScene();
|
||||
break;
|
||||
case DisplaySaverMode::DISPLAY_SAVER_BOUNCE:
|
||||
break;
|
||||
case DisplaySaverMode::DISPLAY_SAVER_PIPES:
|
||||
break;
|
||||
case DisplaySaverMode::DISPLAY_SAVER_TOAST:
|
||||
initToasters();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySaverScreen::shutdown() {
|
||||
clearElements();
|
||||
}
|
||||
|
||||
void DisplaySaverScreen::drawScreen() {
|
||||
switch (displaySaverMode) {
|
||||
case DisplaySaverMode::DISPLAY_SAVER_SNOW:
|
||||
drawSnowScene();
|
||||
break;
|
||||
case DisplaySaverMode::DISPLAY_SAVER_BOUNCE:
|
||||
drawBounceScene();
|
||||
break;
|
||||
case DisplaySaverMode::DISPLAY_SAVER_PIPES:
|
||||
drawPipeScene();
|
||||
break;
|
||||
case DisplaySaverMode::DISPLAY_SAVER_TOAST:
|
||||
drawToasterScene();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t DisplaySaverScreen::update() {
|
||||
if (!Storage::getInstance().GetConfigMode()) {
|
||||
uint16_t buttonState = getGamepad()->state.buttons;
|
||||
if (prevButtonState && !buttonState) {
|
||||
if (prevButtonState != 0) {
|
||||
prevButtonState = 0;
|
||||
return DisplayMode::BUTTONS;
|
||||
}
|
||||
}
|
||||
prevButtonState = buttonState;
|
||||
}
|
||||
|
||||
return -1; // -1 means no change in screen state
|
||||
}
|
||||
|
||||
void DisplaySaverScreen::initSnowScene() {
|
||||
for (uint8_t x = 0; x < SCREEN_WIDTH; ++x) {
|
||||
for (uint8_t y = 0; y < SCREEN_HEIGHT; ++y) {
|
||||
snowflakeSpeeds[x][y] = 0;
|
||||
snowflakeDrift[x][y] = 0;
|
||||
getRenderer()->drawPixel(x, y, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySaverScreen::drawSnowScene() {
|
||||
for (int8_t y = SCREEN_HEIGHT - 1; y >= 0; --y) {
|
||||
for (uint8_t x = 0; x < SCREEN_WIDTH; ++x) {
|
||||
if (snowflakeSpeeds[x][y] > 0) {
|
||||
uint8_t speed = snowflakeSpeeds[x][y];
|
||||
uint8_t newY = y + speed;
|
||||
int8_t drift = snowflakeDrift[x][y];
|
||||
int8_t newX = x + drift;
|
||||
|
||||
if (newX < 0) newX = 0;
|
||||
if (newX >= SCREEN_WIDTH) newX = SCREEN_WIDTH - 1;
|
||||
|
||||
if (newY >= SCREEN_HEIGHT) {
|
||||
getRenderer()->drawPixel(x, y, 0);
|
||||
snowflakeSpeeds[x][y] = 0;
|
||||
snowflakeDrift[x][y] = 0;
|
||||
} else {
|
||||
getRenderer()->drawPixel(x, y, 0);
|
||||
getRenderer()->drawPixel(newX, newY, 1);
|
||||
snowflakeSpeeds[newX][newY] = speed;
|
||||
snowflakeDrift[newX][newY] = drift;
|
||||
snowflakeSpeeds[x][y] = 0;
|
||||
snowflakeDrift[x][y] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t x = 0; x < SCREEN_WIDTH; ++x) {
|
||||
if (rand() % 10 == 0) {
|
||||
getRenderer()->drawPixel(x, 0, 1);
|
||||
snowflakeSpeeds[x][0] = (rand() % 3) + 1;
|
||||
snowflakeDrift[x][0] = (rand() % 3) - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySaverScreen::drawBounceScene() {
|
||||
uint16_t scaledWidth = static_cast<uint16_t>(bounceSpriteWidth * bounceScale);
|
||||
uint16_t scaledHeight = static_cast<uint16_t>(bounceSpriteHeight * bounceScale);
|
||||
|
||||
bounceSpriteX += bounceSpriteVelocityX;
|
||||
bounceSpriteY += bounceSpriteVelocityY;
|
||||
|
||||
if (bounceSpriteX <= 0 || bounceSpriteX + scaledWidth >= SCREEN_WIDTH) bounceSpriteVelocityX = -bounceSpriteVelocityX;
|
||||
|
||||
if (bounceSpriteY <= 0 || bounceSpriteY + scaledHeight >= SCREEN_HEIGHT) bounceSpriteVelocityY = -bounceSpriteVelocityY;
|
||||
|
||||
getRenderer()->drawSprite((uint8_t *)bootLogoBottom, bounceSpriteWidth, bounceSpriteHeight, 0, bounceSpriteX, bounceSpriteY, 0, bounceScale);
|
||||
}
|
||||
|
||||
void DisplaySaverScreen::drawPipeScene() {
|
||||
const uint8_t PIPE_WIDTH = 4;
|
||||
const uint8_t PIPE_COLOR = 1;
|
||||
|
||||
uint8_t currentX = 0;
|
||||
uint8_t currentY = 0;
|
||||
|
||||
while (currentY < SCREEN_HEIGHT) {
|
||||
bool connectRight = rand() % 2;
|
||||
bool connectDown = rand() % 2;
|
||||
|
||||
if (connectRight && currentX + PIPE_WIDTH < SCREEN_WIDTH) {
|
||||
for (uint8_t i = 0; i < PIPE_WIDTH; ++i) {
|
||||
getRenderer()->drawPixel(currentX + i, currentY, PIPE_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
if (connectDown && currentY + PIPE_WIDTH < SCREEN_HEIGHT) {
|
||||
for (uint8_t i = 0; i < PIPE_WIDTH; ++i) {
|
||||
getRenderer()->drawPixel(currentX, currentY + i, PIPE_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
getRenderer()->drawPixel(currentX, currentY, PIPE_COLOR);
|
||||
|
||||
currentX += PIPE_WIDTH;
|
||||
if (currentX >= SCREEN_WIDTH) {
|
||||
currentX = 0;
|
||||
currentY += PIPE_WIDTH;
|
||||
}
|
||||
|
||||
for (volatile uint32_t delay = 0; delay < 10000; ++delay) {
|
||||
// Do nothing, just burn some CPU cycles
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySaverScreen::initToasters() {
|
||||
for (uint16_t i = 0; i < numberOfToasters; ++i) {
|
||||
double scale = (static_cast<double>(rand()) / RAND_MAX);
|
||||
int16_t dx = (-1 - rand() % 3);
|
||||
int16_t dy = (1 + rand() % 3);
|
||||
|
||||
toasters.push_back({
|
||||
(uint8_t *)bootLogoTop,
|
||||
toasterSpriteWidth,
|
||||
toasterSpriteHeight,
|
||||
scale,
|
||||
static_cast<int16_t>(SCREEN_WIDTH - toasterSpriteWidth * scale),
|
||||
static_cast<int16_t>(rand() % (SCREEN_HEIGHT - static_cast<int16_t>(toasterSpriteHeight * scale))),
|
||||
static_cast<int16_t>(dx),
|
||||
static_cast<int16_t>(dy)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySaverScreen::drawToasterScene() {
|
||||
for (uint16_t i = 0; i < toasters.size(); ++i) {
|
||||
ToastParams& sprite = toasters[i];
|
||||
|
||||
getRenderer()->drawSprite(sprite.image, sprite.width, sprite.height, 0, sprite.x, sprite.y, 0, sprite.scale);
|
||||
|
||||
sprite.x += sprite.dx;
|
||||
sprite.y += sprite.dy;
|
||||
|
||||
if (sprite.x + sprite.width * sprite.scale < 0) {
|
||||
sprite.x = SCREEN_WIDTH;
|
||||
sprite.y = rand() % (SCREEN_HEIGHT - static_cast<int16_t>(sprite.height * sprite.scale));
|
||||
}
|
||||
|
||||
if (sprite.y > SCREEN_HEIGHT) {
|
||||
sprite.y = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +1,114 @@
|
||||
#include "MainMenuScreen.h"
|
||||
#include "hardware/watchdog.h"
|
||||
#include "system.h"
|
||||
|
||||
extern uint32_t getMillis();
|
||||
|
||||
void MainMenuScreen::init() {
|
||||
getRenderer()->clearScreen();
|
||||
currentMenu = &mainMenu;
|
||||
previousMenu = nullptr;
|
||||
|
||||
exitToScreen = -1;
|
||||
|
||||
gpMenu = new GPMenu();
|
||||
gpMenu->setRenderer(getRenderer());
|
||||
gpMenu->setPosition(8, 16);
|
||||
gpMenu->setStrokeColor(1);
|
||||
gpMenu->setFillColor(1);
|
||||
gpMenu->setMenuSize(18, 4);
|
||||
gpMenu->setViewport(this->getViewport());
|
||||
gpMenu->setShape(GPShape_Type::GP_SHAPE_SQUARE);
|
||||
gpMenu->setMenuData(currentMenu);
|
||||
gpMenu->setMenuTitle(MAIN_MENU_NAME);
|
||||
addElement(gpMenu);
|
||||
|
||||
mapMenuUp = new GamepadButtonMapping(0);
|
||||
mapMenuDown = new GamepadButtonMapping(0);
|
||||
mapMenuLeft = new GamepadButtonMapping(0);
|
||||
mapMenuRight = new GamepadButtonMapping(0);
|
||||
mapMenuSelect = new GamepadButtonMapping(0);
|
||||
mapMenuBack = new GamepadButtonMapping(0);
|
||||
mapMenuToggle = new GamepadButtonMapping(0);
|
||||
|
||||
// populate the profiles menu
|
||||
uint8_t profileCount = (sizeof(Storage::getInstance().getProfileOptions().gpioMappingsSets)/sizeof(GpioMappings))+1;
|
||||
for (uint8_t profileCtr = 0; profileCtr < profileCount; profileCtr++) {
|
||||
std::string menuLabel = "";
|
||||
if (profileCtr == 0) {
|
||||
menuLabel = Storage::getInstance().getGpioMappings().profileLabel;
|
||||
} else {
|
||||
menuLabel = Storage::getInstance().getProfileOptions().gpioMappingsSets[profileCtr-1].profileLabel;
|
||||
}
|
||||
if (menuLabel.empty()) {
|
||||
menuLabel = "Profile #" + std::to_string(profileCtr);
|
||||
}
|
||||
MenuEntry menuEntry = {menuLabel, NULL, nullptr, std::bind(&MainMenuScreen::currentProfile, this), std::bind(&MainMenuScreen::selectProfile, this), profileCtr+1};
|
||||
profilesMenu.push_back(menuEntry);
|
||||
}
|
||||
|
||||
GpioMappingInfo* pinMappings = Storage::getInstance().getProfilePinMappings();
|
||||
for (Pin_t pin = 0; pin < (Pin_t)NUM_BANK0_GPIOS; pin++) {
|
||||
switch (pinMappings[pin].action) {
|
||||
case GpioAction::MENU_NAVIGATION_UP: mapMenuUp->pinMask |= 1 << pin; break;
|
||||
case GpioAction::MENU_NAVIGATION_DOWN: mapMenuDown->pinMask |= 1 << pin; break;
|
||||
case GpioAction::MENU_NAVIGATION_LEFT: mapMenuLeft->pinMask |= 1 << pin; break;
|
||||
case GpioAction::MENU_NAVIGATION_RIGHT: mapMenuRight->pinMask |= 1 << pin; break;
|
||||
case GpioAction::MENU_NAVIGATION_SELECT: mapMenuSelect->pinMask |= 1 << pin; break;
|
||||
case GpioAction::MENU_NAVIGATION_BACK: mapMenuBack->pinMask |= 1 << pin; break;
|
||||
case GpioAction::MENU_NAVIGATION_TOGGLE: mapMenuToggle->pinMask |= 1 << pin; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
changeRequiresReboot = false;
|
||||
changeRequiresSave = false;
|
||||
prevInputMode = Storage::getInstance().GetGamepad()->getOptions().inputMode;
|
||||
updateInputMode = Storage::getInstance().GetGamepad()->getOptions().inputMode;
|
||||
|
||||
prevDpadMode = Storage::getInstance().GetGamepad()->getOptions().dpadMode;
|
||||
updateDpadMode = Storage::getInstance().GetGamepad()->getOptions().dpadMode;
|
||||
|
||||
prevSocdMode = Storage::getInstance().GetGamepad()->getOptions().socdMode;
|
||||
updateSocdMode = Storage::getInstance().GetGamepad()->getOptions().socdMode;
|
||||
|
||||
prevProfile = Storage::getInstance().GetGamepad()->getOptions().profileNumber;
|
||||
updateProfile = Storage::getInstance().GetGamepad()->getOptions().profileNumber;
|
||||
|
||||
prevFocus = Storage::getInstance().getAddonOptions().focusModeOptions.enabled;
|
||||
updateFocus = Storage::getInstance().getAddonOptions().focusModeOptions.enabled;
|
||||
|
||||
prevTurbo = Storage::getInstance().getAddonOptions().turboOptions.enabled;
|
||||
updateTurbo = Storage::getInstance().getAddonOptions().turboOptions.enabled;
|
||||
}
|
||||
|
||||
void MainMenuScreen::shutdown() {
|
||||
clearElements();
|
||||
exitToScreen = -1;
|
||||
}
|
||||
|
||||
void MainMenuScreen::drawScreen() {
|
||||
getRenderer()->drawText(1, 1, "GPGFX_UI Test Menu");
|
||||
gpMenu->setVisibility(!screenIsPrompting);
|
||||
|
||||
for (size_t i = 0; i < currentMenu->size(); ++i) {
|
||||
MenuEntry entry = currentMenu->at(i);
|
||||
if (!screenIsPrompting) {
|
||||
|
||||
getRenderer()->drawText(3, 3+i, entry.label);
|
||||
}
|
||||
|
||||
/*
|
||||
if (!isPressed) {
|
||||
if (pressedUp()) {
|
||||
if (menuIndex > 0) {
|
||||
menuIndex--;
|
||||
} else {
|
||||
menuIndex = currentMenu->size()-1;
|
||||
}
|
||||
checkDebounce = getMillis();
|
||||
isPressed = true;
|
||||
} else if (pressedDown()) {
|
||||
if (menuIndex < currentMenu->size()-1) {
|
||||
menuIndex++;
|
||||
} else {
|
||||
menuIndex = 0;
|
||||
}
|
||||
checkDebounce = getMillis();
|
||||
isPressed = true;
|
||||
} else if (pressedB1()) {
|
||||
currentMenu->at(menuIndex).action();
|
||||
checkDebounce = getMillis();
|
||||
isPressed = true;
|
||||
}
|
||||
} else {
|
||||
if (isPressed && ((getMillis() - checkDebounce) > 400)) {
|
||||
isPressed = false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
getRenderer()->drawText(1, 1, "Config has changed.");
|
||||
if (changeRequiresSave && !changeRequiresReboot) {
|
||||
getRenderer()->drawText(3, 3, "Would you like");
|
||||
getRenderer()->drawText(6, 4, "to save?");
|
||||
} else if (changeRequiresSave && changeRequiresReboot) {
|
||||
getRenderer()->drawText(3, 3, "Would you like");
|
||||
getRenderer()->drawText(1, 4, "to save & restart?");
|
||||
} else {
|
||||
|
||||
getRenderer()->drawText(1, 3+menuIndex, ">");
|
||||
}
|
||||
|
||||
if (promptChoice) getRenderer()->drawText(5, 6, CHAR_RIGHT);
|
||||
getRenderer()->drawText(6, 6, "Yes");
|
||||
if (!promptChoice) getRenderer()->drawText(11, 6, CHAR_RIGHT);
|
||||
getRenderer()->drawText(12, 6, "No");
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenuScreen::setMenu(std::vector<MenuEntry>* menu) {
|
||||
@@ -57,51 +116,284 @@ void MainMenuScreen::setMenu(std::vector<MenuEntry>* menu) {
|
||||
}
|
||||
|
||||
int8_t MainMenuScreen::update() {
|
||||
Gamepad * gamepad = Storage::getInstance().GetGamepad();
|
||||
Mask_t values = Storage::getInstance().GetGamepad()->debouncedGpio;
|
||||
|
||||
uint16_t buttonState = getGamepad()->state.buttons;
|
||||
|
||||
if (prevButtonState && !buttonState) {
|
||||
switch (prevButtonState) {
|
||||
case (GAMEPAD_MASK_B1):
|
||||
if (!isPressed && prevValues != values) {
|
||||
if (values & mapMenuUp->pinMask) {
|
||||
updateMenuNavigation(GpioAction::MENU_NAVIGATION_UP);
|
||||
} else if (values & mapMenuDown->pinMask) {
|
||||
updateMenuNavigation(GpioAction::MENU_NAVIGATION_DOWN);
|
||||
} else if (values & mapMenuSelect->pinMask) {
|
||||
updateMenuNavigation(GpioAction::MENU_NAVIGATION_SELECT);
|
||||
} else if (values & mapMenuBack->pinMask) {
|
||||
updateMenuNavigation(GpioAction::MENU_NAVIGATION_BACK);
|
||||
}
|
||||
} else {
|
||||
isPressed = false;
|
||||
}
|
||||
|
||||
prevButtonState = buttonState;
|
||||
prevValues = values;
|
||||
|
||||
if ((exitToScreen != -1) && ((changeRequiresSave) || (changeRequiresReboot))) {
|
||||
// trying to exit menu but a change requires a save/reboot
|
||||
exitToScreenBeforePrompt = exitToScreen;
|
||||
exitToScreen = -1;
|
||||
screenIsPrompting = true;
|
||||
}
|
||||
|
||||
return exitToScreen;
|
||||
}
|
||||
|
||||
void MainMenuScreen::updateMenuNavigation(GpioAction action) {
|
||||
bool changeIndex = false;
|
||||
uint16_t menuSize = gpMenu->getDataSize();
|
||||
|
||||
switch (action) {
|
||||
case GpioAction::MENU_NAVIGATION_UP:
|
||||
if (!screenIsPrompting) {
|
||||
if (menuIndex > 0) {
|
||||
menuIndex--;
|
||||
} else {
|
||||
menuIndex = currentMenu->size()-1;
|
||||
menuIndex = menuSize-1;
|
||||
}
|
||||
break;
|
||||
case (GAMEPAD_MASK_B2):
|
||||
if (menuIndex < currentMenu->size()-1) {
|
||||
changeIndex = true;
|
||||
} else {
|
||||
promptChoice = !promptChoice;
|
||||
}
|
||||
isPressed = true;
|
||||
break;
|
||||
case GpioAction::MENU_NAVIGATION_DOWN:
|
||||
if (!screenIsPrompting) {
|
||||
if (menuIndex < menuSize-1) {
|
||||
menuIndex++;
|
||||
} else {
|
||||
menuIndex = 0;
|
||||
}
|
||||
break;
|
||||
case (GAMEPAD_MASK_S1):
|
||||
currentMenu->at(menuIndex).action();
|
||||
break;
|
||||
default:
|
||||
//prevDisplayMode = DisplayMode::CONFIG_INSTRUCTION;
|
||||
break;
|
||||
}
|
||||
changeIndex = true;
|
||||
} else {
|
||||
promptChoice = !promptChoice;
|
||||
}
|
||||
isPressed = true;
|
||||
break;
|
||||
case GpioAction::MENU_NAVIGATION_LEFT:
|
||||
if (screenIsPrompting) {
|
||||
promptChoice = !promptChoice;
|
||||
}
|
||||
isPressed = true;
|
||||
break;
|
||||
case GpioAction::MENU_NAVIGATION_RIGHT:
|
||||
if (screenIsPrompting) {
|
||||
promptChoice = !promptChoice;
|
||||
}
|
||||
isPressed = true;
|
||||
break;
|
||||
case GpioAction::MENU_NAVIGATION_SELECT:
|
||||
if (!screenIsPrompting) {
|
||||
if (currentMenu->at(menuIndex).submenu != nullptr) {
|
||||
previousMenu = currentMenu;
|
||||
currentMenu = currentMenu->at(menuIndex).submenu;
|
||||
gpMenu->setMenuData(currentMenu);
|
||||
gpMenu->setMenuTitle(previousMenu->at(menuIndex).label);
|
||||
menuIndex = 0;
|
||||
changeIndex = true;
|
||||
} else {
|
||||
currentMenu->at(menuIndex).action();
|
||||
}
|
||||
} else {
|
||||
if (promptChoice) {
|
||||
saveOptions();
|
||||
} else {
|
||||
resetOptions();
|
||||
exitToScreen = DisplayMode::BUTTONS;
|
||||
exitToScreenBeforePrompt = DisplayMode::BUTTONS;
|
||||
isPressed = false;
|
||||
}
|
||||
}
|
||||
isPressed = true;
|
||||
break;
|
||||
case GpioAction::MENU_NAVIGATION_BACK:
|
||||
if (!screenIsPrompting) {
|
||||
if (previousMenu != nullptr) {
|
||||
currentMenu = previousMenu;
|
||||
previousMenu = nullptr;
|
||||
menuIndex = 0;
|
||||
changeIndex = true;
|
||||
gpMenu->setMenuData(currentMenu);
|
||||
gpMenu->setMenuTitle(MAIN_MENU_NAME);
|
||||
} else {
|
||||
exitToScreen = DisplayMode::BUTTONS;
|
||||
exitToScreenBeforePrompt = DisplayMode::BUTTONS;
|
||||
isPressed = false;
|
||||
}
|
||||
} else {
|
||||
// back again goes back to the menu
|
||||
screenIsPrompting = false;
|
||||
isPressed = false;
|
||||
}
|
||||
isPressed = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
prevButtonState = buttonState;
|
||||
if (changeIndex) gpMenu->setIndex(menuIndex);
|
||||
}
|
||||
|
||||
void MainMenuScreen::saveAndExit() {
|
||||
saveOptions();
|
||||
}
|
||||
|
||||
int32_t MainMenuScreen::modeValue() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
void testMenu();
|
||||
void MainMenuScreen::selectInputMode() {
|
||||
if (currentMenu->at(menuIndex).optionValue != -1) {
|
||||
InputMode valueToSave = (InputMode)currentMenu->at(menuIndex).optionValue;
|
||||
prevInputMode = Storage::getInstance().GetGamepad()->getOptions().inputMode;
|
||||
updateInputMode = valueToSave;
|
||||
|
||||
std::vector<MenuEntry> mainMenu = {
|
||||
{"Menu 1", NULL, std::bind(&DisplayAddon::testMenu, this)},
|
||||
{"Menu 2", NULL, std::bind(&DisplayAddon::testMenu, this)},
|
||||
{"Menu 3", NULL, std::bind(&DisplayAddon::testMenu, this)},
|
||||
{"Menu 4", NULL, std::bind(&DisplayAddon::testMenu, this)},
|
||||
{"Menu 5", NULL, std::bind(&DisplayAddon::testMenu, this)},
|
||||
{"Menu 6", NULL, std::bind(&DisplayAddon::testMenu, this)},
|
||||
{"Menu 7", NULL, std::bind(&DisplayAddon::testMenu, this)},
|
||||
{"Menu 8", NULL, std::bind(&DisplayAddon::testMenu, this)},
|
||||
};
|
||||
if (prevInputMode != valueToSave) {
|
||||
// input mode requires a save and reboot
|
||||
changeRequiresReboot = true;
|
||||
changeRequiresSave = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<MenuEntry>* currentMenu = &mainMenu;
|
||||
*/
|
||||
int32_t MainMenuScreen::currentInputMode() {
|
||||
return updateInputMode;
|
||||
}
|
||||
|
||||
void MainMenuScreen::selectDPadMode() {
|
||||
if (currentMenu->at(menuIndex).optionValue != -1) {
|
||||
DpadMode valueToSave = (DpadMode)currentMenu->at(menuIndex).optionValue;
|
||||
prevDpadMode = Storage::getInstance().GetGamepad()->getOptions().dpadMode;
|
||||
updateDpadMode = valueToSave;
|
||||
|
||||
if (prevDpadMode != valueToSave) changeRequiresSave = true;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t MainMenuScreen::currentDpadMode() {
|
||||
return updateDpadMode;
|
||||
}
|
||||
|
||||
void MainMenuScreen::selectSOCDMode() {
|
||||
if (currentMenu->at(menuIndex).optionValue != -1) {
|
||||
SOCDMode valueToSave = (SOCDMode)currentMenu->at(menuIndex).optionValue;
|
||||
prevSocdMode = Storage::getInstance().GetGamepad()->getOptions().socdMode;
|
||||
updateSocdMode = valueToSave;
|
||||
|
||||
if (prevDpadMode != valueToSave) changeRequiresSave = true;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t MainMenuScreen::currentSOCDMode() {
|
||||
return updateSocdMode;
|
||||
}
|
||||
|
||||
void MainMenuScreen::resetOptions() {
|
||||
if (changeRequiresSave) {
|
||||
if (prevInputMode != updateInputMode) updateInputMode = prevInputMode;
|
||||
if (prevDpadMode != updateDpadMode) updateDpadMode = prevDpadMode;
|
||||
if (prevSocdMode != updateSocdMode) updateSocdMode = prevSocdMode;
|
||||
if (prevProfile != updateProfile) updateProfile = prevProfile;
|
||||
if (prevFocus != updateFocus) updateFocus = prevFocus;
|
||||
if (prevTurbo != updateTurbo) updateTurbo = prevTurbo;
|
||||
}
|
||||
|
||||
changeRequiresSave = false;
|
||||
changeRequiresReboot = false;
|
||||
screenIsPrompting = false;
|
||||
}
|
||||
|
||||
void MainMenuScreen::saveOptions() {
|
||||
GamepadOptions& options = Storage::getInstance().getGamepadOptions();
|
||||
|
||||
if (changeRequiresSave) {
|
||||
bool saveHasChanged = false;
|
||||
if (prevInputMode != updateInputMode) {
|
||||
options.inputMode = updateInputMode;
|
||||
saveHasChanged = true;
|
||||
}
|
||||
if (prevDpadMode != updateDpadMode) {
|
||||
options.dpadMode = updateDpadMode;
|
||||
saveHasChanged = true;
|
||||
}
|
||||
if (prevSocdMode != updateSocdMode) {
|
||||
options.socdMode = updateSocdMode;
|
||||
saveHasChanged = true;
|
||||
}
|
||||
if (prevProfile != updateProfile) {
|
||||
options.profileNumber = updateProfile;
|
||||
saveHasChanged = true;
|
||||
}
|
||||
if (prevFocus != updateFocus) {
|
||||
Storage::getInstance().getAddonOptions().focusModeOptions.enabled = updateFocus;
|
||||
saveHasChanged = true;
|
||||
}
|
||||
if (prevTurbo != updateTurbo) {
|
||||
Storage::getInstance().getAddonOptions().turboOptions.enabled = updateTurbo;
|
||||
saveHasChanged = true;
|
||||
}
|
||||
|
||||
if (saveHasChanged) {
|
||||
EventManager::getInstance().triggerEvent(new GPStorageSaveEvent(true, changeRequiresReboot));
|
||||
screenIsPrompting = false;
|
||||
}
|
||||
changeRequiresSave = false;
|
||||
changeRequiresReboot = false;
|
||||
}
|
||||
|
||||
if (exitToScreenBeforePrompt != -1) {
|
||||
exitToScreen = exitToScreenBeforePrompt;
|
||||
exitToScreenBeforePrompt = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void MainMenuScreen::selectProfile() {
|
||||
if (currentMenu->at(menuIndex).optionValue != -1) {
|
||||
uint8_t valueToSave = currentMenu->at(menuIndex).optionValue;
|
||||
prevProfile = Storage::getInstance().GetGamepad()->getOptions().profileNumber;
|
||||
updateProfile = valueToSave;
|
||||
|
||||
if (prevProfile != valueToSave) changeRequiresSave = true;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t MainMenuScreen::currentProfile() {
|
||||
return updateProfile;
|
||||
}
|
||||
|
||||
void MainMenuScreen::selectFocusMode() {
|
||||
if (currentMenu->at(menuIndex).optionValue != -1) {
|
||||
uint8_t valueToSave = currentMenu->at(menuIndex).optionValue;
|
||||
prevFocus = Storage::getInstance().getAddonOptions().focusModeOptions.enabled;
|
||||
updateFocus = valueToSave;
|
||||
|
||||
if (prevFocus != valueToSave) changeRequiresSave = true;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t MainMenuScreen::currentFocusMode() {
|
||||
return updateFocus;
|
||||
}
|
||||
|
||||
void MainMenuScreen::selectTurboMode() {
|
||||
if (currentMenu->at(menuIndex).optionValue != -1) {
|
||||
uint8_t valueToSave = currentMenu->at(menuIndex).optionValue;
|
||||
prevTurbo = Storage::getInstance().getAddonOptions().turboOptions.enabled;
|
||||
updateTurbo = valueToSave;
|
||||
|
||||
if (updateTurbo != valueToSave) changeRequiresSave = true;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t MainMenuScreen::currentTurboMode() {
|
||||
return updateTurbo;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
#include "storagemanager.h"
|
||||
#include "enums.pb.h"
|
||||
|
||||
void EventManager::init() {
|
||||
clearEventHandlers();
|
||||
}
|
||||
|
||||
void EventManager::registerEventHandler(GPEventType eventType, EventFunction handler) {
|
||||
typename std::vector<EventEntry>::iterator it = std::find_if(eventList.begin(), eventList.end(), [&eventType](const EventEntry& entry) { return entry.first == eventType; });
|
||||
|
||||
@@ -26,4 +30,8 @@ void EventManager::triggerEvent(GPEvent* event) {
|
||||
}
|
||||
}
|
||||
delete event;
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::clearEventHandlers() {
|
||||
|
||||
}
|
||||
|
||||
@@ -656,12 +656,47 @@ void Gamepad::processHotkeyAction(GamepadHotkey action) {
|
||||
reqSave = true;
|
||||
}
|
||||
break;
|
||||
case HOTKEY_MENU_NAV_UP:
|
||||
if (action != lastAction) {
|
||||
EventManager::getInstance().triggerEvent(new GPMenuNavigateEvent(GpioAction::MENU_NAVIGATION_UP));
|
||||
}
|
||||
break;
|
||||
case HOTKEY_MENU_NAV_DOWN:
|
||||
if (action != lastAction) {
|
||||
EventManager::getInstance().triggerEvent(new GPMenuNavigateEvent(GpioAction::MENU_NAVIGATION_DOWN));
|
||||
}
|
||||
break;
|
||||
case HOTKEY_MENU_NAV_LEFT:
|
||||
if (action != lastAction) {
|
||||
EventManager::getInstance().triggerEvent(new GPMenuNavigateEvent(GpioAction::MENU_NAVIGATION_LEFT));
|
||||
}
|
||||
break;
|
||||
case HOTKEY_MENU_NAV_RIGHT:
|
||||
if (action != lastAction) {
|
||||
EventManager::getInstance().triggerEvent(new GPMenuNavigateEvent(GpioAction::MENU_NAVIGATION_RIGHT));
|
||||
}
|
||||
break;
|
||||
case HOTKEY_MENU_NAV_SELECT:
|
||||
if (action != lastAction) {
|
||||
EventManager::getInstance().triggerEvent(new GPMenuNavigateEvent(GpioAction::MENU_NAVIGATION_SELECT));
|
||||
}
|
||||
break;
|
||||
case HOTKEY_MENU_NAV_BACK:
|
||||
if (action != lastAction) {
|
||||
EventManager::getInstance().triggerEvent(new GPMenuNavigateEvent(GpioAction::MENU_NAVIGATION_BACK));
|
||||
}
|
||||
break;
|
||||
case HOTKEY_MENU_NAV_TOGGLE:
|
||||
if (action != lastAction) {
|
||||
EventManager::getInstance().triggerEvent(new GPMenuNavigateEvent(GpioAction::MENU_NAVIGATION_TOGGLE));
|
||||
}
|
||||
break;
|
||||
default: // Unknown action
|
||||
return;
|
||||
}
|
||||
|
||||
// only save if requested
|
||||
if (reqSave) {
|
||||
Storage::getInstance().save();
|
||||
EventManager::getInstance().triggerEvent(new GPStorageSaveEvent(true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
static const uint32_t REBOOT_HOTKEY_ACTIVATION_TIME_MS = 50;
|
||||
static const uint32_t REBOOT_HOTKEY_HOLD_TIME_MS = 4000;
|
||||
|
||||
const static uint32_t rebootDelayMs = 500;
|
||||
static absolute_time_t rebootDelayTimeout = nil_time;
|
||||
|
||||
void GP2040::setup() {
|
||||
Storage::getInstance().init();
|
||||
|
||||
@@ -184,6 +187,9 @@ void GP2040::setup() {
|
||||
// before USB host will be used so we can force it to ignore the check
|
||||
Storage::getInstance().save(true);
|
||||
}
|
||||
|
||||
// register system event handlers
|
||||
EventManager::getInstance().registerEventHandler(GP_EVENT_STORAGE_SAVE, GPEVENT_CALLBACK(this->handleStorageSave(event)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,6 +323,24 @@ void GP2040::run() {
|
||||
addons.ProcessAddons(ADDON_PROCESS::CORE0_USBREPORT);
|
||||
|
||||
tud_task(); // TinyUSB Task update
|
||||
|
||||
if (rebootRequested) {
|
||||
rebootRequested = false;
|
||||
if (saveRequested) {
|
||||
saveRequested = false;
|
||||
Storage::getInstance().save(true);
|
||||
}
|
||||
rebootDelayTimeout = make_timeout_time_ms(rebootDelayMs);
|
||||
} else {
|
||||
if (saveRequested) {
|
||||
saveRequested = false;
|
||||
Storage::getInstance().save(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_nil_time(rebootDelayTimeout) && time_reached(rebootDelayTimeout)) {
|
||||
System::reboot(System::BootMode::DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,3 +550,12 @@ void GP2040::checkProcessedState(GamepadState prevState, GamepadState currState)
|
||||
EventManager::getInstance().triggerEvent(new GPAnalogProcessedMoveEvent(currState.lx, currState.ly, currState.rx, currState.ry, currState.lt, currState.rt));
|
||||
}
|
||||
}
|
||||
|
||||
void GP2040::handleStorageSave(GPEvent* e) {
|
||||
saveRequested = true;
|
||||
rebootRequested = ((GPStorageSaveEvent*)e)->restartAfterSave;
|
||||
}
|
||||
|
||||
void GP2040::handleSystemReboot(GPEvent* e) {
|
||||
rebootRequested = true;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,10 @@ void GPGFX_OBD_SSD1306::drawPixel(uint8_t x, uint8_t y, uint32_t color) {
|
||||
obdSetPixel(&obd, x, y, color, 1);
|
||||
}
|
||||
|
||||
uint32_t GPGFX_OBD_SSD1306::getPixel(uint8_t x, uint8_t y) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GPGFX_OBD_SSD1306::drawText(uint8_t x, uint8_t y, std::string text, uint8_t invert) {
|
||||
obdWriteString(&obd, 0, x, y, (char*)text.c_str(), FONT_6x8, 0, 1);
|
||||
}
|
||||
@@ -62,7 +66,7 @@ void GPGFX_OBD_SSD1306::drawRectangle(uint16_t x, uint16_t y, uint16_t width, ui
|
||||
obdRectangle(&obd, x, y, width, height, color, filled);
|
||||
}
|
||||
|
||||
void GPGFX_OBD_SSD1306::drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority) {
|
||||
void GPGFX_OBD_SSD1306::drawSprite(uint8_t* spriteData, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority, double scale) {
|
||||
obdDrawSprite(&obd, spriteData, width, height, pitch, x, y, priority);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,25 @@ void GPGFX_TinySSD1306::clear() {
|
||||
memset(frameBuffer, 0, MAX_SCREEN_SIZE);
|
||||
}
|
||||
|
||||
uint32_t GPGFX_TinySSD1306::getPixel(uint8_t x, uint8_t y) {
|
||||
uint16_t row, bitIndex;
|
||||
uint32_t result = 0;
|
||||
|
||||
if ((x<MAX_SCREEN_WIDTH) and (y<MAX_SCREEN_HEIGHT))
|
||||
{
|
||||
if (this->screenType == ScreenAlternatives::SCREEN_132x64) {
|
||||
x+=2;
|
||||
}
|
||||
|
||||
row=((y/8)*MAX_SCREEN_WIDTH)+x;
|
||||
bitIndex=y % 8;
|
||||
|
||||
result = (frameBuffer[row] >> bitIndex) && 0x01;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void GPGFX_TinySSD1306::drawPixel(uint8_t x, uint8_t y, uint32_t color) {
|
||||
uint16_t row, bitIndex;
|
||||
|
||||
@@ -395,20 +414,22 @@ void GPGFX_TinySSD1306::drawPolygon(uint16_t x, uint16_t y, uint16_t radius, uin
|
||||
}
|
||||
}
|
||||
|
||||
void GPGFX_TinySSD1306::drawSprite(uint8_t* image, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority) {
|
||||
void GPGFX_TinySSD1306::drawSprite(uint8_t* image, uint16_t width, uint16_t height, uint16_t pitch, uint16_t x, uint16_t y, uint8_t priority, double scale) {
|
||||
uint8_t spriteByte;
|
||||
uint8_t spriteBit;
|
||||
uint8_t spriteX, spriteY;
|
||||
uint8_t color;
|
||||
|
||||
for (spriteY = 0; spriteY < height; spriteY++) {
|
||||
for (spriteX = 0; spriteX < width; spriteX++) {
|
||||
for (uint16_t scaledY = 0; scaledY < height * scale; ++scaledY) {
|
||||
for (uint16_t scaledX = 0; scaledX < width * scale; ++scaledX) {
|
||||
spriteX = scaledX / scale;
|
||||
spriteY = scaledY / scale;
|
||||
|
||||
spriteBit = spriteX % 8;
|
||||
//spriteByte = image[(spriteY * (width / 8)) + (spriteX / 8)];
|
||||
spriteByte = image[(spriteY * ((width + 7) / 8)) + (spriteX / 8)];
|
||||
color = ((spriteByte >> (7 - spriteBit)) & 0x01);
|
||||
|
||||
drawPixel(x+spriteX, y+spriteY, color);
|
||||
|
||||
drawPixel(x + scaledX, y + scaledY, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,35 @@
|
||||
#include "enums.pb.h"
|
||||
|
||||
LayoutManager::LayoutList LayoutManager::getLayoutA() {
|
||||
uint16_t layoutLeft = Storage::getInstance().getDisplayOptions().buttonLayout;
|
||||
return getLeftLayout(layoutLeft);
|
||||
const DisplayOptions& options = Storage::getInstance().getDisplayOptions();
|
||||
uint16_t layoutLeft = options.buttonLayout;
|
||||
if (options.buttonLayoutOrientation != BUTTON_ORIENTATION_DEFAULT) {
|
||||
uint16_t layoutRight = options.buttonLayoutRight;
|
||||
LayoutManager::LayoutList rightLayout = getRightLayout(layoutRight);
|
||||
if (options.buttonLayoutOrientation == BUTTON_ORIENTATION_SWITCHED) {
|
||||
return adjustByOffset(rightLayout, -64);
|
||||
} else {
|
||||
return adjustByOffset(flipHorizontally(rightLayout, 64, 0, 128, 0), -64);
|
||||
}
|
||||
} else {
|
||||
return getLeftLayout(layoutLeft);
|
||||
}
|
||||
}
|
||||
|
||||
LayoutManager::LayoutList LayoutManager::getLayoutB() {
|
||||
uint16_t layoutRight = Storage::getInstance().getDisplayOptions().buttonLayoutRight;
|
||||
return getRightLayout(layoutRight);
|
||||
const DisplayOptions& options = Storage::getInstance().getDisplayOptions();
|
||||
uint16_t layoutRight = options.buttonLayoutRight;
|
||||
if (options.buttonLayoutOrientation != BUTTON_ORIENTATION_DEFAULT) {
|
||||
uint16_t layoutLeft = options.buttonLayout;
|
||||
LayoutManager::LayoutList leftLayout = getLeftLayout(layoutLeft);
|
||||
if (options.buttonLayoutOrientation == BUTTON_ORIENTATION_SWITCHED) {
|
||||
return adjustByOffset(leftLayout, 64);
|
||||
} else {
|
||||
return adjustByOffset(flipHorizontally(leftLayout, 0, 0, 64, 0), 64);
|
||||
}
|
||||
} else {
|
||||
return getRightLayout(layoutRight);
|
||||
}
|
||||
}
|
||||
|
||||
std::string LayoutManager::getLayoutAName() {
|
||||
@@ -145,6 +167,8 @@ LayoutManager::LayoutList LayoutManager::getRightLayout(uint16_t index) {
|
||||
return this->drawCapcom6();
|
||||
case BUTTON_LAYOUT_SEGA2P:
|
||||
return this->drawSega2p();
|
||||
case BUTTON_LAYOUT_SEGA2P_6B:
|
||||
return this->drawSega2p6b();
|
||||
case BUTTON_LAYOUT_NOIR8:
|
||||
return this->drawNoir8();
|
||||
case BUTTON_LAYOUT_KEYBOARDB:
|
||||
@@ -155,6 +179,8 @@ LayoutManager::LayoutList LayoutManager::getRightLayout(uint16_t index) {
|
||||
return this->drawBlankB();
|
||||
case BUTTON_LAYOUT_VLXB:
|
||||
return this->drawVLXB();
|
||||
case BUTTON_LAYOUT_VLXB_6B:
|
||||
return this->drawVLXB6B();
|
||||
case BUTTON_LAYOUT_FIGHTBOARD:
|
||||
return this->drawFightboard();
|
||||
case BUTTON_LAYOUT_FIGHTBOARD_STICK_MIRRORED:
|
||||
@@ -255,6 +281,52 @@ LayoutManager::LayoutList LayoutManager::adjustByCustomSettings(LayoutManager::L
|
||||
return layout;
|
||||
}
|
||||
|
||||
LayoutManager::LayoutList LayoutManager::adjustByOffset(LayoutManager::LayoutList layout, int16_t originX, int16_t originY) {
|
||||
if (layout.size() > 0) {
|
||||
int16_t minX = INT16_MAX;
|
||||
int16_t maxX = INT16_MIN;
|
||||
|
||||
for (uint16_t elementCtr = 0; elementCtr < layout.size(); elementCtr++) {
|
||||
int16_t newX = layout[elementCtr].parameters.x1 + originX;
|
||||
if (((GPShape_Type)layout[elementCtr].parameters.shape == GP_SHAPE_ELLIPSE) || ((GPShape_Type)layout[elementCtr].parameters.shape == GP_SHAPE_POLYGON)) {
|
||||
newX = (layout[elementCtr].parameters.x1-(layout[elementCtr].parameters.x2)) + originX;
|
||||
} else if ((GPShape_Type)layout[elementCtr].parameters.shape == GP_SHAPE_SQUARE) {
|
||||
if (originX > 0) newX = layout[elementCtr].parameters.x2 + originX;
|
||||
}
|
||||
minX = std::min(minX, newX);
|
||||
maxX = std::max(maxX, newX);
|
||||
}
|
||||
|
||||
int16_t offsetX = 0;
|
||||
if (minX < 0) {
|
||||
offsetX = -minX;
|
||||
} else if (maxX > 127) {
|
||||
offsetX = 127 - maxX;
|
||||
}
|
||||
|
||||
// Apply the calculated adjustment to all objects
|
||||
for (uint16_t elementCtr = 0; elementCtr < layout.size(); elementCtr++) {
|
||||
layout[elementCtr].parameters.x1 += originX + offsetX;
|
||||
if ((GPShape_Type)layout[elementCtr].parameters.shape == GP_SHAPE_SQUARE) {
|
||||
layout[elementCtr].parameters.x2 += originX + offsetX;
|
||||
}
|
||||
layout[elementCtr].parameters.y1 += originY; // Apply y offset directly
|
||||
}
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
LayoutManager::LayoutList LayoutManager::flipHorizontally(LayoutList layout, int16_t startX, int16_t startY, int16_t endX, int16_t endY) {
|
||||
if (layout.size() > 0) {
|
||||
for (uint16_t elementCtr = 0; elementCtr < layout.size(); elementCtr++) {
|
||||
int16_t originalX = layout[elementCtr].parameters.x1;
|
||||
|
||||
layout[elementCtr].parameters.x1 = (endX-1) - (originalX - startX);
|
||||
}
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
LayoutManager::LayoutList LayoutManager::drawStickless()
|
||||
{
|
||||
return BUTTON_GROUP_STICKLESS;
|
||||
@@ -345,6 +417,11 @@ LayoutManager::LayoutList LayoutManager::drawVLXB()
|
||||
return BUTTON_GROUP_VLXB;
|
||||
}
|
||||
|
||||
LayoutManager::LayoutList LayoutManager::drawVLXB6B()
|
||||
{
|
||||
return BUTTON_GROUP_VLXB_6B;
|
||||
}
|
||||
|
||||
LayoutManager::LayoutList LayoutManager::drawFightboard()
|
||||
{
|
||||
return BUTTON_GROUP_FIGHTBOARD;
|
||||
@@ -360,6 +437,11 @@ LayoutManager::LayoutList LayoutManager::drawSega2p()
|
||||
return BUTTON_GROUP_SEGA_2P;
|
||||
}
|
||||
|
||||
LayoutManager::LayoutList LayoutManager::drawSega2p6b()
|
||||
{
|
||||
return BUTTON_GROUP_SEGA_2P_6B;
|
||||
}
|
||||
|
||||
LayoutManager::LayoutList LayoutManager::drawNoir8()
|
||||
{
|
||||
return BUTTON_GROUP_NOIR8;
|
||||
|
||||
@@ -56,6 +56,7 @@ app.get('/api/getDisplayOptions', (req, res) => {
|
||||
invertDisplay: 1,
|
||||
buttonLayout: 0,
|
||||
buttonLayoutRight: 3,
|
||||
buttonLayoutOrientation: 0,
|
||||
splashMode: 3,
|
||||
splashChoice: 0,
|
||||
splashDuration: 0,
|
||||
@@ -77,7 +78,18 @@ app.get('/api/getDisplayOptions', (req, res) => {
|
||||
},
|
||||
|
||||
displaySaverTimeout: 0,
|
||||
displaySaverMode: 0,
|
||||
turnOffWhenSuspended: 0,
|
||||
inputMode: 1,
|
||||
turboMode: 1,
|
||||
dpadMode: 1,
|
||||
socdMode: 1,
|
||||
macroMode: 1,
|
||||
profileMode: 0,
|
||||
inputHistoryEnabled: 0,
|
||||
inputHistoryLength: 21,
|
||||
inputHistoryCol: 0,
|
||||
inputHistoryRow: 7,
|
||||
};
|
||||
console.log('data', data);
|
||||
return res.send(data);
|
||||
@@ -510,10 +522,6 @@ app.get('/api/getAddonsOptions', (req, res) => {
|
||||
TurboInputEnabled: 1,
|
||||
WiiExtensionAddonEnabled: 1,
|
||||
SNESpadAddonEnabled: 1,
|
||||
InputHistoryAddonEnabled: 1,
|
||||
inputHistoryLength: 21,
|
||||
inputHistoryCol: 0,
|
||||
inputHistoryRow: 7,
|
||||
Analog1256Enabled: 1,
|
||||
analog1256Block: 0,
|
||||
analog1256CsPin: -1,
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FormCheck, Row } from 'react-bootstrap';
|
||||
import * as yup from 'yup';
|
||||
|
||||
import Section from '../Components/Section';
|
||||
|
||||
import FormControl from '../Components/FormControl';
|
||||
|
||||
export const inputHistoryScheme = {
|
||||
InputHistoryAddonEnabled: yup
|
||||
.number()
|
||||
.required()
|
||||
.label('Input History Enabled'),
|
||||
inputHistoryLength: yup
|
||||
.number()
|
||||
.label('Input History Length')
|
||||
.validateRangeWhenValue('InputHistoryAddonEnabled', 1, 21),
|
||||
inputHistoryCol: yup
|
||||
.number()
|
||||
.label('Col')
|
||||
.validateRangeWhenValue('InputHistoryAddonEnabled', 0, 20),
|
||||
inputHistoryRow: yup
|
||||
.number()
|
||||
.label('Row')
|
||||
.validateRangeWhenValue('InputHistoryAddonEnabled', 0, 7),
|
||||
};
|
||||
|
||||
export const inputHistoryState = {
|
||||
InputHistoryAddonEnabled: 0,
|
||||
inputHistoryLength: 21,
|
||||
inputHistoryCol: 0,
|
||||
inputHistoryRow: 7,
|
||||
};
|
||||
|
||||
const InputHistory = ({ values, errors, handleChange, handleCheckbox }) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Section title={t('AddonsConfig:input-history-header-text')}>
|
||||
<div id="InputHistoryOptions" hidden={!values.InputHistoryAddonEnabled}>
|
||||
<Row className="mb-3">
|
||||
<FormControl
|
||||
type="number"
|
||||
label={t('AddonsConfig:input-history-length-label')}
|
||||
name="inputHistoryLength"
|
||||
className="form-control-sm"
|
||||
groupClassName="col-sm-3 mb-3"
|
||||
value={values.inputHistoryLength}
|
||||
error={errors.inputHistoryLength}
|
||||
isInvalid={errors.inputHistoryLength}
|
||||
onChange={handleChange}
|
||||
min={1}
|
||||
max={21}
|
||||
/>
|
||||
<FormControl
|
||||
type="number"
|
||||
label={t('AddonsConfig:input-history-col-label')}
|
||||
name="inputHistoryCol"
|
||||
className="form-control-sm"
|
||||
groupClassName="col-sm-3 mb-3"
|
||||
value={values.inputHistoryCol}
|
||||
error={errors.inputHistoryCol}
|
||||
isInvalid={errors.inputHistoryCol}
|
||||
onChange={handleChange}
|
||||
min={0}
|
||||
max={20}
|
||||
/>
|
||||
<FormControl
|
||||
type="number"
|
||||
label={t('AddonsConfig:input-history-row-label')}
|
||||
name="inputHistoryRow"
|
||||
className="form-control-sm"
|
||||
groupClassName="col-sm-3 mb-3"
|
||||
value={values.inputHistoryRow}
|
||||
error={errors.inputHistoryRow}
|
||||
isInvalid={errors.inputHistoryRow}
|
||||
onChange={handleChange}
|
||||
min={0}
|
||||
max={7}
|
||||
/>
|
||||
</Row>
|
||||
</div>
|
||||
<FormCheck
|
||||
label={t('Common:switch-enabled')}
|
||||
type="switch"
|
||||
id="InputHistoryButton"
|
||||
reverse
|
||||
isInvalid={false}
|
||||
checked={Boolean(values.InputHistoryAddonEnabled)}
|
||||
onChange={(e) => {
|
||||
handleCheckbox('InputHistoryAddonEnabled', values);
|
||||
handleChange(e);
|
||||
}}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export default InputHistory;
|
||||
@@ -74,6 +74,13 @@ export const BUTTON_ACTIONS = {
|
||||
BUTTON_PRESS_INPUT_REVERSE: 69,
|
||||
SUSTAIN_FOCUS_MODE: 70,
|
||||
SUSTAIN_4_8_WAY_MODE: 71,
|
||||
MENU_NAVIGATION_UP: 72,
|
||||
MENU_NAVIGATION_DOWN: 73,
|
||||
MENU_NAVIGATION_LEFT: 74,
|
||||
MENU_NAVIGATION_RIGHT: 75,
|
||||
MENU_NAVIGATION_SELECT: 76,
|
||||
MENU_NAVIGATION_BACK: 77,
|
||||
MENU_NAVIGATION_TOGGLE: 78,
|
||||
} as const;
|
||||
|
||||
export const PIN_DIRECTIONS = {
|
||||
|
||||
@@ -8,6 +8,10 @@ export default {
|
||||
'hardware-header': 'Hardware Options',
|
||||
'screen-header': 'Screen Options',
|
||||
'layout-header': 'Layout Options',
|
||||
'mode-header': 'Mode Options',
|
||||
'button-layout-header': 'Button Layout',
|
||||
'status-layout-header': 'Status Bar Layout',
|
||||
'history-layout-header': 'Input History Layout',
|
||||
},
|
||||
table: {
|
||||
header:
|
||||
@@ -25,6 +29,7 @@ export default {
|
||||
'invert-display-label': 'Invert Display',
|
||||
'button-layout-label': 'Button Layout (Left)',
|
||||
'button-layout-right-label': 'Button Layout (Right)',
|
||||
'button-layout-orientation': 'Button Layout Orientation',
|
||||
'button-layout-custom-header': 'Custom Button Layout Params',
|
||||
'button-layout-custom-left-label': 'Layout Left',
|
||||
'button-layout-custom-right-label': 'Layout Right',
|
||||
@@ -35,12 +40,46 @@ export default {
|
||||
'splash-mode-label': 'Splash Mode',
|
||||
'splash-duration-label': 'Splash Duration (seconds, 0 for Always On)',
|
||||
'display-saver-timeout-label': 'Display Saver Timeout (minutes)',
|
||||
'screen-saver-mode-label': 'Display Saver Mode',
|
||||
'inverted-label': 'Inverted',
|
||||
'power-management-header': 'Power Management',
|
||||
'turn-off-when-suspended': 'Turn Off When Suspended',
|
||||
'flip-display-none': 'None',
|
||||
'flip-display-flip': 'Flip',
|
||||
'flip-display-mirror': 'Mirror',
|
||||
'flip-display-flip-mirror': 'Flip and Mirror',
|
||||
'input-history-label': 'Input History',
|
||||
'display-state': {
|
||||
'disabled': 'Disabled',
|
||||
'enabled': 'Enabled'
|
||||
},
|
||||
'flip-display': {
|
||||
'none': 'None',
|
||||
'flip': 'Flip',
|
||||
'mirror': 'Mirror',
|
||||
'flip-mirror': 'Flip and Mirror',
|
||||
},
|
||||
'splash-modes': {
|
||||
'enabled': 'Enabled (Custom Splash Screen)',
|
||||
'close-in': 'Logo Close In',
|
||||
'close-in-custom': 'Logo Close In Custom',
|
||||
'disabled': 'Disabled',
|
||||
},
|
||||
'saver-modes': {
|
||||
'display-off': 'Display Off',
|
||||
'snow': 'Snow',
|
||||
'bounce': 'Logo Bounce',
|
||||
'pipes': 'Pipes',
|
||||
'toast': 'Toast',
|
||||
},
|
||||
'layout-modes': {
|
||||
'standard': 'Default',
|
||||
'southpaw': 'Southpaw',
|
||||
'switched': 'Switched',
|
||||
},
|
||||
'status-header': {
|
||||
'input-mode': 'Input Mode',
|
||||
'turbo-mode': 'Turbo',
|
||||
'dpad-mode': 'D-Pad Mode',
|
||||
'socd-mode': 'SOCD Mode',
|
||||
'macro-mode': 'Macro',
|
||||
'profile-mode': 'Profile',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -49,12 +49,14 @@ export default {
|
||||
BUTTON_LAYOUT_CAPCOM: 'Capcom',
|
||||
BUTTON_LAYOUT_CAPCOM6: 'Capcom 6',
|
||||
BUTTON_LAYOUT_SEGA2P: 'Sega 2P',
|
||||
BUTTON_LAYOUT_SEGA2P_6B: 'Sega 2P 6',
|
||||
BUTTON_LAYOUT_NOIR8: 'Noir 8',
|
||||
BUTTON_LAYOUT_KEYBOARDB: 'Keyboard',
|
||||
BUTTON_LAYOUT_DANCEPADB: 'Dancepad',
|
||||
BUTTON_LAYOUT_TWINSTICKB: 'Twinstick',
|
||||
BUTTON_LAYOUT_BLANKB: 'Blank',
|
||||
BUTTON_LAYOUT_VLXB: 'VLX',
|
||||
BUTTON_LAYOUT_VLXB_6B: 'VLX 6',
|
||||
BUTTON_LAYOUT_FIGHTBOARD: 'Fightboard',
|
||||
BUTTON_LAYOUT_FIGHTBOARD_STICK_MIRRORED: 'Fightboard Mirrored',
|
||||
BUTTON_LAYOUT_CUSTOM: 'Custom',
|
||||
|
||||
@@ -99,5 +99,12 @@ export default {
|
||||
BUTTON_PRESS_INPUT_REVERSE: 'Reverse Input',
|
||||
SUSTAIN_FOCUS_MODE: 'Focus Mode Enable',
|
||||
SUSTAIN_4_8_WAY_MODE: 'Toggle 4-Way Mode',
|
||||
MENU_NAVIGATION_UP: 'Menu Up',
|
||||
MENU_NAVIGATION_DOWN: 'Menu Down',
|
||||
MENU_NAVIGATION_LEFT: 'Menu Left',
|
||||
MENU_NAVIGATION_RIGHT: 'Menu Right',
|
||||
MENU_NAVIGATION_SELECT: 'Menu Select',
|
||||
MENU_NAVIGATION_BACK: 'Menu Back',
|
||||
MENU_NAVIGATION_TOGGLE: 'Menu Toggle',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -130,6 +130,13 @@ export default {
|
||||
'save-config': 'Save Config',
|
||||
'next-profile': 'Next Profile',
|
||||
'previous-profile': 'Previous Profile',
|
||||
'menu-nav-up': 'Menu Up',
|
||||
'menu-nav-down': 'Menu Down',
|
||||
'menu-nav-left': 'Menu Left',
|
||||
'menu-nav-right': 'Menu Right',
|
||||
'menu-nav-select': 'Menu Select',
|
||||
'menu-nav-back': 'Menu Back',
|
||||
'menu-nav-toggle': 'Menu Toggle',
|
||||
},
|
||||
'forced-setup-mode-label': 'Forced Setup Mode',
|
||||
'forced-setup-mode-options': {
|
||||
|
||||
@@ -47,10 +47,6 @@ import FocusMode, {
|
||||
} from '../Addons/FocusMode';
|
||||
import Keyboard, { keyboardScheme, keyboardState } from '../Addons/Keyboard';
|
||||
import GamepadUSBHost, { gamepadUSBHostScheme, gamepadUSBHostState} from '../Addons/GamepadUSBHost';
|
||||
import InputHistory, {
|
||||
inputHistoryScheme,
|
||||
inputHistoryState,
|
||||
} from '../Addons/InputHistory';
|
||||
import Rotary, { rotaryScheme, rotaryState } from '../Addons/Rotary';
|
||||
import PCF8575, { pcf8575Scheme, pcf8575State } from '../Addons/PCF8575';
|
||||
import DRV8833Rumble, {
|
||||
@@ -79,7 +75,6 @@ const schema = yup.object().shape({
|
||||
...wiiScheme,
|
||||
...focusModeScheme,
|
||||
...keyboardScheme,
|
||||
...inputHistoryScheme,
|
||||
...rotaryScheme,
|
||||
...pcf8575Scheme,
|
||||
...drv8833RumbleScheme,
|
||||
@@ -104,7 +99,6 @@ const defaultValues = {
|
||||
...snesState,
|
||||
...focusModeState,
|
||||
...keyboardState,
|
||||
...inputHistoryState,
|
||||
...rotaryState,
|
||||
...pcf8575State,
|
||||
...drv8833RumbleState,
|
||||
@@ -130,7 +124,6 @@ const ADDONS = [
|
||||
FocusMode,
|
||||
Keyboard,
|
||||
GamepadUSBHost,
|
||||
InputHistory,
|
||||
Rotary,
|
||||
PCF8575,
|
||||
DRV8833Rumble,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -287,6 +287,13 @@ const HOTKEY_ACTIONS = [
|
||||
{ labelKey: 'hotkey-actions.dpad-down', value: 39 },
|
||||
{ labelKey: 'hotkey-actions.dpad-left', value: 40 },
|
||||
{ labelKey: 'hotkey-actions.dpad-right', value: 41 },
|
||||
{ labelKey: 'hotkey-actions.menu-nav-up', value: 44 },
|
||||
{ labelKey: 'hotkey-actions.menu-nav-down', value: 45 },
|
||||
{ labelKey: 'hotkey-actions.menu-nav-left', value: 46 },
|
||||
{ labelKey: 'hotkey-actions.menu-nav-right', value: 47 },
|
||||
{ labelKey: 'hotkey-actions.menu-nav-select', value: 48 },
|
||||
{ labelKey: 'hotkey-actions.menu-nav-back', value: 49 },
|
||||
{ labelKey: 'hotkey-actions.menu-nav-toggle', value: 50 },
|
||||
];
|
||||
|
||||
const FORCED_SETUP_MODES = [
|
||||
|
||||
Reference in New Issue
Block a user