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