Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1250 lines
47 KiB

// testSqPlus2.cpp
// Created by John Schultz 9/21/2005
// Free for any use.
// Step through the code with a debugger (setting breakpoints in functions)
// to get an idea how everything works.
#include <stdarg.h>
#include <stdio.h>
#if 0
#include <string>
//#define SQPLUS_SUPPORT_STD_STRING
#define SQPLUS_SUPPORT_SQ_STD_STRING
#endif
//#define SQPLUS_CONST_OPT
#include "sqplus.h"
using namespace SqPlus;
void scprintfunc(HSQUIRRELVM v,const SQChar *s,...) {
static SQChar temp[2048];
va_list vl;
va_start(vl,s);
scvsprintf( temp,s,vl);
SCPUTS(temp);
va_end(vl);
}
void newtest(void) {
scprintf(_T("NewTest\n"));
}
SQChar * newtestR1(const SQChar * inString) {
scprintf(_T("NewTestR1: %s\n"),inString);
return _T("Returned String");
}
struct Vector3 {
static float staticVar;
float x,y,z;
Vector3() {
x = 1.f;
y = 2.f;
z = 3.f;
}
Vector3(float _x,float _y,float _z) : x(_x), y(_y), z(_z) {}
~Vector3() {
scprintf(_T("~Vector()\n"));
}
Vector3 Inc(Vector3 & v) {
x += v.x;
y += v.y;
z += v.z;
return *this;
} // Inc
Vector3 operator+(Vector3 & v) {
return Vector3(x+v.x,y+v.y,z+v.z);
}
};
float Vector3::staticVar = 898.434f;
#if 0 // It may be possible to make this method work in the future. If so, the DECLARE_INSTANCE_FUNCS() macro
// would not be needed. The issue is duplicate compiler matching for const SQChar * and Push():
// Push(const SQChar * &) and Push(const SQChar *) both match.
// The typeid() compiler function may not be portable to other compilers.
#include <typeinfo.h>
template<typename TYPE>
inline const SQChar * GetTypeName(const TYPE & n) { return typeid(TYPE).name(); }
template<typename TYPE>
inline void Push(HSQUIRRELVM v,const TYPE & value) { CreateCopyInstance(GetTypeName(value),value); }
template<typename TYPE>
inline bool Match(TypeWrapper<TYPE &>,HSQUIRRELVM v,int idx) { return GetInstance<TYPE>(v,idx) != NULL; }
template<typename TYPE>
inline TYPE & Get(TypeWrapper<TYPE &>,HSQUIRRELVM v,int idx) { return *GetInstance<TYPE>(v,idx); }
#endif
DECLARE_INSTANCE_TYPE(Vector3)
Vector3 Add2(Vector3 & a,Vector3 & b) {
Vector3 c;
c.x = a.x + b.x;
c.y = a.y + b.y;
c.z = a.z + b.z;
return c;
} // Add2
int Add(HSQUIRRELVM v) {
// StackHandler sa(v);
Vector3 * self = GetInstance<Vector3,true>(v,1);
Vector3 * arg = GetInstance<Vector3,true>(v,2);
// SquirrelObject so = sa.GetObjectHandle(1);
#if 0
SQUserPointer type=0;
so.GetTypeTag(&type);
SQUserPointer reqType = ClassType<Vector3>::type();
if (type != reqType) {
throw SquirrelError(_T("Invalid class type"));
} // if
#endif
// Vector3 * self = (Vector3 *)so.GetInstanceUP(ClassType<Vector3>::type());
// if (!self) throw SquirrelError(_T("Invalid class type"));
Vector3 tv;
tv.x = arg->x + self->x;
tv.y = arg->y + self->y;
tv.z = arg->z + self->z;
return ReturnCopy(v,tv);
}
struct NewTestObj {
ScriptStringVar64 s1;
ScriptStringVar32 s2;
bool b;
int val;
int c1;
ScriptStringVar8 c2; // 8 char plus null (max string is 8 printable chars).
NewTestObj() : val(777) {
s1 = _T("s1=s1");
s2 = _T("s2=s2");
c1 = 996;
c2 = _T("It's a 997"); // Prints: "It's a 9", as only 8 chars in static buffer (plus null).
}
NewTestObj(const SQChar * _s1,int _val,bool _b) {
s1 = _s1;
val = _val;
b = _b;
s2 = _T("s2=s2");
c1 = 993;
c2 = _T("It's a 998"); // Prints: "It's a 9", as only 8 chars in static buffer (plus null).
}
static int construct(HSQUIRRELVM v) {
// StackHandler sa(v);
// SquirrelObject so = sa.GetObjectHandle(1);
return PostConstruct<NewTestObj>(v,new NewTestObj(),release);
} // construct
SQ_DECLARE_RELEASE(NewTestObj) // Required when using a custom constructor.
void newtest(void) {
scprintf(_T("NewTest: %d\n"),val);
}
SQChar * newtestR1(const SQChar * inString) {
scprintf(_T("NewTestR1: Member var val is %d, function arg is %s\n"),val,inString);
return _T("Returned String");
}
int multiArgs(HSQUIRRELVM v) {
StackHandler sa(v);
SquirrelObject so = sa.GetObjectHandle(1);
int paramCount = sa.GetParamCount();
int p1 = sa.GetInt(2);
int p2 = sa.GetInt(3);
int p3 = sa.GetInt(4);
return 0;
} // multiArgs
int _set(HSQUIRRELVM v) {
StackHandler sa(v);
int paramCount = sa.GetParamCount();
const SQChar * el = sa.GetString(2);
val = sa.GetInt(3);
return sa.Return(val);
}
int _get(HSQUIRRELVM v) {
StackHandler sa(v);
int paramCount = sa.GetParamCount();
return sa.Return(val);
}
};
// Using global functions to construct and release classes.
int releaseNewTestObj(SQUserPointer up,SQInteger size) {
SQ_DELETE_CLASS(NewTestObj);
} // releaseNewTestObj
int constructNewTestObj(HSQUIRRELVM v) {
StackHandler sa(v);
int paramCount = sa.GetParamCount();
if (paramCount == 1) {
return PostConstruct<NewTestObj>(v,new NewTestObj(),releaseNewTestObj);
} else if (paramCount == 4) {
return PostConstruct<NewTestObj>(v,new NewTestObj(sa.GetString(2),sa.GetInt(3),sa.GetBool(4)?true:false),releaseNewTestObj);
} // if
return sq_throwerror(v,_T("Invalid Constructor arguments"));
} // constructNewTestObj
// Using fixed args with auto-marshaling. Note that the HSQUIRRELVM must be last in the argument list (and must be present to send to PostConstruct).
// SquirrelVM::GetVMPtr() could also be used with PostConstruct(): no HSQUIRRELVM argument would be required.
int constructNewTestObjFixedArgs(const SQChar * s,int val,bool b,HSQUIRRELVM v) {
StackHandler sa(v);
int paramCount = sa.GetParamCount();
return PostConstruct<NewTestObj>(v,new NewTestObj(s,val,b),releaseNewTestObj);
} // constructNewTestObj
// Will be registered in a class namespace.
void globalFunc(const SQChar * s,int val) {
scprintf(_T("globalFunc: s: %s val: %d\n"),s,val);
} // globalFunc
class GlobalClass {
public:
void func(const SQChar * s,int val) {
scprintf(_T("globalClassFunc: s: %s val: %d\n"),s,val);
} // func
} globalClass;
struct CustomTestObj {
ScriptStringVar128 name;
int val;
bool state;
CustomTestObj() : val(0), state(false) { name = _T("empty"); }
CustomTestObj(const SQChar * _name,int _val,bool _state) : val(_val), state(_state) {
name = _name;
}
// Custom variable argument constructor
static int construct(HSQUIRRELVM v) {
StackHandler sa(v);
int paramCount = sa.GetParamCount();
if (paramCount == 1) {
return PostConstruct<CustomTestObj>(v,new CustomTestObj(),release);
} if (paramCount == 4) {
return PostConstruct<CustomTestObj>(v,new CustomTestObj(sa.GetString(2),sa.GetInt(3),sa.GetBool(4)?true:false),release);
} // if
return sq_throwerror(v,_T("Invalid Constructor arguments"));
} // construct
SQ_DECLARE_RELEASE(CustomTestObj) // Required when using a custom constructor.
// Member function that handles variable types.
int varArgTypes(HSQUIRRELVM v) {
StackHandler sa(v);
int paramCount = sa.GetParamCount();
if (sa.GetType(2) == OT_INTEGER) {
val = sa.GetInt(2);
} // if
if (sa.GetType(2) == OT_STRING) {
name = sa.GetString(2);
} // if
if (sa.GetType(3) == OT_INTEGER) {
val = sa.GetInt(3);
} // if
if (sa.GetType(3) == OT_STRING) {
name = sa.GetString(3);
} // if
// return sa.ThrowError(_T("varArgTypes() error"));
return 0;
} // varArgTypes
// Member function that handles variable types and has variable return types+count.
int varArgTypesAndCount(HSQUIRRELVM v) {
StackHandler sa(v);
int paramCount = sa.GetParamCount();
SQObjectType type1 = (SQObjectType)sa.GetType(1); // Always OT_INSTANCE
SQObjectType type2 = (SQObjectType)sa.GetType(2);
SQObjectType type3 = (SQObjectType)sa.GetType(3);
SQObjectType type4 = (SQObjectType)sa.GetType(4);
int returnCount = 0;
if (paramCount == 3) {
sq_pushinteger(v,val);
returnCount = 1;
} else if (paramCount == 4) {
sq_pushinteger(v,val);
sq_pushstring(v,name,-1);
returnCount = 2;
} // if
return returnCount;
} //
int noArgsVariableReturn(HSQUIRRELVM v) {
if (val == 123) {
val++;
return 0; // This will print (null).
} else if (val == 124) {
sq_pushinteger(v,val); // Will return int:124.
val++;
return 1;
} else if (val == 125) {
sq_pushinteger(v,val);
name = _T("Case 125");
sq_pushstring(v,name,-1);
val = 123; // reset
return 2;
} // if
return 0;
} // noArgsVariableReturn
// Registered with func() instead of funcVarArgs(): fixed (single) return type.
const SQChar * variableArgsFixedReturnType(HSQUIRRELVM v) {
StackHandler sa(v);
int paramCount = sa.GetParamCount();
SQObjectType type1 = (SQObjectType)sa.GetType(1); // Always OT_INSTANCE
SQObjectType type2 = (SQObjectType)sa.GetType(2);
SQObjectType type3 = (SQObjectType)sa.GetType(3);
if (paramCount == 1) {
return _T("No Args");
} else if (paramCount == 2) {
return _T("One Arg");
} else if (paramCount == 3) {
return _T("Two Args");
} // if
return _T("More than two args");
} // variableArgsFixedReturnType
void manyArgs(int i,float f,bool b,const SQChar * s) {
scprintf(_T("i: %d, f: %f, b: %s, s: %s\n"),i,f,b?_T("true"):_T("false"),s);
} // manyArgs
float manyArgsR1(int i,float f,bool b,const SQChar * s) {
manyArgs(i,f,b,s);
return i+f;
} // manyArgsR1
};
// === Standard (non member) function ===
int testFunc(HSQUIRRELVM v) {
StackHandler sa(v);
int paramCount = sa.GetParamCount();
scprintf(_T("testFunc: numParams[%d]\n"),paramCount);
for (int i=1; i <= paramCount; i++) {
scprintf(_T("param[%d]: "),i);
switch(sa.GetType(i)) {
case OT_TABLE: scprintf(_T("OT_TABLE[0x%x]\n"),sa.GetObjectHandle(i)); break;
case OT_INTEGER: scprintf(_T("OT_INTEGER[%d]\n"),sa.GetInt(i)); break;
case OT_FLOAT: scprintf(_T("OT_FLOAT[%f]\n"),sa.GetFloat(i)); break;
case OT_STRING: scprintf(_T("OT_STRING[%s]\n"),sa.GetString(i)); break;
default:
scprintf(_T("TYPEID[%d]\n"),sa.GetType(i));
} // switch
} // for
return SQ_OK;
} // testFunc
int globalVar = 5551234;
class Creature {
int health;
public:
enum {MaxHealth=100};
Creature() : health(MaxHealth) {}
int GetMaxHealth(void) {
return MaxHealth;
}
int GetHealth(void) {
return health;
}
void SetHealth(int newHealth) {
health = newHealth;
}
};
DECLARE_INSTANCE_TYPE(Creature)
// === BEGIN Class Instance Test ===
class PlayerManager {
public:
struct Player {
ScriptStringVar64 name;
void printName(void) {
scprintf(_T("Player.name = %s\n"),name.s);
}
};
Player playerVar; // Will be accessed directly.
Player players[2];
Player * GetPlayer(int player) { // Must return pointer: a returned reference will behave the same as return by value.
return &players[player];
}
PlayerManager() {
players[0].name = _T("Player1");
players[1].name = _T("Player2");
playerVar.name = _T("PlayerVar");
}
} playerManager;
DECLARE_INSTANCE_TYPE(PlayerManager)
DECLARE_INSTANCE_TYPE(PlayerManager::Player)
PlayerManager * getPlayerManager(void) { // Must return pointer: a returned reference will behave the same as return by value.
return &playerManager;
}
// Example from forum post question:
class STestScripts {}; // Proxy class
class TestScripts {
public:
int Var_ToBind1,Var_ToBind2;
void InitScript1(void) {
Var_ToBind1 = 808;
RegisterGlobal(*this,&TestScripts::Test1,_T("Test1"));
RegisterGlobal(*this,&TestScripts::Test2,_T("Test2"));
BindVariable(&Var_ToBind1,_T("Var_ToBind1"));
} // InitScript1
void InitScript2(void) {
Var_ToBind2 = 909;
SQClassDef<STestScripts>(_T("STestScripts")).
staticFunc(*this,&TestScripts::Test1,_T("Test1")).
staticFunc(*this,&TestScripts::Test2,_T("Test2")).
staticVar(&Var_ToBind2,_T("Var_ToBind2"));
} // InitScript2
void Test1(void) {
scprintf(_T("Test1 called.\n"));
}
void Test2(void) {
scprintf(_T("Test2 called.\n"));
}
} testScripts;
// From forum questions
#if 1
template<typename T>
struct Point {
Point() {}
Point(T X, T Y) : X(X), Y(Y) {}
T X, Y;
};
template<typename T>
struct Box {
Box() {}
Box(Point<T> UpperLeft, Point<T> LowerRight) : UpperLeft(UpperLeft), LowerRight(LowerRight) {}
Point<T> UpperLeft, LowerRight;
void print(void) {
scprintf(_T("UL.X %f UL.Y %f LR.X %f LR.Y %f\n"),UpperLeft.X,UpperLeft.Y,LowerRight.X,LowerRight.Y);
}
};
template<typename T>
struct Window {
int id;
Box<T> box;
};
typedef Point<float> Pointf;
typedef Box<float> Boxf;
typedef Window<float> Windowf;
#else
struct Pointf {
float X,Y;
Pointf() {}
Pointf(float _X, float _Y) : X(_X), Y(_Y) {}
};
struct Boxf {
Pointf UpperLeft,LowerRight;
Boxf() {}
Boxf(Pointf _UpperLeft,Pointf _LowerRight) : UpperLeft(_UpperLeft), LowerRight(_LowerRight) {}
void print(void) {
scprintf(_T("UL.X %f UL.Y %f LR.X %f LR.Y %f\n"),UpperLeft.X,UpperLeft.Y,LowerRight.X,LowerRight.Y);
}
};
struct Windowf {
int id;
Boxf box;
};
#endif
DECLARE_INSTANCE_TYPE(Pointf)
DECLARE_INSTANCE_TYPE(Boxf)
DECLARE_INSTANCE_TYPE(Windowf)
int constructPointf(float X,float Y,HSQUIRRELVM v) {
return PostConstruct<Pointf>(v,new Pointf(X,Y),ReleaseClassPtr<Pointf>::release);
} // constructPointf
// Must pass by reference or pointer (not copy)
int constructBoxf(Pointf & UpperLeft,Pointf & LowerRight,HSQUIRRELVM v) {
return PostConstruct<Boxf>(v,new Boxf(UpperLeft,LowerRight),ReleaseClassPtr<Boxf>::release);
} // constructBoxf
struct WindowHolder {
static Windowf * currentWindow;
static Windowf * getWindow(void) {
return currentWindow;
} // getWindow
};
Windowf * WindowHolder::currentWindow = 0;
// From forum post: compiler works OK.
void testCompiler(void) {
SquirrelObject test = SquirrelVM::CompileBuffer(_T("\
local SceneManager = getSceneManager() ; \n\
\n\
SceneManager.AddScene(\"Scene1\") ; \n\
SceneManager.AddScene(\"Scene4\") ; \n\
SceneManager.ActivateScene(\"Scene1\") ; \n\
"));
SquirrelVM::RunScript(test);
}
void testPointfBoxf(void) {
// testCompiler();
SQClassDef<Pointf>(_T("Pointf")).
staticFunc(constructPointf,_T("constructor")).
var(&Pointf::X,_T("X")).
var(&Pointf::Y,_T("Y"));
SQClassDef<Boxf>(_T("Boxf")).
staticFunc(constructBoxf,_T("constructor")).
func(&Boxf::print,_T("print")).
var(&Boxf::UpperLeft,_T("UpperLeft")).
var(&Boxf::LowerRight,_T("LowerRight"));
SQClassDef<Windowf>(_T("Windowf")).
var(&Windowf::id,_T("Id")).
var(&Windowf::box,_T("Box"));
RegisterGlobal(WindowHolder::getWindow,_T("getWindow"));
Windowf myWindow;
myWindow.id = 42;
myWindow.box = Boxf(Pointf(1.f,2.f),Pointf(3.f,4.f));
WindowHolder::currentWindow = &myWindow;
// The createWindow() function below creates a new instance on the root table.
// The instance data is a pointer to the C/C++ instance, and will not be freed
// or otherwise managed.
SquirrelObject test = SquirrelVM::CompileBuffer(_T("\
local MyWindow = Windowf(); \n\
MyWindow.Box = Boxf(Pointf(11.,22.),Pointf(33.,44.)); \n\
print(MyWindow.Box.LowerRight.Y); \n\
MyWindow.Box.LowerRight.Y += 1.; \n\
local MyWindow2 = Windowf(); \n\
MyWindow2 = MyWindow; \n\
print(MyWindow2.Box.LowerRight.Y); \n\
local MyBox = Boxf(Pointf(10.,20.),Pointf(30.,40.)); \n\
MyBox.UpperLeft = Pointf(1000.,1000.); \n\
MyBox.UpperLeft.X = 5000. \n\
print(MyBox.UpperLeft.X) \n\
print(MyBox.UpperLeft.Y) \n\
MyWindow2.Box = MyBox; \n\
MyWindow2.Box.print(); \n\
MyWindow2 = getWindow(); \n\
print(\"MyWindow2: \"+MyWindow2.Id); \n\
MyWindow2.Box.print(); \n\
function createWindow(name,instance) { \n\
::rawset(name,instance); \n\
} \n\
"));
SquirrelVM::RunScript(test);
Windowf window = myWindow;
window.id = 54;
window.box.UpperLeft.X += 1;
window.box.UpperLeft.Y += 1;
window.box.LowerRight.X += 1;
window.box.LowerRight.Y += 1;
// Create a new Window instance "NewWindow" on the root table.
SquirrelFunction<void>(_T("createWindow"))(_T("NewWindow"),&window);
SquirrelObject test2 = SquirrelVM::CompileBuffer(_T("\
print(\"NewWindow: \"+NewWindow.Id); \n\
NewWindow.Box.print(); \n\
"));
SquirrelVM::RunScript(test2);
} // testPointfBoxf
// Example debug hook: called back during script execution.
SQInteger debug_hook(HSQUIRRELVM v) {
SQUserPointer up;
int event_type,line;
const SQChar *src,*func;
sq_getinteger(v,2,&event_type);
sq_getstring(v,3,&src);
sq_getinteger(v,4,&line);
sq_getstring(v,5,&func);
sq_getuserpointer(v,-1,&up);
return 0;
} // debug_hook
// You can add functions/vars here, as well as bind globals to be accessed through this class as shown in the NameSpace example.
// If the class is instantiated in script, the instance is "locked", preventing accidental changes to elements.
// Thus using an instance as the namespace can be a better design for development.
// If variables/constants are bound to the class and/or non-static/non-global functions, the class must be instantiated before use.
struct NamespaceClass {
};
// === END Class Instance Test ===
class TestBase {
public:
int x;
TestBase() : x(0) {
printf("Constructing TestBase[0x%x]\n",(size_t)this);
}
void print(void) {
printf("TestBase[0x%x], x[%d]\n",(size_t)this,x);
}
};
DECLARE_INSTANCE_TYPE(TestBase)
class TestDerivedCPP : public TestBase {
public:
int y;
TestDerivedCPP() {
x = 121;
}
};
typedef void (TestDerivedCPP::*TestDerivedCPP_print)(void);
void testInhertianceCase(void) {
SQClassDef<TestBase>(_T("TestBase")).
var(&TestBase::x,_T("x")).
func(&TestBase::print,_T("print"));
SQClassDef<TestDerivedCPP>(_T("TestDerivedCPP")).
func((TestDerivedCPP_print)&TestDerivedCPP::print,_T("print"));
// Note that the constructor definition and call below is not required for this example.
// (The C/C++ constructor will be called automatically).
SquirrelObject testInheritance2 = SquirrelVM::CompileBuffer(_T("\
class TestDerived extends TestBase { \n\
function print() { \n\
::TestBase.print(); \n\
::print(\"Derived: \"+x); \n\
} \n\
constructor() { \n\
TestBase.constructor(); \n\
} \n\
} \n\
local a = TestDerived(); \n\
local b = TestDerived(); \n\
a.x = 1; \n\
b.x = 2; \n\
print(\"a.x = \"+a.x); \n\
print(\"b.x = \"+b.x); \n\
a.print(); \n\
b.print(); \n\
local c = TestDerivedCPP(); \n\
c.print(); \n\
"));
SquirrelVM::RunScript(testInheritance2);
}
// === BEGIN from a forum post by jkleinecke. 8/23/06 jcs ===
namespace Scripting {
class ScriptEntity {
public:
ScriptEntity() {
Bind();
}
static void Bind() {
SqPlus::SQClassDef<ScriptEntity>(_T("ScriptEntity")).
var(&ScriptEntity::m_strName,_T("name"));
} // Bind
SqPlus::ScriptStringVar64 m_strName;
};
}
DECLARE_INSTANCE_TYPE_NAME(Scripting::ScriptEntity,ScriptEntity)
void testScriptingTypeName(void) {
try {
Scripting::ScriptEntity entity ;
SqPlus::BindVariable(&entity,_T("instance"));
SquirrelObject sqObj = SquirrelVM::CompileBuffer(_T("instance.name = \"Testing an instance variable bind: member assignment.\"; print(instance.name);"));
SquirrelVM::RunScript(sqObj);
} // try
catch (SquirrelError e) {
scprintf(_T("testScriptingTypeName: %s\n"),e.desc);
} // catch
}
// === END from a forum post by jkleinecke. 8/23/06 jcs ===
// === BEGIN Interface Test ===
class PureInterface {
public:
virtual void pureFunc1(void)=0;
virtual void pureFunc2(void)=0;
};
class MyImp : public PureInterface {
public:
PureInterface * getInterface(void) { return (PureInterface *)this; }
void pureFunc1(void) {
scprintf(_T("PureFunc1 called [0x%p].\n"),this);
}
void pureFunc2(void) {
scprintf(_T("PureFunc2 called [0x%p].\n"),this);
}
};
class InterfaceHolder {
public:
PureInterface * theInterface;
void setInterface(PureInterface * pureInterface) {
theInterface = pureInterface;
}
PureInterface * getInterface(void) {
return theInterface;
}
};
DECLARE_INSTANCE_TYPE(PureInterface)
DECLARE_INSTANCE_TYPE(MyImp)
DECLARE_INSTANCE_TYPE(InterfaceHolder)
void testPureVirtualInterface(void) {
SQClassDefNoConstructor<PureInterface>(_T("PureInterface")).
func(&PureInterface::pureFunc1,_T("pureFunc1")).
func(&PureInterface::pureFunc2,_T("pureFunc2"));
SQClassDef<InterfaceHolder>(_T("InterfaceHolder")).
func(&InterfaceHolder::setInterface,_T("setInterface")).
func(&InterfaceHolder::getInterface,_T("getInterface"));
SQClassDef<MyImp>(_T("MyImp")).
func(&MyImp::getInterface,_T("getInterface"));
MyImp myImp;
SquirrelObject test = SquirrelVM::CompileBuffer(_T("ih <- InterfaceHolder();"));
SquirrelVM::RunScript(test);
SquirrelObject root = SquirrelVM::GetRootTable();
SquirrelObject ih = root.GetValue(_T("ih"));
InterfaceHolder * ihp = (InterfaceHolder * )ih.GetInstanceUP(ClassType<InterfaceHolder>::type());
ihp->setInterface(&myImp);
test = SquirrelVM::CompileBuffer(_T("\
ih.getInterface().pureFunc1(); \n\
ih.getInterface().pureFunc2(); \n\
ihp <- ih.getInterface(); \n\
ihp.pureFunc1(); \n\
ihp.pureFunc2(); \n\
myIh <- MyImp(); \n\
ih.setInterface(myIh.getInterface()); \n\
ih.getInterface().pureFunc1(); \n\
ih.getInterface().pureFunc2(); \n\
"));
SquirrelVM::RunScript(test);
} // testPureVirtualInterface
// === END Interface Test ===
void testSquirrelObjectSetGet(void) {
// We can pass in arguments:
// by value ('true' arg, required for constant float, int, etc., or when a copy is desired),
// by reference (data will be copied to SquirrelObject and memory managed),
// by pointer (no data copying: pointer is used directly in SquirrelObject; the memory will not be managed).
SquirrelObject tc(5.678f); // constant argument is passed by value (even though declaration is by ref: const & results in by-value in this case), memory will be allocated and managed for the copy.
float valc = tc.Get<float>();
scprintf(_T("Valc is: %f\n"),valc);
float val = 1.234f;
SquirrelObject t(val); // val is passed by reference, memory will be allocated, and the value copied once.
float val2 = t.Get<float>();
scprintf(_T("Val2 is: %f\n"),val2);
if (1) {
SquirrelObject v(Vector3(1.f,2.f,3.f)); // Pass in by reference: will be copied once, with memory for new copy managed by Squirrel.
Vector3 * pv = v.Get<Vector3 *>();
scprintf(_T("Vector3 is: %f %f %f\n"),pv->x,pv->y,pv->z);
pv->z += 1.f;
if (1) {
SquirrelObject v2p(pv); // This is a pointer to v's instance (passed in by pointer: see SquirrelObject.h).
// A new Squirrel Instance will be created, but the C++ instance pointer will not get freed when v2p goes out of scope (release hook will be null).
pv = v2p.Get<Vector3 *>();
scprintf(_T("Vector3 is: %f %f %f\n"),pv->x,pv->y,pv->z);
} // if
} // if
scprintf(_T("Vector3() instance has been released.\n\n"));
} // testSquirrelObjectSetGet
#define SQDBG_DEBUG_HOOK _T("_sqdebughook_")
class TestSqPlus {
public:
enum {SQ_ENUM_TEST=1234321};
void init(void) {
SquirrelVM::Init();
HSQUIRRELVM _v = SquirrelVM::GetVMPtr();
#if 1
sq_pushregistrytable(_v);
sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1);
sq_pushuserpointer(_v,this);
sq_newclosure(_v,debug_hook,1);
sq_createslot(_v,-3);
// sq_pop(_v,1);
// sq_pushregistrytable(_v);
sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1);
sq_rawget(_v,-2);
sq_setdebughook(_v);
sq_pop(_v,1);
#endif
sq_enabledebuginfo(_v,SQTrue);
} // init
TestSqPlus() {
init();
testPureVirtualInterface();
testScriptingTypeName();
try {
HSQUIRRELVM v = SquirrelVM::GetVMPtr();
SquirrelObject root = SquirrelVM::GetRootTable();
testPointfBoxf();
// Example from forum question:
testScripts.InitScript1();
testScripts.InitScript2();
SquirrelObject testScriptBinding = SquirrelVM::CompileBuffer(_T("\
local testScripts = STestScripts(); \n\
testScripts.Test1(); \n\
testScripts.Test2(); \n\
print(testScripts.Var_ToBind2); \n\
Test1(); \n\
Test2(); \n\
print(Var_ToBind1); \n\
"));
SquirrelVM::RunScript(testScriptBinding);
// === BEGIN Global Function binding tests ===
// Implemented as SquirrelVM::CreateFunction(rootTable,func,name,typeMask). CreateFunctionGlobal() binds a standard SQFUNCTION (stack args).
SquirrelVM::CreateFunctionGlobal(testFunc,_T("testFunc0"));
SquirrelVM::CreateFunctionGlobal(testFunc,_T("testFuncN"),_T("n"));
SquirrelVM::CreateFunctionGlobal(testFunc,_T("testFuncS"),_T("s"));
#if 0
SquirrelObject testStandardFuncs = SquirrelVM::CompileBuffer(_T(" testFunc0(); testFuncN(1.); testFuncS(\"Hello\"); "));
SquirrelVM::RunScript(testStandardFuncs);
#endif
// === Register Standard Functions using template system (function will be directly called with argument auto-marshaling) ===
RegisterGlobal(v,newtest,_T("test"));
RegisterGlobal(v,newtestR1,_T("testR1"));
// === Register Member Functions to existing classes (as opposed to instances of classes) ===
NewTestObj t1,t2,t3;
t1.val = 123;
t2.val = 456;
t3.val = 789;
RegisterGlobal(v,t1,&NewTestObj::newtest,_T("testObj_newtest1"));
RegisterGlobal(v,t2,&NewTestObj::newtest,_T("testObj_newtest2")); // Register newtest() again with different name and object pointer.
SquirrelObject tr = SquirrelVM::GetRootTable(); // Can be any object supporting closures (functions).
Register(v,tr.GetObjectHandle(),t3,&NewTestObj::newtestR1,_T("testObj_newtestR1")); // Return value version.
// === END Global Function binding tests ===
// === BEGIN Namespace examples ===
// Create a namespace using a table.
SquirrelObject nameSpaceTable = SquirrelVM::CreateTable();
root.SetValue(_T("Namespace1"),nameSpaceTable);
Register(v,nameSpaceTable.GetObjectHandle(),globalFunc,_T("namespaceFunc"));
// Create a namespace using a class. If an instance is created from the class, using the instance will prevent accidental changes to the instance members.
// Using the class/instance form also allows extra information to be added to the proxy class, if desired (such as vars/funcs).
// NOTE: If any variables/static-variables/constants are registered to the class, it must be instantiated before use.
SQClassDef<NamespaceClass>(_T("Namespace2")).
staticFunc(globalFunc,_T("namespaceFunc"));
SquirrelObject testNameSpace = SquirrelVM::CompileBuffer(_T("\
Namespace1.namespaceFunc(\"Hello Namespace1 (table),\",321); \n\
Namespace2.namespaceFunc(\"Hello Namespace2 (class),\",654); \n\
local Namespace3 = Namespace2(); \n\
Namespace3.namespaceFunc(\"Hello Namespace3 (instance),\",987); \n\
"));
SquirrelVM::RunScript(testNameSpace);
// === END Namespace examples ===
// === BEGIN Class Instance tests ===
// Example showing two methods for registration.
#if 0
SQClassDef<NewTestObj> sqClass(_T("NewTestObj"));
sqClass.func(NewTestObj::newtestR1,_T("newtestR1"));
sqClass.var(&NewTestObj::val,_T("val"));
sqClass.var(&NewTestObj::s1,_T("s1"));
sqClass.var(&NewTestObj::s2,_T("s2"));
sqClass.var(&NewTestObj::c1,_T("c1"),VAR_ACCESS_READ_ONLY);
sqClass.var(&NewTestObj::c2,_T("c2"),VAR_ACCESS_READ_ONLY);
sqClass.funcVarArgs(NewTestObj::multiArgs,_T("multiArgs"));
#else
SQClassDef<NewTestObj>(_T("NewTestObj")). // If a special constructor+destructor are not needed, the auto-generated versions can be used.
// Example methods for custom constructors:
staticFuncVarArgs(constructNewTestObj,_T("constructor"),_T("*")). // Using a global constructor: useful in cases where a custom constructor/destructor are required and the original class is not to be modified.
// staticFunc(constructNewTestObjFixedArgs,_T("constructor")). // Using a global constructor: useful in cases where a custom constructor/destructor are required and the original class is not to be modified.
// staticFuncVarArgs(NewTestObj::construct,_T("constructor")). // Using a static member constructor.
staticFunc(globalFunc,_T("globalFunc")). // Any global function can be registered in a class namespace (no 'this' pointer will be passed to the function).
staticFunc(globalClass,&GlobalClass::func,_T("globalClassFunc")).
func(&NewTestObj::newtestR1,_T("newtestR1")).
var(&NewTestObj::val,_T("val")).
var(&NewTestObj::s1,_T("s1")).
var(&NewTestObj::s2,_T("s2")).
var(&NewTestObj::c1,_T("c1"),VAR_ACCESS_READ_ONLY).
var(&NewTestObj::c2,_T("c2"),VAR_ACCESS_READ_ONLY).
funcVarArgs(&NewTestObj::multiArgs,_T("multiArgs"));
#define SQ_10 10
#define SQ_E 2.71828182845904523536f
#define SQ_PI 3.14159265358979323846264338327950288f
#define SQ_CONST_STRING _T("A constant string")
const int intConstant = 7;
const float floatConstant = 8.765f;
const bool boolConstant = true;
#if 1
SQClassDef<Vector3>(_T("Vector3")).
var(&Vector3::x,_T("x")).
var(&Vector3::y,_T("y")).
var(&Vector3::z,_T("z")).
func(&Vector3::Inc,_T("Inc")).
func(&Vector3::operator+,_T("_add")).
staticFunc(&Add2,_T("Add2")).
staticFuncVarArgs(&Add,_T("Add")).
#if 1
staticVar(&Vector3::staticVar,_T("staticVar")).
#else
staticVar(&Vector3::staticVar,_T("staticVar"),VAR_ACCESS_READ_ONLY).
#endif
staticVar(&globalVar,_T("globalVar")).
constant(SQ_10,_T("SQ_10")).
constant(SQ_E,_T("SQ_E")).
constant(SQ_PI,_T("SQ_PI")).
constant(SQ_CONST_STRING,_T("SQ_CONST_STRING")).
enumInt(SQ_ENUM_TEST,_T("SQ_ENUM_TEST")).
constant(intConstant,_T("intConstant")).
constant(floatConstant,_T("floatConstant")).
constant(true,_T("boolTrue")).
constant(false,_T("boolFalse")).
constant(boolConstant,_T("boolConstant"));
#endif
#endif
testSquirrelObjectSetGet(); // Uses Vector3().
BindConstant(SQ_PI*2,_T("SQ_PI_2"));
BindConstant(SQ_10*2,_T("SQ_10_2"));
BindConstant(_T("Global String"),_T("GLOBAL_STRING"));
SquirrelObject testStaticVars = SquirrelVM::CompileBuffer(_T(" local v = Vector3(); local v2 = Vector3(); local v3 = v+v2; v3 += v2; print(\"v3.x: \"+v3.x); print(\"Vector3::staticVar: \"+v.staticVar+\" Vector3::globalVar: \"+v.globalVar); v.staticVar = 0; "));
SquirrelVM::RunScript(testStaticVars);
SquirrelObject testConstants0 = SquirrelVM::CompileBuffer(_T(" print(\"SQ_PI*2: \"+SQ_PI_2+\" SQ_10_2: \"+SQ_10_2+\" GLOBAL_STRING: \"+GLOBAL_STRING); "));
SquirrelVM::RunScript(testConstants0);
SquirrelObject testConstants1 = SquirrelVM::CompileBuffer(_T("local v = Vector3(); print(\"SQ_10: \"+v.SQ_10+\" SQ_E: \"+v.SQ_E+\" SQ_PI: \"+v.SQ_PI+\" SQ_CONST_STRING: \"+v.SQ_CONST_STRING+\" SQ_ENUM_TEST: \"+v.SQ_ENUM_TEST);" ));
SquirrelVM::RunScript(testConstants1);
SquirrelObject testConstants2 = SquirrelVM::CompileBuffer(_T("local v = Vector3(); print(\"intConstant: \"+v.intConstant+\" floatConstant: \"+v.floatConstant+\" boolTrue: \"+(v.boolTrue?\"True\":\"False\")+\" boolFalse: \"+(v.boolFalse?\"True\":\"False\")+\" boolConstant: \"+(v.boolConstant?\"True\":\"False\"));" ));
SquirrelVM::RunScript(testConstants2);
SquirrelObject scriptedBase = SquirrelVM::CompileBuffer(_T(" class ScriptedBase { sbval = 5551212; function multiArgs(a,...) { print(\"SBase: \"+a+val); } \n } \n ")); // Note val does not exist in base.
SquirrelVM::RunScript(scriptedBase);
// === BEGIN Instance Test ===
SQClassDef<PlayerManager::Player>(_T("PlayerManager::Player")).
func(&PlayerManager::Player::printName,_T("printName")).
var(&PlayerManager::Player::name,_T("name"));
SQClassDef<PlayerManager>(_T("PlayerManager")).
func(&PlayerManager::GetPlayer,_T("GetPlayer")).
var(&PlayerManager::playerVar,_T("playerVar"));
RegisterGlobal(getPlayerManager,_T("getPlayerManager"));
BindVariable(&playerManager,_T("playerManagerVar"));
SquirrelObject testGetInstance = SquirrelVM::CompileBuffer(_T("\
local PlayerManager = getPlayerManager(); \n\
local oPlayer = PlayerManager.GetPlayer(0); \n\
print(typeof oPlayer); \n\
oPlayer.printName(); \n\
PlayerManager.playerVar.printName(); \n\
print(PlayerManager.playerVar.name); \n\
oPlayer = PlayerManager.playerVar; \n\
oPlayer.name = \"New_Name1\"; \n\
playerManagerVar.playerVar.printName(); \n\
oPlayer.name = \"New_Name2\"; \n\
"));
SquirrelVM::RunScript(testGetInstance);
scprintf(_T("playerManager.playerVar.name: %s\n"),playerManager.playerVar.name.s);
// === END Instance Test ===
// === BEGIN example from forum post ===
SQClassDef<Creature>(_T("Creature")).
func(&Creature::GetMaxHealth,_T("GetMaxHealth")).
func(&Creature::GetHealth,_T("GetHealth")).
func(&Creature::SetHealth,_T("SetHealth"));
SquirrelObject testClass = SquirrelVM::CompileBuffer( _T("function HealthPotionUse(Target) { \n\
local curHealth = Target.GetHealth(); \n\
local maxHealth = Target.GetMaxHealth(); \n\
if ((maxHealth - curHealth) > 15) { \n\
curHealth += 15; \n\
} else { \n\
curHealth = maxHealth; \n\
} \n\
Target.SetHealth(curHealth); \n\
print(typeof Target); \n\
return Target; \n\
}"));
Creature frodo;
frodo.SetHealth(frodo.GetMaxHealth()/2);
SquirrelVM::RunScript(testClass);
Creature newFrodo = SquirrelFunction<Creature &>(_T("HealthPotionUse"))(frodo); // Pass by value and return a copy (Must return by reference due to template system design).
SquirrelFunction<void>(_T("HealthPotionUse"))(&frodo); // Pass the address to directly modify frodo.
scprintf(_T("Frodo's health: %d %d\n"),frodo.GetHealth(),newFrodo.GetHealth());
// === END example from forum post ===
#ifdef SQ_USE_CLASS_INHERITANCE
// Base class constructors, if registered, must use this form: static int construct(HSQUIRRELVM v).
// SQClassDef<CustomTestObj> customClass(_T("CustomTestObj"));
SQClassDef<CustomTestObj> customClass(_T("CustomTestObj"),_T("ScriptedBase"));
// SQClassDef<CustomTestObj> customClass(_T("CustomTestObj"),_T("NewTestObj"));
customClass.staticFuncVarArgs(&CustomTestObj::construct,_T("constructor"),_T("*")); // MUST use this form (or no args) if CustomTestObj will be used as a base class.
// Using the "*" form will allow a single constructor to be used for all cases.
// customClass.staticFuncVarArgs(CustomTestObj::construct,_T("constructor")); // (this form is also OK if used as a base class)
customClass.funcVarArgs(&CustomTestObj::varArgTypesAndCount,_T("multiArgs"),_T("*")); // "*": no type or count checking.
customClass.funcVarArgs(&CustomTestObj::varArgTypesAndCount,_T("varArgTypesAndCount"),_T("*")); // "*": no type or count checking.
#else
SQClassDef<CustomTestObj> customClass(_T("CustomTestObj"));
customClass.staticFuncVarArgs(&CustomTestObj::construct,_T("constructor"),_T("snb")); // string, number, bool (all types must match).
customClass.funcVarArgs(&CustomTestObj::varArgTypesAndCount,_T("varArgTypesAndCount"),_T("*")); // "*": no type or count checking.
#endif
customClass.funcVarArgs(&CustomTestObj::varArgTypes,_T("varArgTypes"),_T("s|ns|ns|ns|n")); // string or number + string or number.
customClass.funcVarArgs(&CustomTestObj::noArgsVariableReturn,_T("noArgsVariableReturn")); // No type string means no arguments allowed.
customClass.func(&CustomTestObj::variableArgsFixedReturnType,_T("variableArgsFixedReturnType")); // Variables args, fixed return type.
customClass.func(&CustomTestObj::manyArgs,_T("manyArgs")); // Many args, type checked.
customClass.func(&CustomTestObj::manyArgsR1,_T("manyArgsR1")); // Many args, type checked, one return value.
#ifdef SQ_USE_CLASS_INHERITANCE
// SquirrelObject testInheritance = SquirrelVM::CompileBuffer(_T(" class Derived extends NewTestObj { s1 = 123; \n constructor() { NewTestObj.constructor(this); }; function getParentS2() return s2; \n }; \n local t = Derived(); \n print(\"DerS2: \"+t.getParentS2()); t.multiArgs(); //t.newtestR1(\"R1in\"); "));
// SquirrelObject testInheritance = SquirrelVM::CompileBuffer(_T(" local t = CustomTestObj(\"sa\",321,true); \n t.val = 444; print(t.val); t.variableArgsFixedReturnType(4,5.5); t.multiArgs(1,2,3); t.newtestR1(\"R1in\"); "));
// SquirrelObject testInheritance = SquirrelVM::CompileBuffer(_T(" class Derived extends CustomTestObj { val = 888; \n function func(a) print(a+dVal);\n } \n local x = Derived(); print(\"x.val \"+x.val); local t = CustomTestObj(\"sa\",321,true); \n t.val = 444; print(t.val); t.variableArgsFixedReturnType(4,5.5); t.multiArgs(1,2,3); t.newtestR1(\"R1in\"); "));
SquirrelObject testInheritance = SquirrelVM::CompileBuffer(_T(" class Derived extends CustomTestObj { val = 888; \n function multiArgs(a,...) { print(a+val); \n print(sbval); ::CustomTestObj.multiArgs(4); ::ScriptedBase.multiArgs(5,6,7); \n }\n } \n local x = Derived(); print(\"x.val \"+x.val); x.multiArgs(1,2,3); "));
// SquirrelObject testInheritance = SquirrelVM::CompileBuffer(_T(" class Derived extends CustomTestObj { val = 888; \n function multiArgs(a,...) print(a+val);\n } \n local x = Derived(); print(\"x.val \"+x.val); x.multiArgs(1,2,3); //local t = CustomTestObj(); \n t.val = 444; print(t.val); t.variableArgsFixedReturnType(4,5.5); t.multiArgs(1,2,3); t.newtestR1(\"R1in\"); "));
printf("=== BEGIN INHERITANCE ===\n");
testInhertianceCase();
SquirrelVM::RunScript(testInheritance);
printf("=== END INHERITANCE ===\n");
#endif
SquirrelObject testRegV = SquirrelVM::CompileBuffer(_T(" local vec = Vector3(); print(vec.x); vec = vec.Add(vec); print(vec.x); vec = vec.Add(vec); print(vec.x); vec = vec.Add2(vec,vec); print(vec.x); local v2 = Vector3(); vec = v2.Inc(vec); print(vec.x); print(v2.x); "));
SquirrelVM::RunScript(testRegV);
#ifdef SQ_USE_CLASS_INHERITANCE
SquirrelObject testReg0 = SquirrelVM::CompileBuffer(_T(" co <- CustomTestObj(\"hello\",123,true); co.varArgTypes(\"str\",123,123,\"str\"); co.varArgTypes(123,\"str\",\"str\",123); "));
SquirrelVM::RunScript(testReg0);
SquirrelObject testReg0a = SquirrelVM::CompileBuffer(_T(" print(co.varArgTypesAndCount(1,true)); print(co.varArgTypesAndCount(2,false,3.)); print(\"\\n\"); "));
SquirrelVM::RunScript(testReg0a);
SquirrelObject testReg0b = SquirrelVM::CompileBuffer(_T(" print(co.noArgsVariableReturn()); print(co.noArgsVariableReturn()); print(co.noArgsVariableReturn()); print(\"\\n\"); "));
SquirrelVM::RunScript(testReg0b);
SquirrelObject testReg0c = SquirrelVM::CompileBuffer(_T(" print(co.variableArgsFixedReturnType(1)); print(co.variableArgsFixedReturnType(1,2)); print(co.variableArgsFixedReturnType(1,2,3)); print(\"\\n\"); "));
SquirrelVM::RunScript(testReg0c);
SquirrelObject testReg0d = SquirrelVM::CompileBuffer(_T(" co.manyArgs(111,222.2,true,\"Hello\"); print(co.manyArgsR1(333,444.3,false,\"World\")); print(\"\\n\"); "));
SquirrelVM::RunScript(testReg0d);
SquirrelObject testReg1a = SquirrelVM::CompileBuffer(_T(" co <- CustomTestObj(\"hello\",123,true); co.noArgsVariableReturn(); local t = NewTestObj(\"S1in\",369,true); print(\"C1: \"+t.c1); print(\"C2: \"+t.c2); // t.c1 = 123; "));
SquirrelVM::RunScript(testReg1a);
// Constant test (read only var). Var can change on C++ side, but not on script side.
try {
SquirrelObject testRegConstant = SquirrelVM::CompileBuffer(_T(" local t = NewTestObj(); t.c1 = 123; "));
SquirrelVM::RunScript(testRegConstant);
} // try
catch (SquirrelError & e) {
scprintf(_T("Error: %s, %s\n"),e.desc,_T("Squirrel::TestConstant"));
} // catch
SquirrelObject testReg1 = SquirrelVM::CompileBuffer(_T(" local t = NewTestObj(); t.newtestR1(\"Hello\"); t.val = 789; print(t.val); print(t.s1); print(t.s2); t.s1 = \"New S1\"; print(t.s1); "));
SquirrelVM::RunScript(testReg1);
SquirrelObject testReg2 = SquirrelVM::CompileBuffer(_T(" local t = NewTestObj(); t.val = 789; print(t.val); t.val = 876; print(t.val); t.multiArgs(1,2,3); t.multiArgs(1,2,3,4); t.globalFunc(\"Hola\",5150,false); t.globalClassFunc(\"Bueno\",5151,true); "));
SquirrelVM::RunScript(testReg2);
SquirrelObject testReg3 = SquirrelVM::CompileBuffer(_T(" test(); local rv = testR1(\"Hello\"); print(rv); "));
SquirrelVM::RunScript(testReg3);
SquirrelObject testReg4 = SquirrelVM::CompileBuffer(_T(" print(\"\\nMembers:\"); testObj_newtest1(); testObj_newtest2(); print(testObj_newtestR1(\"Hello Again\")); "));
SquirrelVM::RunScript(testReg4);
SquirrelObject defCallFunc = SquirrelVM::CompileBuffer(_T(" function callMe(var) { print(\"I was called by: \"+var); return 123; }"));
SquirrelVM::RunScript(defCallFunc);
SquirrelObject defCallFuncStrRet = SquirrelVM::CompileBuffer(_T(" function callMeStrRet(var) { print(\"I was called by: \"+var); return var; }"));
SquirrelVM::RunScript(defCallFuncStrRet);
SquirrelFunction<void>(_T("callMe"))(_T("Squirrel 1"));
// Get a function from the root table and call it.
#if 1
SquirrelFunction<int> callFunc(_T("callMe"));
int ival = callFunc(_T("Squirrel"));
scprintf(_T("IVal: %d\n"),ival);
SquirrelFunction<const SQChar *> callFuncStrRet(_T("callMeStrRet"));
const SQChar * sval = callFuncStrRet(_T("Squirrel StrRet"));
scprintf(_T("SVal: %s\n"),sval);
#endif
ival = 0;
// Get a function from any table.
SquirrelFunction<int> callFunc2(root.GetObjectHandle(),_T("callMe"));
ival = callFunc(456); // Argument count is checked; type is not.
// === END Class Instance tests ===
SquirrelObject main = SquirrelVM::CompileBuffer(_T("table1 <- {key1=\"keyVal\",key2 = 123};\n if (\"key1\" in table1)\n print(\"Sq: Found it\");\n else\n print(\"Sq: Not found\");"));
SquirrelVM::RunScript(main);
SquirrelObject table1 = root.GetValue(_T("table1"));
if (table1.Exists(_T("key1"))) {
scprintf(_T("C++: Found it.\n"));
} else {
scprintf(_T("C++: Did not find it.\n"));
} // if
// === BEGIN Simple variable binding tests ===
int iVar = 777;
float fVar = 88.99f;
bool bVar = true;
BindVariable(root,&iVar,_T("iVar"));
BindVariable(root,&fVar,_T("fVar"));
BindVariable(root,&bVar,_T("bVar"));
static ScriptStringVar128 testString;
scsprintf(testString,_T("This is a test string"));
BindVariable(root,&testString,_T("testString"));
// === END Simple variable binding tests ===
// === BEGIN Array Tests ===
SquirrelObject array = SquirrelVM::CreateArray(10);
int i;
for (i = 0; i < 10; i++) array.SetValue(i,i);
array.ArrayAppend(123); // int
array.ArrayAppend(true); // bool (must use bool and not SQBool (SQBool is treated as INT by compiler).
array.ArrayAppend(false); // bool (must use bool and not SQBool (SQBool is treated as INT by compiler).
array.ArrayAppend(123.456f); // float
array.ArrayAppend(_T("string")); // string
array.ArrayAppend(456); // Will be popped and thrown away (below).
array.ArrayAppend((SQUserPointer)0);
// Pop 3 items from array:
array.ArrayPop(SQFalse); // Don't retrieve the popped value (int:123).
SquirrelObject so1 = array.ArrayPop(); // Retrieve the popped value.
const SQChar * val1 = so1.ToString(); // Get string.
float val2 = array.ArrayPop().ToFloat(); // Pop and get float.
scprintf(_T("[Popped values] Val1: %s, Val2: %f\n"),val1,val2);
int startIndex = array.Len();
array.ArrayExtend(10); // Implemented as: ArrayResize(Len()+amount).
for (i = startIndex; i < array.Len(); i++) array.SetValue(i,i*10);
root.SetValue(_T("array"),array);
SquirrelObject arrayr = array.Clone(); // Get a copy as opposed to another reference.
arrayr.ArrayReverse();
root.SetValue(_T("arrayr"),arrayr);
// === END Array Tests ===
SquirrelObject define_printArray = SquirrelVM::CompileBuffer(_T(" function printArray(name,array) { print(name+\".len() = \"+array.len()); foreach(i, v in array) if (v != null) { if (typeof v == \"bool\") v = v ? \"true\" : \"false\"; print(\"[\"+i+\"]: \"+v); } } "));
SquirrelVM::RunScript(define_printArray);
SquirrelObject test = SquirrelVM::CompileBuffer(_T(" printArray(\"array\",array); printArray(\"arrayr\",arrayr); "));
SquirrelVM::RunScript(test);
#endif
} // try
catch (SquirrelError & e) {
scprintf(_T("Error: %s, in %s\n"),e.desc,_T("TestSqPlus"));
} // catch
}
~TestSqPlus() {
SquirrelVM::Shutdown();
}
};
void doTest(void) {
TestSqPlus testSqPlus;
} // doTest
int main(int argc,char * argv[]) {
// Run twice to make sure cleanup/shutdown works OK.
SCPUTS(_T("Start Pass 1\n"));
doTest();
#if 0
SCPUTS(_T("Start Pass 2\n"));
doTest();
#endif
SCPUTS(_T("Done.\n"));
scprintf(_T("Press RETURN to exit."));
getchar();
return 0;
}