mirror of
https://codeberg.org/armin/sm-26.git
synced 2026-10-11 17:01:53 +02:00
70 lines
2.4 KiB
C
70 lines
2.4 KiB
C
|
|
#pragma once
|
||
|
|
|
||
|
|
#include <JuceHeader.h>
|
||
|
|
|
||
|
|
// Small flat circular button matching the joystick pad's dark style.
|
||
|
|
class RoundNavButton : public juce::Button
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
explicit RoundNavButton (const juce::String& label) : juce::Button (label) {}
|
||
|
|
|
||
|
|
void paintButton (juce::Graphics& g, bool isDown, bool isOver) override
|
||
|
|
{
|
||
|
|
const float w = (float) getWidth();
|
||
|
|
const float h = (float) getHeight();
|
||
|
|
const float cx = w * 0.5f;
|
||
|
|
const float cy = h * 0.5f;
|
||
|
|
const float r = juce::jmin (w, h) * 0.5f - 1.0f;
|
||
|
|
|
||
|
|
g.fillAll (juce::Colour (0xFF000000));
|
||
|
|
|
||
|
|
g.setColour (isDown ? juce::Colour (0xFFECECEC) : juce::Colour (0xFF151515));
|
||
|
|
g.fillEllipse (cx - r, cy - r, r * 2.0f, r * 2.0f);
|
||
|
|
|
||
|
|
g.setColour (isDown ? juce::Colour (0xFFECECEC) : juce::Colour (0xFF242424));
|
||
|
|
g.drawEllipse (cx - r, cy - r, r * 2.0f, r * 2.0f, 1.0f);
|
||
|
|
|
||
|
|
g.setFont (juce::Font (juce::FontOptions { juce::Font::getDefaultMonospacedFontName(),
|
||
|
|
12.0f, isDown ? juce::Font::bold : juce::Font::plain }));
|
||
|
|
g.setColour (isDown ? juce::Colour (0xFF0A0A0A) : juce::Colour (0xFF9A9A9A));
|
||
|
|
g.drawText (getButtonText(), juce::Rectangle<float> (0, 0, w, h), juce::Justification::centred);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// A flat dark virtual-analog joystick pad. A circular well holds four
|
||
|
|
// quarter-circle buttons (up/down/left/right). Holding a direction glows
|
||
|
|
// the matching quarter and emits repeat actions like a gamepad D-pad.
|
||
|
|
class JoystickPad : public juce::Component, private juce::Timer
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
enum Direction : int { None = -1, Up = 0, Down = 1, Left = 2, Right = 3 };
|
||
|
|
|
||
|
|
JoystickPad();
|
||
|
|
~JoystickPad() override = default;
|
||
|
|
|
||
|
|
void paint (juce::Graphics&) override;
|
||
|
|
void mouseDown (const juce::MouseEvent&) override;
|
||
|
|
void mouseDrag (const juce::MouseEvent&) override;
|
||
|
|
void mouseUp (const juce::MouseEvent&) override;
|
||
|
|
|
||
|
|
// Called on press (immediately) and then on repeat while held.
|
||
|
|
std::function<void (int direction)> onAction;
|
||
|
|
|
||
|
|
void setRepeatSpeed (int initialDelayMs, int repeatMs);
|
||
|
|
|
||
|
|
private:
|
||
|
|
void timerCallback() override;
|
||
|
|
void beginHold (int direction);
|
||
|
|
void endHold();
|
||
|
|
int directionFrom (const juce::MouseEvent&) const;
|
||
|
|
|
||
|
|
Direction active = None;
|
||
|
|
int initialDelayMs = 250;
|
||
|
|
int repeatMs = 50;
|
||
|
|
|
||
|
|
int64 holdStartMs = 0;
|
||
|
|
int64 lastFireMs = 0;
|
||
|
|
bool repeatsStarted = false;
|
||
|
|
|
||
|
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JoystickPad)
|
||
|
|
};
|