| 13 | enum class ButtonState { Normal, Pressed, Disabled }; |
| 14 | |
| 15 | template <Concepts::Drawable T> class Button { |
| 16 | T _drawable; |
| 17 | ButtonDef _def; |
| 18 | ButtonState _state; |
| 19 | std::string _text; |
| 20 | Label _label; |
| 21 | std::function<void()> _onClick; |
| 22 | bool _hasFocus{false}; |
| 23 | bool _canFocus{false}; |
| 24 | Streams::SoundEffect _clickSound; |
| 25 | |
| 26 | void handleMouse(const int x, const int y) { |
| 27 | const auto mouseState = Singletons::getMouseProvider().getMouseState(); |
| 28 | int mouseX, mouseY; |
| 29 | mouseState.getPosition(mouseX, mouseY); |
| 30 | const auto leftMousePressed = mouseState.isButtonPressed(Enums::MouseButton::Left); |
| 31 | |
| 32 | mouseX -= x; |
| 33 | mouseY -= y; |
| 34 | const auto isMouseOver = mouseX >= _def.clickableRect.x && mouseX <= _def.clickableRect.x + _def.clickableRect.w && mouseY >= _def.clickableRect.y && |
| 35 | mouseY <= _def.clickableRect.y + _def.clickableRect.h; |
| 36 | |
| 37 | if (isMouseOver && !leftMousePressed && _hasFocus) { |
| 38 | _onClick(); |
| 39 | _hasFocus = false; |
| 40 | _state = ButtonState::Normal; // TODO: Disabled state |
| 41 | } |
| 42 | |
| 43 | if (isMouseOver && leftMousePressed && !_hasFocus && _canFocus) { |
| 44 | _hasFocus = true; |
| 45 | _clickSound.play(); |
| 46 | } |
| 47 | |
| 48 | if (!_hasFocus) |
| 49 | _canFocus = !leftMousePressed; |
| 50 | |
| 51 | if (!leftMousePressed) { |
| 52 | _hasFocus = false; |
| 53 | _canFocus = true; |
| 54 | } |
| 55 | |
| 56 | _state = isMouseOver && leftMousePressed && _canFocus ? ButtonState::Pressed : ButtonState::Normal; |
| 57 | } |
| 58 | |
| 59 | public: |
| 60 | explicit Button(const ButtonDef &buttonDef, const std::string_view text, const Concepts::FontRenderer &fontRenderer, std::function<void()> onClick) |
| 61 | : _drawable(buttonDef.resourceName), _def(buttonDef), _state(ButtonState::Normal), _text(text), _label(fontRenderer), _onClick(std::move(onClick)), |
| 62 | _clickSound(std::make_unique<Streams::AudioStream>(Singletons::getFileProvider().loadFile(buttonDef.clickSound))) { |
| 63 | _drawable.setPalette(_def.palette); |
| 64 | _label.setText(_text); |
| 65 | } |
| 66 | |
| 67 | auto draw(const int x, const int y) -> void { |
| 68 | handleMouse(x, y); |
| 69 | |
| 70 | auto posX = x; |
| 71 | auto posY = y; |
| 72 | auto frameIdx = -1; |
nothing calls this directly
no outgoing calls
no test coverage detected