Réimplémentation initiale de la toolbar de l'éditeur

This commit is contained in:
Mattéo Delabre 2016-04-19 17:52:05 +02:00
parent f1c0d67b32
commit dca255f7bd
6 changed files with 191 additions and 362 deletions

View File

@ -3,7 +3,7 @@
#include "level.hpp"
#include "widget_timer.hpp"
#include "widget_toolbar.hpp"
#include "toolbar.hpp"
#include <unordered_map>
#include <memory>
@ -26,7 +26,7 @@ private:
DragMode drag_mode;
WidgetTimer widget_timer;
WidgetToolbar widget_toolbar;
Toolbar toolbar;
/**
* Renvoie l'objet pointé à la position donnée

54
include/toolbar.hpp Normal file
View File

@ -0,0 +1,54 @@
#ifndef __SKIZZLE_TOOLBAR_HPP__
#define __SKIZZLE_TOOLBAR_HPP__
#include <SFGUI/Widgets.hpp>
#include <SFGUI/RadioButtonGroup.hpp>
#include <SFML/Graphics.hpp>
#include <map>
#include <functional>
#include "object.hpp"
#include "level.hpp"
class Editor;
/**
* Barre d'outils pour l'éditeur
*/
class Toolbar {
private:
Editor& editor;
// widgets de la barre
sfg::Window::Ptr toolbar_window;
sfg::ScrolledWindow::Ptr scrolled_zone;
sfg::Box::Ptr toolbar_box;
// types d'objets de la barre d'outils
sfg::RadioButtonGroup::Ptr objects_group;
std::map<sfg::RadioButton::Ptr, std::function<Object::Ptr()>> creators;
void addCreator(sf::String label, std::function<Object::Ptr()> creator);
Object::Ptr createBlock();
Object::Ptr createMovableBlock();
Object::Ptr createPlayer();
Object::Ptr createSwitchBlock();
Object::Ptr createFinishBlock();
Object::Ptr createKillBlock();
Object::Ptr createGravityBlock(GravityDirection direction);
public:
Toolbar(Editor& editor);
/**
* Crée un nouvel objet du type actuellement sélectionné
*/
Object::Ptr createObject();
/**
* Récupère la fenêtre de la barre d'outils
*/
sfg::Window::Ptr getWindow();
};
#endif

View File

@ -1,115 +0,0 @@
#ifndef __SKIZZLE_UTIL_WIDGET_TOOLBAR_HPP__
#define __SKIZZLE_UTIL_WIDGET_TOOLBAR_HPP__
#include <SFML/Graphics.hpp>
#include <functional>
#include "object.hpp"
#include "level.hpp"
class Manager;
/**
* Représente un objet plaçable depuis la barre d'outils
*/
struct ToolbarObject {
typedef std::shared_ptr<ToolbarObject> Ptr;
// image représentant cet objet visuellement
sf::Sprite sprite;
// fonction appelée pour instancier un objet de ce type
std::function<Object::Ptr(void)> create_object;
};
/**
* Représente une catégorie d'objets plaçables dans la barre
*/
struct ToolbarCategory {
typedef std::shared_ptr<ToolbarCategory> Ptr;
// nom de la catégorie
sf::String name;
// liste des objets dans la catégorie
std::vector<ToolbarObject::Ptr> objects;
/**
* Ajoute un nouvel objet dans cette catégorie
*/
ToolbarObject::Ptr addObject(
sf::Texture& texture,
std::function<Object::Ptr(void)> create_object
);
};
/**
* Affiche une barre d'outils pour l'éditeur
*/
class WidgetToolbar {
private:
Manager& manager;
sf::RectangleShape background;
std::vector<ToolbarCategory::Ptr> categories;
ToolbarObject::Ptr selected;
/**
* Crée un objet de type Block
*/
Object::Ptr createBlock();
/**
* Crée un objet de type Block déplaçable
*/
Object::Ptr createMovableBlock();
/**
* Crée un objet de type Player
*/
Object::Ptr createPlayer();
/**
* Crée un objet de type SwitchBlock
*/
Object::Ptr createSwitchBlock();
/**
* Crée un objet de type FinishBlock
*/
Object::Ptr createFinishBlock();
/**
* Crée un objet de type KillBlock
*/
Object::Ptr createKillBlock();
/**
* Crée un objet de type GravityBlock
*/
Object::Ptr createGravityBlock(GravityDirection direction);
public:
WidgetToolbar(Manager& manager);
/**
* Ajoute une nouvelle catégorie de choix
*/
ToolbarCategory::Ptr addCategory(sf::String name);
/**
* Génère un objet du type actuellement sélectionné et le retourne
*/
Object::Ptr createObject();
/**
* Traite l'événement et renvoie true si l'on s'en est servi
*/
bool processEvent(const sf::Event& event);
/**
* Dessine le widget à la position donnée et avec la taille donnée
*/
void draw(sf::Vector2f position, sf::Vector2f size);
};
#endif

