1 // configfile.cpp
2 //
3 // Copyright (C) 2001-2009, the Celestia Development Team
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9
10 #include <iostream>
11 #include <fstream>
12 #include <cassert>
13 #include <celutil/debug.h>
14 #include <celutil/directory.h>
15 #include <celutil/util.h>
16 #include <celengine/celestia.h>
17 #include <celengine/texmanager.h>
18 #include "configfile.h"
19
20 using namespace std;
21
22
getUint(Hash * params,const string & paramName,unsigned int defaultValue)23 static unsigned int getUint(Hash* params,
24 const string& paramName,
25 unsigned int defaultValue)
26 {
27 double value = 0.0;
28 if (params->getNumber(paramName, value))
29 return (unsigned int) value;
30 else
31 return defaultValue;
32 }
33
34
ReadCelestiaConfig(string filename,CelestiaConfig * config)35 CelestiaConfig* ReadCelestiaConfig(string filename, CelestiaConfig *config)
36 {
37 ifstream configFile(filename.c_str());
38 if (!configFile.good())
39 {
40 DPRINTF(0, "Error opening config file '%s'.\n", filename.c_str());
41 return config;
42 }
43
44 Tokenizer tokenizer(&configFile);
45 Parser parser(&tokenizer);
46
47 if (tokenizer.nextToken() != Tokenizer::TokenName)
48 {
49 DPRINTF(0, "%s:%d 'Configuration' expected.\n", filename.c_str(),
50 tokenizer.getLineNumber());
51 return config;
52 }
53
54 if (tokenizer.getStringValue() != "Configuration")
55 {
56 DPRINTF(0, "%s:%d 'Configuration' expected.\n", filename.c_str(),
57 tokenizer.getLineNumber());
58 return config;
59 }
60
61 Value* configParamsValue = parser.readValue();
62 if (configParamsValue == NULL || configParamsValue->getType() != Value::HashType)
63 {
64 DPRINTF(0, "%s: Bad configuration file.\n", filename.c_str());
65 return config;
66 }
67
68 Hash* configParams = configParamsValue->getHash();
69
70 if (config == NULL)
71 config = new CelestiaConfig();
72
73 #ifdef CELX
74 config->configParams = configParams;
75 configParams->getString("LuaHook", config->luaHook);
76 config->luaHook = WordExp(config->luaHook);
77 #endif
78
79 config->faintestVisible = 6.0f;
80 configParams->getNumber("FaintestVisibleMagnitude", config->faintestVisible);
81 configParams->getString("FavoritesFile", config->favoritesFile);
82 config->favoritesFile = WordExp(config->favoritesFile);
83 configParams->getString("DestinationFile", config->destinationsFile);
84 config->destinationsFile = WordExp(config->destinationsFile);
85 configParams->getString("InitScript", config->initScriptFile);
86 config->initScriptFile = WordExp(config->initScriptFile);
87 configParams->getString("DemoScript", config->demoScriptFile);
88 config->demoScriptFile = WordExp(config->demoScriptFile);
89 configParams->getString("AsterismsFile", config->asterismsFile);
90 config->asterismsFile = WordExp(config->asterismsFile);
91 configParams->getString("BoundariesFile", config->boundariesFile);
92 config->boundariesFile = WordExp(config->boundariesFile);
93 configParams->getString("StarDatabase", config->starDatabaseFile);
94 config->starDatabaseFile = WordExp(config->starDatabaseFile);
95 configParams->getString("StarNameDatabase", config->starNamesFile);
96 config->starNamesFile = WordExp(config->starNamesFile);
97 configParams->getString("HDCrossIndex", config->HDCrossIndexFile);
98 config->HDCrossIndexFile = WordExp(config->HDCrossIndexFile);
99 configParams->getString("SAOCrossIndex", config->SAOCrossIndexFile);
100 config->SAOCrossIndexFile = WordExp(config->SAOCrossIndexFile);
101 configParams->getString("GlieseCrossIndex", config->GlieseCrossIndexFile);
102 config->GlieseCrossIndexFile = WordExp(config->GlieseCrossIndexFile);
103 configParams->getString("Font", config->mainFont);
104 configParams->getString("LabelFont", config->labelFont);
105 configParams->getString("TitleFont", config->titleFont);
106 configParams->getString("LogoTexture", config->logoTextureFile);
107 configParams->getString("Cursor", config->cursor);
108
109 double aaSamples = 1;
110 configParams->getNumber("AntialiasingSamples", aaSamples);
111 config->aaSamples = (unsigned int) aaSamples;
112
113 config->hdr = false;
114 configParams->getBoolean("HighDynamicRange", config->hdr);
115
116 config->rotateAcceleration = 120.0f;
117 configParams->getNumber("RotateAcceleration", config->rotateAcceleration);
118 config->mouseRotationSensitivity = 1.0f;
119 configParams->getNumber("MouseRotationSensitivity", config->mouseRotationSensitivity);
120 config->reverseMouseWheel = false;
121 configParams->getBoolean("ReverseMouseWheel", config->reverseMouseWheel);
122 configParams->getString("ScriptScreenshotDirectory", config->scriptScreenshotDirectory);
123 config->scriptScreenshotDirectory = WordExp(config->scriptScreenshotDirectory);
124 config->scriptSystemAccessPolicy = "ask";
125 configParams->getString("ScriptSystemAccessPolicy", config->scriptSystemAccessPolicy);
126
127 config->ringSystemSections = getUint(configParams, "RingSystemSections", 100);
128 config->orbitPathSamplePoints = getUint(configParams, "OrbitPathSamplePoints", 100);
129 config->shadowTextureSize = getUint(configParams, "ShadowTextureSize", 256);
130 config->eclipseTextureSize = getUint(configParams, "EclipseTextureSize", 128);
131
132 config->consoleLogRows = getUint(configParams, "LogSize", 200);
133
134 Value* solarSystemsVal = configParams->getValue("SolarSystemCatalogs");
135 if (solarSystemsVal != NULL)
136 {
137 if (solarSystemsVal->getType() != Value::ArrayType)
138 {
139 DPRINTF(0, "%s: SolarSystemCatalogs must be an array.\n", filename.c_str());
140 }
141 else
142 {
143 Array* solarSystems = solarSystemsVal->getArray();
144 // assert(solarSystems != NULL);
145
146 for (Array::iterator iter = solarSystems->begin(); iter != solarSystems->end(); iter++)
147 {
148 Value* catalogNameVal = *iter;
149 // assert(catalogNameVal != NULL);
150 if (catalogNameVal->getType() == Value::StringType)
151 {
152 config->solarSystemFiles.insert(config->solarSystemFiles.end(),
153 WordExp(catalogNameVal->getString()));
154 }
155 else
156 {
157 DPRINTF(0, "%s: Solar system catalog name must be a string.\n",
158 filename.c_str());
159 }
160 }
161 }
162 }
163
164 Value* starCatalogsVal = configParams->getValue("StarCatalogs");
165 if (starCatalogsVal != NULL)
166 {
167 if (starCatalogsVal->getType() != Value::ArrayType)
168 {
169 DPRINTF(0, "%s: StarCatalogs must be an array.\n",
170 filename.c_str());
171 }
172 else
173 {
174 Array* starCatalogs = starCatalogsVal->getArray();
175 assert(starCatalogs != NULL);
176
177 for (Array::iterator iter = starCatalogs->begin();
178 iter != starCatalogs->end(); iter++)
179 {
180 Value* catalogNameVal = *iter;
181 assert(catalogNameVal != NULL);
182
183 if (catalogNameVal->getType() == Value::StringType)
184 {
185 config->starCatalogFiles.push_back(WordExp(catalogNameVal->getString()));
186 }
187 else
188 {
189 DPRINTF(0, "%s: Star catalog name must be a string.\n",
190 filename.c_str());
191 }
192 }
193 }
194 }
195
196 Value* dsoCatalogsVal = configParams->getValue("DeepSkyCatalogs");
197 if (dsoCatalogsVal != NULL)
198 {
199 if (dsoCatalogsVal->getType() != Value::ArrayType)
200 {
201 DPRINTF(0, "%s: DeepSkyCatalogs must be an array.\n",
202 filename.c_str());
203 }
204 else
205 {
206 Array* dsoCatalogs = dsoCatalogsVal->getArray();
207 assert(dsoCatalogs != NULL);
208
209 for (Array::iterator iter = dsoCatalogs->begin();
210 iter != dsoCatalogs->end(); iter++)
211 {
212 Value* catalogNameVal = *iter;
213 assert(catalogNameVal != NULL);
214
215 if (catalogNameVal->getType() == Value::StringType)
216 {
217 config->dsoCatalogFiles.push_back(WordExp(catalogNameVal->getString()));
218 }
219 else
220 {
221 DPRINTF(0, "%s: DeepSky catalog name must be a string.\n",
222 filename.c_str());
223 }
224 }
225 }
226 }
227
228 Value* extrasDirsVal = configParams->getValue("ExtrasDirectories");
229 if (extrasDirsVal != NULL)
230 {
231 if (extrasDirsVal->getType() == Value::ArrayType)
232 {
233 Array* extrasDirs = extrasDirsVal->getArray();
234 assert(extrasDirs != NULL);
235
236 for (Array::iterator iter = extrasDirs->begin();
237 iter != extrasDirs->end(); iter++)
238 {
239 Value* dirNameVal = *iter;
240 if (dirNameVal->getType() == Value::StringType)
241 {
242 config->extrasDirs.insert(config->extrasDirs.end(),
243 WordExp(dirNameVal->getString()));
244 }
245 else
246 {
247 DPRINTF(0, "%s: Extras directory name must be a string.\n",
248 filename.c_str());
249 }
250 }
251 }
252 else if (extrasDirsVal->getType() == Value::StringType)
253 {
254 config->extrasDirs.insert(config->extrasDirs.end(),
255 WordExp(extrasDirsVal->getString()));
256 }
257 else
258 {
259 DPRINTF(0, "%s: ExtrasDirectories must be an array or string.\n", filename.c_str());
260 }
261 }
262
263 Value* ignoreExtVal = configParams->getValue("IgnoreGLExtensions");
264 if (ignoreExtVal != NULL)
265 {
266 if (ignoreExtVal->getType() != Value::ArrayType)
267 {
268 DPRINTF(0, "%s: IgnoreGLExtensions must be an array.\n",
269 filename.c_str());
270 }
271 else
272 {
273 Array* ignoreExt = ignoreExtVal->getArray();
274
275 for (Array::iterator iter = ignoreExt->begin();
276 iter != ignoreExt->end(); iter++)
277 {
278 Value* extVal = *iter;
279 if (extVal->getType() == Value::StringType)
280 {
281 config->ignoreGLExtensions.push_back(extVal->getString());
282 }
283 else
284 {
285 DPRINTF(0, "%s: extension name must be a string.\n", filename.c_str());
286 }
287 }
288 }
289 }
290
291 Value* starTexValue = configParams->getValue("StarTextures");
292 if (starTexValue != NULL)
293 {
294 if (starTexValue->getType() != Value::HashType)
295 {
296 DPRINTF(0, "%s: StarTextures must be a property list.\n", filename.c_str());
297 }
298 else
299 {
300 Hash* starTexTable = starTexValue->getHash();
301 string starTexNames[StellarClass::Spectral_Count];
302 starTexTable->getString("O", starTexNames[StellarClass::Spectral_O]);
303 starTexTable->getString("B", starTexNames[StellarClass::Spectral_B]);
304 starTexTable->getString("A", starTexNames[StellarClass::Spectral_A]);
305 starTexTable->getString("F", starTexNames[StellarClass::Spectral_F]);
306 starTexTable->getString("G", starTexNames[StellarClass::Spectral_G]);
307 starTexTable->getString("K", starTexNames[StellarClass::Spectral_K]);
308 starTexTable->getString("M", starTexNames[StellarClass::Spectral_M]);
309 starTexTable->getString("R", starTexNames[StellarClass::Spectral_R]);
310 starTexTable->getString("S", starTexNames[StellarClass::Spectral_S]);
311 starTexTable->getString("N", starTexNames[StellarClass::Spectral_N]);
312 starTexTable->getString("WC", starTexNames[StellarClass::Spectral_WC]);
313 starTexTable->getString("WN", starTexNames[StellarClass::Spectral_WN]);
314 starTexTable->getString("Unknown", starTexNames[StellarClass::Spectral_Unknown]);
315 starTexTable->getString("L", starTexNames[StellarClass::Spectral_L]);
316 starTexTable->getString("T", starTexNames[StellarClass::Spectral_T]);
317 starTexTable->getString("C", starTexNames[StellarClass::Spectral_C]);
318
319 // One texture for all white dwarf types; not sure if this needs to be
320 // changed. White dwarfs vary widely in temperature, so texture choice
321 // should probably be based on that instead of spectral type.
322 starTexTable->getString("WD", starTexNames[StellarClass::Spectral_D]);
323
324 string neutronStarTexName;
325 if (starTexTable->getString("NeutronStar", neutronStarTexName))
326 {
327 config->starTextures.neutronStarTex.setTexture(neutronStarTexName, "textures");
328 }
329
330 string defaultTexName;
331 if (starTexTable->getString("Default", defaultTexName))
332 {
333 config->starTextures.defaultTex.setTexture(defaultTexName, "textures");
334 }
335
336 for (unsigned int i = 0; i < (unsigned int) StellarClass::Spectral_Count; i++)
337 {
338 if (starTexNames[i] != "")
339 {
340 config->starTextures.starTex[i].setTexture(starTexNames[i], "textures");
341 }
342 }
343 }
344 }
345
346 // TODO: not cleaning up properly here--we're just saving the hash, not the instance of Value
347 config->params = configParams;
348
349 #ifndef CELX
350 delete configParamsValue;
351 #endif
352
353 return config;
354 }
355
356
357 float
getFloatValue(const string & name)358 CelestiaConfig::getFloatValue(const string& name)
359 {
360 assert(params != NULL);
361
362 double x = 0.0;
363 params->getNumber(name, x);
364
365 return (float) x;
366 }
367
368
369 const string
getStringValue(const string & name)370 CelestiaConfig::getStringValue(const string& name)
371 {
372 assert(params != NULL);
373
374 Value* v = params->getValue(name);
375 if (v == NULL || v->getType() != Value::StringType)
376 return string("");
377
378 return v->getString();
379 }
380