Peoplemon  0.1.0
Peoplemon 3 game source documentation
Tileset.cpp
Go to the documentation of this file.
2 
3 #include <BLIB/Engine.hpp>
4 #include <BLIB/Util/Random.hpp>
5 #include <Core/Properties.hpp>
6 #include <Core/Resources.hpp>
9 
10 namespace editor
11 {
12 namespace page
13 {
14 namespace
15 {
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)) {
20  std::stringstream ss;
21  ss << bl::util::FileUtil::getBaseName(base) << "_" << std::hex
22  << bl::util::Random::get<int>(1000, 10000000) << "."
23  << bl::util::FileUtil::getExtension(base);
24  return ss.str();
25  }
26  return base;
27 }
28 } // namespace
29 
30 using namespace bl::gui;
31 
32 Tileset::Tileset(bl::engine::Engine& engine, const DeleteCb& dcb, MapArea& map)
33 : deleteCb(dcb)
34 , catchables(map.editMap())
35 , towns(engine, map)
36 , tool(Active::Tiles)
37 , activeTile(core::map::Tile::Blank)
38 , activeAnim(core::map::Tile::Blank)
39 , dirty(false) {
40  content = Notebook::create();
41 
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"};
48  const char* file =
49  bl::dialog::tinyfd_openFileDialog("Add tile(s)", nullptr, 4, filters, "Image files", 1);
50  if (file) {
51  std::stringstream ss(file);
52  std::string tile;
53  while (std::getline(ss, tile, '|')) {
54  sf::Image img;
55  std::string filename = makeCopyName(core::Properties::MapTilePath(), tile);
56  filename = bl::util::FileUtil::getBaseName(filename) + ".png";
57  if (!img.loadFromFile(tile)) {
58  BL_LOG_ERROR << "Failed to load tile: " << tile;
59  continue;
60  }
61  if (!img.saveToFile(
62  bl::util::FileUtil::joinPath(core::Properties::MapTilePath(), filename))) {
63  BL_LOG_ERROR << "Failed to copy tile: " << tile << " -> " << filename;
64  continue;
65  }
66  tileset->addTexture(filename);
67  }
68  dirty = true;
69  updateGui();
70  }
71  });
72  bl::gui::Button::Ptr importSpritesheetBut = Button::create("Add Tilesheet");
73  importSpritesheetBut->setTooltip("Import a spritesheet as many tiles");
74  // TODO - implement sprite sheet import
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",
80  "yesno",
81  "warning",
82  0)) {
83  deleteCb(activeTile, false);
84  tileset->removeTexture(activeTile);
85  dirty = true;
86  updateGui();
87  }
88  });
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);
94 
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);
99 
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);
107  if (file) {
108  const std::string animFile = makeCopyName(core::Properties::MapAnimationPath(), file);
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);
113  return;
114  }
115 
116  bl::util::FileUtil::copyFile(
117  file, bl::util::FileUtil::joinPath(core::Properties::MapAnimationPath(), animFile));
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(
122  sp,
123  bl::util::FileUtil::joinPath(core::Properties::SpritesheetPath(),
124  anim.spritesheetFile()));
125  }
126 
127  tileset->addAnimation(animFile);
128  dirty = true;
129  updateGui();
130  }
131  });
132  bl::gui::Button::Ptr delAnimBut = Button::create("Delete Animation");
133  delAnimBut->getSignal(Event::LeftClicked).willAlwaysCall([this](const Event&, Element*) {
134  if (1 ==
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",
138  "yesno",
139  "warning",
140  0)) {
141  deleteCb(activeAnim, true);
142  tileset->removeAnimation(activeAnim);
143  dirty = true;
144  updateGui();
145  }
146  });
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);
151 
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);
156 
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; });
161  content->addPage(
162  "col", "Collisions", collisions.getContent(), [this]() { tool = Active::CollisionTiles; });
163  content->addPage(
164  "catch", "Catch Tiles", catchables.getContent(), [this]() { tool = Active::CatchTiles; });
165  content->addPage("level", "Level Transitions", levelTransitions.getContent(), [this]() {
166  tool = Active::LevelTiles;
167  });
168 
169  loadTileset("Worldtileset.tlst");
170 }
171 
172 void Tileset::setGUI(GUI* gui) {
173  catchables.setGUI(gui);
174  towns.setGUI(gui);
175 }
176 
177 Element::Ptr Tileset::getContent() { return content; }
178 
179 Tileset::Active Tileset::getActiveTool() const { return tool; }
180 
181 core::map::Tile::IdType Tileset::getActiveTile() const { return activeTile; }
182 
183 core::map::Tile::IdType Tileset::getActiveAnim() const { return activeAnim; }
184 
186 
187 std::uint8_t Tileset::getActiveCatch() const { return catchables.selected(); }
188 
189 std::uint8_t Tileset::getActiveTown() const { return towns.selected(); }
190 
191 core::map::LevelTransition Tileset::getActiveLevel() const { return levelTransitions.getActive(); }
192 
193 bool Tileset::loadTileset(const std::string& file) {
194  auto newTileset = TilesetManager::load(core::map::Tileset::getFullPath(file));
195  if (!newTileset) return false;
196  if (newTileset.get() != tileset.get()) {
197  tileset = newTileset;
198  updateGui();
199  }
200  return true;
201 }
202 
203 void Tileset::updateGui() {
204  tilesBox->clearChildren(true);
205  animsBox->clearChildren(true);
206 
207  // tiles
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;
216  });
217  if (!group) {
218  activeTile = pair->first;
219  button->setValue(true);
220  }
221  group = button->getRadioGroup();
222  tilesBox->pack(button);
223  }
224 
225  // animations
226  group = nullptr;
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;
235  });
236  if (!group) {
237  activeAnim = pair->first;
238  button->setValue(true);
239  }
240  group = button->getRadioGroup();
241  animsBox->pack(button);
242  }
243 
244  catchables.refresh();
245  towns.refresh();
246 }
247 
248 bool Tileset::unsavedChanges() const { return dirty; }
249 
250 void Tileset::markSaved() { dirty = false; }
251 
253  catchables.refresh();
254  towns.refresh();
255 }
256 
257 } // namespace page
258 } // namespace editor
std::uint32_t base
Definition: WildIntro.cpp:26
Collision
The different types of collisions in maps.
Definition: Collision.hpp:16
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.
Definition: Tile.hpp:11
std::uint16_t IdType
Definition: Tile.hpp:33
static std::string getFullPath(const std::string &path)
Generates the full path to the given tileset file.
Definition: Tileset.cpp:190
static const std::string & MapAnimationPath()
Definition: Properties.cpp:357
static const std::string & MapTilePath()
Definition: Properties.cpp:351
static const std::string & SpritesheetPath()
Definition: Properties.cpp:309
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.
Definition: Catchables.cpp:53
void refresh()
Refreshes GUI elements.
Definition: Catchables.cpp:63
std::uint8_t selected() const
Returns the currently selected catch type.
Definition: Catchables.cpp:57
bl::gui::Element::Ptr getContent()
Returns the GUI element to pack.
Definition: Catchables.cpp:55
bl::gui::Element::Ptr getContent()
Returns GUI content to pack.
Definition: Collisions.cpp:69
core::map::Collision selected() const
Returns the currently selected collision.
Definition: Collisions.cpp:71
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.
Definition: MapArea.hpp:16
void markSaved()
Marks the tileset clean.
Definition: Tileset.cpp:250
std::uint8_t getActiveCatch() const
Returns the active catch type.
Definition: Tileset.cpp:187
Tileset(bl::engine::Engine &engine, const DeleteCb &deleteCb, MapArea &map)
Creates the GUI elements.
Definition: Tileset.cpp:32
Active getActiveTool() const
Returns what is currently selected as the active edit type.
Definition: Tileset.cpp:179
bool unsavedChanges() const
Returns whether or not the tileset is in a dirty state.
Definition: Tileset.cpp:248
core::map::LevelTransition getActiveLevel() const
Returns the actively selected level transition type.
Definition: Tileset.cpp:191
bool loadTileset(const std::string &tileset)
Loads the given tileset and updates the GUI elements.
Definition: Tileset.cpp:193
void refresh()
Refreshes the GUI.
Definition: Tileset.cpp:252
void setGUI(bl::gui::GUI *gui)
Sets the parent GUI object.
Definition: Tileset.cpp:172
bl::gui::Element::Ptr getContent()
Returns the gui element to pack.
Definition: Tileset.cpp:177
core::map::Tile::IdType getActiveAnim() const
Returns the id of the active animation.
Definition: Tileset.cpp:183
core::map::Tile::IdType getActiveTile() const
Returns the id of the active tile.
Definition: Tileset.cpp:181
std::function< void(core::map::Tile::IdType, bool)> DeleteCb
Definition: Tileset.hpp:30
std::uint8_t getActiveTown() const
Returns the currently selected town.
Definition: Tileset.cpp:189
core::map::Collision getActiveCollision() const
Returns the active collision type.
Definition: Tileset.cpp:185
bl::gui::Element::Ptr getContent()
Returns the GUI element to pack.
Definition: Towns.cpp:117
void refresh()
Refreshes the list of towns in the page.
Definition: Towns.cpp:125
void setGUI(bl::gui::GUI *gui)
Set the primary GUI object.
Definition: Towns.cpp:121
std::uint8_t selected() const
Returns the currently selected town index.
Definition: Towns.cpp:119