14 constexpr std::uint16_t NoSpawn = std::numeric_limits<std::uint16_t>::max();
15 constexpr
float FlymapScale = 0.5f;
17 using namespace bl::gui;
24 , playlistWindow(std::bind(&
Towns::onPlaylistPick, this, std::placeholders::_1),
25 std::bind(&
Towns::takeFocus, this)) {
26 content = Box::create(LinePacker::create(LinePacker::Vertical, 6.f));
28 Box::Ptr row = Box::create(LinePacker::create(LinePacker::Horizontal, 4.f));
29 noTownBut = RadioButton::create(
"No town",
"none");
30 noTownBut->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
33 row->pack(noTownBut,
false,
true);
35 Button::Ptr but = Button::create(
"New Town");
36 but->getSignal(Event::LeftClicked).willAlwaysCall(std::bind(&Towns::newTown,
this));
37 row->pack(but,
false,
true);
38 content->pack(row,
true,
false);
40 scrollRegion = ScrollArea::create(LinePacker::create(LinePacker::Vertical, 4.f));
41 scrollRegion->setColor(sf::Color::Transparent, sf::Color::Black);
42 scrollRegion->setOutlineThickness(1.5f);
43 content->pack(scrollRegion,
true,
true);
45 window = Window::create(LinePacker::create(LinePacker::Vertical, 4.f),
"Edit Town");
46 window->getSignal(Event::Closed).willAlwaysCall(std::bind(&Towns::closeWindow,
this));
48 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4.f));
49 nameEntry = TextEntry::create();
50 nameEntry->setRequisition({100.f, 15.f});
51 row->pack(Label::create(
"Name:"));
52 row->pack(nameEntry,
false,
false);
53 window->pack(row,
true,
false);
55 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4.f));
56 descEntry = TextEntry::create();
57 descEntry->setRequisition({200.f, 15.f});
58 row->pack(Label::create(
"Description:"));
59 row->pack(descEntry,
true,
false);
60 window->pack(row,
true,
false);
62 playlistLabel = Label::create(
"");
63 playlistLabel->setColor(sf::Color(20, 230, 255), sf::Color::Transparent);
64 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4.f));
65 but = Button::create(
"Pick Playlist");
66 but->getSignal(Event::LeftClicked).willAlwaysCall([
this](
const Event&, Element*) {
67 window->setForceFocus(
false);
68 playlistWindow.
open(gui, playlistLabel->getText());
70 row->pack(but,
false,
true);
71 row->pack(playlistLabel,
true,
false);
72 window->pack(row,
true,
false);
74 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4.f));
76 row->pack(Label::create(
"Weather:"));
77 row->pack(weatherSelect);
78 window->pack(row,
true,
false);
80 row = Box::create(LinePacker::create(LinePacker::Horizontal, 4.f));
81 row->pack(Label::create(
"PC Spawn:"),
false,
true);
82 spawnSelect = ComboBox::create();
83 spawnSelect->setMaxHeight(150.f);
84 row->pack(spawnSelect,
false,
true);
85 window->pack(row,
true,
false);
87 scene = engine.renderer().scenePool().allocateScene<bl::rc::scene::Scene2D>();
88 flymapTxtr = engine.renderer().texturePool().getOrLoadTexture(
90 flyMap.create(engine, flymapTxtr);
91 flyMap.getTransform().setScale(FlymapScale, FlymapScale);
92 flyMap.getTransform().setDepth(2.f);
93 flyMap.addToScene(scene, bl::rc::UpdateSpeed::Static);
95 townCircle.create(engine, 5.f);
96 townCircle.setFillColor(sf::Color::Black);
97 townCircle.setOutlineColor(sf::Color::Red);
98 townCircle.setOutlineThickness(1.f);
99 townCircle.getTransform().setOrigin(5.f, 5.f);
100 townCircle.getTransform().setDepth(1.f);
101 townCircle.addToScene(scene, bl::rc::UpdateSpeed::Static);
103 const glm::vec2 halfSize = flymapTxtr->size() * 0.5f;
104 window->pack(Label::create(
"Fly map position:"));
105 mapPosCanvas = Canvas::create(halfSize.x, halfSize.y);
106 mapPosCanvas->setScene(scene);
107 auto* cam = mapPosCanvas->setCamera<bl::cam::Camera2D>(halfSize * 0.5f, halfSize);
108 mapPosCanvas->getSignal(Event::LeftClicked)
109 .willAlwaysCall(std::bind(&Towns::setMapPos,
this, std::placeholders::_1));
110 window->pack(mapPosCanvas,
false,
false);
112 but = Button::create(
"Save");
113 but->getSignal(Event::LeftClicked).willAlwaysCall(std::bind(&Towns::onTownEdit,
this));
126 scrollRegion->clearChildren(
true);
128 noTownBut->setValue(
true);
130 for (
unsigned int i = 0; i < map.
towns.size(); ++i) {
131 scrollRegion->pack(makeRow(i, map.
towns[i].name),
true,
false);
134 refreshSpawns(NoSpawn);
137 void Towns::refreshSpawns(std::uint16_t s) {
138 spawnSelect->clearOptions();
139 spawnSelect->addOption(
"None");
141 std::vector<std::uint16_t> spawns;
142 spawns.reserve(map.
spawns.size());
143 for (
const auto& spawn : map.
spawns) { spawns.emplace_back(spawn.first); }
144 std::sort(spawns.begin(), spawns.end());
147 for (
unsigned int i = 0; i < spawns.size(); ++i) {
148 spawnSelect->addOption(std::to_string(spawns[i]));
149 if (spawns[i] == s) { opt = i + 1; }
151 spawnSelect->setSelectedOption(opt);
154 void Towns::onPlaylistPick(
const std::string& p) {
155 playlistLabel->setText(p);
156 window->setForceFocus(
true);
159 void Towns::takeFocus() { window->setForceFocus(
true); }
161 void Towns::closeWindow() {
162 window->setForceFocus(
false);
166 void Towns::newTown() { map.
addTown(); }
168 void Towns::editTown(std::uint8_t i) {
170 nameEntry->setInput(map.
towns[i].name);
171 descEntry->setInput(map.
towns[i].description);
172 playlistLabel->setText(map.
towns[i].playlist);
173 weatherSelect->setSelectedWeather(map.
towns[i].weather);
174 mapPos = map.
towns[i].mapPos;
175 refreshFlymapCanvas();
176 refreshSpawns(map.
towns[i].pcSpawn);
179 window->setForceFocus(
true);
182 void Towns::removeTown(std::uint8_t i) { map.
removeTown(i); }
184 void Towns::onTownEdit() {
186 t.
name = nameEntry->getInput();
188 t.
playlist = playlistLabel->getText();
189 t.
weather = weatherSelect->selectedWeather();
191 if (spawnSelect->getSelectedOptionText() ==
"None") { t.
pcSpawn = NoSpawn; }
192 else { t.
pcSpawn = std::atoi(spawnSelect->getSelectedOptionText().c_str()); }
197 Box::Ptr Towns::makeRow(std::uint8_t i,
const std::string& name) {
198 Box::Ptr row = Box::create(LinePacker::create(
199 LinePacker::Horizontal, 4.f, LinePacker::Compact, LinePacker::RightAlign));
200 row->setColor(
getColor(i + 1), sf::Color::Black);
202 RadioButton::Ptr but = RadioButton::create(name, name, noTownBut->getRadioGroup());
203 but->getSignal(Event::LeftClicked).willAlwaysCall([
this, i](
const Event&, Element*) {
206 but->setHorizontalAlignment(RenderSettings::Left);
208 Button::Ptr edit = Button::create(
"Edit");
209 edit->getSignal(Event::LeftClicked).willAlwaysCall(std::bind(&Towns::editTown,
this, i));
211 Button::Ptr del = Button::create(
"Remove");
212 del->getSignal(Event::LeftClicked).willAlwaysCall(std::bind(&Towns::removeTown,
this, i));
213 del->setColor(sf::Color::Red, sf::Color::Black);
215 row->pack(del,
false,
true);
216 row->pack(edit,
false,
true);
217 row->pack(but,
true,
true);
222 void Towns::setMapPos(
const Event& click) {
223 const sf::Vector2f localPos =
224 (click.mousePosition() - mapPosCanvas->getPosition()) / FlymapScale;
225 mapPos = sf::Vector2i(localPos);
226 refreshFlymapCanvas();
229 void Towns::refreshFlymapCanvas() {
230 townCircle.getTransform().setPosition(glm::vec2(mapPos.x, mapPos.y) * FlymapScale);
All classes and functionality used for implementing the game editor.
std::unordered_map< std::uint16_t, Spawn > spawns
std::vector< Town > towns
Represents a town, route, or region within a map. Maps may have many towns. Individual tiles are asso...
static const std::string & MenuImagePath()
void removeTown(std::uint8_t i)
Removes a town.
void addTown()
Adds a town.
void editTown(std::uint8_t i, const core::map::Town &town)
Modifies an existing town.
void open(bl::gui::GUI *gui, const std::string &plist)
Opens the window with an optional file to load.
static Ptr create()
Creates a new weather selector.
static sf::Color getColor(std::uint8_t index)
Returns the color to use for the given catch region.
Section of the map area with the map itself and related controls.
void disableControls()
Disables the map controls when a dialog is opened or the map tab is inactive.
Subpage for creating, editing, deleting, and placing towns in maps.
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.
static sf::Color getColor(std::uint8_t index)
Returns the color to use for the given town.
std::uint8_t selected() const
Returns the currently selected town index.
Towns(bl::engine::Engine &engine, MapArea &map)
Creates the towns subpage and GUI elements.