1 /*
2 * Copyright (C) 2011-2016 OpenDungeons Team
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "modes/MenuModeEditorLoad.h"
19
20 #include "utils/Helper.h"
21 #include "render/Gui.h"
22 #include "modes/ModeManager.h"
23 #include "sound/MusicPlayer.h"
24 #include "gamemap/GameMap.h"
25 #include "render/ODFrameListener.h"
26 #include "network/ODServer.h"
27 #include "network/ODClient.h"
28 #include "network/ServerMode.h"
29 #include "utils/LogManager.h"
30 #include "gamemap/MapHandler.h"
31 #include "utils/ResourceManager.h"
32 #include "utils/ConfigManager.h"
33
34 #include <CEGUI/CEGUI.h>
35
36 #include <boost/filesystem.hpp>
37
MenuModeEditorLoad(ModeManager * modeManager)38 MenuModeEditorLoad::MenuModeEditorLoad(ModeManager* modeManager):
39 AbstractApplicationMode(modeManager, ModeManager::MENU_EDITOR_LOAD)
40 {
41 CEGUI::Window* window = modeManager->getGui().getGuiSheet(Gui::guiSheet::editorLoadMenu);
42
43 // Fills the Level type combo box with the available level types.
44 const CEGUI::Image* selImg = &CEGUI::ImageManager::getSingleton().get("OpenDungeonsSkin/SelectionBrush");
45 CEGUI::Combobox* levelTypeCb = static_cast<CEGUI::Combobox*>(window->getChild(Gui::EDM_LIST_LEVEL_TYPES));
46 levelTypeCb->resetList();
47
48 CEGUI::ListboxTextItem* item = new CEGUI::ListboxTextItem("Official Skirmish Levels", 0);
49 item->setSelectionBrushImage(selImg);
50 levelTypeCb->addItem(item);
51
52 item = new CEGUI::ListboxTextItem("Official Multiplayer Levels", 1);
53 item->setSelectionBrushImage(selImg);
54 levelTypeCb->addItem(item);
55
56 item = new CEGUI::ListboxTextItem("Custom Skirmish Levels", 2);
57 item->setSelectionBrushImage(selImg);
58 levelTypeCb->addItem(item);
59
60 item = new CEGUI::ListboxTextItem("Custom Multiplayer Levels", 3);
61 item->setSelectionBrushImage(selImg);
62 levelTypeCb->addItem(item);
63
64 addEventConnection(
65 window->getChild(Gui::EDM_BUTTON_LAUNCH)->subscribeEvent(
66 CEGUI::PushButton::EventClicked,
67 CEGUI::Event::Subscriber(&MenuModeEditorLoad::launchSelectedButtonPressed, this)
68 )
69 );
70 addEventConnection(
71 window->getChild(Gui::EDM_LIST_LEVELS)->subscribeEvent(
72 CEGUI::Listbox::EventMouseDoubleClick,
73 CEGUI::Event::Subscriber(&MenuModeEditorLoad::launchSelectedButtonPressed, this)
74 )
75 );
76 addEventConnection(
77 window->getChild(Gui::EDM_LIST_LEVELS)->subscribeEvent(
78 CEGUI::Listbox::EventMouseClick,
79 CEGUI::Event::Subscriber(&MenuModeEditorLoad::updateDescription, this)
80 )
81 );
82 addEventConnection(
83 window->getChild(Gui::EDM_BUTTON_BACK)->subscribeEvent(
84 CEGUI::PushButton::EventClicked,
85 CEGUI::Event::Subscriber(&AbstractApplicationMode::goBack,
86 static_cast<AbstractApplicationMode*>(this))
87 )
88 );
89 addEventConnection(
90 window->getChild("LevelWindowFrame")->subscribeEvent(
91 CEGUI::FrameWindow::EventCloseClicked,
92 CEGUI::Event::Subscriber(&AbstractApplicationMode::goBack,
93 static_cast<AbstractApplicationMode*>(this))
94 )
95 );
96
97 addEventConnection(
98 window->getChild(Gui::EDM_LIST_LEVEL_TYPES)->subscribeEvent(
99 CEGUI::Combobox::EventListSelectionAccepted,
100 CEGUI::Event::Subscriber(&MenuModeEditorLoad::updateFilesList, this)
101 )
102 );
103 }
104
activate()105 void MenuModeEditorLoad::activate()
106 {
107 // Loads the corresponding Gui sheet.
108 getModeManager().getGui().loadGuiSheet(Gui::editorLoadMenu);
109
110 giveFocus();
111
112 // Play the main menu music
113 MusicPlayer::getSingleton().play(ConfigManager::getSingleton().getMainMenuMusic());
114
115 GameMap* gameMap = ODFrameListener::getSingleton().getClientGameMap();
116 gameMap->clearAll();
117 gameMap->setGamePaused(true);
118
119 CEGUI::Combobox* levelTypeCb = static_cast<CEGUI::Combobox*>(getModeManager().getGui().
120 getGuiSheet(Gui::editorLoadMenu)->getChild(Gui::EDM_LIST_LEVEL_TYPES));
121 levelTypeCb->setItemSelectState(static_cast<size_t>(0), true);
122 updateFilesList();
123 }
124
findFileStemIn(const std::vector<std::string> & fileList,std::string filename)125 static bool findFileStemIn(const std::vector<std::string>& fileList, std::string filename)
126 {
127 for (const std::string& file : fileList)
128 {
129 if (boost::filesystem::path(file).stem().string() ==
130 boost::filesystem::path(filename).stem().string())
131 return true;
132 }
133 return false;
134 }
135
updateFilesList(const CEGUI::EventArgs &)136 bool MenuModeEditorLoad::updateFilesList(const CEGUI::EventArgs&)
137 {
138 CEGUI::Window* window = getModeManager().getGui().getGuiSheet(Gui::guiSheet::editorLoadMenu);
139 CEGUI::Listbox* levelSelectList = static_cast<CEGUI::Listbox*>(window->getChild(Gui::EDM_LIST_LEVELS));
140
141 CEGUI::Combobox* levelTypeCb = static_cast<CEGUI::Combobox*>(window->getChild(Gui::EDM_LIST_LEVEL_TYPES));
142
143 CEGUI::Window* loadText = window->getChild(Gui::EDM_TEXT_LOADING);
144 loadText->setText("");
145 mFilesList.clear();
146 mDescriptionList.clear();
147 levelSelectList->resetList();
148
149 std::string levelPath;
150 size_t selection = levelTypeCb->getItemIndex(levelTypeCb->getSelectedItem());
151 bool officialSkirmishMaps = false;
152 bool officialMultiplayerMaps = false;
153 switch (selection)
154 {
155 default:
156 case 0:
157 levelPath = ResourceManager::getSingleton().getGameLevelPathSkirmish();
158 officialSkirmishMaps = true;
159 break;
160 case 1:
161 levelPath = ResourceManager::getSingleton().getGameLevelPathMultiplayer();
162 officialMultiplayerMaps = true;
163 break;
164 case 2:
165 levelPath = ResourceManager::getSingleton().getUserLevelPathSkirmish();
166 break;
167 case 3:
168 levelPath = ResourceManager::getSingleton().getUserLevelPathMultiplayer();
169 break;
170 }
171
172 if(Helper::fillFilesList(levelPath, mFilesList, MapHandler::LEVEL_EXTENSION))
173 {
174 std::vector<std::string> officialFileList;
175 if (officialSkirmishMaps)
176 levelPath = ResourceManager::getSingleton().getUserLevelPathSkirmish();
177 if (officialMultiplayerMaps)
178 levelPath = ResourceManager::getSingleton().getUserLevelPathMultiplayer();
179
180 if (officialSkirmishMaps || officialMultiplayerMaps)
181 {
182 if (!Helper::fillFilesList(levelPath, officialFileList, MapHandler::LEVEL_EXTENSION))
183 officialFileList.clear();
184 }
185
186 for (uint32_t n = 0; n < mFilesList.size(); ++n)
187 {
188 std::string filename = mFilesList[n];
189
190 LevelInfo levelInfo;
191 std::string mapName;
192 std::string mapDescription;
193 bool customMapExists = findFileStemIn(officialFileList, filename);
194 if(MapHandler::getMapInfo(filename, levelInfo))
195 {
196 mapName.clear();
197 if (customMapExists)
198 mapName = "[image-size='w:16 h:16'][image='OpenDungeonsIcons/CogIcon'][vert-alignment='centre'] ";
199 mapName += levelInfo.mLevelName;
200 mapDescription = levelInfo.mLevelDescription;
201 if (customMapExists)
202 mapDescription += "\n(A custom map exists for this level.)";
203 }
204 else
205 {
206 mapName = "invalid map";
207 mapDescription = "invalid map";
208 }
209
210 mDescriptionList.push_back(mapDescription);
211 CEGUI::ListboxTextItem* item = new CEGUI::ListboxTextItem(mapName);
212 item->setID(n);
213 item->setSelectionBrushImage("OpenDungeonsSkin/SelectionBrush");
214 levelSelectList->addItem(item);
215 }
216 }
217
218 updateDescription();
219 return true;
220 }
221
launchSelectedButtonPressed(const CEGUI::EventArgs &)222 bool MenuModeEditorLoad::launchSelectedButtonPressed(const CEGUI::EventArgs&)
223 {
224 CEGUI::Window* window = getModeManager().getGui().getGuiSheet(Gui::guiSheet::editorLoadMenu);
225 CEGUI::Listbox* levelSelectList = static_cast<CEGUI::Listbox*>(window->getChild(Gui::EDM_LIST_LEVELS));
226
227 if(levelSelectList->getSelectedCount() == 0)
228 {
229 window->getChild(Gui::EDM_TEXT_LOADING)->setText("Please select a level first.");
230 return true;
231 }
232
233 window->getChild(Gui::EDM_TEXT_LOADING)->setText("Loading...");
234
235 CEGUI::ListboxItem* selItem = levelSelectList->getFirstSelectedItem();
236 int id = selItem->getID();
237
238 const std::string& level = mFilesList[id];
239
240 // In editor mode, we act as a server
241 ConfigManager& config = ConfigManager::getSingleton();
242 std::string nickname = config.getGameValue(Config::NICKNAME, std::string(), false);
243 if(!ODServer::getSingleton().startServer(nickname, level, ServerMode::ModeEditor, false))
244 {
245 OD_LOG_ERR("Could not start server for editor !!!");
246 window->getChild(Gui::EDM_TEXT_LOADING)->setText("ERROR: Could not start server for editor !!!");
247 }
248
249 int port = ODServer::getSingleton().getNetworkPort();
250 uint32_t timeout = ConfigManager::getSingleton().getClientConnectionTimeout();
251 std::string replayFilename = ResourceManager::getSingleton().getReplayDataPath()
252 + ResourceManager::getSingleton().buildReplayFilename();
253 if(!ODClient::getSingleton().connect("localhost", port, timeout, replayFilename))
254 {
255 OD_LOG_ERR("Could not connect to server for editor !!!");
256 window->getChild(Gui::EDM_TEXT_LOADING)->setText("Error: Couldn't connect to local server!");
257 return true;
258 }
259 return true;
260 }
261
updateDescription(const CEGUI::EventArgs &)262 bool MenuModeEditorLoad::updateDescription(const CEGUI::EventArgs&)
263 {
264 CEGUI::Window* window = getModeManager().getGui().getGuiSheet(Gui::editorLoadMenu);
265 CEGUI::Listbox* levelSelectList = static_cast<CEGUI::Listbox*>(window->getChild(Gui::SKM_LIST_LEVELS));
266 CEGUI::Window* descTxt = window->getChild("LevelWindowFrame/MapDescriptionText");
267
268 if(levelSelectList->getSelectedCount() == 0)
269 {
270 descTxt->setText("");
271 return true;
272 }
273
274 getModeManager().getGui().playButtonClickSound();
275
276 // Get the level corresponding id
277 CEGUI::ListboxItem* selItem = levelSelectList->getFirstSelectedItem();
278 int id = selItem->getID();
279
280 std::string description = mDescriptionList[id];
281 descTxt->setText(description);
282 return true;
283 }
284