123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code 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 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "Window.h"
- #include "Winvar.h"
- #include "GuiScript.h"
- #include "UserInterfaceLocal.h"
- /*
- =========================
- Script_Set
- =========================
- */
- void Script_Set(idWindow *window, idList<idGSWinVar> *src) {
- idStr key, val;
- idWinStr *dest = dynamic_cast<idWinStr*>((*src)[0].var);
- if (dest) {
- if (idStr::Icmp(*dest, "cmd") == 0) {
- dest = dynamic_cast<idWinStr*>((*src)[1].var);
- int parmCount = src->Num();
- if (parmCount > 2) {
- val = dest->c_str();
- int i = 2;
- while (i < parmCount) {
- val += " \"";
- val += (*src)[i].var->c_str();
- val += "\"";
- i++;
- }
- window->AddCommand(val);
- } else {
- window->AddCommand(*dest);
- }
- return;
- }
- }
- (*src)[0].var->Set((*src)[1].var->c_str());
- (*src)[0].var->SetEval(false);
- }
- /*
- =========================
- Script_SetFocus
- =========================
- */
- void Script_SetFocus(idWindow *window, idList<idGSWinVar> *src) {
- idWinStr *parm = dynamic_cast<idWinStr*>((*src)[0].var);
- if (parm) {
- drawWin_t *win = window->GetGui()->GetDesktop()->FindChildByName(*parm);
- if (win && win->win) {
- window->SetFocus(win->win);
- }
- }
- }
- /*
- =========================
- Script_ShowCursor
- =========================
- */
- void Script_ShowCursor(idWindow *window, idList<idGSWinVar> *src) {
- idWinStr *parm = dynamic_cast<idWinStr*>((*src)[0].var);
- if ( parm ) {
- if ( atoi( *parm ) ) {
- window->GetGui()->GetDesktop()->ClearFlag( WIN_NOCURSOR );
- } else {
- window->GetGui()->GetDesktop()->SetFlag( WIN_NOCURSOR );
- }
- }
- }
- /*
- =========================
- Script_RunScript
- run scripts must come after any set cmd set's in the script
- =========================
- */
- void Script_RunScript(idWindow *window, idList<idGSWinVar> *src) {
- idWinStr *parm = dynamic_cast<idWinStr*>((*src)[0].var);
- if (parm) {
- idStr str = window->cmd;
- str += " ; runScript ";
- str += parm->c_str();
- window->cmd = str;
- }
- }
- /*
- =========================
- Script_LocalSound
- =========================
- */
- void Script_LocalSound(idWindow *window, idList<idGSWinVar> *src) {
- idWinStr *parm = dynamic_cast<idWinStr*>((*src)[0].var);
- if (parm) {
- session->sw->PlayShaderDirectly(*parm);
- }
- }
- /*
- =========================
- Script_EvalRegs
- =========================
- */
- void Script_EvalRegs(idWindow *window, idList<idGSWinVar> *src) {
- window->EvalRegs(-1, true);
- }
- /*
- =========================
- Script_EndGame
- =========================
- */
- void Script_EndGame( idWindow *window, idList<idGSWinVar> *src ) {
- cvarSystem->SetCVarBool( "g_nightmare", true );
- cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "disconnect\n" );
- }
- /*
- =========================
- Script_ResetTime
- =========================
- */
- void Script_ResetTime(idWindow *window, idList<idGSWinVar> *src) {
- idWinStr *parm = dynamic_cast<idWinStr*>((*src)[0].var);
- drawWin_t *win = NULL;
- if (parm && src->Num() > 1) {
- win = window->GetGui()->GetDesktop()->FindChildByName(*parm);
- parm = dynamic_cast<idWinStr*>((*src)[1].var);
- }
- if (win && win->win) {
- win->win->ResetTime(atoi(*parm));
- win->win->EvalRegs(-1, true);
- } else {
- window->ResetTime(atoi(*parm));
- window->EvalRegs(-1, true);
- }
- }
- /*
- =========================
- Script_ResetCinematics
- =========================
- */
- void Script_ResetCinematics(idWindow *window, idList<idGSWinVar> *src) {
- window->ResetCinematics();
- }
- /*
- =========================
- Script_Transition
- =========================
- */
- void Script_Transition(idWindow *window, idList<idGSWinVar> *src) {
- // transitions always affect rect or vec4 vars
- if (src->Num() >= 4) {
- idWinRectangle *rect = NULL;
- idWinVec4 *vec4 = dynamic_cast<idWinVec4*>((*src)[0].var);
- //
- // added float variable
- idWinFloat* val = NULL;
- //
- if (vec4 == NULL) {
- rect = dynamic_cast<idWinRectangle*>((*src)[0].var);
- //
- // added float variable
- if ( NULL == rect ) {
- val = dynamic_cast<idWinFloat*>((*src)[0].var);
- }
- //
- }
- idWinVec4 *from = dynamic_cast<idWinVec4*>((*src)[1].var);
- idWinVec4 *to = dynamic_cast<idWinVec4*>((*src)[2].var);
- idWinStr *timeStr = dynamic_cast<idWinStr*>((*src)[3].var);
- //
- // added float variable
- if (!((vec4 || rect || val) && from && to && timeStr)) {
- //
- common->Warning("Bad transition in gui %s in window %s\n", window->GetGui()->GetSourceFile(), window->GetName());
- return;
- }
- int time = atoi(*timeStr);
- float ac = 0.0f;
- float dc = 0.0f;
- if (src->Num() > 4) {
- idWinStr *acv = dynamic_cast<idWinStr*>((*src)[4].var);
- idWinStr *dcv = dynamic_cast<idWinStr*>((*src)[5].var);
- assert(acv && dcv);
- ac = atof(*acv);
- dc = atof(*dcv);
- }
-
- if (vec4) {
- vec4->SetEval(false);
- window->AddTransition(vec4, *from, *to, time, ac, dc);
- //
- // added float variable
- } else if ( val ) {
- val->SetEval ( false );
- window->AddTransition(val, *from, *to, time, ac, dc);
- //
- } else {
- rect->SetEval(false);
- window->AddTransition(rect, *from, *to, time, ac, dc);
- }
- window->StartTransition();
- }
- }
- typedef struct {
- const char *name;
- void (*handler) (idWindow *window, idList<idGSWinVar> *src);
- int mMinParms;
- int mMaxParms;
- } guiCommandDef_t;
- guiCommandDef_t commandList[] = {
- { "set", Script_Set, 2, 999 },
- { "setFocus", Script_SetFocus, 1, 1 },
- { "endGame", Script_EndGame, 0, 0 },
- { "resetTime", Script_ResetTime, 0, 2 },
- { "showCursor", Script_ShowCursor, 1, 1 },
- { "resetCinematics", Script_ResetCinematics, 0, 2 },
- { "transition", Script_Transition, 4, 6 },
- { "localSound", Script_LocalSound, 1, 1 },
- { "runScript", Script_RunScript, 1, 1 },
- { "evalRegs", Script_EvalRegs, 0, 0 }
- };
- int scriptCommandCount = sizeof(commandList) / sizeof(guiCommandDef_t);
- /*
- =========================
- idGuiScript::idGuiScript
- =========================
- */
- idGuiScript::idGuiScript() {
- ifList = NULL;
- elseList = NULL;
- conditionReg = -1;
- handler = NULL;
- parms.SetGranularity( 2 );
- }
- /*
- =========================
- idGuiScript::~idGuiScript
- =========================
- */
- idGuiScript::~idGuiScript() {
- delete ifList;
- delete elseList;
- int c = parms.Num();
- for ( int i = 0; i < c; i++ ) {
- if ( parms[i].own ) {
- delete parms[i].var;
- }
- }
- }
- /*
- =========================
- idGuiScript::WriteToSaveGame
- =========================
- */
- void idGuiScript::WriteToSaveGame( idFile *savefile ) {
- int i;
- if ( ifList ) {
- ifList->WriteToSaveGame( savefile );
- }
- if ( elseList ) {
- elseList->WriteToSaveGame( savefile );
- }
- savefile->Write( &conditionReg, sizeof( conditionReg ) );
- for ( i = 0; i < parms.Num(); i++ ) {
- if ( parms[i].own ) {
- parms[i].var->WriteToSaveGame( savefile );
- }
- }
- }
- /*
- =========================
- idGuiScript::ReadFromSaveGame
- =========================
- */
- void idGuiScript::ReadFromSaveGame( idFile *savefile ) {
- int i;
- if ( ifList ) {
- ifList->ReadFromSaveGame( savefile );
- }
- if ( elseList ) {
- elseList->ReadFromSaveGame( savefile );
- }
- savefile->Read( &conditionReg, sizeof( conditionReg ) );
- for ( i = 0; i < parms.Num(); i++ ) {
- if ( parms[i].own ) {
- parms[i].var->ReadFromSaveGame( savefile );
- }
- }
- }
- /*
- =========================
- idGuiScript::Parse
- =========================
- */
- bool idGuiScript::Parse(idParser *src) {
- int i;
-
- // first token should be function call
- // then a potentially variable set of parms
- // ended with a ;
- idToken token;
- if ( !src->ReadToken(&token) ) {
- src->Error( "Unexpected end of file" );
- return false;
- }
- handler = NULL;
-
- for ( i = 0; i < scriptCommandCount ; i++ ) {
- if ( idStr::Icmp(token, commandList[i].name) == 0 ) {
- handler = commandList[i].handler;
- break;
- }
- }
- if (handler == NULL) {
- src->Error("Uknown script call %s", token.c_str());
- }
- // now read parms til ;
- // all parms are read as idWinStr's but will be fixed up later
- // to be proper types
- while (1) {
- if ( !src->ReadToken(&token) ) {
- src->Error( "Unexpected end of file" );
- return false;
- }
-
- if (idStr::Icmp(token, ";") == 0) {
- break;
- }
- if (idStr::Icmp(token, "}") == 0) {
- src->UnreadToken(&token);
- break;
- }
- idWinStr *str = new idWinStr();
- *str = token;
- idGSWinVar wv;
- wv.own = true;
- wv.var = str;
- parms.Append( wv );
- }
- //
- // verify min/max params
- if ( handler && (parms.Num() < commandList[i].mMinParms || parms.Num() > commandList[i].mMaxParms ) ) {
- src->Error("incorrect number of parameters for script %s", commandList[i].name );
- }
- //
- return true;
- }
- /*
- =========================
- idGuiScriptList::Execute
- =========================
- */
- void idGuiScriptList::Execute(idWindow *win) {
- int c = list.Num();
- for (int i = 0; i < c; i++) {
- idGuiScript *gs = list[i];
- assert(gs);
- if (gs->conditionReg >= 0) {
- if (win->HasOps()) {
- float f = win->EvalRegs(gs->conditionReg);
- if (f) {
- if (gs->ifList) {
- win->RunScriptList(gs->ifList);
- }
- } else if (gs->elseList) {
- win->RunScriptList(gs->elseList);
- }
- }
- }
- gs->Execute(win);
- }
- }
- /*
- =========================
- idGuiScriptList::FixupParms
- =========================
- */
- void idGuiScript::FixupParms(idWindow *win) {
- if (handler == &Script_Set) {
- bool precacheBackground = false;
- bool precacheSounds = false;
- idWinStr *str = dynamic_cast<idWinStr*>(parms[0].var);
- assert(str);
- idWinVar *dest = win->GetWinVarByName(*str, true);
- if (dest) {
- delete parms[0].var;
- parms[0].var = dest;
- parms[0].own = false;
- if ( dynamic_cast<idWinBackground *>(dest) != NULL ) {
- precacheBackground = true;
- }
- } else if ( idStr::Icmp( str->c_str(), "cmd" ) == 0 ) {
- precacheSounds = true;
- }
- int parmCount = parms.Num();
- for (int i = 1; i < parmCount; i++) {
- idWinStr *str = dynamic_cast<idWinStr*>(parms[i].var);
- if (idStr::Icmpn(*str, "gui::", 5) == 0) {
- // always use a string here, no point using a float if it is one
- // FIXME: This creates duplicate variables, while not technically a problem since they
- // are all bound to the same guiDict, it does consume extra memory and is generally a bad thing
- idWinStr* defvar = new idWinStr();
- defvar->Init ( *str, win );
- win->AddDefinedVar ( defvar );
- delete parms[i].var;
- parms[i].var = defvar;
- parms[i].own = false;
- //dest = win->GetWinVarByName(*str, true);
- //if (dest) {
- // delete parms[i].var;
- // parms[i].var = dest;
- // parms[i].own = false;
- //}
- //
- } else if ((*str[0]) == '$') {
- //
- // dont include the $ when asking for variable
- dest = win->GetGui()->GetDesktop()->GetWinVarByName((const char*)(*str) + 1, true);
- //
- if (dest) {
- delete parms[i].var;
- parms[i].var = dest;
- parms[i].own = false;
- }
- } else if ( idStr::Cmpn( str->c_str(), STRTABLE_ID, STRTABLE_ID_LENGTH ) == 0 ) {
- str->Set( common->GetLanguageDict()->GetString( str->c_str() ) );
- } else if ( precacheBackground ) {
- const idMaterial *mat = declManager->FindMaterial( str->c_str() );
- mat->SetSort( SS_GUI );
- } else if ( precacheSounds ) {
- // Search for "play <...>"
- idToken token;
- idParser parser( LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
- parser.LoadMemory(str->c_str(), str->Length(), "command");
- while ( parser.ReadToken(&token) ) {
- if ( token.Icmp("play") == 0 ) {
- if ( parser.ReadToken(&token) && ( token != "" ) ) {
- declManager->FindSound( token.c_str() );
- }
- }
- }
- }
- }
- } else if (handler == &Script_Transition) {
- if (parms.Num() < 4) {
- common->Warning("Window %s in gui %s has a bad transition definition", win->GetName(), win->GetGui()->GetSourceFile());
- }
- idWinStr *str = dynamic_cast<idWinStr*>(parms[0].var);
- assert(str);
- //
- drawWin_t *destowner;
- idWinVar *dest = win->GetWinVarByName(*str, true, &destowner );
- //
- if (dest) {
- delete parms[0].var;
- parms[0].var = dest;
- parms[0].own = false;
- } else {
- common->Warning("Window %s in gui %s: a transition does not have a valid destination var %s", win->GetName(), win->GetGui()->GetSourceFile(),str->c_str());
- }
- //
- // support variables as parameters
- int c;
- for ( c = 1; c < 3; c ++ ) {
- str = dynamic_cast<idWinStr*>(parms[c].var);
- idWinVec4 *v4 = new idWinVec4;
- parms[c].var = v4;
- parms[c].own = true;
- drawWin_t* owner;
- if ( (*str[0]) == '$' ) {
- dest = win->GetWinVarByName ( (const char*)(*str) + 1, true, &owner );
- } else {
- dest = NULL;
- }
- if ( dest ) {
- idWindow* ownerparent;
- idWindow* destparent;
- if ( owner ) {
- ownerparent = owner->simp?owner->simp->GetParent():owner->win->GetParent();
- destparent = destowner->simp?destowner->simp->GetParent():destowner->win->GetParent();
- // If its the rectangle they are referencing then adjust it
- if ( ownerparent && destparent &&
- (dest == (owner->simp?owner->simp->GetWinVarByName ( "rect" ):owner->win->GetWinVarByName ( "rect" ) ) ) )
- {
- idRectangle rect;
- rect = *(dynamic_cast<idWinRectangle*>(dest));
- ownerparent->ClientToScreen ( &rect );
- destparent->ScreenToClient ( &rect );
- *v4 = rect.ToVec4 ( );
- } else {
- v4->Set ( dest->c_str ( ) );
- }
- } else {
- v4->Set ( dest->c_str ( ) );
- }
- } else {
- v4->Set(*str);
- }
-
- delete str;
- }
- //
- } else {
- int c = parms.Num();
- for (int i = 0; i < c; i++) {
- parms[i].var->Init(parms[i].var->c_str(), win);
- }
- }
- }
- /*
- =========================
- idGuiScriptList::FixupParms
- =========================
- */
- void idGuiScriptList::FixupParms(idWindow *win) {
- int c = list.Num();
- for (int i = 0; i < c; i++) {
- idGuiScript *gs = list[i];
- gs->FixupParms(win);
- if (gs->ifList) {
- gs->ifList->FixupParms(win);
- }
- if (gs->elseList) {
- gs->elseList->FixupParms(win);
- }
- }
- }
- /*
- =========================
- idGuiScriptList::WriteToSaveGame
- =========================
- */
- void idGuiScriptList::WriteToSaveGame( idFile *savefile ) {
- int i;
- for ( i = 0; i < list.Num(); i++ ) {
- list[i]->WriteToSaveGame( savefile );
- }
- }
- /*
- =========================
- idGuiScriptList::ReadFromSaveGame
- =========================
- */
- void idGuiScriptList::ReadFromSaveGame( idFile *savefile ) {
- int i;
- for ( i = 0; i < list.Num(); i++ ) {
- list[i]->ReadFromSaveGame( savefile );
- }
- }
|