diff --git a/include/editor.hpp b/include/editor.hpp index 49243b8..b6cbbd7 100644 --- a/include/editor.hpp +++ b/include/editor.hpp @@ -8,6 +8,16 @@ * niveaux du jeu */ class Editor : public Level { +private: + ObjectPtr selected_object; + +protected: + /** + * Dessine tous les objets, le fond et + * l'interface de l'éditeur + */ + virtual void draw(); + public: Editor(Manager& manager); virtual ~Editor(); diff --git a/include/level.hpp b/include/level.hpp index 34b997d..eea93ad 100644 --- a/include/level.hpp +++ b/include/level.hpp @@ -25,7 +25,7 @@ protected: /** * Dessine tous les objets et le fond à l'écran */ - void draw(); + virtual void draw(); public: Level(Manager& manager); diff --git a/include/manager.hpp b/include/manager.hpp index be28741..c42e48c 100644 --- a/include/manager.hpp +++ b/include/manager.hpp @@ -13,6 +13,7 @@ class Manager { private: sf::RenderWindow window; sf::Clock clock; + sf::View window_view; ResourceManager resource_manager; std::vector events; @@ -53,6 +54,16 @@ public: */ const std::vector& getEvents(); + /** + * Renvoie la vue de la fenêtre (position centrale, taille) + */ + sf::View getWindowView(); + + /** + * Modifie la vue de la fenêtre + */ + void setWindowView(sf::View set_window_view); + /** * Renvoie un booléen attestant de l'appui sur la * touche donnée ou non diff --git a/include/object.hpp b/include/object.hpp index c342e2f..6ade96a 100644 --- a/include/object.hpp +++ b/include/object.hpp @@ -18,6 +18,9 @@ private: mutable float inv_mass; + sf::Sprite selection_sprite; + bool is_selected; + float mass; float charge; float restitution; @@ -192,6 +195,16 @@ 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/res/selection.png b/res/selection.png new file mode 100644 index 0000000..344428e Binary files /dev/null and b/res/selection.png differ diff --git a/src/editor.cpp b/src/editor.cpp index 08b56fd..9020192 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1,9 +1,10 @@ #include +#include #include "editor.hpp" #include "block.hpp" #include "constants.hpp" -Editor::Editor(Manager& manager) : Level(manager) { +Editor::Editor(Manager& manager) : Level(manager), selected_object(nullptr) { // activation de la synchronisation verticale // car, dans l'éditeur, nous n'avons besoin que de dessiner // (pas de mise à jour physique) @@ -22,40 +23,76 @@ 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); - int remove_object_index = -1; - - // recherche d'un objet intersectant la position cliquée - for (unsigned int i = 0; i < objects.size(); i++) { - if (objects[i]->getAABB()->contains(position)) { - remove_object_index = i; - } - } - - if (remove_object_index >= 0) { - // si un objet a été cliqué, on le supprime - objects.erase(objects.begin() + remove_object_index); - } else { - // sinon on crée un nouvel objet à la position cliquée - 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; + 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()->intersects(*object->getAABB())) { - overlaps = true; + 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); + } } } - if (!overlaps) { - objects.push_back(object); + // 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); + } + } + } + + 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); } } } @@ -63,3 +100,13 @@ void Editor::frame() { draw(); } + +void Editor::draw() { + Level::draw(); + + // menu + sf::RectangleShape menu(sf::Vector2f(manager.getWindowView().getSize().x, 64)); + menu.setPosition(sf::Vector2f(0, manager.getWindowView().getSize().y - 64)); + + manager.getWindow().draw(menu); +} diff --git a/src/level.cpp b/src/level.cpp index 805f639..b4547cc 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -123,8 +123,6 @@ void Level::draw() { display_queue.top()->draw(manager); display_queue.pop(); } - - window.display(); } std::string Level::getName() { diff --git a/src/manager.cpp b/src/manager.cpp index da216ab..7bc4524 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -3,7 +3,9 @@ Manager::Manager() : window( sf::VideoMode(704, 480), "Projet CMI", sf::Style::Default, sf::ContextSettings(0, 0, 2) -), view(NULL) {} +), view(NULL) { + window_view = window.getView(); +} void Manager::start() { while (window.isOpen()) { @@ -22,7 +24,7 @@ void Manager::start() { if (event.type == sf::Event::Resized) { // mise à jour de la caméra en fonction de la taille de la fenêtre sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height); - window.setView(sf::View(visibleArea)); + setWindowView(sf::View(visibleArea)); } events.push_back(event); @@ -35,6 +37,7 @@ void Manager::start() { } view->frame(); + window.display(); } } @@ -58,6 +61,15 @@ const std::vector& Manager::getEvents() { return events; } +sf::View Manager::getWindowView() { + return window_view; +} + +void Manager::setWindowView(sf::View set_window_view) { + window.setView(set_window_view); + window_view = set_window_view; +} + bool Manager::isKeyPressed(sf::Keyboard::Key key) const { return sf::Keyboard::isKeyPressed(key) && window.hasFocus(); } diff --git a/src/object.cpp b/src/object.cpp index d0386d2..1d7bcbb 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), + inv_mass(-1.f), is_selected(false), // valeurs par défaut pour les propriétés // de tous les objets du jeu @@ -129,7 +129,16 @@ sf::Vector2f Object::getForces( } 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::updateVelocity( @@ -317,6 +326,25 @@ 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(); }