|
|
//===== Copyright � Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines scripting system.
//
//===========================================================================//
#include "tier0/dbg.h"
#include "gameuiscript.h"
#include "gameuiscriptinterface.h"
#include "gameuidefinition.h"
#include "keyvalues.h"
#include "fmtstr.h"
static ConVar ui_script_error_path( "ui_script_error_path", "", FCVAR_DEVELOPMENTONLY );
//-------------------------------------------------------------
//
//-------------------------------------------------------------
static void ScriptOutputFunc( const char *pszText ) { Msg( "%s\n", pszText ); }
//-------------------------------------------------------------
//
//-------------------------------------------------------------
static bool ScriptErrorFunc( ScriptErrorLevel_t eLevel, const char *pszText ) { // Attempt to parse the error for Visual Studio presentation for double-click
if ( char const *pParse1 = StringAfterPrefix( pszText, "[string \"" ) ) { if ( char const *pQuote = strchr( pParse1, '\"' ) ) { if ( char const *pParse2 = StringAfterPrefix( pQuote, "\"]:" ) ) { if ( char const *pEndNum = strchr( pParse2, ':' ) ) { char const *szType = (eLevel == SCRIPT_LEVEL_WARNING) ? "WARNING" : "ERROR"; Warning( "%s%.*s(%.*s): %s: %s\n", ui_script_error_path.GetString(), pQuote - pParse1, pParse1, // file name
pEndNum - pParse2, pParse2, // line number
szType, pEndNum + 1 ); return true; } } } }
switch( eLevel ) { case SCRIPT_LEVEL_WARNING: Warning( "WARNING: %s\n", pszText ); break;
case SCRIPT_LEVEL_ERROR: Warning( "ERROR: %s\n", pszText ); break; }
return true; }
//-------------------------------------------------------------
// Constructor
//-------------------------------------------------------------
CGameUIScript::CGameUIScript( ) { m_pScriptVM = GameUIScriptSystemCreate();
m_pScriptVM->SetOutputCallback( ScriptOutputFunc ); m_pScriptVM->SetErrorCallback( ScriptErrorFunc );
m_IsActive = false; m_pGameUIScriptInterface = NULL; m_Version = -1; m_Name = "unknown"; }
//-------------------------------------------------------------
// Destructor
//-------------------------------------------------------------
CGameUIScript::~CGameUIScript( ) { Shutdown(); }
void CGameUIScript::Shutdown() { if ( m_pGameUIScriptInterface ) { delete m_pGameUIScriptInterface; m_pGameUIScriptInterface = NULL; } }
//-------------------------------------------------------------
// Assign this class a script file and a menu to run it on
//-------------------------------------------------------------
bool CGameUIScript::SetScript( const char *pszFileName, CGameUIDefinition *pDef ) { ScriptVariant_t Value;
m_ScriptFile = pszFileName; m_pGameUIScriptInterface = new CGameUIScriptInterface( m_pScriptVM, pDef ); if ( GameUIScriptSystemRun( m_pScriptVM, m_ScriptFile, NULL, true ) == false ) { return false; }
if ( !m_pScriptVM->GetValue( pDef->GetName(), &Value ) ) { return false; }
m_Scope = Value.m_hScript; // we don't release Value as that would kill m_Scope.
//GetScriptName();
GetScriptVersion();
#ifndef _DEBUG
//if ( m_Version != build_number() && 0 )
//{
// Msg( "Script %s is out of date. Got %d. Expected %d.\n", pszFileName, m_Version, build_number() );
// return false;
//}
#endif
return true; }
//-------------------------------------------------------------
//
//-------------------------------------------------------------
bool CGameUIScript::GetScriptName( ) { HSCRIPT ExecuteFuncProc = m_pScriptVM->LookupFunction( "Name", m_Scope ); if ( ExecuteFuncProc == NULL ) { return false; }
ScriptVariant_t Return;
m_pScriptVM->Call( ExecuteFuncProc, m_Scope, true, &Return );
m_Name = Return.m_pszString;
m_pScriptVM->ReleaseFunction( ExecuteFuncProc ); m_pScriptVM->ReleaseValue( Return );
return true; }
//-------------------------------------------------------------
//
//-------------------------------------------------------------
bool CGameUIScript::GetScriptVersion( ) { HSCRIPT ExecuteFuncProc = m_pScriptVM->LookupFunction( "Version", m_Scope ); if ( ExecuteFuncProc == NULL ) { return false; }
ScriptVariant_t Return;
m_pScriptVM->Call( ExecuteFuncProc, m_Scope, true, &Return );
if ( Return.m_type == FIELD_FLOAT ) { m_Version = ( int )Return.m_float; } else { m_Version = Return.m_int; }
m_pScriptVM->ReleaseFunction( ExecuteFuncProc ); m_pScriptVM->ReleaseValue( Return );
return true; }
//-------------------------------------------------------------
// Call a scripting function that takes an array of strings as an arg.
//-------------------------------------------------------------
bool CGameUIScript::Execute( KeyValues *pData, KeyValues **ppResult ) { const char *eventName = pData->GetName(); HSCRIPT ExecuteFuncProc = m_pScriptVM->LookupFunction( eventName, m_Scope ); if ( ExecuteFuncProc == NULL ) { return false; }
// Transform the key values into script scope to execute
HSCRIPT hParams = CGameUIScriptInterface::ScriptTableFromKeyValues( m_pScriptVM, pData ); ScriptVariant_t varParams = hParams, varResult; ScriptStatus_t ret = m_pScriptVM->ExecuteFunction( ExecuteFuncProc, &varParams, 1, &varResult, m_Scope, true );
if ( hParams ) { m_pScriptVM->ReleaseValue( varParams ); } if ( ret == SCRIPT_DONE && varResult.m_type == FIELD_HSCRIPT && ppResult ) { Assert( !*ppResult ); // storing return value, might overwrite caller's keyvalues
*ppResult = CGameUIScriptInterface::ScriptVmKeyValueFromVariant( m_pScriptVM, varResult ); } m_pScriptVM->ReleaseValue( varResult ); m_pScriptVM->ReleaseFunction( ExecuteFuncProc );
return true; }
|