12#include <SFML/Window/Joystick.hpp>
32 : sf::Mouse::getPosition(
_window);
42 static bool wasPressed =
false;
43 bool isPressed = sf::Mouse::isButtonPressed(sf::Mouse::Button::Left);
45 if (isPressed && !wasPressed) {
49 wasPressed = isPressed;
54 if (
const auto *te = event.getIf<sf::Event::TextEntered>()) {
57 if (
const auto *kp = event.getIf<sf::Event::KeyPressed>()) {
69 auto &buttons = buttonsResult.value().get();
70 for (
const auto &entity : buttons.entities()) {
71 auto &button = buttons[entity];
83 auto dropdownsResult =
85 if (dropdownsResult) {
86 auto &dropdowns = dropdownsResult.value().get();
88 for (
const auto &entity : dropdowns.entities()) {
89 auto &dropdown = dropdowns[entity];
91 if (dropdown.isOpen) {
94 if (optionIndex >= 0) {
95 dropdown.selectedIndex = optionIndex;
96 dropdown.isOpen =
false;
98 if (dropdown.onSelect) {
99 dropdown.onSelect(optionIndex);
109 for (
const auto &entity : dropdowns.entities()) {
110 auto &dropdown = dropdowns[entity];
113 dropdown.isOpen = !dropdown.isOpen;
115 dropdown.isOpen ?
"open" :
"closed");
117 for (
const auto &otherEntity : dropdowns.entities()) {
118 if (otherEntity != entity) {
119 dropdowns[otherEntity].isOpen =
false;
126 bool hadOpenDropdown =
false;
127 for (
const auto &entity : dropdowns.entities()) {
128 if (dropdowns[entity].isOpen) {
129 dropdowns[entity].isOpen =
false;
130 hadOpenDropdown =
true;
133 if (hadOpenDropdown) {
142 auto &inputs = inputsResult.
value().get();
158 bool clickedOnAnyInput =
false;
160 for (
const auto &entity : inputs.entities()) {
162 clickedOnAnyInput =
true;
167 if (clickedOnAnyInput) {
168 for (
const auto &entity : inputs.entities()) {
169 auto &in = inputs[entity];
174 in.showCursor =
true;
175 in.blinkTimer = 0.0f;
177 in.showCursor =
false;
178 in.blinkTimer = 0.0f;
185 bool hadFocus =
false;
186 for (
const auto &entity : inputs.entities()) {
187 auto &in = inputs[entity];
190 in.isFocused =
false;
191 in.showCursor =
false;
192 in.blinkTimer = 0.0f;
204 auto &buttons = buttonsResult.value().get();
206 std::vector<std::pair<
ecs::Entity, std::function<void()>>>
208 for (
const auto &entity : buttons.entities()) {
209 auto &button = buttons[entity];
210 if (!button.onClick && button.text.empty()) {
220 if (button.onClick) {
221 buttonCallbacks.emplace_back(entity, button.onClick);
224 log::info(
"Button '{}' clicked", button.text);
229 for (
auto &[entity, callback] : buttonCallbacks) {
239 auto &sliders = slidersResult.value().get();
240 for (
const auto &entity : sliders.entities()) {
241 auto &slider = sliders[entity];
247 slider.currentValue);
256 const sf::Vector2i &mousePos)
272 const sf::Vector2i &mousePos)
288 const sf::Vector2i &mousePos)
303 const sf::Vector2i &mousePos)
305 float relativeX = mousePos.x - slider.
position.
x;
306 float percentage = std::clamp(relativeX / slider.
size.
x, 0.0f, 1.0f);
318 const sf::Vector2i &mousePos)
320 float optionHeight = dropdown.
size.
y;
323 for (
size_t i = 0; i < dropdown.
options.size(); ++i) {
324 float optionY = startY + i * optionHeight;
336 return static_cast<int>(i);
345 const sf::Vector2i &mousePos)
const
366 auto &inputs = inputsResult.
value().get();
367 for (
const auto &e : inputs.entities()) {
368 inputs[e].isFocused =
false;
369 inputs[e].showCursor =
false;
370 inputs[e].blinkTimer = 0.0f;
381 auto &inputs = inputsResult.
value().get();
383 bool focusedOne =
false;
384 for (
const auto &e : inputs.entities()) {
385 auto &in = inputs[e];
388 in.showCursor =
true;
389 in.blinkTimer = 0.0f;
392 in.isFocused =
false;
393 in.showCursor =
false;
394 in.blinkTimer = 0.0f;
406 auto &inputs = inputsResult.
value().get();
409 for (
const auto &e : inputs.entities()) {
410 auto &in = inputs[e];
413 if (!in.value.empty()) {
416 in.onChange(in.value);
422 for (
const auto &e : inputs.entities()) {
423 auto &in = inputs[e];
427 in.onSubmit(in.value);
439 const char c =
static_cast<char>(unicode);
441 for (
const auto &e : inputs.entities()) {
442 auto &in = inputs[e];
446 if (in.value.size() >= in.maxLength)
449 in.value.push_back(c);
451 in.onChange(in.value);
463 auto &inputs = inputsResult.
value().get();
465 if (key == sf::Keyboard::Key::Escape) {
470 if (key == sf::Keyboard::Key::Backspace) {
471 for (
const auto &e : inputs.entities()) {
472 auto &in = inputs[e];
476 if (!in.value.empty()) {
479 in.onChange(in.value);
485 if (key == sf::Keyboard::Key::Enter) {
486 for (
const auto &e : inputs.entities()) {
487 auto &in = inputs[e];
492 in.onSubmit(in.value);
507 float axisX = sf::Joystick::getAxisPosition(0, sf::Joystick::Axis::X);
508 float axisY = sf::Joystick::getAxisPosition(0, sf::Joystick::Axis::Y);
511 if (std::abs(axisX) > deadzone || std::abs(axisY) > deadzone) {
514 if (std::abs(axisX) > deadzone)
516 if (std::abs(axisY) > deadzone)
521 float povX = sf::Joystick::getAxisPosition(0, sf::Joystick::Axis::PovX);
522 float povY = sf::Joystick::getAxisPosition(0, sf::Joystick::Axis::PovY);
524 if (std::abs(povX) > 50 || std::abs(povY) > 50) {
542 static sf::Vector2i lastMousePos = sf::Mouse::getPosition(
_window);
543 sf::Vector2i currentMousePos = sf::Mouse::getPosition(
_window);
544 if (currentMousePos != lastMousePos) {
547 lastMousePos = currentMousePos;
556 static bool wasValidatePressed =
false;
559 if (isValidatePressed && !wasValidatePressed) {
565 wasValidatePressed = isValidatePressed;
574 sf::CircleShape cursor(12.0f);
576 cursor.setFillColor(sf::Color(0, 0, 0, 0));
577 cursor.setOutlineThickness(3.0f);
578 cursor.setOutlineColor(sf::Color(255, 200, 100));
581 sf::CircleShape dot(4.0f);
583 dot.setFillColor(sf::Color(255, 200, 100));
593 log::error(
"Failed to spawn click sound event entity");
599 clickSound.
soundPath =
"assets/sounds/click.mp3";
600 clickSound.
volume = 100.0f;
601 clickSound.
pitch = 1.0f;
603 log::info(
"Creating click sound event with volume: {}", clickSound.
volume);
Logger declaration with support for multiple log levels.
bool getGamepadEnabled() const
float getGamepadCursorSpeed() const
unsigned int getGamepadValidateButton() const
float getGamepadDeadzone() const
void updateSliderValue(ecs::components::ui::Slider &slider, const sf::Vector2i &mousePos)
void clearAllTextInputFocus()
void handleMouseMove(const sf::Vector2i &mousePos)
sf::RenderWindow & _window
bool isMouseOverTextInput(const ecs::components::ui::TextInput &input, const sf::Vector2i &mousePos) const
ecs::Registry & _registry
void handleGamepadInput()
void handleTextEntered(std::uint32_t unicode)
bool isMouseOverDropdown(const ecs::components::ui::Dropdown &dropdown, const sf::Vector2i &mousePos)
void focusTextInputAt(const sf::Vector2i &mousePos)
void handleEvent(const sf::Event &event)
void update(float dt) override
Update system logic for one frame.
void updateGamepadCursor(float dt)
sf::Vector2f _gamepadCursorPos
void handleKeyPressed(sf::Keyboard::Key key)
bool isMouseOverSlider(const ecs::components::ui::Slider &slider, const sf::Vector2i &mousePos)
bool isMouseOverButton(const ecs::components::ui::Button &button, const sf::Vector2i &mousePos)
void handleMouseClick(const sf::Vector2i &mousePos)
int getDropdownOptionAtMouse(const ecs::components::ui::Dropdown &dropdown, const sf::Vector2i &mousePos)
void renderGamepadCursor(sf::RenderWindow &window)
Represents an entity in the ECS (Entity-Component-System) architecture.
auto spawn(void) -> std::expected< Entity, rtp::Error >
auto add(Entity entity, Args &&...args) -> std::expected< std::reference_wrapper< T >, rtp::Error >
auto get(this const Self &self) -> std::expected< std::reference_wrapper< ConstLike< Self, SparseArray< T > > >, rtp::Error >
void error(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log an error message.
void info(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log an informational message.
Component for triggering one-time sound effects (SFX)
float volume
Volume level (0.0 - 1.0)
std::string soundPath
Path to the sound file.
float pitch
Pitch multiplier.
Component for dropdown menu selection.
Vec2f position
Position of the dropdown.
std::vector< std::string > options
Available options.
Vec2f size
Size of the dropdown button.
Component for a draggable slider control.
Vec2f position
Position of the slider.
float currentValue
Current value.
Vec2f size
Size of the slider.
float minValue
Minimum value.
bool isDragging
Is currently being dragged.
float maxValue
Maximum value.
std::function< void(float)> onChange
Callback when value changes.