View File

@ -34,7 +34,7 @@ inline sf::Vector2f roundVectorToGrid(sf::Vector2f input) {
Editor::Editor(Manager& manager) : Level(manager),
drag_control_point(nullptr), drag_mode(Editor::DragMode::NONE),
widget_timer(manager, true, std::bind(&Editor::setTotalTime, this, std::placeholders::_1)),
widget_toolbar(manager) {}
toolbar(*this) {}
Editor::~Editor() {}
@ -47,6 +47,9 @@ void Editor::enable() {
// joue la musique de l'éditeur
getResourceManager().playMusic("editor.ogg");
// ajout de la toolbar à la liste des widgets
getManager().getDesktop().Add(toolbar.getWindow());
}
void Editor::processEvent(const sf::Event& event) {
@ -57,11 +60,6 @@ void Editor::processEvent(const sf::Event& event) {
return;
}
// traitement des événements du widget barre d'outils
if (widget_toolbar.processEvent(event)) {
return;
}
// lorsque l'on clique dans l'éditeur
if (event.type == sf::Event::MouseButtonPressed) {
sf::Vector2i mouse_position(event.mouseButton.x, event.mouseButton.y);
@ -327,11 +325,12 @@ void Editor::draw() {
widget_timer.setTimeLeft(getTotalTime());
widget_timer.draw(sf::Vector2f(window_size.x / 2 - 50, 0));
// barre d'outils
widget_toolbar.draw(
sf::Vector2f(window_size.x - 64, 0),
sf::Vector2f(64, window_size.y)
);
// on redimensionne la toolbar pour qu'elle occupe l'espace droite
const sfg::Window::Ptr& toolbar_window = toolbar.getWindow();
toolbar_window->SetAllocation(sf::FloatRect(
window_size.x - 200, 0,
200, window_size.y
));
}
Object::Ptr Editor::getObject(sf::Vector2f position) {
@ -359,33 +358,27 @@ sf::Vector2f* Editor::getControlPoint(sf::Vector2f position) {
}
Object::Ptr Editor::addObject(sf::Vector2f position) {
const std::vector<Object::Ptr>& objects = getObjects();
// on arrondit à l'unité de grille la plus proche
position = roundVectorToGrid(position);
Object::Ptr object = widget_toolbar.createObject();
Object::Ptr created_object = toolbar.createObject();
if (object == nullptr) {
if (created_object == nullptr) {
return nullptr;
}
object->setPosition(position);
created_object->setPosition(position);
// avant d'ajouter l'objet, on vérifie qu'il ne soit
// pas superposé à un autre
float overlaps = false;
for (auto it = objects.begin(); it != objects.end(); it++) {
if ((*it)->getAABB().intersects(object->getAABB())) {
overlaps = true;
// pas superposé à un autre. Si c'est le cas, on annule
// la procédure
for (auto const &object : getObjects()) {
if (object->getAABB().intersects(created_object->getAABB())) {
return nullptr;
}
}
if (!overlaps) {
return Level::addObject(object);
}
return nullptr;
// sinon, on ajoute l'objet
return Level::addObject(created_object);
}
void Editor::removeObject(Object::Ptr object) {

115
src/toolbar.cpp Normal file
View File

@ -0,0 +1,115 @@
#include "resource_manager.hpp"
#include "editor.hpp"
#include "toolbar.hpp"
#include "block.hpp"
#include "player.hpp"
#include "switch_block.hpp"
#include "gravity_block.hpp"
#include "kill_block.hpp"
#include "finish_block.hpp"
Toolbar::Toolbar(Editor& editor) : editor(editor) {
// création de la boîte de la barre d'outils
toolbar_box = sfg::Box::Create(sfg::Box::Orientation::VERTICAL, 5.f);
objects_group = sfg::RadioButtonGroup::Create();
// catégorie des blocs de base
toolbar_box->PackEnd(sfg::Label::Create(L"BLOCS"));
addCreator(L"Bloc normal", std::bind(&Toolbar::createBlock, this));
addCreator(L"Caisse", std::bind(&Toolbar::createMovableBlock, this));
// catégorie des blocs contrôlant les joueurs
toolbar_box->PackEnd(sfg::Label::Create(L"JOUEURS"));
addCreator(L"Joueur", std::bind(&Toolbar::createPlayer, this));
addCreator(L"Bloc changeur", std::bind(&Toolbar::createSwitchBlock, this));
addCreator(L"Bloc de fin", std::bind(&Toolbar::createFinishBlock, this));
addCreator(L"Bloc tueur", std::bind(&Toolbar::createKillBlock, this));
// catégorie des blocs changeant la gravité
toolbar_box->PackEnd(sfg::Label::Create(L"GRAVITÉ"));
addCreator(L"Bloc de gravité nord", std::bind(
&Toolbar::createGravityBlock, this, GravityDirection::NORTH
));
addCreator(L"Bloc de gravité est", std::bind(
&Toolbar::createGravityBlock, this, GravityDirection::EAST
));
addCreator(L"Bloc de gravité sud", std::bind(
&Toolbar::createGravityBlock, this, GravityDirection::SOUTH
));
addCreator(L"Bloc de gravité ouest", std::bind(
&Toolbar::createGravityBlock, this, GravityDirection::WEST
));
// création de la fenêtre de la barre d'outils
scrolled_zone = sfg::ScrolledWindow::Create();
scrolled_zone->SetScrollbarPolicy(
sfg::ScrolledWindow::ScrollbarPolicy::VERTICAL_AUTOMATIC |
sfg::ScrolledWindow::ScrollbarPolicy::HORIZONTAL_NEVER
);
scrolled_zone->AddWithViewport(toolbar_box);
toolbar_window = sfg::Window::Create(sfg::Window::Style::BACKGROUND);
toolbar_window->Add(scrolled_zone);
toolbar_window->SetPosition(sf::Vector2f(0, 0));
}
void Toolbar::addCreator(sf::String label, std::function<Object::Ptr()> creator) {
sfg::RadioButton::Ptr radio = sfg::RadioButton::Create(label, objects_group);
creators[radio] = creator;
toolbar_box->PackEnd(radio);
}
Object::Ptr Toolbar::createBlock() {
return Object::Ptr(new Block);
}
Object::Ptr Toolbar::createMovableBlock() {
Object::Ptr movable = Object::Ptr(new Block);
movable->setMass(2.f);
return movable;
}
Object::Ptr Toolbar::createPlayer() {
Object::Ptr player = Object::Ptr(new Player);
player->setMass(1.f);
return player;
}
Object::Ptr Toolbar::createSwitchBlock() {
return Object::Ptr(new SwitchBlock);
}
Object::Ptr Toolbar::createFinishBlock() {
return Object::Ptr(new FinishBlock);
}
Object::Ptr Toolbar::createKillBlock() {
return Object::Ptr(new KillBlock);
}
Object::Ptr Toolbar::createGravityBlock(GravityDirection direction) {
GravityBlock::Ptr gravity_block = GravityBlock::Ptr(new GravityBlock);
gravity_block->setGravityDirection(direction);
return std::dynamic_pointer_cast<Object>(gravity_block);
}
Object::Ptr Toolbar::createObject() {
for (auto const &creator : creators) {
// on recherche le bouton actif actuellement, si on
// le trouve, on appelle le créateur associé
if (creator.first->IsActive()) {
return creator.second();
}
}
// on n'a aucun bouton actif, on renvoie nullptr
return nullptr;
}
sfg::Window::Ptr Toolbar::getWindow() {
return toolbar_window;
}

View File

@ -1,218 +0,0 @@
#include "manager.hpp"
#include "widget_toolbar.hpp"
#include "block.hpp"
#include "player.hpp"
#include "gravity_block.hpp"
#include "switch_block.hpp"
#include "finish_block.hpp"
#include "kill_block.hpp"
#include <utility>
/**
* Définition des variables et fonctions globales internes
* (accessibles uniquement dans ce fichier)
*/
namespace {
const int PADDING = 8;
}
ToolbarCategory::Ptr WidgetToolbar::addCategory(sf::String name) {
auto cat = ToolbarCategory::Ptr(new ToolbarCategory);
cat->name = name;
categories.push_back(cat);
return cat;
}
ToolbarObject::Ptr ToolbarCategory::addObject(
sf::Texture& texture,
std::function<Object::Ptr(void)> create_object
) {
auto object = std::shared_ptr<ToolbarObject>(new ToolbarObject);
object->sprite.setTexture(texture, true);
object->create_object = create_object;
objects.push_back(object);
return object;
}
Object::Ptr WidgetToolbar::createBlock() {
return Object::Ptr(new Block);
}
Object::Ptr WidgetToolbar::createMovableBlock() {
Object::Ptr movable = Object::Ptr(new Block);
movable->setMass(2.f);
return movable;
}
Object::Ptr WidgetToolbar::createPlayer() {
Object::Ptr player = Object::Ptr(new Player);
player->setMass(1.f);
return player;
}
Object::Ptr WidgetToolbar::createSwitchBlock() {
return Object::Ptr(new SwitchBlock);
}
Object::Ptr WidgetToolbar::createFinishBlock() {
return Object::Ptr(new FinishBlock);
}
Object::Ptr WidgetToolbar::createKillBlock() {
return Object::Ptr(new KillBlock);
}
Object::Ptr WidgetToolbar::createGravityBlock(GravityDirection direction) {
GravityBlock::Ptr gravity_block = GravityBlock::Ptr(new GravityBlock);
gravity_block->setGravityDirection(direction);
return std::dynamic_pointer_cast<Object>(gravity_block);
}
Object::Ptr WidgetToolbar::createObject() {
if (selected != nullptr) {
return selected->create_object();
}
return nullptr;
}
WidgetToolbar::WidgetToolbar(Manager& manager) : manager(manager), selected(nullptr) {
// catégorie des objets plaçables de base
ResourceManager& resources = manager.getResourceManager();
ToolbarCategory::Ptr block_cat = addCategory("BLOCS");
selected = block_cat->addObject(
resources.getTexture("toolbar_block.tga"),
std::bind(&WidgetToolbar::createBlock, this)
);
block_cat->addObject(
resources.getTexture("toolbar_movable_block.tga"),
std::bind(&WidgetToolbar::createMovableBlock, this)
);
// catégorie des blocs contrôlant les joueurs
ToolbarCategory::Ptr player_cat = addCategory("JOUEURS");
player_cat->addObject(
resources.getTexture("toolbar_player.tga"),
std::bind(&WidgetToolbar::createPlayer, this)
);
player_cat->addObject(
resources.getTexture("toolbar_switch_block.tga"),
std::bind(&WidgetToolbar::createSwitchBlock, this)
);
player_cat->addObject(
resources.getTexture("toolbar_kill_block.tga"),
std::bind(&WidgetToolbar::createKillBlock, this)
);
player_cat->addObject(
resources.getTexture("toolbar_finish_block.tga"),
std::bind(&WidgetToolbar::createFinishBlock, this)
);
// catégorie des blocs changeant la gravité
ToolbarCategory::Ptr gravity_cat = addCategory(L"GRAVITÉ");
gravity_cat->addObject(
resources.getTexture("toolbar_gravity_block_north.tga"),
std::bind(&WidgetToolbar::createGravityBlock, this, GravityDirection::NORTH)
);
gravity_cat->addObject(
resources.getTexture("toolbar_gravity_block_east.tga"),
std::bind(&WidgetToolbar::createGravityBlock, this, GravityDirection::EAST)
);
gravity_cat->addObject(
resources.getTexture("toolbar_gravity_block_south.tga"),
std::bind(&WidgetToolbar::createGravityBlock, this, GravityDirection::SOUTH)
);
gravity_cat->addObject(
resources.getTexture("toolbar_gravity_block_west.tga"),
std::bind(&WidgetToolbar::createGravityBlock, this, GravityDirection::WEST)
);
}
bool WidgetToolbar::processEvent(const sf::Event& event) {
if (event.type == sf::Event::MouseButtonPressed) {
sf::Vector2f position(event.mouseButton.x, event.mouseButton.y);
// clic gauche sur un item : on le sélectionne
if (event.mouseButton.button == sf::Mouse::Left) {
for (unsigned int i = 0; i < categories.size(); i++) {
for (unsigned int j = 0; j < categories[i]->objects.size(); j++) {
if (categories[i]->objects[j]->sprite.getGlobalBounds().contains(position)) {
selected = categories[i]->objects[j];
return true;
}
}
}
// ne pas laisser traverser les clics sur la barre d'outils
if (background.getGlobalBounds().contains(position)) {
return true;
}
}
}
return false;
}
void WidgetToolbar::draw(sf::Vector2f position, sf::Vector2f size) {
sf::RenderWindow& window = manager.getWindow();
background.setSize(size);
background.setPosition(position);
window.draw(background);
float total_y = PADDING;
for (unsigned int i = 0; i < categories.size(); i++) {
std::shared_ptr<ToolbarCategory> category = categories[i];
// affichage du label de la catégorie
sf::Text category_label(
category->name,
manager.getResourceManager().getFont("raleway.ttf"), 12
);
category_label.setColor(sf::Color::Black);
category_label.setPosition(position + sf::Vector2f(
floor(size.x / 2 - category_label.getGlobalBounds().width / 2),
total_y
));
window.draw(category_label);
for (unsigned int j = 0; j < category->objects.size(); j++) {
total_y += PADDING + 32;
std::shared_ptr<ToolbarObject> object = category->objects[j];
sf::Vector2f sprite_position = position + sf::Vector2f(
size.x / 2 - object->sprite.getGlobalBounds().width / 2,
total_y
);
if (selected == object) {
sf::RectangleShape selection_rectangle(sf::Vector2f(32, 32));
selection_rectangle.setPosition(sprite_position + sf::Vector2f(-4, -4));
selection_rectangle.setFillColor(sf::Color(0, 0, 0, 20));
window.draw(selection_rectangle);
}
// affichage du sprite de l'objet
object->sprite.setPosition(sprite_position);
window.draw(object->sprite);
}
total_y += 64;
}
}