diff --git a/include/editor.hpp b/include/editor.hpp index d4052c0..40910d9 100644 --- a/include/editor.hpp +++ b/include/editor.hpp @@ -15,8 +15,8 @@ enum class SelectionMode {REPLACE, FLIP, ADD}; class Editor : public Level { private: std::vector selection; - sf::Vector2f drag_start; - sf::Vector2f drag_end; + sf::Vector2i drag_start; + sf::Vector2i drag_end; DragMode drag_mode; WidgetTimer widget_timer; diff --git a/include/level.hpp b/include/level.hpp index afc6e55..84690d0 100644 --- a/include/level.hpp +++ b/include/level.hpp @@ -15,6 +15,7 @@ */ class Level : public View { private: + sf::View camera; sf::String name; int total_time; sf::Sprite background; @@ -32,7 +33,13 @@ protected: * Traite un événement et renvoie true si le * dessin de la frame doit être interrompu */ - virtual bool processEvent(const sf::Event& event) = 0; + virtual bool processEvent(const sf::Event& event); + + /** + * Convertit les coordonnées à l'écran en coordonnées du monde + * d'après la vue caméra + */ + sf::Vector2f convertCoords(sf::Vector2i initial); public: Level(Manager& manager); @@ -95,14 +102,14 @@ public: std::vector>& getZone(); /** - * Récupère le centre de la vue + * Récupère la caméra actuelle */ - sf::Vector2f getViewCenter(); + sf::View getCamera(); /** - * Modifie le centre de la vue + * Modifie la caméra */ - void setViewCenter(sf::Vector2f set_view_center); + void setCamera(sf::View set_camera); }; #endif diff --git a/include/manager.hpp b/include/manager.hpp index 9651610..9b91741 100644 --- a/include/manager.hpp +++ b/include/manager.hpp @@ -15,6 +15,7 @@ private: sf::Clock clock; sf::View window_view; sf::String title; + sf::View default_view; ResourceManager resource_manager; std::vector events; @@ -61,14 +62,9 @@ public: const std::vector& getEvents(); /** - * Renvoie la vue de la fenêtre (position centrale, taille) + * Remet la vue par défaut (zoom 1:1, origine en haut à gauche) */ - sf::View& getWindowView(); - - /** - * Modifie la vue de la fenêtre - */ - void setWindowView(sf::View& set_window_view); + void resetDefaultView(); /** * Renvoie le titre actuel de la fenêtre diff --git a/src/editor.cpp b/src/editor.cpp index db36657..9f31dbe 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -8,6 +8,8 @@ const sf::Color SELECTION_COLOR = sf::Color(33, 33, 33, 40); const sf::Color SELECTION_BORDER_COLOR = sf::Color(33, 33, 33, 127); +const int SCROLL_SPEED = 2; +const int SCROLL_PADDING = 8; Editor::Editor(Manager& manager) : Level(manager), drag_mode(DragMode::NONE), widget_timer(manager, true, std::bind(&Editor::setTotalTime, this, std::placeholders::_1)) {} @@ -34,6 +36,10 @@ bool Editor::frame() { } bool Editor::processEvent(const sf::Event& event) { + if (Level::processEvent(event)) { + return true; + } + // traitement des événements du widget timer if (widget_timer.processEvent(event)) { return false; @@ -41,22 +47,23 @@ bool Editor::processEvent(const sf::Event& event) { // lorsque l'on clique dans l'éditeur if (event.type == sf::Event::MouseButtonPressed) { - sf::Vector2f position(event.mouseButton.x, event.mouseButton.y); + sf::Vector2i mouse_position(event.mouseButton.x, event.mouseButton.y); + sf::Vector2f position = convertCoords(mouse_position); ObjectPtr pointed_object = getObject(position); if (event.mouseButton.button == sf::Mouse::Left) { // clic + shift : sélection par rectangle de sélection if (manager.isKeyPressed(sf::Keyboard::LShift)) { - drag_start = position; - drag_end = position; + drag_start = mouse_position; + drag_end = mouse_position; drag_mode = DragMode::SELECT_RECT; } // clic sur un objet : démarrage de la sélection libre else if (pointed_object != nullptr) { if (manager.isKeyPressed(sf::Keyboard::LControl)) { - drag_start = position; - drag_end = position; + drag_start = mouse_position; + drag_end = mouse_position; drag_mode = DragMode::SELECT_BULK; select(pointed_object, SelectionMode::ADD); @@ -67,8 +74,8 @@ bool Editor::processEvent(const sf::Event& event) { // clic gauche dans le vide : démarrage du placement en drag&drop else { - drag_start = position; - drag_end = position; + drag_start = mouse_position; + drag_end = mouse_position; drag_mode = DragMode::PLACE; select(addObject(position), SelectionMode::REPLACE); @@ -78,8 +85,8 @@ bool Editor::processEvent(const sf::Event& event) { if (event.mouseButton.button == sf::Mouse::Right) { // clic droit sur un objet : démarrage de la suppression en drag&drop if (pointed_object != nullptr) { - drag_start = position; - drag_end = position; + drag_start = mouse_position; + drag_end = mouse_position; drag_mode = DragMode::REMOVE; removeObject(pointed_object); @@ -89,9 +96,11 @@ bool Editor::processEvent(const sf::Event& event) { // lorsqu'on déplace la souris if (event.type == sf::Event::MouseMoved) { - sf::Vector2f position(event.mouseMove.x, event.mouseMove.y); + sf::Vector2i mouse_position(event.mouseMove.x, event.mouseMove.y); + sf::Vector2f position = convertCoords(mouse_position); ObjectPtr pointed_object = getObject(position); - drag_end = position; + + drag_end = mouse_position; // mode placement d'objets if (drag_mode == DragMode::PLACE && pointed_object == nullptr) { @@ -111,11 +120,9 @@ bool Editor::processEvent(const sf::Event& event) { // lorsqu'on relâche un clic dans l'éditeur if (event.type == sf::Event::MouseButtonReleased) { - sf::Vector2f position(event.mouseButton.x, event.mouseButton.y); - // mode sélection rectangulaire : on applique la sélection if (drag_mode == DragMode::SELECT_RECT) { - select(drag_start, drag_end); + select(convertCoords(drag_start), convertCoords(drag_end)); } drag_mode = DragMode::NONE; @@ -155,15 +162,37 @@ bool Editor::processEvent(const sf::Event& event) { } void Editor::draw() { - Level::draw(); - sf::RenderWindow& window = manager.getWindow(); - sf::View window_view = manager.getWindowView(); + sf::Vector2i window_size = (sf::Vector2i) window.getSize(); + + // scroll de la caméra lorsque la souris se situe sur les bords + if (window.hasFocus()) { + sf::View camera = getCamera(); + sf::Vector2i mouse = sf::Mouse::getPosition(window); + + if (mouse.x < SCROLL_PADDING) { + camera.move(sf::Vector2f(-SCROLL_SPEED, 0)); + } else if (mouse.x > window_size.x - SCROLL_PADDING) { + camera.move(sf::Vector2f(SCROLL_SPEED, 0)); + } else if (mouse.y < SCROLL_PADDING) { + camera.move(sf::Vector2f(0, -SCROLL_SPEED)); + } else if (mouse.y > window_size.y - SCROLL_PADDING) { + camera.move(sf::Vector2f(0, SCROLL_SPEED)); + } + + setCamera(camera); + } + + // dessin des objets du niveau + Level::draw(); // dessin du rectangle de sélection if (drag_mode == DragMode::SELECT_RECT) { - sf::RectangleShape selection_rect(drag_end - drag_start); - selection_rect.setPosition(drag_start); + sf::Vector2f size = (sf::Vector2f) (drag_end - drag_start); + sf::Vector2f pos = (sf::Vector2f) drag_start; + + sf::RectangleShape selection_rect(size); + selection_rect.setPosition(pos); selection_rect.setFillColor(SELECTION_COLOR); selection_rect.setOutlineThickness(2.f); selection_rect.setOutlineColor(SELECTION_BORDER_COLOR); @@ -173,11 +202,11 @@ void Editor::draw() { // dessin du widget timer widget_timer.setTimeLeft(getTotalTime()); - widget_timer.draw(sf::Vector2f(window_view.getSize().x / 2 - 50, 0)); + widget_timer.draw(sf::Vector2f(window_size.x / 2 - 50, 0)); // menu - sf::RectangleShape menu(sf::Vector2f(window_view.getSize().x, 64)); - menu.setPosition(sf::Vector2f(0, window_view.getSize().y - 64)); + sf::RectangleShape menu(sf::Vector2f(window_size.x, 64)); + menu.setPosition(sf::Vector2f(0, window_size.y - 64)); window.draw(menu); } diff --git a/src/level.cpp b/src/level.cpp index fc734e0..0834cc7 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -17,9 +17,12 @@ std::map> object_type_map {Block::TYPE_ID, Block::load} }; -Level::Level(Manager& manager) : View(manager), total_time(30) {} +Level::Level(Manager& manager) : View(manager), total_time(30) { + camera = manager.getWindow().getDefaultView(); + camera.setCenter(0, 0); +} + Level::~Level() { - setViewCenter(sf::Vector2f(0, 0)); objects.clear(); } @@ -29,8 +32,8 @@ void Level::load(std::ifstream& file) { objects.clear(); } - // positionnement de la vue au centre - setViewCenter(sf::Vector2f(0, 0)); + // positionnement de la caméra au centre du niveau + camera.setCenter(0, 0); // lecture de la signture du fichier ("BAR") char signature[3]; @@ -132,9 +135,23 @@ bool Level::frame() { return false; } +bool Level::processEvent(const sf::Event& event) { + // lorsque la fenêtre est redimensionnée, mise à jour + // de la taille de la caméra + if (event.type == sf::Event::Resized) { + camera.setSize(event.size.width, event.size.height); + } + + return false; +} + void Level::draw() { - // efface la scène précédente et dessine la couche de fond sf::RenderWindow& window = manager.getWindow(); + + // passage sur la vue caméra + window.setView(camera); + + // efface la scène précédente et dessine la couche de fond window.clear(sf::Color(66, 165, 245)); window.draw(background); @@ -150,6 +167,9 @@ void Level::draw() { display_queue.top()->draw(manager); display_queue.pop(); } + + // passage sur la vue par défaut + manager.resetDefaultView(); } sf::String Level::getName() const { @@ -188,10 +208,21 @@ std::vector>& Level::getZone() { return zone; } -sf::Vector2f Level::getViewCenter() { - return manager.getWindowView().getCenter(); +sf::View Level::getCamera() { + return camera; } -void Level::setViewCenter(sf::Vector2f set_view_center) { - manager.getWindowView().setCenter(set_view_center); +sf::Vector2f Level::convertCoords(sf::Vector2i initial) { + sf::RenderWindow& window = manager.getWindow(); + sf::View old_view = window.getView(); + + window.setView(camera); + sf::Vector2f converted = window.mapPixelToCoords(initial); + window.setView(old_view); + + return converted; +} + +void Level::setCamera(sf::View set_camera) { + camera = set_camera; } diff --git a/src/manager.cpp b/src/manager.cpp index ee57158..45cf6be 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -18,6 +18,12 @@ void Manager::start() { return; } + if (event.type == sf::Event::Resized) { + default_view = sf::View(sf::FloatRect( + 0, 0, event.size.width, event.size.height + )); + } + events.push_back(event); } @@ -56,13 +62,8 @@ 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; +void Manager::resetDefaultView() { + window.setView(default_view); } sf::String Manager::getTitle() {