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