diff --git a/include/Cubed/ui/slider.hpp b/include/Cubed/ui/slider.hpp new file mode 100644 index 0000000..b7ada89 --- /dev/null +++ b/include/Cubed/ui/slider.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include "Cubed/ui/image.hpp" +#include "Cubed/ui/widget.hpp" + +namespace Cubed { +class Slider : public Widget { +public: + Slider(Widget* parent); + + Slider& set_slider(float* value, const float& min, const float& max); + + Image& set_track(); + + Image& set_thumb(); + + float width() const override; + float height() const override; + + Slider& set_scale(float scale); + + Slider& set_width(float width); + Slider& set_height(float h); + + bool handle_mouse_move_event(const MouseMoveEvent& e) override; + bool handle_mouse_button_event(const MouseButtonEvent& e) override; + +private: + void update_value(float mouse_x); + + void on_update(float) override; + + void on_render(Renderer& renderer) override; + + std::unique_ptr m_track; + std::unique_ptr m_thumb; + float m_scale = 1.0f; + float m_width = 0.0f; + float m_height = 0.0f; + float m_xpos = 0.0f; + bool m_dragging = false; + bool m_inside = false; + float* m_value = nullptr; + float m_min = 0; + float m_max = 0; +}; +} // namespace Cubed \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba18be4..b44b734 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -73,4 +73,5 @@ target_sources(${PROJECT_NAME} ui/pause_menu_ui_manager.cpp scene/credits_scene.cpp ui/credits_ui.cpp + ui/slider.cpp ) \ No newline at end of file diff --git a/src/ui/button.cpp b/src/ui/button.cpp index ee8c537..0eac515 100644 --- a/src/ui/button.cpp +++ b/src/ui/button.cpp @@ -30,11 +30,7 @@ bool Button::handle_mouse_move_event(const MouseMoveEvent& e) { } m_hovered = false; - if (Widget::handle_mouse_move_event(e)) { - return true; - } - - return false; + return Widget::handle_mouse_move_event(e); } bool Button::handle_mouse_button_event(const MouseButtonEvent& e) { if (e.action == KeyAction::PRESS && e.key == MouseKey::LEFT_BUTTON) { @@ -45,11 +41,7 @@ bool Button::handle_mouse_button_event(const MouseButtonEvent& e) { } } - if (Widget::handle_mouse_button_event(e)) { - return true; - } - - return false; + return Widget::handle_mouse_button_event(e); } Button& Button::set_scale(float scale) { diff --git a/src/ui/slider.cpp b/src/ui/slider.cpp new file mode 100644 index 0000000..419aca6 --- /dev/null +++ b/src/ui/slider.cpp @@ -0,0 +1,135 @@ +#include "Cubed/ui/slider.hpp" + +#include "Cubed/tools/cubed_assert.hpp" +#include "Cubed/tools/log.hpp" + +#include +namespace Cubed { + +Slider::Slider(Widget* parent) : Widget(parent) {} + +Slider& Slider::set_slider(float* value, const float& min, const float& max) { + m_value = value; + m_min = min; + m_max = max; + return *this; +} + +Image& Slider::set_track() { + m_track = std::make_unique(this); + m_track->set_fill(true); + m_track->set_anchor(Anchor::TOP_LEFT); + return *m_track; +} + +Image& Slider::set_thumb() { + m_thumb = std::make_unique(this); + m_thumb->set_height(height()); + m_thumb->set_width(10.0f); + m_thumb->set_anchor(Anchor::TOP_LEFT); + m_thumb->set_scale(m_scale); + return *m_thumb; +} + +float Slider::width() const { return m_width * m_scale; } +float Slider::height() const { return m_height * m_scale; } + +Slider& Slider::set_scale(float scale) { + m_scale = scale; + m_track->set_width(width()).set_height(height()); + m_thumb->set_height(height()); + return *this; +} + +Slider& Slider::set_width(float width) { + if (!m_thumb || width < m_thumb->width()) { + return *this; + } + m_width = width; + return *this; +} + +Slider& Slider::set_height(float h) { + m_height = h; + if (m_thumb) { + m_thumb->set_height(height()); + } + return *this; +} + +bool Slider::handle_mouse_move_event(const MouseMoveEvent& e) { + auto p = pos(); + m_xpos = e.xpos; + if (e.xpos >= p.x && e.xpos <= p.x + width() && e.ypos >= p.y && + e.ypos <= p.y + height()) { + m_inside = true; + } else { + m_inside = false; + } + if (m_dragging && m_value) { + update_value(e.xpos); + return true; + } + return Widget::handle_mouse_move_event(e); +} +bool Slider::handle_mouse_button_event(const MouseButtonEvent& e) { + if (e.action == KeyAction::PRESS && e.key == MouseKey::LEFT_BUTTON) { + if (m_inside) { + m_dragging = true; + update_value(m_xpos); + return true; + } + } + + if (e.action == KeyAction::RELEASE && e.key == MouseKey::LEFT_BUTTON) { + if (m_dragging) { + m_dragging = false; + return true; + } + } + + return Widget::handle_mouse_button_event(e); +} + +void Slider::update_value(float mouse_x) { + if (width() <= 0.0f) { + Logger::info("Slider Width is less then 0"); + return; + } + float t = std::clamp((mouse_x - pos().x) / width(), 0.0f, 1.0f); + + *m_value = m_min + t * (m_max - m_min); +} + +void Slider::on_update(float) { + if (!m_value || !m_thumb || !m_track) { + Logger::error("Please Set value and thumb and track"); + ASSERT(false); + return; + } + float range = m_max - m_min; + if (range <= 0.0f) { + Logger::error("Range {} is <= 0.0f", range); + ASSERT(false); + return; + } + + float t = (*m_value - m_min) / range; + + t = std::clamp(t, 0.0f, 1.0f); + + float offset = t * (width() - m_thumb->width()); + + m_thumb->set_offset({offset, 0}); +} + +void Slider::on_render(Renderer& renderer) { + if (m_track) { + m_track->render(renderer); + } + if (m_thumb) { + m_thumb->render(renderer); + } +} + +} // namespace Cubed \ No newline at end of file