From cb3e02ff4afcfda7453a800b06d14dfadb808096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Delabre?= Date: Tue, 5 Apr 2016 19:27:37 +0200 Subject: [PATCH] =?UTF-8?q?Gestion=20de=20la=20s=C3=A9lection=20en=20exter?= =?UTF-8?q?ne=20des=20objets=20&=20multis=C3=A9lection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/editor.hpp | 21 +++++- include/object.hpp | 13 ---- src/editor.cpp | 176 +++++++++++++++++++++++++++------------------ src/object.cpp | 34 +-------- 4 files changed, 127 insertions(+), 117 deletions(-) diff --git a/include/editor.hpp b/include/editor.hpp index b6cbbd7..c077155 100644 --- a/include/editor.hpp +++ b/include/editor.hpp @@ -1,6 +1,7 @@ #ifndef __PTF_GAME_HPP__ #define __PTF_GAME_HPP__ +#include #include "level.hpp" /** @@ -9,7 +10,25 @@ */ class Editor : public Level { private: - ObjectPtr selected_object; + std::unordered_map selection; + + /** + * Ajoute un objet du type actuel à la position donnée + */ + void addObject(sf::Vector2f position); + + /** + * Supprime les objets passant par la position donnée + */ + void removeObject(sf::Vector2f position); + + /** + * Met à jour la sélection avec la position donnée : + * - si la position correspond à un objet, si cet objet n'est + * pas sélectionné on le sélectionne, sinon on le désélectionne + * - si la sélection est modifiée, renvoie true, sinon false + */ + bool updateSelection(sf::Vector2f position); protected: /** diff --git a/include/object.hpp b/include/object.hpp index 6ade96a..c342e2f 100644 --- a/include/object.hpp +++ b/include/object.hpp @@ -18,9 +18,6 @@ private: mutable float inv_mass; - sf::Sprite selection_sprite; - bool is_selected; - float mass; float charge; float restitution; @@ -195,16 +192,6 @@ public: * Modifie la couche d'affichage de l'objet */ void setLayer(int set_layer); - - /** - * Récupère si l'objet est actuellement sélectionné - */ - bool isSelected() const; - - /** - * Sélectionne ou désélectionne l'objet - */ - void setSelected(bool set_selected); }; /** diff --git a/src/editor.cpp b/src/editor.cpp index 9020192..aaedf70 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1,10 +1,9 @@ #include -#include #include "editor.hpp" #include "block.hpp" #include "constants.hpp" -Editor::Editor(Manager& manager) : Level(manager), selected_object(nullptr) { +Editor::Editor(Manager& manager) : Level(manager) { // activation de la synchronisation verticale // car, dans l'éditeur, nous n'avons besoin que de dessiner // (pas de mise à jour physique) @@ -15,7 +14,6 @@ Editor::~Editor() {} void Editor::frame() { const std::vector& events = manager.getEvents(); - std::vector& objects = getObjects(); for (unsigned int i = 0; i < events.size(); i++) { const sf::Event& event = events[i]; @@ -23,77 +21,18 @@ void Editor::frame() { // lorsque l'on clique dans l'éditeur if (event.type == sf::Event::MouseButtonPressed) { sf::Vector2f position(event.mouseButton.x, event.mouseButton.y); - bool selection_changed = false; if (event.mouseButton.button == sf::Mouse::Left) { - // recherche d'un objet intersectant la position cliquée - // et le sélectionne si c'est le cas - for (unsigned int i = 0; i < objects.size(); i++) { - if (objects[i]->getAABB()->contains(position)) { - selection_changed = true; - - // si l'objet n'est pas sélectionné, on le sélectionne - // sinon on le désélectionne - if (objects[i]->isSelected()) { - objects[i]->setSelected(false); - selected_object = nullptr; - } else { - // désélection du précédent objet (si applicable) - if (selected_object != nullptr) { - selected_object->setSelected(false); - } - - selected_object = objects[i]; - objects[i]->setSelected(true); - } - } - } - - // si aucune opération de sélection, on - // crée un nouvel objet à la position cliquée - if (!selection_changed) { - // on désélectionne tout objet sélectionné - if (selected_object != nullptr) { - selected_object->setSelected(false); - selected_object = nullptr; - } - - position /= Constants::GRID; - position.x = round(position.x); - position.y = round(position.y); - position *= Constants::GRID; - - std::shared_ptr object = std::shared_ptr(new Block); - object->setPosition(position); - - // avant d'ajouter l'objet, on vérifie qu'il ne soit - // pas superposé à un autre - float overlaps = false; - - for (unsigned int i = 0; i < objects.size(); i++) { - if (objects[i]->getAABB()->intersects(*object->getAABB())) { - overlaps = true; - } - } - - if (!overlaps) { - objects.push_back(object); - } + // clic gauche : on met à jour la sélection, + // si aucune mise à jour n'est à faire, on ajoute un objet + if (!updateSelection(position)) { + addObject(position); } } if (event.mouseButton.button == sf::Mouse::Right) { - int remove_object_index = -1; - - for (unsigned int i = 0; i < objects.size(); i++) { - if (objects[i]->getAABB()->contains(position)) { - remove_object_index = i; - } - } - - if (remove_object_index >= 0) { - objects.erase(objects.begin() + remove_object_index); - } + // clic droit : on supprime l'objet pointé + removeObject(position); } } } @@ -103,10 +42,105 @@ void Editor::frame() { void Editor::draw() { Level::draw(); + sf::RenderWindow& window = manager.getWindow(); + sf::View window_view = manager.getWindowView(); + sf::Color selection_color(255, 50, 41); + + // on dessine des carrés de sélection autour des objets sélectionnés + for (auto iter = selection.begin(); iter != selection.end(); iter++) { + sf::VertexArray selection(sf::LinesStrip, 5); + std::unique_ptr aabb = iter->first->getAABB(); + + selection[0].position = sf::Vector2f(aabb->left - .5f, aabb->top - .5f); + selection[0].color = selection_color; + selection[1].position = sf::Vector2f(aabb->left + aabb->width + .5f, aabb->top - .5f); + selection[1].color = selection_color; + selection[2].position = sf::Vector2f(aabb->left + aabb->width + .5f, aabb->top + aabb->height + .5f); + selection[2].color = selection_color; + selection[3].position = sf::Vector2f(aabb->left - .5f, aabb->top + aabb->height + .5f); + selection[3].color = selection_color; + selection[4].position = sf::Vector2f(aabb->left - .5f, aabb->top - .5f); + selection[4].color = selection_color; + + window.draw(selection); + } // menu - sf::RectangleShape menu(sf::Vector2f(manager.getWindowView().getSize().x, 64)); - menu.setPosition(sf::Vector2f(0, manager.getWindowView().getSize().y - 64)); + sf::RectangleShape menu(sf::Vector2f(window_view.getSize().x, 64)); + menu.setPosition(sf::Vector2f(0, window_view.getSize().y - 64)); - manager.getWindow().draw(menu); + window.draw(menu); +} + +void Editor::addObject(sf::Vector2f position) { + std::vector& objects = getObjects(); + + // si demandé, on arrondit à l'unité de grille la plus proche + position /= Constants::GRID; + position.x = round(position.x); + position.y = round(position.y); + position *= Constants::GRID; + + // TODO: ajouter un objet du type choisi, pas uniquement de bloc + std::shared_ptr object = std::shared_ptr(new Block); + object->setPosition(position); + + // avant d'ajouter l'objet, on vérifie qu'il ne soit + // pas superposé à un autre + float overlaps = false; + + for (unsigned int i = 0; i < objects.size(); i++) { + if (objects[i]->getAABB()->intersects(*object->getAABB())) { + overlaps = true; + } + } + + if (!overlaps) { + objects.push_back(object); + updateSelection(position); + } +} + +void Editor::removeObject(sf::Vector2f position) { + std::vector& objects = getObjects(); + int remove_object_index = -1; + + for (unsigned int i = 0; i < objects.size(); i++) { + if (objects[i]->getAABB()->contains(position)) { + remove_object_index = i; + } + } + + if (remove_object_index >= 0) { + selection.erase(objects[remove_object_index]); + objects.erase(objects.begin() + remove_object_index); + } +} + +bool Editor::updateSelection(sf::Vector2f position) { + std::vector& objects = getObjects(); + bool has_changed = false; + bool multi = manager.isKeyPressed(sf::Keyboard::LShift); + + for (unsigned int i = 0; i < objects.size(); i++) { + if (objects[i]->getAABB()->contains(position)) { + has_changed = true; + + // si l'objet n'est pas sélectionné, on le sélectionne + // sinon on le désélectionne + if (selection.count(objects[i])) { + selection.erase(objects[i]); + } else { + // avant de sélectionner le nouvel objet, on + // vide la sélection si on n'est pas en mode multi + if (!multi) { + selection.clear(); + } + + selection[objects[i]] = true; + } + } + } + + return has_changed; } diff --git a/src/object.cpp b/src/object.cpp index 1d7bcbb..a0a280e 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -11,7 +11,7 @@ const unsigned int Object::PROP_LAYER = 6; Object::Object() : acceleration(0, 0), velocity(0, 0), position(0, 0), - inv_mass(-1.f), is_selected(false), + inv_mass(-1.f), // valeurs par défaut pour les propriétés // de tous les objets du jeu @@ -128,18 +128,7 @@ sf::Vector2f Object::getForces( return forces; } -void Object::draw(Manager& manager) { - // si l'objet est sélectionné, dessin de la texture de sélection - if (isSelected()) { - selection_sprite.setOrigin(sf::Vector2f(22, 22)); - selection_sprite.setPosition(getPosition()); - selection_sprite.setTexture( - manager.getResourceManager().getTexture("selection.png") - ); - - manager.getWindow().draw(selection_sprite); - } -} +void Object::draw(Manager& manager) {} void Object::updateVelocity( const Manager& manager, const std::vector& objects, float delta @@ -326,25 +315,6 @@ void Object::setLayer(int set_layer) { layer = set_layer; } -bool Object::isSelected() const { - return is_selected; -} - -void Object::setSelected(bool set_selected) { - is_selected = set_selected; -} - bool ObjectCompare::operator()(ObjectPtr const &t1, ObjectPtr const &t2) const { - // détermine la priorité de dessin des objets - // - si un objet est sélectionné, il est prioritaire - // - sinon, l'objet de la plus haute couche est prioritaire - if (t1->isSelected()) { - return true; - } - - if (t2->isSelected()) { - return false; - } - return t1->getLayer() > t2->getLayer(); }