csgo-2018-source/vgui2/game_controls/gameuiscript.cpp
2021-07-24 21:11:47 -07:00

226 lines
5.7 KiB
C++

//===== 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;
}