Ajout la possibilité d'interrompre la frame pour éviter segfault

This commit is contained in:
Mattéo Delabre 2016-04-08 00:19:01 +02:00
parent ddbd125f8f
commit c560073c5f
11 changed files with 186 additions and 91 deletions

View File

@ -49,16 +49,21 @@ private:
void select(sf::Vector2f position, SelectionMode mode); void select(sf::Vector2f position, SelectionMode mode);
void select(sf::Vector2f top_left, sf::Vector2f bottom_right); void select(sf::Vector2f top_left, sf::Vector2f bottom_right);
/**
* Vide la sélection
*/
void clearSelection();
/**
* Sélectionne tout
*/
void selectAll();
/** /**
* Lance le test du niveau * Lance le test du niveau
*/ */
void test(); void test();
/**
* Traite l'événement et renvoie true si on s'en est servi
*/
bool processEvent(const sf::Event& event);
protected: protected:
/** /**
* Dessine tous les objets, le fond et * Dessine tous les objets, le fond et
@ -66,20 +71,26 @@ protected:
*/ */
virtual void draw(); virtual void draw();
/**
* Traite un événement et renvoie true si le
* dessin de la frame doit être interrompu
*/
virtual bool processEvent(const sf::Event& event);
public: public:
Editor(Manager& manager); Editor(Manager& manager);
virtual ~Editor(); virtual ~Editor();
/**
* Demande le passage à la frame suivante sur cette vue,
* renvoie true si le rendu de la frame a é interrompu
*/
virtual bool frame();
/** /**
* Charge un niveau de jeu depuis le fichier donné * Charge un niveau de jeu depuis le fichier donné
*/ */
virtual void load(std::ifstream& file); virtual void load(std::ifstream& file);
/**
* Demande le passage à la frame suivante sur
* cette vue
*/
void frame();
}; };
#endif #endif

View File

@ -28,6 +28,12 @@ protected:
*/ */
virtual void draw(); virtual void draw();
/**
* Traite un événement et renvoie true si le
* dessin de la frame doit être interrompu
*/
virtual bool processEvent(const sf::Event& event);
public: public:
Game(Manager& manager); Game(Manager& manager);
virtual ~Game(); virtual ~Game();
@ -38,10 +44,10 @@ public:
virtual void load(std::ifstream& file); virtual void load(std::ifstream& file);
/** /**
* Demande le passage à la frame suivante sur * Demande le passage à la frame suivante sur cette vue,
* cette vue * renvoie true si le rendu de la frame a é interrompu
*/ */
void frame(); virtual bool frame();
/** /**
* Mise en mode test : l'appui sur espace renvoie * Mise en mode test : l'appui sur espace renvoie

View File

@ -28,6 +28,12 @@ protected:
*/ */
virtual void draw(); virtual void draw();
/**
* Traite un événement et renvoie true si le
* dessin de la frame doit être interrompu
*/
virtual bool processEvent(const sf::Event& event) = 0;
public: public:
Level(Manager& manager); Level(Manager& manager);
virtual ~Level(); virtual ~Level();
@ -42,6 +48,12 @@ public:
*/ */
virtual void save(); virtual void save();
/**
* Demande le passage à la frame suivante sur
* cette vue
*/
virtual bool frame();
/** /**
* Récupère le nom du niveau * Récupère le nom du niveau
*/ */
@ -81,6 +93,16 @@ public:
* Récupère la zone du niveau * Récupère la zone du niveau
*/ */
std::vector<std::pair<float, float>>& getZone(); std::vector<std::pair<float, float>>& getZone();
/**
* Récupère le centre de la vue
*/
sf::Vector2f getViewCenter();
/**
* Modifie le centre de la vue
*/
void setViewCenter(sf::Vector2f set_view_center);
}; };
#endif #endif

View File

@ -63,12 +63,12 @@ public:
/** /**
* Renvoie la vue de la fenêtre (position centrale, taille) * Renvoie la vue de la fenêtre (position centrale, taille)
*/ */
sf::View getWindowView(); sf::View& getWindowView();
/** /**
* Modifie la vue de la fenêtre * Modifie la vue de la fenêtre
*/ */
void setWindowView(sf::View set_window_view); void setWindowView(sf::View& set_window_view);
/** /**
* Renvoie le titre actuel de la fenêtre * Renvoie le titre actuel de la fenêtre

View File

@ -26,7 +26,7 @@ public:
/** /**
* Dessine le menu * Dessine le menu
*/ */
void frame(); bool frame();
/** /**
* Permet de changer le choix sélectionné * Permet de changer le choix sélectionné

View File

@ -18,10 +18,10 @@ public:
virtual ~View(); virtual ~View();
/** /**
* Demande le passage à la frame suivante sur * Demande le passage à la frame suivante sur cette vue,
* cette vue * renvoie true si le rendu de la frame a é interrompu
*/ */
virtual void frame() = 0; virtual bool frame() = 0;
}; };
#endif #endif

