Gestion améliorée de la caméra

This commit is contained in:
Mattéo Delabre 2016-04-08 02:21:19 +02:00
parent c560073c5f
commit 266c0529d9
6 changed files with 116 additions and 52 deletions

View File

@ -15,8 +15,8 @@ enum class SelectionMode {REPLACE, FLIP, ADD};
class Editor : public Level {
private:
std::vector<ObjectPtr> selection;
sf::Vector2f drag_start;
sf::Vector2f drag_end;
sf::Vector2i drag_start;
sf::Vector2i drag_end;
DragMode drag_mode;
WidgetTimer widget_timer;

View File

@ -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<std::pair<float, float>>& 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

View File

@ -15,6 +15,7 @@ private:
sf::Clock clock;
sf::View window_view;
sf::String title;
sf::View default_view;
ResourceManager resource_manager;
std::vector<sf::Event> events;
@ -61,14 +62,9 @@ public:
const std::vector<sf::Event>& 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

View File

@ -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);
}

View File

@ -17,9 +17,12 @@ std::map<unsigned int, std::function<ObjectPtr(std::ifstream&)>> 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<std::pair<float, float>>& 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;
}

View File

@ -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<sf::Event>& 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() {