3 #include <BLIB/Engine.hpp>
4 #include <BLIB/Util/Random.hpp>
16 std::string makeCopyName(
const std::string& dest,
const std::string& file) {
17 const std::string&
base = bl::util::FileUtil::getFilename(file);
18 const std::string result = bl::util::FileUtil::joinPath(dest,
base);
19 if (bl::util::FileUtil::exists(result)) {
21 ss << bl::util::FileUtil::getBaseName(
base) <<
"_" << std::hex
22 << bl::util::Random::get<int>(1000, 10000000) <<
"."
23 << bl::util::FileUtil::getExtension(
base);
30 using namespace bl::gui;
34 , catchables(map.editMap())
37 , activeTile(
core::map::Tile::Blank)
38 , activeAnim(
core::map::Tile::Blank)
40 content = Notebook::create();
42 bl::gui::Box::Ptr tilePage = Box::create(LinePacker::create(LinePacker::Vertical, 4));
43 bl::gui::Box::Ptr tileButBox = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
44 bl::gui::Button::Ptr addTileBut = Button::create(
"Add Tile");
45 addTileBut->setTooltip(
"Import an image as a tile");
46 addTileBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
47 const char* filters[] = {
"*.png",
"*.jpg",
"*.bmp",
"*.gif"};
49 bl::dialog::tinyfd_openFileDialog(
"Add tile(s)",
nullptr, 4, filters,
"Image files", 1);
51 std::stringstream ss(file);
53 while (std::getline(ss, tile,
'|')) {
56 filename = bl::util::FileUtil::getBaseName(filename) +
".png";
57 if (!img.loadFromFile(tile)) {
58 BL_LOG_ERROR <<
"Failed to load tile: " << tile;
63 BL_LOG_ERROR <<
"Failed to copy tile: " << tile <<
" -> " << filename;
66 tileset->addTexture(filename);
72 bl::gui::Button::Ptr importSpritesheetBut = Button::create(
"Add Tilesheet");
73 importSpritesheetBut->setTooltip(
"Import a spritesheet as many tiles");
75 bl::gui::Button::Ptr delTileBut = Button::create(
"Delete Tile");
76 delTileBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
77 if (1 == bl::dialog::tinyfd_messageBox(
"Remove tile?",
78 "Are you sure you want to delete this tile?\nThis "
79 "action cannot be undone and clears edit history",
83 deleteCb(activeTile,
false);
84 tileset->removeTexture(activeTile);
89 delTileBut->setColor(sf::Color(180, 15, 15), sf::Color(60, 0, 0));
90 tileButBox->pack(addTileBut,
false,
true);
91 tileButBox->pack(importSpritesheetBut,
false,
true);
92 tileButBox->pack(delTileBut,
false,
true);
93 tilePage->pack(tileButBox,
true,
false);
95 tilesBox = Box::create(GridPacker::createDynamicGrid(GridPacker::Rows, 300, 10));
96 ScrollArea::Ptr scroll = ScrollArea::create(LinePacker::create(LinePacker::Vertical));
97 scroll->pack(tilesBox,
true,
true);
98 tilePage->pack(scroll,
true,
true);
100 bl::gui::Box::Ptr animPage = Box::create(LinePacker::create(LinePacker::Vertical, 4));
101 bl::gui::Box::Ptr animButBox = Box::create(LinePacker::create(LinePacker::Horizontal, 4));
102 bl::gui::Button::Ptr addAnimBut = Button::create(
"Add Animation");
103 addAnimBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
104 const char* filters[] = {
"*.anim"};
105 const char* file = bl::dialog::tinyfd_openFileDialog(
106 "Add animation",
nullptr, 1, filters,
"Animation files", 0);
109 bl::gfx::a2d::AnimationData anim;
110 if (!anim.loadFromFile(file)) {
111 bl::dialog::tinyfd_messageBox(
112 "Bad Animation",
"Failed to load animation",
"ok",
"error", 0);
116 bl::util::FileUtil::copyFile(
118 const std::string sp = bl::util::FileUtil::joinPath(bl::util::FileUtil::getPath(file),
119 anim.spritesheetFile());
120 if (bl::util::FileUtil::exists(sp)) {
121 bl::util::FileUtil::copyFile(
124 anim.spritesheetFile()));
127 tileset->addAnimation(animFile);
132 bl::gui::Button::Ptr delAnimBut = Button::create(
"Delete Animation");
133 delAnimBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
135 bl::dialog::tinyfd_messageBox(
"Remove animation?",
136 "Are you sure you want to delete this animation?\nThis "
137 "action cannot be undone and clears edit history",
141 deleteCb(activeAnim,
true);
142 tileset->removeAnimation(activeAnim);
147 delAnimBut->setColor(sf::Color(180, 15, 15), sf::Color(60, 0, 0));
148 animButBox->pack(addAnimBut);
149 animButBox->pack(delAnimBut);
150 animPage->pack(animButBox);
152 animsBox = Box::create(GridPacker::createDynamicGrid(GridPacker::Rows, 300, 10));
153 scroll = ScrollArea::create(LinePacker::create(LinePacker::Vertical));
154 scroll->pack(animsBox,
true,
true);
155 animPage->pack(scroll,
true,
true);
157 content->setMaxTabWidth(250.f);
158 content->addPage(
"tile",
"Tiles", tilePage, [
this]() { tool = Active::Tiles; });
159 content->addPage(
"anim",
"Animations", animPage, [
this]() { tool = Active::Animations; });
160 content->addPage(
"towns",
"Towns", towns.
getContent(), [
this]() { tool = Active::TownTiles; });
162 "col",
"Collisions", collisions.
getContent(), [
this]() { tool = Active::CollisionTiles; });
164 "catch",
"Catch Tiles", catchables.
getContent(), [
this]() { tool = Active::CatchTiles; });
165 content->addPage(
"level",
"Level Transitions", levelTransitions.
getContent(), [
this]() {
166 tool = Active::LevelTiles;
195 if (!newTileset)
return false;
196 if (newTileset.get() != tileset.get()) {
197 tileset = newTileset;
203 void Tileset::updateGui() {
204 tilesBox->clearChildren(
true);
205 animsBox->clearChildren(
true);
208 RadioButton::Group* group =
nullptr;
209 for (
const auto& pair : tileset->getTiles()) {
210 Image::Ptr img = Image::create(pair->second);
211 img->scaleToSize({56, 56});
214 button->getSignal(Event::LeftClicked).willAlwaysCall([
this, pair](
const Event&, Element*) {
215 activeTile = pair->first;
218 activeTile = pair->first;
219 button->setValue(
true);
221 group = button->getRadioGroup();
222 tilesBox->pack(button);
227 for (
const auto& pair : tileset->getAnims()) {
228 Animation::Ptr anim = Animation::create(pair->second);
229 anim->scaleToSize({56, 56});
230 anim->setVerticalAlignment(RenderSettings::Top);
233 button->getSignal(Event::LeftClicked).willAlwaysCall([
this, pair](
const Event&, Element*) {
234 activeAnim = pair->first;
237 activeAnim = pair->first;
238 button->setValue(
true);
240 group = button->getRadioGroup();
241 animsBox->pack(button);
Collision
The different types of collisions in maps.
LevelTransition
Represents a level transition in a map. Level transitions are applied when an entity moves either ont...
Core classes and functionality for both the editor and game.
All classes and functionality used for implementing the game editor.
static std::string getFullPath(const std::string &path)
Generates the full path to the given tileset file.
static const std::string & MapAnimationPath()
static const std::string & MapTilePath()
static const std::string & SpritesheetPath()
static Ptr create(bl::gui::Element::Ptr child, bl::gui::RadioButton::Group *group=nullptr)
Creates a new HighlightRadioButton.
std::shared_ptr< HighlightRadioButton > Ptr
Pointer to a HighlightRadioButton.
void setGUI(bl::gui::GUI *gui)
Sets the parent GUI object.
void refresh()
Refreshes GUI elements.
std::uint8_t selected() const
Returns the currently selected catch type.
bl::gui::Element::Ptr getContent()
Returns the GUI element to pack.
bl::gui::Element::Ptr getContent()
Returns GUI content to pack.
core::map::Collision selected() const
Returns the currently selected collision.
core::map::LevelTransition getActive() const
Returns the currently selected level transition type.
bl::gui::Element::Ptr getContent()
Returns a packable GUI element to add this page to the GUI.
Section of the map area with the map itself and related controls.
void markSaved()
Marks the tileset clean.
std::uint8_t getActiveCatch() const
Returns the active catch type.
Tileset(bl::engine::Engine &engine, const DeleteCb &deleteCb, MapArea &map)
Creates the GUI elements.
Active getActiveTool() const
Returns what is currently selected as the active edit type.
bool unsavedChanges() const
Returns whether or not the tileset is in a dirty state.
core::map::LevelTransition getActiveLevel() const
Returns the actively selected level transition type.
bool loadTileset(const std::string &tileset)
Loads the given tileset and updates the GUI elements.
void refresh()
Refreshes the GUI.
void setGUI(bl::gui::GUI *gui)
Sets the parent GUI object.
bl::gui::Element::Ptr getContent()
Returns the gui element to pack.
core::map::Tile::IdType getActiveAnim() const
Returns the id of the active animation.
core::map::Tile::IdType getActiveTile() const
Returns the id of the active tile.
std::function< void(core::map::Tile::IdType, bool)> DeleteCb
std::uint8_t getActiveTown() const
Returns the currently selected town.
core::map::Collision getActiveCollision() const
Returns the active collision type.
bl::gui::Element::Ptr getContent()
Returns the GUI element to pack.
void refresh()
Refreshes the list of towns in the page.
void setGUI(bl::gui::GUI *gui)
Set the primary GUI object.
std::uint8_t selected() const
Returns the currently selected town index.