2 * See settings.hh for information about this file.
4 * Copyright (C) 2008 David Kolossa
6 * This file is part of OpenStranded
8 * OpenStranded is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * OpenStranded is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with OpenStranded. If not, see <http://www.gnu.org/licenses/>.
24 #include "tinyxml/tinyxml.h"
25 #include "settings.hh"
26 #include "s2string.hh"
29 GlobalSettings::GlobalSettings(std::string configPath
) :
30 configPath(configPath
)
32 this->initializeStandardValues();
33 this->readConfigFile();
36 GlobalSettings::~GlobalSettings()
40 GlobalSettings::initializeStandardValues()
42 this->setResolutionX(1024);
43 this->setResolutionY(768);
44 this->setColorDepth(32);
45 this->setFullScreen(false);
48 this->setRenderer("Irrlicht");
49 #elif defined(HAVE_HORDE3D)
50 this->setRenderer("Horde3D");
52 this->setRenderer("");
55 this->setViewRange(2);
57 this->setTerrainDetail(1);
58 this->setWaterDetail(3);
59 this->setSkyDetail(1);
60 this->setEffectDetail(1);
61 this->setGrassDetail(2);
63 this->setMusicVolume(1.0);
64 this->setSoundVolume(1.0);
67 this->setLightFx(true);
68 this->setWindSwayFx(true);
70 this->setMultiTex(true);
71 this->setMotionBlur(true);
72 this->setMotionBlurIntensity(1.0);
74 this->setPlayerName("Mr. Stranded");
79 GlobalSettings::updateConfigFile()
83 // Create XML declaration
84 TiXmlDeclaration
*declaration
= new TiXmlDeclaration("1.0", "utf-8", "");
85 xml
.LinkEndChild(declaration
);
87 // Create <config> environment
88 TiXmlElement
*root
= new TiXmlElement("config");
89 xml
.LinkEndChild(root
);
91 // Traverse setting map
92 for (std::map
<std::string
, std::string
>::iterator i
= this->settings
.begin(); i
!= this->settings
.end(); i
++)
94 std::string substrings
[2];
96 std::string key
= std::string(i
->first
);
97 std::string value
= std::string(i
->second
);
99 flag
= s2str::explode(key
, substrings
, "_", 2);
100 if (inFlag(flag
, EXPLODE_GREATER
) || inFlag(flag
, EXPLODE_LOWER
) )
102 Out::debug
<< "Malformed setting name, skipped it." << Out::endl
;
105 else if (inFlag(flag
, EXPLODE_NO_TOKEN
))
107 // TODO: Catch special case of categoryless setting
108 Out::debug
<< "Not Implemented: Categoryless setting, skipped it" << Out::endl
;
113 // Check for existing category
114 TiXmlElement
*categoryElement
= NULL
;
115 TiXmlNode
*categoryNode
= NULL
;
116 while((categoryNode
= root
->IterateChildren(categoryNode
)) != 0)
118 categoryElement
= categoryNode
->Clone()->ToElement();
119 if (std::string(categoryElement
->Attribute("name")) == substrings
[0])
121 delete categoryElement
;
122 categoryElement
= NULL
;
124 delete categoryElement
;
125 categoryElement
= NULL
;
127 // No matching category found: Create it
128 if (categoryNode
== NULL
)
130 categoryElement
= new TiXmlElement("category");
131 categoryElement
->SetAttribute("name", substrings
[0].c_str());
132 root
->LinkEndChild(categoryElement
);
136 categoryElement
= categoryNode
->ToElement();
141 TiXmlElement
*element
= new TiXmlElement("setting");
142 element
->SetAttribute("name", substrings
[1].c_str());
144 // Set the type of the setting
145 // FIXME: This is both BUGGY and UGLY
146 if (s2str::isInteger(value
))
148 element
->SetAttribute("type", "int");
150 else if (s2str::isDecimal(value
))
152 element
->SetAttribute("type", "float");
154 else if (s2str::isBool(value
))
156 element
->SetAttribute("type", "bool");
160 element
->SetAttribute("type", "string");
163 categoryElement
->LinkEndChild(element
);
165 // Store value in setting
166 TiXmlText
*text
= new TiXmlText(value
.c_str());
167 element
->LinkEndChild(text
);
172 if (!xml
.SaveFile(this->configPath
.c_str()))
174 Out::fatal
<< "Error when writing config file: " << xml
.ErrorDesc() << Out::endl
;
182 GlobalSettings::readConfigFile()
184 TiXmlDocument
xml(this->configPath
.c_str());
185 // Check for regular file problems.
188 Out::fatal
<< "Error when reading config file: " << xml
.ErrorDesc() << Out::endl
;
192 TiXmlHandle
handle(&xml
);
195 root
= handle
.FirstChild("config").ToElement();
197 // Make sure that the top-level of our XML file is <config>
200 Out::fatal
<< "Invalid Markup: Top level element in config file is not <config> or missing" << Out::endl
;
204 for (TiXmlElement
*e
= root
->FirstChild("category")->ToElement(); e
; e
= e
->NextSiblingElement())
206 for (TiXmlElement
*f
= e
->FirstChild("setting")->ToElement(); f
; f
= f
->NextSiblingElement())
208 std::string category
= std::string(e
->Attribute("name"));
209 std::string type
= std::string(f
->Attribute("type"));
210 std::string name
= std::string(f
->Attribute("name"));
211 std::string value
= std::string(f
->GetText());
214 if (s2str::isInteger(value
))
216 this->setSetting(category
+ "_" + name
, value
);
220 Out::error
<< "Invalid int value for setting with name \"" << name
<< "\" in config file!" << Out::endl
;
224 else if (type
== "float")
226 if (s2str::isDecimal(value
))
228 this->setSetting(category
+ "_" + name
, value
);
232 Out::error
<< "Invalid float value for setting with name \"" << name
<< "\" in config file!" << Out::endl
;
235 else if (type
== "bool")
237 if (s2str:: isBool(value
))
239 this->setSetting(category
+ "_" + name
, value
);
243 Out::error
<< "Invalid bool value for setting with name \"" << name
<< "\" in config file!" << Out::endl
;
246 else if (type
== "string")
248 this->setSetting(category
+ "_" + name
, value
);
252 Out::error
<< "Invalid type of setting with name \"" << name
<< "\" in config file!" << Out::endl
;
261 GlobalSettings::getSetting(const std::string
&setting
)
263 std::map
<std::string
, std::string
>::iterator settingIterator
;
264 if (settings
.empty())
267 settingIterator
= settings
.find(setting
);
268 if (settingIterator
!= settings
.end())
269 return settingIterator
->second
;
275 GlobalSettings::getTemporary(const std::string
&setting
)
277 std::map
<std::string
, std::string
>::iterator settingIterator
;
278 if (tempSettings
.empty())
281 settingIterator
= tempSettings
.find(setting
);
282 if (settingIterator
!= tempSettings
.end())
283 return settingIterator
->second
;
289 GlobalSettings::setSetting(const std::string
&setting
, const std::string
&settingString
)
291 settings
[setting
] = settingString
;
295 GlobalSettings::setTemporary(const std::string
&setting
, const std::string
&settingString
)
297 tempSettings
[setting
] = settingString
;