View File

@ -1,3 +1,4 @@
#include <iostream>
#include <cmath> #include <cmath>
#include <algorithm> #include <algorithm>
#include "editor.hpp" #include "editor.hpp"
@ -18,23 +19,24 @@ void Editor::load(std::ifstream& file) {
manager.setTitle(sf::String(L"Édition de ") + getName()); manager.setTitle(sf::String(L"Édition de ") + getName());
} }
void Editor::frame() { bool Editor::frame() {
const std::vector<sf::Event>& events = manager.getEvents(); // si le dessin de la frame a été interrompu par
// le traitement événementiel, on arrête
// traitement des événements if (Level::frame()) {
for (unsigned int i = 0; i < events.size(); i++) { return true;
processEvent(events[i]);
} }
// dessin de la frame // dessin de la frame
draw(); draw();
sf::sleep(sf::seconds(1.f / 30)); sf::sleep(sf::seconds(1.f / 30));
return true;
} }
bool Editor::processEvent(const sf::Event& event) { bool Editor::processEvent(const sf::Event& event) {
// traitement des événements du widget timer // traitement des événements du widget timer
if (widget_timer.processEvent(event)) { if (widget_timer.processEvent(event)) {
return true; return false;
} }
// lorsque l'on clique dans l'éditeur // lorsque l'on clique dans l'éditeur
@ -48,12 +50,10 @@ bool Editor::processEvent(const sf::Event& event) {
drag_start = position; drag_start = position;
drag_end = position; drag_end = position;
drag_mode = DragMode::SELECT_RECT; drag_mode = DragMode::SELECT_RECT;
return true;
} }
// clic sur un objet : démarrage de la sélection libre // clic sur un objet : démarrage de la sélection libre
if (pointed_object != nullptr) { else if (pointed_object != nullptr) {
if (manager.isKeyPressed(sf::Keyboard::LControl)) { if (manager.isKeyPressed(sf::Keyboard::LControl)) {
drag_start = position; drag_start = position;
drag_end = position; drag_end = position;
@ -63,17 +63,16 @@ bool Editor::processEvent(const sf::Event& event) {
} else { } else {
select(pointed_object, SelectionMode::FLIP); select(pointed_object, SelectionMode::FLIP);
} }
return true;
} }
// clic gauche dans le vide : démarrage du placement en drag&drop // clic gauche dans le vide : démarrage du placement en drag&drop
else {
drag_start = position; drag_start = position;
drag_end = position; drag_end = position;
drag_mode = DragMode::PLACE; drag_mode = DragMode::PLACE;
select(addObject(position), SelectionMode::REPLACE); select(addObject(position), SelectionMode::REPLACE);
return true; }
} }
if (event.mouseButton.button == sf::Mouse::Right) { if (event.mouseButton.button == sf::Mouse::Right) {
@ -84,7 +83,6 @@ bool Editor::processEvent(const sf::Event& event) {
drag_mode = DragMode::REMOVE; drag_mode = DragMode::REMOVE;
removeObject(pointed_object); removeObject(pointed_object);
return true;
} }
} }
} }
@ -98,19 +96,16 @@ bool Editor::processEvent(const sf::Event& event) {
// mode placement d'objets // mode placement d'objets
if (drag_mode == DragMode::PLACE && pointed_object == nullptr) { if (drag_mode == DragMode::PLACE && pointed_object == nullptr) {
select(addObject(position), SelectionMode::ADD); select(addObject(position), SelectionMode::ADD);
return true;
} }
// mode suppression d'objets // mode suppression d'objets
if (drag_mode == DragMode::REMOVE && pointed_object != nullptr) { if (drag_mode == DragMode::REMOVE && pointed_object != nullptr) {
removeObject(pointed_object); removeObject(pointed_object);
return true;
} }
// mode sélection libre : on l'objet à la sélection // mode sélection libre : on l'objet à la sélection
if (drag_mode == DragMode::SELECT_BULK) { if (drag_mode == DragMode::SELECT_BULK) {
select(position, SelectionMode::ADD); select(position, SelectionMode::ADD);
return true;
} }
} }
@ -124,7 +119,6 @@ bool Editor::processEvent(const sf::Event& event) {
} }
drag_mode = DragMode::NONE; drag_mode = DragMode::NONE;
return true;
} }
// gestion des touches // gestion des touches
@ -139,13 +133,20 @@ bool Editor::processEvent(const sf::Event& event) {
), objects.end()); ), objects.end());
} }
selection.clear(); clearSelection();
return true; }
// appui sur Ctrl + A : sélection de tous les objets
if (event.key.code == sf::Keyboard::A && event.key.control) {
selectAll();
} }
// appui sur espace : test du niveau en cours d'édition // appui sur espace : test du niveau en cours d'édition
if (event.key.code == sf::Keyboard::Space) { if (event.key.code == sf::Keyboard::Space) {
test(); test();
// demande l'interruption du dessin de la
// frame car l'objet risque d'être détruit
return true; return true;
} }
} }
@ -257,11 +258,7 @@ void Editor::select(ObjectPtr object, SelectionMode mode) {
// pour REPLACE, on sélectionne forcément l'objet // 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 // 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 == SelectionMode::REPLACE || mode == SelectionMode::FLIP) {
for (unsigned int i = 0; i < selection.size(); i++) { clearSelection();
selection[i]->setSelected(false);
}
selection.clear();
// on resélectionne l'objet ssi. on force la sélection // on resélectionne l'objet ssi. on force la sélection
// ou s'il n'était pas déjà sélectionné // ou s'il n'était pas déjà sélectionné
@ -291,12 +288,7 @@ void Editor::select(sf::Vector2f top_left, sf::Vector2f bottom_right) {
std::abs(bottom_right.y - top_left.y) std::abs(bottom_right.y - top_left.y)
); );
// réinitialisation de la sélectionne clearSelection();
for (unsigned int i = 0; i < selection.size(); i++) {
selection[i]->setSelected(false);
}
selection.clear();
// sélection des éléments intersectant le rectangle // sélection des éléments intersectant le rectangle
for (unsigned int i = 0; i < objects.size(); i++) { for (unsigned int i = 0; i < objects.size(); i++) {
@ -306,8 +298,26 @@ void Editor::select(sf::Vector2f top_left, sf::Vector2f bottom_right) {
} }
} }
void Editor::clearSelection() {
for (unsigned int i = 0; i < selection.size(); i++) {
selection[i]->setSelected(false);
}
selection.clear();
}
void Editor::selectAll() {
std::vector<ObjectPtr>& objects = getObjects();
for (unsigned int i = 0; i < objects.size(); i++) {
objects[i]->setSelected(true);
selection.push_back(objects[i]);
}
}
void Editor::test() { void Editor::test() {
std::shared_ptr<Game> game = std::shared_ptr<Game>(new Game(manager)); std::shared_ptr<Game> game = std::shared_ptr<Game>(new Game(manager));
clearSelection();
// copie des propriétés // copie des propriétés
game->setName(getName()); game->setName(getName());

View File

@ -13,23 +13,15 @@ void Game::load(std::ifstream& file) {
manager.setTitle(getName()); manager.setTitle(getName());
} }
void Game::frame() { bool Game::frame() {
const std::vector<sf::Event>& events = manager.getEvents(); // si le dessin de la frame a été interrompu par
// le traitement événementiel, on arrête
if (Level::frame()) {
return true;
}
sf::Time current_time = manager.getCurrentTime(); sf::Time current_time = manager.getCurrentTime();
// traitement des événements
for (unsigned int i = 0; i < events.size(); i++) {
const sf::Event& event = events[i];
// appui sur espace en mode test : retour à l'éditeur
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space && test_mode) {
test_mode = false;
manager.setView(return_view);
return; // important : ne pas dessiner la frame
// on risque d'avoir perdu le pointeur en changeant de vue
}
}
if (current_time >= next_frame_time) { if (current_time >= next_frame_time) {
// si nous sommes en retard ou dans les temps // si nous sommes en retard ou dans les temps
// on replanifie la prochaine frame // on replanifie la prochaine frame
@ -47,6 +39,22 @@ void Game::frame() {
// le temps nécessaire pour revenir dans les temps // le temps nécessaire pour revenir dans les temps
sf::sleep(next_frame_time - current_time); sf::sleep(next_frame_time - current_time);
} }
return false;
}
bool Game::processEvent(const sf::Event& event) {
// appui sur espace en mode test : retour à l'éditeur
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space && test_mode) {
test_mode = false;
manager.setView(return_view);
// demande l'interruption du dessin de la
// frame car l'objet risque d'être détruit
return true;
}
return false;
} }
void Game::draw() { void Game::draw() {

View File

@ -19,6 +19,7 @@ std::map<unsigned int, std::function<ObjectPtr(std::ifstream&)>> object_type_map
Level::Level(Manager& manager) : View(manager), total_time(30) {} Level::Level(Manager& manager) : View(manager), total_time(30) {}
Level::~Level() { Level::~Level() {
setViewCenter(sf::Vector2f(0, 0));
objects.clear(); objects.clear();
} }
@ -28,6 +29,9 @@ void Level::load(std::ifstream& file) {
objects.clear(); objects.clear();
} }
// positionnement de la vue au centre
setViewCenter(sf::Vector2f(0, 0));
// lecture de la signture du fichier ("BAR") // lecture de la signture du fichier ("BAR")
char signature[3]; char signature[3];
file.read(signature, sizeof(signature)); file.read(signature, sizeof(signature));
@ -111,6 +115,23 @@ void Level::save() {
// TODO: faire une fonction d'enregistrement // TODO: faire une fonction d'enregistrement
} }
bool Level::frame() {
const std::vector<sf::Event>& events = manager.getEvents();
// traitement des événements
for (unsigned int i = 0; i < events.size(); i++) {
if (processEvent(events[i])) {
// /!\ On arrête là si on a demandé l'interruption.
// Il est important de ne plus appeler aucune autre
// fonction de la classe pour éviter une erreur
// de segmentation
return true;
}
}
return false;
}
void Level::draw() { void Level::draw() {
// efface la scène précédente et dessine la couche de fond // efface la scène précédente et dessine la couche de fond
sf::RenderWindow& window = manager.getWindow(); sf::RenderWindow& window = manager.getWindow();
@ -166,3 +187,11 @@ std::vector<ObjectPtr>& Level::getObjects() {
std::vector<std::pair<float, float>>& Level::getZone() { std::vector<std::pair<float, float>>& Level::getZone() {
return zone; return zone;
} }
sf::Vector2f Level::getViewCenter() {
return manager.getWindowView().getCenter();
}
void Level::setViewCenter(sf::Vector2f set_view_center) {
manager.getWindowView().setCenter(set_view_center);
}

View File

@ -18,13 +18,6 @@ void Manager::start() {
return; return;
} }
// lorsque la fenêtre est redimensionnée par l'utilisateur
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);
setWindowView(sf::View(visibleArea));
}
events.push_back(event); events.push_back(event);
} }
@ -63,11 +56,11 @@ const std::vector<sf::Event>& Manager::getEvents() {
return events; return events;
} }
sf::View Manager::getWindowView() { sf::View& Manager::getWindowView() {
return window_view; return window_view;
} }
void Manager::setWindowView(sf::View set_window_view) { void Manager::setWindowView(sf::View& set_window_view) {
window.setView(set_window_view); window.setView(set_window_view);
window_view = set_window_view; window_view = set_window_view;
} }

