【M5coreS3】自作Button

2024/07/23に公開
#include <M5CoreS3.h>

typedef void (*ButtonCallback)();

class Button {
private:
    const char* label;
    int x;
    int y;
    int width;
    int height;
    uint32_t color;
    uint32_t textColor;
    ButtonCallback onPressed;
    unsigned long pressTime;
    bool isHighlighted;
    uint8_t textSize;
    bool autoDrawEnabled;

public:
    // デフォルトコンストラクタ
    Button() : x(0), y(0), width(0), height(0), color(WHITE), textColor(BLACK), label(nullptr), onPressed(nullptr), pressTime(0), isHighlighted(false), textSize(1), autoDrawEnabled(true) {}

    // パラメータ付きコンストラクタ(デフォルト値を設定)
    Button(
           const char* _label,             
           int _x, int _y, int _width, int _height,
           ButtonCallback _onPressed,
           uint32_t _color = WHITE,
           uint32_t _textColor = BLACK,
           uint8_t _textSize = 1,
           bool _autoDraw = true)
        : x(_x), y(_y), width(_width), height(_height), 
          color(_color), textColor(_textColor), 
          label(_label), onPressed(_onPressed), 
          pressTime(0), isHighlighted(false), textSize(_textSize),
          autoDrawEnabled(_autoDraw) 
        {
            if (autoDrawEnabled) {
                draw();
            }
        }

    void draw() const {
        CoreS3.Display.setTextSize(textSize);

        if (isHighlighted) {
            CoreS3.Display.fillRect(x, y, width, height, TFT_TRANSPARENT);
            CoreS3.Display.setTextColor(color);
        } else {
            CoreS3.Display.fillRect(x, y, width, height, color);
            CoreS3.Display.setTextColor(textColor);
        }

        CoreS3.Display.drawString(label, x + width / 2, y + height / 2);
        CoreS3.Display.drawRect(x,y,width,height,BLACK);
    }

    bool isPressed(int touchX, int touchY) {
        bool pressed = (touchX >= x && touchX < x + width &&
                        touchY >= y && touchY < y + height);
        if (pressed && !isHighlighted) {
            isHighlighted = true;
            pressTime = millis();
            draw();
            if (onPressed != nullptr) {
                onPressed();
            }
        }
        return pressed;
    }

    void update() {
        if (isHighlighted && millis() - pressTime > 200) {
            isHighlighted = false;
            draw();
        }
    }
};

Button BtnA, BtnB, BtnC;
static m5::touch_state_t prev_state;

void buttonAPressed() {
    Serial.println("Btn A pressed");
    int displayWidth = CoreS3.Display.width();
    int displayHeight = CoreS3.Display.height();
    CoreS3.Display.drawString("Btn A", displayWidth/2, displayHeight/2);
}

void buttonBPressed() {
    Serial.println("Btn B pressed");
    int displayWidth = CoreS3.Display.width();
    int displayHeight = CoreS3.Display.height();
    CoreS3.Display.drawString("Btn B", displayWidth/2, displayHeight/2);
}

void buttonCPressed() {
    Serial.println("Btn C pressed");
    int displayWidth = CoreS3.Display.width();
    int displayHeight = CoreS3.Display.height();
    CoreS3.Display.drawString("Btn C", displayWidth/2, displayHeight/2);
}

void setup(void) {
    Serial.begin(115200);

    auto cfg = M5.config();
    CoreS3.begin(cfg);

    CoreS3.Display.setTextColor(RED);
    CoreS3.Display.setTextDatum(middle_center);
    CoreS3.Display.setFont(&fonts::Orbitron_Light_24);
    CoreS3.Display.setTextSize(1);

    CoreS3.Display.drawString("Touch Button Test", CoreS3.Display.width() / 2, 15);

    int buttonHeight = 40;
    int buttonWidth = CoreS3.Display.width() / 3;
    int buttonY = CoreS3.Display.height() - buttonHeight;

    BtnA = Button("Btn A", buttonWidth*0, buttonY, buttonWidth, buttonHeight, buttonAPressed);
    BtnB = Button("Btn B", buttonWidth*1, buttonY, buttonWidth, buttonHeight, buttonBPressed);
    BtnC = Button("Btn C", buttonWidth*2, buttonY, buttonWidth, buttonHeight, buttonCPressed);
}

void loop(void) {
    CoreS3.update();
    auto touchPoint = CoreS3.Touch.getDetail();

    if (prev_state != touchPoint.state) {
        prev_state = touchPoint.state;
    }

    if (touchPoint.state == m5::touch_state_t::touch_begin) {
        Serial.printf("Touch detected at x:%d, y:%d\n", touchPoint.x, touchPoint.y);
        
        BtnA.isPressed(touchPoint.x, touchPoint.y);
        BtnB.isPressed(touchPoint.x, touchPoint.y);
        BtnC.isPressed(touchPoint.x, touchPoint.y);
    }

    BtnA.update();
    BtnB.update();
    BtnC.update();
}

Discussion