Serious-Engine/Sources/SeriousSam/VarList.cpp

265 lines
6.5 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as published by
the Free Software Foundation
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#include "SeriousSam/StdH.h"
#include "SeriousSam/VarList.h"
CListHead _lhVarSettings;
static CTString _strFile;
static INDEX _ctLines;
static CTString GetNonEmptyLine_t(CTStream &strm)
{
FOREVER {
if(strm.AtEOF()) {
ThrowF_t(TRANS("Unexpected end of file"));
}
CTString str;
_ctLines++;
strm.GetLine_t(str);
str.TrimSpacesLeft();
if (str.RemovePrefix("//")) { // skip comments
continue;
}
if (str!="") {
str.TrimSpacesRight();
return str;
}
}
}
void TranslateLine(CTString &str)
{
str.TrimSpacesLeft();
if (str.RemovePrefix("TTRS")) {
str.TrimSpacesLeft();
str = TranslateConst(str, 0);
}
str.TrimSpacesLeft();
}
static void FixupFileName_t(CTString &strFnm)
{
strFnm.TrimSpacesLeft();
strFnm.TrimSpacesRight();
if (!strFnm.RemovePrefix(CTString("TF") +"NM ")) { // must not directly have ids in code
ThrowF_t(TRANS("Expected %s%s before filename"), "TF", "NM");
}
}
void CheckPVS_t(CVarSetting *pvs)
{
if (pvs==NULL) {
ThrowF_t("Gadget expected");
}
}
void ParseCFG_t(CTStream &strm)
{
CVarSetting *pvs = NULL;
// repeat
FOREVER {
// read one line
CTString strLine = GetNonEmptyLine_t(strm);
if (strLine.RemovePrefix("MenuEnd")) {
return;
} else if (strLine.RemovePrefix("Gadget:")) {
pvs = new CVarSetting;
_lhVarSettings.AddTail(pvs->vs_lnNode);
TranslateLine(strLine);
strLine.TrimSpacesLeft();
pvs->vs_strName = strLine;
} else if (strLine.RemovePrefix("Type:")) {
CheckPVS_t(pvs);
strLine.TrimSpacesLeft();
strLine.TrimSpacesRight();
if (strLine=="Toggle") {
pvs->vs_bSeparator = FALSE;
} else if (strLine=="Separator") {
pvs->vs_bSeparator = TRUE;
}
} else if (strLine.RemovePrefix("Schedule:")) {
CheckPVS_t(pvs);
FixupFileName_t(strLine);
pvs->vs_strSchedule = strLine;
} else if (strLine.RemovePrefix("Tip:")) {
CheckPVS_t(pvs);
TranslateLine(strLine);
strLine.TrimSpacesLeft();
strLine.TrimSpacesRight();
pvs->vs_strTip = strLine;
} else if (strLine.RemovePrefix("Var:")) {
CheckPVS_t(pvs);
strLine.TrimSpacesLeft();
strLine.TrimSpacesRight();
pvs->vs_strVar = strLine;
} else if (strLine.RemovePrefix("Filter:")) {
CheckPVS_t(pvs);
strLine.TrimSpacesLeft();
strLine.TrimSpacesRight();
pvs->vs_strFilter = strLine;
} else if (strLine.RemovePrefix("Slider:")) {
CheckPVS_t(pvs);
strLine.TrimSpacesLeft();
strLine.TrimSpacesRight();
if (strLine=="Fill") {
pvs->vs_iSlider = 1;
} else if (strLine=="Ratio") {
pvs->vs_iSlider = 2;
} else {
pvs->vs_iSlider = 0;
}
} else if (strLine.RemovePrefix("InGame:")) {
CheckPVS_t(pvs);
strLine.TrimSpacesLeft();
strLine.TrimSpacesRight();
if( strLine=="No") {
pvs->vs_bCanChangeInGame = FALSE;
} else {
ASSERT( strLine=="Yes");
pvs->vs_bCanChangeInGame = TRUE;
}
} else if (strLine.RemovePrefix("String:")) {
CheckPVS_t(pvs);
TranslateLine(strLine);
strLine.TrimSpacesLeft();
strLine.TrimSpacesRight();
pvs->vs_astrTexts.Push() = strLine;
} else if (strLine.RemovePrefix("Value:")) {
CheckPVS_t(pvs);
strLine.TrimSpacesLeft();
strLine.TrimSpacesRight();
pvs->vs_astrValues.Push() = strLine;
} else {
ThrowF_t(TRANS("unknown keyword"));
}
}
}
void LoadVarSettings(const CTFileName &fnmCfg)
{
FlushVarSettings(FALSE);
try {
CTFileStream strm;
strm.Open_t(fnmCfg);
_ctLines = 0;
_strFile = fnmCfg;
ParseCFG_t(strm);
} catch (char* strError) {
CPrintF("%s (%d) : %s\n", (const char*)_strFile, _ctLines, strError);
}
FOREACHINLIST(CVarSetting, vs_lnNode, _lhVarSettings, itvs) {
CVarSetting &vs = *itvs;
if (!vs.Validate() || vs.vs_bSeparator) {
continue;
}
INDEX ctValues = vs.vs_ctValues;
CTString strValue = _pShell->GetValue(vs.vs_strVar);
vs.vs_bCustom = TRUE;
vs.vs_iOrgValue = vs.vs_iValue = -1;
for(INDEX iValue=0; iValue<ctValues; iValue++) {
if (strValue == vs.vs_astrValues[iValue]) {
vs.vs_iOrgValue = vs.vs_iValue = iValue;
vs.vs_bCustom = FALSE;
break;
}
}
}
}
void FlushVarSettings(BOOL bApply)
{
CStaticStackArray<CTString> astrScheduled;
if (bApply) {
FOREACHINLIST(CVarSetting, vs_lnNode, _lhVarSettings, itvs) {
CVarSetting &vs = *itvs;
if (vs.vs_iValue!=vs.vs_iOrgValue) {
CTString strCmd;
_pShell->SetValue(vs.vs_strVar, vs.vs_astrValues[vs.vs_iValue]);
if (vs.vs_strSchedule!="") {
BOOL bSheduled = FALSE;
for(INDEX i=0; i<astrScheduled.Count(); i++) {
if (astrScheduled[i]==vs.vs_strSchedule) {
bSheduled = TRUE;
break;
}
}
if (!bSheduled) {
astrScheduled.Push() = vs.vs_strSchedule;
}
}
}
}
}
{FORDELETELIST(CVarSetting, vs_lnNode, _lhVarSettings, itvs) {
delete &*itvs;
}}
for(INDEX i=0; i<astrScheduled.Count(); i++) {
CTString strCmd;
strCmd.PrintF("include \"%s\"", (const char *) astrScheduled[i]);
_pShell->Execute(strCmd);
}
}
CVarSetting::CVarSetting()
{
Clear();
}
void CVarSetting::Clear()
{
vs_iOrgValue = 0;
vs_iValue = 0;
vs_ctValues = 0;
vs_bSeparator = FALSE;
vs_bCanChangeInGame = TRUE;
vs_iSlider = 0;
vs_strName.Clear();
vs_strTip.Clear();
vs_strVar.Clear();
vs_strFilter.Clear();
vs_strSchedule.Clear();
vs_bCustom = FALSE;
}
BOOL CVarSetting::Validate(void)
{
if (vs_bSeparator) {
return TRUE;
}
vs_ctValues = Min(vs_astrValues.Count(), vs_astrTexts.Count());
if (vs_ctValues<=0) {
ASSERT(FALSE);
return FALSE;
}
if (!vs_bCustom) {
vs_iValue = Clamp(vs_iValue, 0L, vs_ctValues-1L);
}
return TRUE;
}