View File

@ -68,7 +68,7 @@ void Menu::MoveDown()
} }
} }
void Menu::frame(){ bool Menu::frame(){
sf::RenderWindow& window = manager.getWindow(); sf::RenderWindow& window = manager.getWindow();
window.clear(sf::Color(66, 40, 245)); window.clear(sf::Color(66, 40, 245));
@ -108,11 +108,19 @@ void Menu::frame(){
file.close(); file.close();
manager.setView(game); manager.setView(game);
// demande l'interruption du dessin de la
// frame car l'objet risque d'être détruit
return true;
} }
//si on choisit "Quitter", la fenêtre se ferme //si on choisit "Quitter", la fenêtre se ferme
if(selection == 3){ if(selection == 3){
manager.getWindow().close(); manager.getWindow().close();
// demande l'interruption du dessin de la
// frame car l'objet risque d'être détruit
return true;
} }
} }
if(menu_nb == 1){ if(menu_nb == 1){
@ -129,11 +137,19 @@ void Menu::frame(){
if(selection==2){ if(selection==2){
std::shared_ptr<View> editor = std::shared_ptr<View>(new Editor(manager)); std::shared_ptr<View> editor = std::shared_ptr<View>(new Editor(manager));
manager.setView(editor); manager.setView(editor);
// demande l'interruption du dessin de la
// frame car l'objet risque d'être détruit
return true;
} }
//si on choisit "quitter", la fenêtre se ferme //si on choisit "quitter", la fenêtre se ferme
if(selection==3){ if(selection==3){
manager.getWindow().close(); manager.getWindow().close();
// demande l'interruption du dessin de la
// frame car l'objet risque d'être détruit
return true;
} }
} }
@ -147,5 +163,5 @@ void Menu::frame(){
window.draw(choice[i]); window.draw(choice[i]);
} }
window.display(); window.display();
return false;
} }