diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b87b12..46ec3ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ project(ptf) # Inclusion des fichiers d'en-tête et de source include_directories(include) -file(GLOB SOURCES "src/*.cpp" "src/*.c") +file(GLOB SOURCES "src/*.cpp" "src/*.c" "src/util/*.cpp") # Affichage de tous les avertisements if(MSVC) diff --git a/include/util/widget_button.hpp b/include/util/widget_button.hpp new file mode 100644 index 0000000..b13009f --- /dev/null +++ b/include/util/widget_button.hpp @@ -0,0 +1,41 @@ +#ifndef __PTF_UTIL_WIDGET_BUTTON_HPP__ +#define __PTF_UTIL_WIDGET_BUTTON_HPP__ + +#include +#include +#include "manager.hpp" + +/** + * Affiche un bouton pouvant être cliqué + */ +class WidgetButton { +private: + Manager& manager; + std::function click_cb; + + unsigned int shape; + sf::RectangleShape button; + sf::VertexArray button_shape; + +public: + static const unsigned int ARROW_UP; + static const unsigned int ARROW_DOWN; + + WidgetButton( + Manager& manager, std::function click_cb, + sf::Vector2f size, unsigned int shape + ); + + /** + * Process l'événement et renvoie true si + * on s'en est servi + */ + bool processEvent(const sf::Event& event); + + /** + * Dessine le widget à la position (haut-gauche) donnée + */ + void draw(sf::Vector2f position); +}; + +#endif diff --git a/include/util/widget_timer.hpp b/include/util/widget_timer.hpp new file mode 100644 index 0000000..e602c74 --- /dev/null +++ b/include/util/widget_timer.hpp @@ -0,0 +1,55 @@ +#ifndef __PTF_UTIL_WIDGET_TIMER_HPP__ +#define __PTF_UTIL_WIDGET_TIMER_HPP__ + +#include +#include +#include "util/widget_button.hpp" +#include "manager.hpp" + +/** + * Affiche le compteur de temps pouvant (ou non) + * être modifié + */ +class WidgetTimer { +private: + Manager& manager; + std::function time_left_cb; + int time_left; + + sf::RectangleShape timer_zone; + sf::Text timer_text; + + WidgetButton timer_up; + WidgetButton timer_down; + +public: + WidgetTimer(Manager& manager, std::function time_left_cb); + + /** + * Process l'événement et renvoie true si + * on s'en est servi + */ + bool processEvent(const sf::Event& event); + + /** + * Dessine le widget à la position (haut-gauche) donnée + */ + void draw(sf::Vector2f position); + + /** + * Augmente le temps de 5 secondes + */ + void addTime(); + + /** + * Diminue le temps de 5 secondes + */ + void subtractTime(); + + /** + * Modifie le temps restant + */ + void setTimeLeft(int set_time_left); +}; + +#endif diff --git a/src/util/widget_button.cpp b/src/util/widget_button.cpp new file mode 100644 index 0000000..8e763e5 --- /dev/null +++ b/src/util/widget_button.cpp @@ -0,0 +1,72 @@ +#include "util/widget_button.hpp" + +const unsigned int WidgetButton::ARROW_UP = 0; +const unsigned int WidgetButton::ARROW_DOWN = 1; + +const sf::Color ARROW_COLOR = sf::Color(33, 33, 33); +const sf::Color CLICKED_COLOR = sf::Color(187, 222, 251); + +WidgetButton::WidgetButton( + Manager& manager, std::function click_cb, + sf::Vector2f size, unsigned int shape +) : manager(manager), click_cb(click_cb), shape(shape), button(size) { + if (shape == WidgetButton::ARROW_UP || shape == WidgetButton::ARROW_DOWN) { + button_shape.setPrimitiveType(sf::Triangles); + button_shape.resize(3); + + button_shape[0].color = ARROW_COLOR; + button_shape[1].color = ARROW_COLOR; + button_shape[2].color = ARROW_COLOR; + } +} + +bool WidgetButton::processEvent(const sf::Event& event) { + if (event.type == sf::Event::MouseButtonPressed) { + sf::Vector2f position(event.mouseButton.x, event.mouseButton.y); + + if (event.mouseButton.button == sf::Mouse::Left) { + // clic gauche sur le bouton : appel de la callback + if (button.getGlobalBounds().contains(position)) { + click_cb(); + return true; + } + } + } + + return false; +} + +void WidgetButton::draw(sf::Vector2f position) { + sf::RenderWindow& window = manager.getWindow(); + + // positionnement du bouton + button.setPosition(position); + sf::FloatRect box = button.getGlobalBounds(); + sf::Vector2f center(box.left + box.width / 2, box.top + box.height / 2); + + if (shape == WidgetButton::ARROW_UP) { + button_shape[0].position = center + sf::Vector2f(-5, 2); + button_shape[1].position = center + sf::Vector2f(5, 2); + button_shape[2].position = center + sf::Vector2f(0, -2); + } + + if (shape == WidgetButton::ARROW_DOWN) { + button_shape[0].position = center + sf::Vector2f(-5, -2); + button_shape[1].position = center + sf::Vector2f(5, -2); + button_shape[2].position = center + sf::Vector2f(0, 2); + } + + // coloration des boutons si enfoncement + button.setFillColor(sf::Color::Transparent); + + if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) { + sf::Vector2f mouse_position = (sf::Vector2f) sf::Mouse::getPosition(window); + + if (button.getGlobalBounds().contains(mouse_position)) { + button.setFillColor(CLICKED_COLOR); + } + } + + window.draw(button); + window.draw(button_shape); +} diff --git a/src/util/widget_timer.cpp b/src/util/widget_timer.cpp new file mode 100644 index 0000000..fe520c9 --- /dev/null +++ b/src/util/widget_timer.cpp @@ -0,0 +1,89 @@ +#include +#include "util/widget_timer.hpp" + +/** + * Formattage du temps en m:ss + */ +std::string formatTime(int time) { + std::string minutes = std::to_string(time / 60); + std::string seconds = std::to_string(time % 60); + + // ajout d'un zéro devant les secondes si nécessaire + if (seconds.size() == 1) { + seconds = "0" + seconds; + } + + return minutes + ":" + seconds; +} + +WidgetTimer::WidgetTimer(Manager& manager, std::function time_left_cb) : + manager(manager), time_left_cb(time_left_cb), timer_zone(sf::Vector2f(100, 32)), + timer_up(manager, std::bind(&WidgetTimer::addTime, this), sf::Vector2f(30, 16), WidgetButton::ARROW_UP), + timer_down(manager, std::bind(&WidgetTimer::addTime, this), sf::Vector2f(30, 16), WidgetButton::ARROW_DOWN) { + + // initialisation des formes + timer_text.setFont(manager.getResourceManager().getFont("main_font.ttf")); + timer_text.setCharacterSize(24); + timer_text.setColor(sf::Color::Black); +} + +bool WidgetTimer::processEvent(const sf::Event& event) { + // gestion des boutons + if (timer_up.processEvent(event)) { + return true; + } + + if (timer_down.processEvent(event)) { + return true; + } + + if (event.type == sf::Event::MouseButtonPressed) { + sf::Vector2f position(event.mouseButton.x, event.mouseButton.y); + + // clic dans le widget : ne rien faire, mais empêcher le traversement + if (timer_zone.getGlobalBounds().contains(position)) { + return true; + } + } + + if (event.type == sf::Event::MouseWheelScrolled && event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel) { + // scroll sur le timer : modification du temps alloué au niveau + sf::Vector2f position(event.mouseWheelScroll.x, event.mouseWheelScroll.y); + + if (timer_zone.getGlobalBounds().contains(position)) { + time_left_cb(time_left + round(event.mouseWheelScroll.delta)); + return true; + } + } + + return false; +} + +void WidgetTimer::draw(sf::Vector2f position) { + sf::RenderWindow& window = manager.getWindow(); + + // zone de fond du timer + timer_zone.setPosition(position); + window.draw(timer_zone); + + // affichage du temps du niveau + timer_text.setPosition(position + sf::Vector2f(35 - round(timer_text.getGlobalBounds().width / 2), 0)); + timer_text.setString(formatTime(time_left)); + window.draw(timer_text); + + // affichage des boutons + timer_up.draw(position + sf::Vector2f(70, 0)); + timer_down.draw(position + sf::Vector2f(70, 16)); +} + +void WidgetTimer::addTime() { + time_left_cb(time_left + 5); +} + +void WidgetTimer::subtractTime() { + time_left_cb(time_left - 5); +} + +void WidgetTimer::setTimeLeft(int set_time_left) { + time_left = set_time_left; +}