/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRYCOMMON_SCRIPTHELPERS_H #define CRYINCLUDE_CRYCOMMON_SCRIPTHELPERS_H #pragma once #include "StringUtils.h" // cry_strcpy() // forward declarations class CScriptBind_GameStatistics; ////////////////////////////////////////////////////////////////////////// // Helper template class. // Handles dispatching of Lua to C script function callbacks to the specified // member functions of the CScriptableBase. // See Also: CScriptableBase::RegisterTemplateFunction ////////////////////////////////////////////////////////////////////////// struct ScriptTemplateCallHelper { template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*), IFunctionHandler* pH) { return (callee->*func)(pH); } template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*, P1), IFunctionHandler* pH) { P1 p1; if (!pH->GetParams(p1)) { return pH->EndFunction(); } return (callee->*func)(pH, p1); } template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*, P1, P2), IFunctionHandler* pH) { P1 p1; P2 p2; if (!pH->GetParams(p1, p2)) { return pH->EndFunction(); } return (callee->*func)(pH, p1, p2); } template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*, P1, P2, P3), IFunctionHandler* pH) { P1 p1; P2 p2; P3 p3; if (!pH->GetParams(p1, p2, p3)) { return pH->EndFunction(); } return (callee->*func)(pH, p1, p2, p3); } template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*, P1, P2, P3, P4), IFunctionHandler* pH) { P1 p1; P2 p2; P3 p3; P4 p4; if (!pH->GetParams(p1, p2, p3, p4)) { return pH->EndFunction(); } return (callee->*func)(pH, p1, p2, p3, p4); } template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*, P1, P2, P3, P4, P5), IFunctionHandler* pH) { P1 p1; P2 p2; P3 p3; P4 p4; P5 p5; if (!pH->GetParams(p1, p2, p3, p4, p5)) { return pH->EndFunction(); } return (callee->*func)(pH, p1, p2, p3, p4, p5); } template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*, P1, P2, P3, P4, P5, P6), IFunctionHandler* pH) { P1 p1; P2 p2; P3 p3; P4 p4; P5 p5; P6 p6; if (!pH->GetParams(p1, p2, p3, p4, p5, p6)) { return pH->EndFunction(); } return (callee->*func)(pH, p1, p2, p3, p4, p5, p6); } template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*, P1, P2, P3, P4, P5, P6, P7), IFunctionHandler* pH) { P1 p1; P2 p2; P3 p3; P4 p4; P5 p5; P6 p6; P7 p7; if (!pH->GetParams(p1, p2, p3, p4, p5, p6, p7)) { return pH->EndFunction(); } return (callee->*func)(pH, p1, p2, p3, p4, p5, p6, p7); } template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*, P1, P2, P3, P4, P5, P6, P7, P8), IFunctionHandler* pH) { P1 p1; P2 p2; P3 p3; P4 p4; P5 p5; P6 p6; P7 p7; P8 p8; if (!pH->GetParams(p1, p2, p3, p4, p5, p6, p7, p8)) { return pH->EndFunction(); } return (callee->*func)(pH, p1, p2, p3, p4, p5, p6, p7, p8); } template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*, P1, P2, P3, P4, P5, P6, P7, P8, P9), IFunctionHandler* pH) { P1 p1; P2 p2; P3 p3; P4 p4; P5 p5; P6 p6; P7 p7; P8 p8; P9 p9; if (!pH->GetParams(p1, p2, p3, p4, p5, p6, p7, p8, p9)) { return pH->EndFunction(); } return (callee->*func)(pH, p1, p2, p3, p4, p5, p6, p7, p8, p9); } template static int Call(Callee* callee, int (Callee::* func)(IFunctionHandler*, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), IFunctionHandler* pH) { P1 p1; P2 p2; P3 p3; P4 p4; P5 p5; P6 p6; P7 p7; P8 p8; P9 p9; P10 p10; if (!pH->GetParams(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)) { return pH->EndFunction(); } return (callee->*func)(pH, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } template struct CallDispatcher { static int Dispatch(IFunctionHandler* pH, void* pBuffer, int nSize) { unsigned char* buffer = (unsigned char*)pBuffer; return ScriptTemplateCallHelper::Call(*(Callee**)buffer, *(Func*)(buffer + sizeof(Callee*)), pH); } }; }; ////////////////////////////////////////////////////////////////////////// // Classes that want to register functions to the script must derive from this interface. ////////////////////////////////////////////////////////////////////////// class CScriptableBase { public: friend class CScriptBind_GameStatistics; virtual ~CScriptableBase() { Done(); }; virtual void Init(IScriptSystem* pSS, ISystem* pSystem, int nParamIdOffset = 0) { m_pSS = pSS; m_pMethodsTable = m_pSS->CreateTable(); m_pMethodsTable->AddRef(); m_nParamIdOffset = nParamIdOffset; } void Done() { if (*m_sGlobalName != 0 && m_pSS) { m_pSS->SetGlobalToNull(m_sGlobalName); } SAFE_RELEASE(m_pMethodsTable); } virtual void GetMemoryStatistics(ICrySizer* pSizer) {}; void SetGlobalName(const char* sGlobalName) { assert(strlen(sGlobalName) < sizeof(m_sGlobalName)); cry_strcpy(m_sGlobalName, sGlobalName); if (m_pMethodsTable) { m_pSS->SetGlobalValue(sGlobalName, m_pMethodsTable); } } IScriptTable* GetMethodsTable() { return m_pMethodsTable; }; protected: CScriptableBase() { m_pSS = NULL; m_pMethodsTable = NULL; m_sGlobalName[0] = 0; } void RegisterGlobal(const char* sName, float fValue) { m_pSS->SetGlobalValue(sName, fValue); } // [K01]: disabled int version since it is overloaded with float and isn't compiled // under GCC for enum types #ifndef LINUX void RegisterGlobal(const char* sName, int nValue) { m_pSS->SetGlobalValue(sName, nValue); } #endif void RegisterFunction(const char* sFuncName, IScriptTable::FunctionFunctor function) { if (m_pMethodsTable) { IScriptTable::SUserFunctionDesc fd; fd.sGlobalName = m_sGlobalName; fd.sFunctionName = sFuncName; fd.pFunctor = function; fd.nParamIdOffset = m_nParamIdOffset; m_pMethodsTable->AddFunction(fd); } } template void RegisterTemplateFunction(const char* sFuncName, const char* sFuncParams, Callee& callee, const Func& func) { typedef Callee* Callee_pointer; if (m_pMethodsTable) { Callee_pointer pCalleePtr = &callee; unsigned char pBuffer[sizeof(Callee_pointer) + sizeof(func)]; memcpy(pBuffer, &pCalleePtr, sizeof(Callee_pointer)); memcpy(pBuffer + sizeof(Callee_pointer), &func, sizeof(func)); IScriptTable::SUserFunctionDesc fd; fd.sGlobalName = m_sGlobalName; fd.sFunctionName = sFuncName; fd.sFunctionParams = sFuncParams; fd.pUserDataFunc = ScriptTemplateCallHelper::CallDispatcher::Dispatch; fd.nDataSize = sizeof(Callee_pointer) + sizeof(func); fd.pDataBuffer = pBuffer; fd.nParamIdOffset = m_nParamIdOffset; m_pMethodsTable->AddFunction(fd); } } protected: ////////////////////////////////////////////////////////////////////////// char m_sGlobalName[64]; IScriptTable* m_pMethodsTable; IScriptSystem* m_pSS; int m_nParamIdOffset; ////////////////////////////////////////////////////////////////////////// }; #define SCRIPT_REG_CLASSNAME #define SCRIPT_REG_FUNC(func) RegisterFunction( #func, functor(*this, SCRIPT_REG_CLASSNAME func)); #define SCRIPT_REG_FUNC_WITH_NAME(name, func) RegisterFunction( name, functor(*this, SCRIPT_REG_CLASSNAME func)); #define SCRIPT_REG_GLOBAL(var) RegisterGlobal( #var, var); #define SCRIPT_REG_TEMPLFUNC(func, sFuncParams) RegisterTemplateFunction( #func, sFuncParams, *this, SCRIPT_REG_CLASSNAME func); #define SCRIPT_CHECK_PARAMETERS(_n) \ if (pH->GetParamCount() != _n) \ { CryWarning(VALIDATOR_MODULE_SCRIPTSYSTEM, VALIDATOR_WARNING, "[%s] %d arguments passed, " #_n " expected)", __FUNCTION__, pH->GetParamCount()); \ return pH->EndFunction(); } #define SCRIPT_CHECK_PARAMETERS_MIN(_n) \ if (pH->GetParamCount() < _n) \ { CryWarning(VALIDATOR_MODULE_SCRIPTSYSTEM, VALIDATOR_WARNING, "[%s] %d arguments passed, at least " #_n " expected)", __FUNCTION__, pH->GetParamCount()); \ return pH->EndFunction(); } #define SCRIPT_CHECK_PARAMETERS2(_n, _n2) \ if ((pH->GetParamCount() != _n) && (pH->GetParamCount() != _n2)) \ { CryWarning(VALIDATOR_MODULE_SCRIPTSYSTEM, VALIDATOR_WARNING, "[%s] %d arguments passed, " #_n " or " #_n2 " expected)", __FUNCTION__, pH->GetParamCount()); \ return pH->EndFunction(); } #define SCRIPT_CHECK_PARAMETERS3(_n, _n2, _n3) \ if ((pH->GetParamCount() != _n) && (pH->GetParamCount() != _n2) && (pH->GetParamCount() != _n3)) \ { CryWarning(VALIDATOR_MODULE_SCRIPTSYSTEM, VALIDATOR_WARNING, "[%s] %d arguments passed, " #_n ", " #_n2 " or " #_n3 " expected)", __FUNCTION__, pH->GetParamCount()); \ return pH->EndFunction(); } ////////////////////////////////////////////////////////////////////////// // Auto Wrapper on IScriptTable interface, will destroy table when exiting scope. ////////////////////////////////////////////////////////////////////////// class SmartScriptTable { public: SmartScriptTable() : p(NULL) {}; SmartScriptTable(const SmartScriptTable& st) { p = st.p; if (p) { p->AddRef(); } } SmartScriptTable(IScriptTable* newp) { if (newp) { newp->AddRef(); } p = newp; } // Copy operator. SmartScriptTable& operator =(IScriptTable* newp) { if (newp) { newp->AddRef(); } if (p) { p->Release(); } p = newp; return *this; } // Copy operator. SmartScriptTable& operator =(const SmartScriptTable& st) { if (st.p) { st.p->AddRef(); } if (p) { p->Release(); } p = st.p; return *this; } explicit SmartScriptTable(IScriptSystem* pSS, bool bCreateEmpty = false) { p = pSS->CreateTable(bCreateEmpty); p->AddRef(); } ~SmartScriptTable() { if (p) { p->Release(); } } ////////////////////////////////////////////////////////////////////////// // Casts ////////////////////////////////////////////////////////////////////////// IScriptTable* operator->() const { return p; } IScriptTable* operator*() const { return p; } operator const IScriptTable*() const { return p; } operator IScriptTable*() const { return p; } operator bool() const { return (p != NULL); } ////////////////////////////////////////////////////////////////////////// // Boolean comparasions. ////////////////////////////////////////////////////////////////////////// bool operator ! () const { return p == NULL; }; bool operator ==(const IScriptTable* p2) const { return p == p2; }; bool operator ==(IScriptTable* p2) const { return p == p2; }; bool operator !=(const IScriptTable* p2) const { return p != p2; }; bool operator !=(IScriptTable* p2) const { return p != p2; }; bool operator < (const IScriptTable* p2) const { return p < p2; }; bool operator > (const IScriptTable* p2) const { return p > p2; }; ////////////////////////////////////////////////////////////////////////// IScriptTable* GetPtr() const { return p; } ////////////////////////////////////////////////////////////////////////// bool Create(IScriptSystem* pSS, bool bCreateEmpty = false) { if (p) { p->Release(); } p = pSS->CreateTable(bCreateEmpty); p->AddRef(); return (p) ? true : false; } private: IScriptTable* p; }; ////////////////////////////////////////////////////////////////////////// // Smart wrapper on top of script function handle. ////////////////////////////////////////////////////////////////////////// class SmartScriptFunction { public: SmartScriptFunction() : m_func(0) , m_pSS(0) { }; SmartScriptFunction(IScriptSystem* pSS, HSCRIPTFUNCTION func) : m_func(func) , m_pSS(pSS) { } SmartScriptFunction(const SmartScriptFunction& other) : m_func(0) , m_pSS(0) { if (other.m_func) { ScriptAnyValue func( other.m_pSS->CloneAny(ScriptAnyValue((HSCRIPTFUNCTION)other.m_func))); func.CopyTo(m_func); m_pSS = other.m_pSS; } } ~SmartScriptFunction() { if (m_func) { m_pSS->ReleaseFunc(m_func); } m_func = 0; m_pSS = 0; } SmartScriptFunction& operator=(const SmartScriptFunction& other) { SmartScriptFunction(other).swap(*this); return *this; } operator HSCRIPTFUNCTION() const { return m_func; } HSCRIPTFUNCTION get() const { return m_func; } void swap(SmartScriptFunction& other) { HSCRIPTFUNCTION otherFunc = other.m_func; IScriptSystem* otherSS = other.m_pSS; other.m_func = m_func; other.m_pSS = m_pSS; m_func = otherFunc; m_pSS = otherSS; } void reset() { SmartScriptFunction().swap(*this); } void reset(IScriptSystem* pSS, HSCRIPTFUNCTION func) { SmartScriptFunction(pSS, func).swap(*this); } private: HSCRIPTFUNCTION m_func; IScriptSystem* m_pSS; }; // Description: // This class map an 3d vector to a LUA table with x,y,z members. class CScriptVector : public SmartScriptTable { public: CScriptVector() {} CScriptVector(IScriptSystem* pSS, bool bCreateEmpty = false) : SmartScriptTable(pSS, bCreateEmpty) {} void Set(const Vec3& v) { CScriptSetGetChain chain(*this); chain.SetValue("x", v.x); chain.SetValue("y", v.y); chain.SetValue("z", v.z); } Vec3 Get() { Vec3 v(0, 0, 0); CScriptSetGetChain chain(*this); chain.GetValue("x", v.x); chain.GetValue("y", v.y); chain.GetValue("z", v.z); return v; } CScriptVector& operator=(const Vec3& v3) { Set(v3); return *this; } }; // Description: // This class map an "color" to a LUA table with indexed 3 numbers [1],[2],[3] members. class CScriptColor : public SmartScriptTable { public: CScriptColor() {} CScriptColor(IScriptSystem* pSS, bool bCreateEmpty = false) : SmartScriptTable(pSS, bCreateEmpty) {} void Set(const Vec3& v) { IScriptTable* pTable = *this; pTable->SetAt(1, v.x); pTable->SetAt(2, v.y); pTable->SetAt(3, v.z); } Vec3 Get() { IScriptTable* pTable = *this; Vec3 v(0, 0, 0); pTable->GetAt(1, v.x); pTable->GetAt(2, v.y); pTable->GetAt(3, v.z); return v; } CScriptColor& operator=(const Vec3& v3) { Set(v3); return *this; } }; ////////////////////////////////////////////////////////////////////////// // Script call helper. struct Script { static SmartScriptTable GetCachedTable(IFunctionHandler* pH, int funcParam) { SmartScriptTable out; if (pH->GetParamCount() >= funcParam && pH->GetParamType(funcParam) == svtObject) { pH->GetParam(funcParam, out); } if (!out.GetPtr()) { out = SmartScriptTable(gEnv->pScriptSystem); } return out; } static SmartScriptTable SetCachedVector(const Vec3& value, IFunctionHandler* pH, int funcParam) { SmartScriptTable out = GetCachedTable(pH, funcParam); { CScriptSetGetChain chain(out); chain.SetValue("x", value.x); chain.SetValue("y", value.y); chain.SetValue("z", value.z); } return out; } static SmartScriptTable GetCachedTable(SmartScriptTable& table, const char* fieldName) { SmartScriptTable out; if (table->GetValue(fieldName, out)) { return out; } out = SmartScriptTable(gEnv->pScriptSystem); table->SetValue(fieldName, out); return out; } static SmartScriptTable SetCachedVector(const Vec3& value, SmartScriptTable& table, const char* fieldName) { SmartScriptTable out = GetCachedTable(table, fieldName); { CScriptSetGetChain chain(out); chain.SetValue("x", value.x); chain.SetValue("y", value.y); chain.SetValue("z", value.z); } return out; } static SmartScriptTable GetCachedTable(CScriptSetGetChain& chain, const char* fieldName) { SmartScriptTable out; if (chain.GetValue(fieldName, out)) { return out; } out = SmartScriptTable(gEnv->pScriptSystem); chain.SetValue(fieldName, out); return out; } static SmartScriptTable SetCachedVector(const Vec3& value, CScriptSetGetChain& chain, const char* fieldName) { SmartScriptTable out = GetCachedTable(chain, fieldName); { CScriptSetGetChain vecChain(out); vecChain.SetValue("x", value.x); vecChain.SetValue("y", value.y); vecChain.SetValue("z", value.z); } return out; } ////////////////////////////////////////////////////////////////////////// static bool Call(IScriptSystem* pSS, HSCRIPTFUNCTION func) { if (!pSS->BeginCall(func)) { return false; } return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// static bool Call(IScriptSystem* pSS, const char* funcName) { if (!pSS->BeginCall(funcName)) { return false; } return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool Call(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool Call(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1, const P2& p2) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1, p2); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool Call(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, const P3& p3) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1, p2, p3); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool Call(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, const P3& p3, const P4& p4) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1, p2, p3, p4); return pSS->EndCall(); } template static bool Call(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1, p2, p3, p4, p5); return pSS->EndCall(); } template static bool Call(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1, p2, p3, p4, p5, p6); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// // Call to table. ////////////////////////////////////////////////////////////////////////// // Arguments: // pTable - must not be 0 static bool CallMethod(IScriptTable* pTable, const char* sMethod) { assert(pTable); IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(pTable, sMethod)) { return false; } PushParams(pSS, pTable); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// // Arguments: // pTable - must not be 0 template static bool CallMethod(IScriptTable* pTable, const char* sMethod, const P1& p1) { assert(pTable); IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(pTable, sMethod)) { return false; } PushParams(pSS, pTable, p1); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool CallMethod(IScriptTable* pTable, const char* sMethod, const P1& p1, const P2& p2) { IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(pTable, sMethod)) { return false; } PushParams(pSS, pTable, p1, p2); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool CallMethod(IScriptTable* pTable, const char* sMethod, const P1& p1, const P2& p2, const P3& p3) { IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(pTable, sMethod)) { return false; } PushParams(pSS, pTable, p1, p2, p3); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool CallMethod(IScriptTable* pTable, const char* sMethod, const P1& p1, const P2& p2, const P3& p3, const P4& p4) { IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(pTable, sMethod)) { return false; } PushParams(pSS, pTable, p1, p2, p3, p4); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool CallMethod(IScriptTable* pTable, const char* sMethod, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) { IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(pTable, sMethod)) { return false; } PushParams(pSS, pTable, p1, p2, p3, p4, p5); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// // Call to table. ////////////////////////////////////////////////////////////////////////// static bool CallMethod(IScriptTable* pTable, HSCRIPTFUNCTION func) { IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, pTable); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool CallMethod(IScriptTable* pTable, HSCRIPTFUNCTION func, const P1& p1) { IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, pTable, p1); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool CallMethod(IScriptTable* pTable, HSCRIPTFUNCTION func, const P1& p1, const P2& p2) { IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, pTable, p1, p2); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool CallMethod(IScriptTable* pTable, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, const P3& p3) { IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, pTable, p1, p2, p3); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool CallMethod(IScriptTable* pTable, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, const P3& p3, const P4& p4) { IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, pTable, p1, p2, p3, p4); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool CallMethod(IScriptTable* pTable, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) { IScriptSystem* pSS = pTable->GetScriptSystem(); if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, pTable, p1, p2, p3, p4, p5); return pSS->EndCall(); } ////////////////////////////////////////////////////////////////////////// template static bool CallReturn(IScriptSystem* pSS, HSCRIPTFUNCTION func, Ret& ret) { if (!pSS->BeginCall(func)) { return false; } return pSS->EndCall(ret); } ////////////////////////////////////////////////////////////////////////// template static bool CallReturn(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1, Ret& ret) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1); return pSS->EndCall(ret); } ////////////////////////////////////////////////////////////////////////// template static bool CallReturn(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, Ret& ret) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1, p2); return pSS->EndCall(ret); } ////////////////////////////////////////////////////////////////////////// template static bool CallReturn(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, const P3& p3, Ret& ret) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1, p2, p3); return pSS->EndCall(ret); } ////////////////////////////////////////////////////////////////////////// template static bool CallReturn(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, const P3& p3, const P4& p4, Ret& ret) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1, p2, p3, p4); return pSS->EndCall(ret); } ////////////////////////////////////////////////////////////////////////// template static bool CallReturn(IScriptSystem* pSS, HSCRIPTFUNCTION func, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, Ret& ret) { if (!pSS->BeginCall(func)) { return false; } PushParams(pSS, p1, p2, p3, p4, p5); return pSS->EndCall(ret); } ////////////////////////////////////////////////////////////////////////// private: template static void PushParams(IScriptSystem* pSS, const P1& p1) { pSS->PushFuncParam(p1); } template static void PushParams(IScriptSystem* pSS, const P1& p1, const P2& p2) { pSS->PushFuncParam(p1); pSS->PushFuncParam(p2); } template static void PushParams(IScriptSystem* pSS, const P1& p1, const P2& p2, const P3& p3) { pSS->PushFuncParam(p1); pSS->PushFuncParam(p2); pSS->PushFuncParam(p3); } template static void PushParams(IScriptSystem* pSS, const P1& p1, const P2& p2, const P3& p3, const P4& p4) { pSS->PushFuncParam(p1); pSS->PushFuncParam(p2); pSS->PushFuncParam(p3); pSS->PushFuncParam(p4); } template static void PushParams(IScriptSystem* pSS, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) { pSS->PushFuncParam(p1); pSS->PushFuncParam(p2); pSS->PushFuncParam(p3); pSS->PushFuncParam(p4); pSS->PushFuncParam(p5); } template static void PushParams(IScriptSystem* pSS, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) { pSS->PushFuncParam(p1); pSS->PushFuncParam(p2); pSS->PushFuncParam(p3); pSS->PushFuncParam(p4); pSS->PushFuncParam(p5); pSS->PushFuncParam(p6); } }; //! utilities for manipulating or creating script tables struct ScriptUtils { //! Convert a `std::vector` into an array-style script table. /*! Converts an `std::vector` of type `T` into a Lua-style array with elements of type `R` created by using the mapping function. Elements are indexed from 1, per Lua convention. */ template static SmartScriptTable ToScriptArray(IScriptSystem* pSS, const DynArray& v, std::function& map) { SmartScriptTable table = pSS->CreateTable(); int i = 1; for (auto e = v.begin(); e != v.end(); ++e) { table->SetAt(i++, map(*e)); } return table; } }; #endif // CRYINCLUDE_CRYCOMMON_SCRIPTHELPERS_H