celestia/src/celestia/configfile.cpp

399 lines
14 KiB
C++

// configfile.cpp
//
// Copyright (C) 2001-2009, the Celestia Development Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <config.h>
#include <iostream>
#include <fstream>
#include <cassert>
#include <celutil/logger.h>
#include <celutil/fsutils.h>
#include <celengine/texmanager.h>
#include <celutil/tokenizer.h>
#include "configfile.h"
using namespace std;
using namespace celestia::util;
static unsigned int getUint(Hash* params,
const string& paramName,
unsigned int defaultValue)
{
double value = 0.0;
if (params->getNumber(paramName, value))
return (unsigned int) value;
return defaultValue;
}
CelestiaConfig* ReadCelestiaConfig(const fs::path& filename, CelestiaConfig *config)
{
ifstream configFile(filename);
if (!configFile.good())
{
GetLogger()->error("Error opening config file '{}'.\n", filename);
return config;
}
Tokenizer tokenizer(&configFile);
Parser parser(&tokenizer);
if (tokenizer.nextToken() != Tokenizer::TokenName)
{
GetLogger()->error("{}:{} 'Configuration' expected.\n", filename,
tokenizer.getLineNumber());
return config;
}
if (tokenizer.getStringValue() != "Configuration")
{
GetLogger()->error("{}:{} 'Configuration' expected.\n", filename,
tokenizer.getLineNumber());
return config;
}
Value* configParamsValue = parser.readValue();
if (configParamsValue == nullptr || configParamsValue->getType() != Value::HashType)
{
GetLogger()->error("{}: Bad configuration file.\n", filename);
return config;
}
Hash* configParams = configParamsValue->getHash();
if (config == nullptr)
config = new CelestiaConfig();
#ifdef CELX
config->configParams = configParams;
configParams->getPath("LuaHook", config->luaHook);
#endif
config->faintestVisible = 6.0f;
configParams->getNumber("FaintestVisibleMagnitude", config->faintestVisible);
configParams->getPath("FavoritesFile", config->favoritesFile);
configParams->getPath("DestinationFile", config->destinationsFile);
configParams->getPath("InitScript", config->initScriptFile);
configParams->getPath("DemoScript", config->demoScriptFile);
configParams->getPath("AsterismsFile", config->asterismsFile);
configParams->getPath("BoundariesFile", config->boundariesFile);
configParams->getPath("StarDatabase", config->starDatabaseFile);
configParams->getPath("StarNameDatabase", config->starNamesFile);
configParams->getPath("HDCrossIndex", config->HDCrossIndexFile);
configParams->getPath("SAOCrossIndex", config->SAOCrossIndexFile);
configParams->getPath("GlieseCrossIndex", config->GlieseCrossIndexFile);
configParams->getString("Font", config->mainFont);
configParams->getString("LabelFont", config->labelFont);
configParams->getString("TitleFont", config->titleFont);
configParams->getPath("LogoTexture", config->logoTextureFile);
configParams->getString("Cursor", config->cursor);
configParams->getString("ProjectionMode", config->projectionMode);
configParams->getString("ViewportEffect", config->viewportEffect);
configParams->getString("WarpMeshFile", config->warpMeshFile);
configParams->getString("X264EncoderOptions", config->x264EncoderOptions);
configParams->getString("FFVHEncoderOptions", config->ffvhEncoderOptions);
configParams->getString("MeasurementSystem", config->measurementSystem);
configParams->getString("TemperatureScale", config->temperatureScale);
float maxDist = 1.0;
configParams->getNumber("SolarSystemMaxDistance", maxDist);
config->SolarSystemMaxDistance = min(max(maxDist, 1.0f), 10.0f);
config->ShadowMapSize = getUint(configParams, "ShadowMapSize", 0);
double aaSamples = 1;
configParams->getNumber("AntialiasingSamples", aaSamples);
config->aaSamples = (unsigned int) aaSamples;
config->hdr = false;
configParams->getBoolean("HighDynamicRange", config->hdr);
config->rotateAcceleration = 120.0f;
configParams->getNumber("RotateAcceleration", config->rotateAcceleration);
config->mouseRotationSensitivity = 1.0f;
configParams->getNumber("MouseRotationSensitivity", config->mouseRotationSensitivity);
config->reverseMouseWheel = false;
configParams->getBoolean("ReverseMouseWheel", config->reverseMouseWheel);
configParams->getPath("ScriptScreenshotDirectory", config->scriptScreenshotDirectory);
config->scriptSystemAccessPolicy = "ask";
configParams->getString("ScriptSystemAccessPolicy", config->scriptSystemAccessPolicy);
config->orbitWindowEnd = 0.5f;
configParams->getNumber("OrbitWindowEnd", config->orbitWindowEnd);
config->orbitPeriodsShown = 1.0f;
configParams->getNumber("OrbitPeriodsShown", config->orbitPeriodsShown);
config->linearFadeFraction = 0.0f;
configParams->getNumber("LinearFadeFraction", config->linearFadeFraction);
config->orbitPathSamplePoints = getUint(configParams, "OrbitPathSamplePoints", 100);
config->shadowTextureSize = getUint(configParams, "ShadowTextureSize", 256);
config->eclipseTextureSize = getUint(configParams, "EclipseTextureSize", 128);
config->consoleLogRows = getUint(configParams, "LogSize", 200);
Value* solarSystemsVal = configParams->getValue("SolarSystemCatalogs");
if (solarSystemsVal != nullptr)
{
if (solarSystemsVal->getType() != Value::ArrayType)
{
GetLogger()->error("{}: SolarSystemCatalogs must be an array.\n", filename);
}
else
{
Array* solarSystems = solarSystemsVal->getArray();
// assert(solarSystems != nullptr);
for (const auto catalogNameVal : *solarSystems)
{
// assert(catalogNameVal != nullptr);
if (catalogNameVal->getType() == Value::StringType)
{
config->solarSystemFiles.push_back(PathExp(catalogNameVal->getString()));
}
else
{
GetLogger()->error("{}: Solar system catalog name must be a string.\n", filename);
}
}
}
}
Value* starCatalogsVal = configParams->getValue("StarCatalogs");
if (starCatalogsVal != nullptr)
{
if (starCatalogsVal->getType() != Value::ArrayType)
{
GetLogger()->error("{}: StarCatalogs must be an array.\n", filename);
}
else
{
Array* starCatalogs = starCatalogsVal->getArray();
assert(starCatalogs != nullptr);
for (const auto catalogNameVal : *starCatalogs)
{
assert(catalogNameVal != nullptr);
if (catalogNameVal->getType() == Value::StringType)
{
config->starCatalogFiles.push_back(PathExp(catalogNameVal->getString()));
}
else
{
GetLogger()->error("{}: Star catalog name must be a string.\n", filename);
}
}
}
}
Value* dsoCatalogsVal = configParams->getValue("DeepSkyCatalogs");
if (dsoCatalogsVal != nullptr)
{
if (dsoCatalogsVal->getType() != Value::ArrayType)
{
GetLogger()->error("{}: DeepSkyCatalogs must be an array.\n", filename);
}
else
{
Array* dsoCatalogs = dsoCatalogsVal->getArray();
assert(dsoCatalogs != nullptr);
for (const auto catalogNameVal : *dsoCatalogs)
{
assert(catalogNameVal != nullptr);
if (catalogNameVal->getType() == Value::StringType)
{
config->dsoCatalogFiles.push_back(PathExp(catalogNameVal->getString()));
}
else
{
GetLogger()->error("{}: DeepSky catalog name must be a string.\n", filename);
}
}
}
}
Value* extrasDirsVal = configParams->getValue("ExtrasDirectories");
if (extrasDirsVal != nullptr)
{
if (extrasDirsVal->getType() == Value::ArrayType)
{
Array* extrasDirs = extrasDirsVal->getArray();
assert(extrasDirs != nullptr);
for (const auto dirNameVal : *extrasDirs)
{
if (dirNameVal->getType() == Value::StringType)
{
config->extrasDirs.push_back(PathExp(dirNameVal->getString()));
}
else
{
GetLogger()->error("{}: Extras directory name must be a string.\n", filename);
}
}
}
else if (extrasDirsVal->getType() == Value::StringType)
{
config->extrasDirs.push_back(PathExp(extrasDirsVal->getString()));
}
else
{
GetLogger()->error("{}: ExtrasDirectories must be an array or a string.\n", filename);
}
}
Value* skipExtrasVal = configParams->getValue("SkipExtras");
if (skipExtrasVal != nullptr)
{
if (skipExtrasVal->getType() == Value::ArrayType)
{
Array* skipExtras = skipExtrasVal->getArray();
assert(skipExtras != nullptr);
for (const auto fileNameVal : *skipExtras)
{
if (fileNameVal->getType() == Value::StringType)
{
config->skipExtras.push_back(PathExp(fileNameVal->getString()));
}
else
{
GetLogger()->error("{}: Skipped file name must be a string.\n", filename);
}
}
}
else if (skipExtrasVal->getType() == Value::StringType)
{
config->skipExtras.push_back(PathExp(skipExtrasVal->getString()));
}
else
{
GetLogger()->error("{}: SkipExtras must be an array or a string.\n", filename);
}
}
Value* ignoreExtVal = configParams->getValue("IgnoreGLExtensions");
if (ignoreExtVal != nullptr)
{
if (ignoreExtVal->getType() != Value::ArrayType)
{
GetLogger()->error("{}: IgnoreGLExtensions must be an array.\n", filename);
}
else
{
Array* ignoreExt = ignoreExtVal->getArray();
for (const auto extVal : *ignoreExt)
{
if (extVal->getType() == Value::StringType)
{
config->ignoreGLExtensions.push_back(extVal->getString());
}
else
{
GetLogger()->error("{}: extension name must be a string.\n", filename);
}
}
}
}
Value* starTexValue = configParams->getValue("StarTextures");
if (starTexValue != nullptr)
{
if (starTexValue->getType() != Value::HashType)
{
GetLogger()->error("{}: StarTextures must be a property list.\n", filename);
}
else
{
Hash* starTexTable = starTexValue->getHash();
string starTexNames[StellarClass::Spectral_Count];
starTexTable->getString("O", starTexNames[StellarClass::Spectral_O]);
starTexTable->getString("B", starTexNames[StellarClass::Spectral_B]);
starTexTable->getString("A", starTexNames[StellarClass::Spectral_A]);
starTexTable->getString("F", starTexNames[StellarClass::Spectral_F]);
starTexTable->getString("G", starTexNames[StellarClass::Spectral_G]);
starTexTable->getString("K", starTexNames[StellarClass::Spectral_K]);
starTexTable->getString("M", starTexNames[StellarClass::Spectral_M]);
starTexTable->getString("R", starTexNames[StellarClass::Spectral_R]);
starTexTable->getString("S", starTexNames[StellarClass::Spectral_S]);
starTexTable->getString("N", starTexNames[StellarClass::Spectral_N]);
starTexTable->getString("WC", starTexNames[StellarClass::Spectral_WC]);
starTexTable->getString("WN", starTexNames[StellarClass::Spectral_WN]);
starTexTable->getString("WO", starTexNames[StellarClass::Spectral_WO]);
starTexTable->getString("Unknown", starTexNames[StellarClass::Spectral_Unknown]);
starTexTable->getString("L", starTexNames[StellarClass::Spectral_L]);
starTexTable->getString("T", starTexNames[StellarClass::Spectral_T]);
starTexTable->getString("Y", starTexNames[StellarClass::Spectral_Y]);
starTexTable->getString("C", starTexNames[StellarClass::Spectral_C]);
// One texture for all white dwarf types; not sure if this needs to be
// changed. White dwarfs vary widely in temperature, so texture choice
// should probably be based on that instead of spectral type.
starTexTable->getString("WD", starTexNames[StellarClass::Spectral_D]);
string neutronStarTexName;
if (starTexTable->getString("NeutronStar", neutronStarTexName))
{
config->starTextures.neutronStarTex.setTexture(neutronStarTexName, "textures");
}
string defaultTexName;
if (starTexTable->getString("Default", defaultTexName))
{
config->starTextures.defaultTex.setTexture(defaultTexName, "textures");
}
for (unsigned int i = 0; i < (unsigned int) StellarClass::Spectral_Count; i++)
{
if (starTexNames[i] != "")
{
config->starTextures.starTex[i].setTexture(starTexNames[i], "textures");
}
}
}
}
// TODO: not cleaning up properly here--we're just saving the hash, not the instance of Value
config->params = configParams;
#ifndef CELX
delete configParamsValue;
#endif
return config;
}
float
CelestiaConfig::getFloatValue(const string& name)
{
assert(params != nullptr);
double x = 0.0;
params->getNumber(name, x);
return (float) x;
}
const string
CelestiaConfig::getStringValue(const string& name)
{
assert(params != nullptr);
Value* v = params->getValue(name);
if (v == nullptr || v->getType() != Value::StringType)
return string("");
return v->getString();
}