diff --git a/include/editor.hpp b/include/editor.hpp index 3d4700d..b5c04e9 100644 --- a/include/editor.hpp +++ b/include/editor.hpp @@ -4,10 +4,7 @@ #include #include "level.hpp" #include "widget_timer.hpp" -#include "widget_selector.hpp" - -enum class DragMode {NONE, PLACE, SELECT_RECT, SELECT_BULK, CONTROL_POINT, REMOVE}; -enum class SelectionMode {REPLACE, FLIP, ADD}; +#include "widget_toolbar.hpp" /** * La classe Editor permet l'édition de @@ -15,6 +12,9 @@ enum class SelectionMode {REPLACE, FLIP, ADD}; */ class Editor : public Level { private: + enum class DragMode {NONE, PLACE, SELECT_RECT, SELECT_BULK, CONTROL_POINT, REMOVE}; + enum class SelectionMode {REPLACE, FLIP, ADD}; + std::vector selection; std::vector control_points_circles; @@ -25,7 +25,7 @@ private: DragMode drag_mode; WidgetTimer widget_timer; - WidgetSelector widget_selector; + WidgetToolbar widget_toolbar; /** * Renvoie l'objet pointé à la position donnée diff --git a/include/widget_selector.hpp b/include/widget_selector.hpp deleted file mode 100644 index 7e274d1..0000000 --- a/include/widget_selector.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef __PTF_UTIL_WIDGET_SELECTOR_HPP__ -#define __PTF_UTIL_WIDGET_SELECTOR_HPP__ - -#include -#include -#include "manager.hpp" - -/** - * Un choix possible dans une catégorie - */ -struct SelectorItem { - sf::String name; - sf::Sprite sprite; -}; - -/** - * Représente une catégorie de choix possibles - */ -struct SelectorCategory { - sf::String name; - std::vector> items; - - /** - * Ajoute un nouvel item dans cette catégorie - */ - std::shared_ptr addItem(sf::String name, sf::Texture& texture); -}; - -/** - * Affiche une liste de sélection - */ -class WidgetSelector { -private: - Manager& manager; - - sf::RectangleShape background; - std::vector> categories; - SelectorItem* selected; - -public: - WidgetSelector(Manager& manager); - - /** - * Ajoute une nouvelle catégorie de choix - */ - std::shared_ptr addCategory(sf::String name); - - /** - * Traite l'événement et renvoie true si l'on s'en est servi - */ - bool processEvent(const sf::Event& event); - - /** - * Dessine le widget à la position donnée et avec la taille donnée - */ - void draw(sf::Vector2f position, sf::Vector2f size); -}; - -#endif diff --git a/include/widget_toolbar.hpp b/include/widget_toolbar.hpp new file mode 100644 index 0000000..3e40f0a --- /dev/null +++ b/include/widget_toolbar.hpp @@ -0,0 +1,88 @@ +#ifndef __PTF_UTIL_WIDGET_TOOLBAR_HPP__ +#define __PTF_UTIL_WIDGET_TOOLBAR_HPP__ + +#include +#include +#include "object.hpp" +#include "level.hpp" +#include "manager.hpp" + +/** + * Représente un objet plaçable depuis la barre d'outils + */ +struct ToolbarObject { + typedef std::shared_ptr Ptr; + + sf::Sprite sprite; + std::function create_object; +}; + +/** + * Représente une catégorie d'objets plaçables dans la barre + */ +struct ToolbarCategory { + typedef std::shared_ptr Ptr; + + sf::String name; + std::vector objects; + + /** + * Ajoute un nouvel objet dans cette catégorie + */ + void addObject( + sf::Texture& texture, + std::function create_object + ); +}; + +/** + * Affiche une barre d'outils pour l'éditeur + */ +class WidgetToolbar { +private: + Manager& manager; + + sf::RectangleShape background; + std::vector categories; + ToolbarObject* selected; + + /** + * Crée un objet de type Block + */ + Object::Ptr createBlock(); + + /** + * Crée un objet de type Player + */ + Object::Ptr createPlayer(); + + /** + * Crée un objet de type GravityBlock + */ + Object::Ptr createGravityBlock(GravityDirection direction); + +public: + WidgetToolbar(Manager& manager); + + /** + * Ajoute une nouvelle catégorie de choix + */ + ToolbarCategory::Ptr addCategory(sf::String name); + + /** + * Génère un objet du type actuellement sélectionné et le retourne + */ + Object::Ptr createObject(); + + /** + * Traite l'événement et renvoie true si l'on s'en est servi + */ + bool processEvent(const sf::Event& event); + + /** + * Dessine le widget à la position donnée et avec la taille donnée + */ + void draw(sf::Vector2f position, sf::Vector2f size); +}; + +#endif diff --git a/src/editor.cpp b/src/editor.cpp index db2bb90..c7bd373 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -27,24 +27,12 @@ inline sf::Vector2f roundVectorToGrid(sf::Vector2f input) { } Editor::Editor(Manager& manager) : Level(manager), - drag_control_point(nullptr), drag_mode(DragMode::NONE), + drag_control_point(nullptr), drag_mode(Editor::DragMode::NONE), widget_timer(manager, true, std::bind(&Editor::setTotalTime, this, std::placeholders::_1)), - widget_selector(manager) { + widget_toolbar(manager) { setName("Nouveau niveau"); setTotalTime(30); - - ResourceManager& resources = getResourceManager(); - - std::shared_ptr basic_cat = widget_selector.addCategory("BASE"); - basic_cat->addItem("Block", resources.getTexture("block.tga")); - basic_cat->addItem("Player", resources.getTexture("player.tga")); - - std::shared_ptr gravity_cat = widget_selector.addCategory(sf::String(L"GRAVITÉ")); - gravity_cat->addItem("GravityN", resources.getTexture("gravity_block_north.tga")); - gravity_cat->addItem("GravityE", resources.getTexture("gravity_block_east.tga")); - gravity_cat->addItem("GravityS", resources.getTexture("gravity_block_south.tga")); - gravity_cat->addItem("GravityW", resources.getTexture("gravity_block_west.tga")); } Editor::~Editor() {} @@ -52,24 +40,20 @@ Editor::~Editor() {} void Editor::begin() { Level::begin(); - getResourceManager().stopMusic(); - // TODO: on doit arrêter la musique car celle du - // niveau est chargée par dessous dans level.. C'est sale getResourceManager().playMusic("editor.ogg"); - getWindow().setFramerateLimit(Manager::FPS); } void Editor::processEvent(const sf::Event& event) { Level::processEvent(event); - // traitement des événements du widget timer + // traitement des événements du widget chronomètre if (widget_timer.processEvent(event)) { return; } - // traitement des événements du widget selector - if (widget_selector.processEvent(event)) { + // traitement des événements du widget barre d'outils + if (widget_toolbar.processEvent(event)) { return; } @@ -84,7 +68,7 @@ void Editor::processEvent(const sf::Event& event) { // clic sur un point de contrôle : déplacement du point if (control_point != nullptr) { drag_control_point = control_point; - drag_mode = DragMode::CONTROL_POINT; + drag_mode = Editor::DragMode::CONTROL_POINT; return; } @@ -92,7 +76,7 @@ void Editor::processEvent(const sf::Event& event) { if (getManager().isKeyPressed(Manager::Modifier::SHIFT)) { drag_start = mouse_position; drag_end = mouse_position; - drag_mode = DragMode::SELECT_RECT; + drag_mode = Editor::DragMode::SELECT_RECT; return; } @@ -101,11 +85,11 @@ void Editor::processEvent(const sf::Event& event) { if (getManager().isKeyPressed(Manager::Modifier::CONTROL)) { drag_start = mouse_position; drag_end = mouse_position; - drag_mode = DragMode::SELECT_BULK; + drag_mode = Editor::DragMode::SELECT_BULK; - select(pointed_object, SelectionMode::ADD); + select(pointed_object, Editor::SelectionMode::ADD); } else { - select(pointed_object, SelectionMode::FLIP); + select(pointed_object, Editor::SelectionMode::FLIP); } return; @@ -114,9 +98,9 @@ void Editor::processEvent(const sf::Event& event) { // clic gauche dans le vide : démarrage du placement en drag&drop drag_start = mouse_position; drag_end = mouse_position; - drag_mode = DragMode::PLACE; + drag_mode = Editor::DragMode::PLACE; - select(addObject(position), SelectionMode::REPLACE); + select(addObject(position), Editor::SelectionMode::REPLACE); } if (event.mouseButton.button == sf::Mouse::Right) { @@ -130,7 +114,7 @@ void Editor::processEvent(const sf::Event& event) { if (pointed_object != nullptr) { drag_start = mouse_position; drag_end = mouse_position; - drag_mode = DragMode::REMOVE; + drag_mode = Editor::DragMode::REMOVE; removeObject(pointed_object); return; @@ -147,23 +131,23 @@ void Editor::processEvent(const sf::Event& event) { drag_end = mouse_position; // mode déplacement de point de contrôle - if (drag_mode == DragMode::CONTROL_POINT) { + if (drag_mode == Editor::DragMode::CONTROL_POINT) { *drag_control_point = roundVectorToGrid(position); } // mode placement d'objets - if (drag_mode == DragMode::PLACE && pointed_object == nullptr) { - select(addObject(position), SelectionMode::ADD); + if (drag_mode == Editor::DragMode::PLACE && pointed_object == nullptr) { + select(addObject(position), Editor::SelectionMode::ADD); } // mode suppression d'objets - if (drag_mode == DragMode::REMOVE && pointed_object != nullptr) { + if (drag_mode == Editor::DragMode::REMOVE && pointed_object != nullptr) { removeObject(pointed_object); } // mode sélection libre : on l'objet à la sélection - if (drag_mode == DragMode::SELECT_BULK) { - select(position, SelectionMode::ADD); + if (drag_mode == Editor::DragMode::SELECT_BULK) { + select(position, Editor::SelectionMode::ADD); } return; @@ -172,12 +156,11 @@ void Editor::processEvent(const sf::Event& event) { // lorsqu'on relâche un clic dans l'éditeur if (event.type == sf::Event::MouseButtonReleased) { // mode sélection rectangulaire : on applique la sélection - if (drag_mode == DragMode::SELECT_RECT) { + if (drag_mode == Editor::DragMode::SELECT_RECT) { select(pixelToCoords(drag_start), pixelToCoords(drag_end)); - return; } - drag_mode = DragMode::NONE; + drag_mode = Editor::DragMode::NONE; } // lorsqu'on scrolle on déplace la vue @@ -291,7 +274,7 @@ void Editor::draw() { getManager().resetDefaultView(); // dessin du rectangle de sélection - if (drag_mode == DragMode::SELECT_RECT) { + if (drag_mode == Editor::DragMode::SELECT_RECT) { sf::Vector2f size = (sf::Vector2f) (drag_end - drag_start); sf::Vector2f pos = (sf::Vector2f) drag_start; @@ -308,8 +291,8 @@ void Editor::draw() { widget_timer.setTimeLeft(getTotalTime()); widget_timer.draw(sf::Vector2f(window_size.x / 2 - 50, 0)); - // sélectionneur d'objet - widget_selector.draw( + // barre d'outils + widget_toolbar.draw( sf::Vector2f(window_size.x - 64, 0), sf::Vector2f(64, window_size.y) ); @@ -345,8 +328,7 @@ Object::Ptr Editor::addObject(sf::Vector2f position) { // on arrondit à l'unité de grille la plus proche position = roundVectorToGrid(position); - // TODO: ajouter un objet du type choisi, pas uniquement de bloc - Object::Ptr object = Object::Ptr(new Block); + Object::Ptr object = widget_toolbar.createObject(); object->setPosition(position); // avant d'ajouter l'objet, on vérifie qu'il ne soit @@ -402,7 +384,7 @@ void Editor::removeObject(sf::Vector2f position) { removeObject(getObject(position)); } -void Editor::select(Object::Ptr object, SelectionMode mode) { +void Editor::select(Object::Ptr object, Editor::SelectionMode mode) { if (object == nullptr) { return; } @@ -412,25 +394,25 @@ void Editor::select(Object::Ptr object, SelectionMode mode) { // dans les modes REPLACE et FLIP, on remplace l'ancienne sélection // pour REPLACE, on sélectionne forcément l'objet // pour FLIP, on le sélectionne s'il ne l'est pas, on le désélectionne sinon - if (mode == SelectionMode::REPLACE || mode == SelectionMode::FLIP) { + if (mode == Editor::SelectionMode::REPLACE || mode == Editor::SelectionMode::FLIP) { clearSelection(); // on resélectionne l'objet ssi. on force la sélection // ou s'il n'était pas déjà sélectionné - if (!already_selected || mode == SelectionMode::REPLACE) { + if (!already_selected || mode == Editor::SelectionMode::REPLACE) { object->setSelected(true); selection.push_back(object); } } // dans le mode ADD, on rajoute juste l'objet à la sélection - if (mode == SelectionMode::ADD && !already_selected) { + if (mode == Editor::SelectionMode::ADD && !already_selected) { object->setSelected(true); selection.push_back(object); } } -void Editor::select(sf::Vector2f position, SelectionMode mode) { +void Editor::select(sf::Vector2f position, Editor::SelectionMode mode) { select(getObject(position), mode); } @@ -448,7 +430,7 @@ void Editor::select(sf::Vector2f top_left, sf::Vector2f bottom_right) { // sélection des éléments intersectant le rectangle for (unsigned int i = 0; i < objects.size(); i++) { if (objects[i]->getAABB().intersects(selection_rect)) { - select(objects[i], SelectionMode::ADD); + select(objects[i], Editor::SelectionMode::ADD); } } } diff --git a/src/game.cpp b/src/game.cpp index e75e0f7..02e4f35 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -13,6 +13,12 @@ Game::~Game() {} void Game::begin() { Level::begin(); + if (getMusic() != "") { + getResourceManager().playMusic(getMusic()); + } else { + getResourceManager().stopMusic(); + } + mode = Game::Mode::NORMAL; getWindow().setFramerateLimit(0); } diff --git a/src/level.cpp b/src/level.cpp index 487fdb1..3f9f09c 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -202,12 +202,6 @@ void Level::begin() { camera.setCenter(0, 0); camera_angle = 180.f; gravity_direction = GravityDirection::SOUTH; - - if (music != "") { - getResourceManager().playMusic(music); - } else { - getResourceManager().stopMusic(); - } } void Level::processEvent(const sf::Event& event) { diff --git a/src/widget_selector.cpp b/src/widget_selector.cpp deleted file mode 100644 index 47e36a6..0000000 --- a/src/widget_selector.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "widget_selector.hpp" -#include - -const int PADDING = 8; - -WidgetSelector::WidgetSelector(Manager& manager) : manager(manager), selected(NULL) { - // -} - -std::shared_ptr WidgetSelector::addCategory(sf::String name) { - auto cat = std::shared_ptr(new SelectorCategory); - cat->name = name; - - categories.push_back(cat); - return cat; -} - -std::shared_ptr SelectorCategory::addItem(sf::String name, sf::Texture& texture) { - auto item = std::shared_ptr(new SelectorItem); - item->sprite.setTexture(texture, true); - float width = item->sprite.getLocalBounds().width; - - // mise à l'échelle si trop grand ou trop petit - if (width < 20 || width > 28) { - item->sprite.scale(24 / width, 24 / width); - width = 24; - } - - item->name = name; - items.push_back(item); - return item; -} - -bool WidgetSelector::processEvent(const sf::Event& event) { - if (event.type == sf::Event::MouseButtonPressed) { - sf::Vector2f position(event.mouseButton.x, event.mouseButton.y); - - // clic gauche sur un item : on le sélectionne - if (event.mouseButton.button == sf::Mouse::Left) { - for (unsigned int i = 0; i < categories.size(); i++) { - for (unsigned int j = 0; j < categories[i]->items.size(); j++) { - if (categories[i]->items[j]->sprite.getGlobalBounds().contains(position)) { - selected = categories[i]->items[j].get(); - return true; - } - } - } - - // ne pas laisser traverser les clics sur le sélecteur - if (background.getGlobalBounds().contains(position)) { - return true; - } - } - } - - return false; -} - -void WidgetSelector::draw(sf::Vector2f position, sf::Vector2f size) { - sf::RenderWindow& window = manager.getWindow(); - - background.setSize(size); - background.setPosition(position); - window.draw(background); - - float total_y = PADDING; - - for (unsigned int i = 0; i < categories.size(); i++) { - std::shared_ptr category = categories[i]; - - // affichage du label de la catégorie - sf::Text category_label( - category->name, - manager.getResourceManager().getFont("raleway.ttf"), 12 - ); - - category_label.setColor(sf::Color::Black); - category_label.setPosition(position + sf::Vector2f( - floor(size.x / 2 - category_label.getGlobalBounds().width / 2), - total_y - )); - - window.draw(category_label); - - for (unsigned int j = 0; j < category->items.size(); j++) { - total_y += PADDING + 24; - - std::shared_ptr item = category->items[j]; - sf::Vector2f sprite_position = position + sf::Vector2f( - size.x / 2 - item->sprite.getGlobalBounds().width / 2, - total_y - ); - - // affichage du sprite de l'item - item->sprite.setPosition(sprite_position); - window.draw(item->sprite); - } - - total_y += 64; - } -} diff --git a/src/widget_toolbar.cpp b/src/widget_toolbar.cpp new file mode 100644 index 0000000..ecbf540 --- /dev/null +++ b/src/widget_toolbar.cpp @@ -0,0 +1,158 @@ +#include "widget_toolbar.hpp" +#include "block.hpp" +#include "player.hpp" +#include "gravity_block.hpp" +#include + +const int PADDING = 8; + +ToolbarCategory::Ptr WidgetToolbar::addCategory(sf::String name) { + auto cat = ToolbarCategory::Ptr(new ToolbarCategory); + cat->name = name; + categories.push_back(cat); + return cat; +} + +void ToolbarCategory::addObject( + sf::Texture& texture, + std::function create_object +) { + auto object = std::shared_ptr(new ToolbarObject); + + object->sprite.setTexture(texture, true); + object->create_object = create_object; + objects.push_back(object); +} + +Object::Ptr WidgetToolbar::createBlock() { + return Object::Ptr(new Block); +} + +Object::Ptr WidgetToolbar::createPlayer() { + return Object::Ptr(new Player); +} + +Object::Ptr WidgetToolbar::createGravityBlock(GravityDirection direction) { + GravityBlock::Ptr gravity_block = GravityBlock::Ptr(new GravityBlock); + gravity_block->setGravityDirection(direction); + return std::dynamic_pointer_cast(gravity_block); +} + +Object::Ptr WidgetToolbar::createObject() { + return selected->create_object(); +} + +WidgetToolbar::WidgetToolbar(Manager& manager) : manager(manager), selected(NULL) { + // catégorie des objets plaçables de base + ResourceManager& resources = manager.getResourceManager(); + ToolbarCategory::Ptr basic_cat = addCategory("BASE"); + + basic_cat->addObject( + resources.getTexture("toolbar_block.tga"), + std::bind(&WidgetToolbar::createBlock, this) + ); + + basic_cat->addObject( + resources.getTexture("toolbar_player.tga"), + std::bind(&WidgetToolbar::createPlayer, this) + ); + + // catégorie des blocs changeant la gravité + ToolbarCategory::Ptr gravity_cat = addCategory(L"GRAVITÉ"); + + gravity_cat->addObject( + resources.getTexture("toolbar_gravity_block_north.tga"), + std::bind(&WidgetToolbar::createGravityBlock, this, GravityDirection::NORTH) + ); + + gravity_cat->addObject( + resources.getTexture("toolbar_gravity_block_east.tga"), + std::bind(&WidgetToolbar::createGravityBlock, this, GravityDirection::EAST) + ); + + gravity_cat->addObject( + resources.getTexture("toolbar_gravity_block_south.tga"), + std::bind(&WidgetToolbar::createGravityBlock, this, GravityDirection::SOUTH) + ); + + gravity_cat->addObject( + resources.getTexture("toolbar_gravity_block_west.tga"), + std::bind(&WidgetToolbar::createGravityBlock, this, GravityDirection::WEST) + ); +} + +bool WidgetToolbar::processEvent(const sf::Event& event) { + if (event.type == sf::Event::MouseButtonPressed) { + sf::Vector2f position(event.mouseButton.x, event.mouseButton.y); + + // clic gauche sur un item : on le sélectionne + if (event.mouseButton.button == sf::Mouse::Left) { + for (unsigned int i = 0; i < categories.size(); i++) { + for (unsigned int j = 0; j < categories[i]->objects.size(); j++) { + if (categories[i]->objects[j]->sprite.getGlobalBounds().contains(position)) { + selected = categories[i]->objects[j].get(); + return true; + } + } + } + + // ne pas laisser traverser les clics sur la barre d'outils + if (background.getGlobalBounds().contains(position)) { + return true; + } + } + } + + return false; +} + +void WidgetToolbar::draw(sf::Vector2f position, sf::Vector2f size) { + sf::RenderWindow& window = manager.getWindow(); + + background.setSize(size); + background.setPosition(position); + window.draw(background); + + float total_y = PADDING; + + for (unsigned int i = 0; i < categories.size(); i++) { + std::shared_ptr category = categories[i]; + + // affichage du label de la catégorie + sf::Text category_label( + category->name, + manager.getResourceManager().getFont("raleway.ttf"), 12 + ); + + category_label.setColor(sf::Color::Black); + category_label.setPosition(position + sf::Vector2f( + floor(size.x / 2 - category_label.getGlobalBounds().width / 2), + total_y + )); + + window.draw(category_label); + + for (unsigned int j = 0; j < category->objects.size(); j++) { + total_y += PADDING + 32; + + std::shared_ptr object = category->objects[j]; + sf::Vector2f sprite_position = position + sf::Vector2f( + size.x / 2 - object->sprite.getGlobalBounds().width / 2, + total_y + ); + + if (selected == object.get()) { + sf::RectangleShape selection_rectangle(sf::Vector2f(32, 32)); + selection_rectangle.setPosition(sprite_position + sf::Vector2f(-4, -4)); + selection_rectangle.setFillColor(sf::Color(0, 0, 0, 20)); + window.draw(selection_rectangle); + } + + // affichage du sprite de l'objet + object->sprite.setPosition(sprite_position); + window.draw(object->sprite); + } + + total_y += 64; + } +}