1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2
3 #include "SelectionWidget.h"
4
5 #include <set>
6
7 #include "System/FileSystem/ArchiveScanner.h"
8 #include "System/FileSystem/VFSHandler.h"
9 #include "System/Exceptions.h"
10 #include "System/Config/ConfigHandler.h"
11 #include "System/AIScriptHandler.h"
12 #include "ExternalAI/LuaAIImplHandler.h"
13 #include "ExternalAI/Interface/SSkirmishAILibrary.h"
14 #include "System/Info.h"
15 #include "alphanum.hpp"
16
17 const std::string SelectionWidget::NoModSelect = "No game selected";
18 const std::string SelectionWidget::NoMapSelect = "No map selected";
19 const std::string SelectionWidget::NoScriptSelect = "No script selected";
20 const std::string SelectionWidget::SandboxAI = "Player Only: Testing Sandbox";
21
22 CONFIG(std::string, LastSelectedMod).defaultValue(SelectionWidget::NoModSelect).description("Stores the previously played game.");
23 CONFIG(std::string, LastSelectedMap).defaultValue(SelectionWidget::NoMapSelect).description("Stores the previously played map.");
24 CONFIG(std::string, LastSelectedScript).defaultValue(SelectionWidget::NoScriptSelect).description("Stores the previously played AI.");
25
SelectionWidget(agui::GuiElement * parent)26 SelectionWidget::SelectionWidget(agui::GuiElement* parent) : agui::GuiElement(parent)
27 {
28 SetPos(0.5f, 0.2f);
29 SetSize(0.4f, 0.2f);
30 curSelect = NULL;
31
32 agui::VerticalLayout* vl = new agui::VerticalLayout(this);
33 vl->SetBorder(1.2f);
34 agui::HorizontalLayout* modL = new agui::HorizontalLayout(vl);
35 mod = new agui::Button("Select", modL);
36 mod->Clicked.connect(boost::bind(&SelectionWidget::ShowModList, this));
37 mod->SetSize(0.1f, 0.00f, true);
38 userMod = configHandler->GetString("LastSelectedMod");
39 if (archiveScanner->GetSingleArchiveChecksum(archiveScanner->ArchiveFromName(userMod)) == 0)
40 userMod = NoModSelect;
41 modT = new agui::TextElement(userMod, modL);
42 agui::HorizontalLayout* mapL = new agui::HorizontalLayout(vl);
43 map = new agui::Button("Select", mapL);
44 map->Clicked.connect(boost::bind(&SelectionWidget::ShowMapList, this));
45 map->SetSize(0.1f, 0.00f, true);
46 userMap = configHandler->GetString("LastSelectedMap");
47 if (archiveScanner->GetSingleArchiveChecksum(archiveScanner->ArchiveFromName(userMap)) == 0)
48 userMap = NoMapSelect;
49 mapT = new agui::TextElement(userMap, mapL);
50 agui::HorizontalLayout* scriptL = new agui::HorizontalLayout(vl);
51 script = new agui::Button("Select", scriptL);
52 script->Clicked.connect(boost::bind(&SelectionWidget::ShowScriptList, this));
53 script->SetSize(0.1f, 0.00f, true);
54 userScript = configHandler->GetString("LastSelectedScript");
55 scriptT = new agui::TextElement(userScript, scriptL);
56 }
57
~SelectionWidget()58 SelectionWidget::~SelectionWidget()
59 {
60 CleanWindow();
61 }
62
ShowModList()63 void SelectionWidget::ShowModList()
64 {
65 if (curSelect)
66 return;
67 curSelect = new ListSelectWnd("Select game");
68 curSelect->Selected.connect(boost::bind(&SelectionWidget::SelectMod, this, _1));
69 curSelect->WantClose.connect(boost::bind(&SelectionWidget::CleanWindow, this));
70
71 const std::vector<CArchiveScanner::ArchiveData> &found = archiveScanner->GetPrimaryMods();
72
73 std::map<std::string, std::string, doj::alphanum_less<std::string> > modMap; // name, desc (using a map to sort)
74 for (std::vector<CArchiveScanner::ArchiveData>::const_iterator it = found.begin(); it != found.end(); ++it) {
75 modMap[it->GetNameVersioned()] = it->GetDescription();
76 }
77
78 std::map<std::string, std::string>::iterator mit;
79 for (mit = modMap.begin(); mit != modMap.end(); ++mit) {
80 curSelect->list->AddItem(mit->first, mit->second);
81 }
82 curSelect->list->SetCurrentItem(userMod);
83 }
84
ShowMapList()85 void SelectionWidget::ShowMapList()
86 {
87 if (curSelect)
88 return;
89 curSelect = new ListSelectWnd("Select map");
90 curSelect->Selected.connect(boost::bind(&SelectionWidget::SelectMap, this, _1));
91 curSelect->WantClose.connect(boost::bind(&SelectionWidget::CleanWindow, this));
92
93 const std::vector<std::string> &arFound = archiveScanner->GetMaps();
94
95 std::set<std::string, doj::alphanum_less<std::string> > mapSet; // use a set to sort them
96 for (std::vector<std::string>::const_iterator it = arFound.begin(); it != arFound.end(); ++it) {
97 mapSet.insert((*it).c_str());
98 }
99
100 for (std::set<std::string>::iterator sit = mapSet.begin(); sit != mapSet.end(); ++sit) {
101 curSelect->list->AddItem(*sit, *sit);
102 }
103 curSelect->list->SetCurrentItem(userMap);
104 }
105
106
GetFileName(const std::string & name)107 static const std::string GetFileName(const std::string& name){
108 if (name.empty())
109 return name;
110 const std::string filename = archiveScanner->ArchiveFromName(name);
111 const std::string path = archiveScanner->GetArchivePath(filename);
112 return path + filename;
113 }
114
AddArchive(const std::string & name)115 static void AddArchive(const std::string& name) {
116 if (!name.empty()) {
117 vfsHandler->AddArchive(GetFileName(name), true);
118 }
119 }
120
RemoveArchive(const std::string & name)121 static void RemoveArchive(const std::string& name) {
122 if (!name.empty()) {
123 vfsHandler->RemoveArchive(GetFileName(name));
124 }
125 }
126
ShowScriptList()127 void SelectionWidget::ShowScriptList()
128 {
129 if (curSelect)
130 return;
131 curSelect = new ListSelectWnd("Select script");
132 curSelect->Selected.connect(boost::bind(&SelectionWidget::SelectScript, this, _1));
133 curSelect->WantClose.connect(boost::bind(&SelectionWidget::CleanWindow, this));
134
135 //FIXME: lua ai's should be handled in AIScriptHandler.cpp, too respecting the selected game and map
136 // maybe also merge it with StartScriptGen.cpp
137
138 // load selected archives to get lua ais
139 AddArchive(userMod);
140 AddArchive(userMap);
141
142 std::vector< std::vector<InfoItem> > luaAIInfos = luaAIImplHandler.LoadInfos();
143 for(int i=0; i<luaAIInfos.size(); i++) {
144 for (int j=0; j<luaAIInfos[i].size(); j++) {
145 if (luaAIInfos[i][j].key==SKIRMISH_AI_PROPERTY_SHORT_NAME)
146 curSelect->list->AddItem(info_getValueAsString(&luaAIInfos[i][j]), "");
147 }
148 }
149
150 // close archives
151 RemoveArchive(userMap);
152 RemoveArchive(userMod);
153
154 // add sandbox script to list
155 curSelect->list->AddItem(SandboxAI, "");
156
157 // add native ai's to the list, too (but second, lua ai's are prefered)
158 CAIScriptHandler::ScriptList scriptList = CAIScriptHandler::Instance().GetScriptList();
159 for (CAIScriptHandler::ScriptList::iterator it = scriptList.begin(); it != scriptList.end(); ++it) {
160 curSelect->list->AddItem(*it, "");
161 }
162
163 curSelect->list->SetCurrentItem(userScript);
164 }
165
SelectMod(std::string mod)166 void SelectionWidget::SelectMod(std::string mod)
167 {
168 userMod = mod;
169 configHandler->SetString("LastSelectedMod", userMod);
170 modT->SetText(userMod);
171
172 CleanWindow();
173 }
174
SelectScript(std::string map)175 void SelectionWidget::SelectScript(std::string map)
176 {
177 userScript = map;
178 configHandler->SetString("LastSelectedScript", userScript);
179 scriptT->SetText(userScript);
180
181 CleanWindow();
182 }
183
SelectMap(std::string script)184 void SelectionWidget::SelectMap(std::string script)
185 {
186 userMap = script;
187 configHandler->SetString("LastSelectedMap", userMap);
188 mapT->SetText(userMap);
189
190 CleanWindow();
191 }
192
CleanWindow()193 void SelectionWidget::CleanWindow()
194 {
195 if (curSelect)
196 {
197 agui::gui->RmElement(curSelect);
198 curSelect = NULL;
199 }
200 }
201