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

  1. // testSqPlus2.cpp
  2. // Created by John Schultz 9/21/2005
  3. // Free for any use.
  4. // Step through the code with a debugger (setting breakpoints in functions)
  5. // to get an idea how everything works.
  6. #include <stdarg.h>
  7. #include <stdio.h>
  8. #if 0
  9. #include <string>
  10. //#define SQPLUS_SUPPORT_STD_STRING
  11. #define SQPLUS_SUPPORT_SQ_STD_STRING
  12. #endif
  13. //#define SQPLUS_CONST_OPT
  14. #include "sqplus.h"
  15. using namespace SqPlus;
  16. void scprintfunc(HSQUIRRELVM v,const SQChar *s,...) {
  17. static SQChar temp[2048];
  18. va_list vl;
  19. va_start(vl,s);
  20. scvsprintf( temp,s,vl);
  21. SCPUTS(temp);
  22. va_end(vl);
  23. }
  24. void newtest(void) {
  25. scprintf(_T("NewTest\n"));
  26. }
  27. SQChar * newtestR1(const SQChar * inString) {
  28. scprintf(_T("NewTestR1: %s\n"),inString);
  29. return _T("Returned String");
  30. }
  31. struct Vector3 {
  32. static float staticVar;
  33. float x,y,z;
  34. Vector3() {
  35. x = 1.f;
  36. y = 2.f;
  37. z = 3.f;
  38. }
  39. Vector3(float _x,float _y,float _z) : x(_x), y(_y), z(_z) {}
  40. ~Vector3() {
  41. scprintf(_T("~Vector()\n"));
  42. }
  43. Vector3 Inc(Vector3 & v) {
  44. x += v.x;
  45. y += v.y;
  46. z += v.z;
  47. return *this;
  48. } // Inc
  49. Vector3 operator+(Vector3 & v) {
  50. return Vector3(x+v.x,y+v.y,z+v.z);
  51. }
  52. };
  53. float Vector3::staticVar = 898.434f;
  54. #if 0 // It may be possible to make this method work in the future. If so, the DECLARE_INSTANCE_FUNCS() macro
  55. // would not be needed. The issue is duplicate compiler matching for const SQChar * and Push():
  56. // Push(const SQChar * &) and Push(const SQChar *) both match.
  57. // The typeid() compiler function may not be portable to other compilers.
  58. #include <typeinfo.h>
  59. template<typename TYPE>
  60. inline const SQChar * GetTypeName(const TYPE & n) { return typeid(TYPE).name(); }
  61. template<typename TYPE>
  62. inline void Push(HSQUIRRELVM v,const TYPE & value) { CreateCopyInstance(GetTypeName(value),value); }
  63. template<typename TYPE>
  64. inline bool Match(TypeWrapper<TYPE &>,HSQUIRRELVM v,int idx) { return GetInstance<TYPE>(v,idx) != NULL; }
  65. template<typename TYPE>
  66. inline TYPE & Get(TypeWrapper<TYPE &>,HSQUIRRELVM v,int idx) { return *GetInstance<TYPE>(v,idx); }
  67. #endif
  68. DECLARE_INSTANCE_TYPE(Vector3)
  69. Vector3 Add2(Vector3 & a,Vector3 & b) {
  70. Vector3 c;
  71. c.x = a.x + b.x;
  72. c.y = a.y + b.y;
  73. c.z = a.z + b.z;
  74. return c;
  75. } // Add2
  76. int Add(HSQUIRRELVM v) {
  77. // StackHandler sa(v);
  78. Vector3 * self = GetInstance<Vector3,true>(v,1);
  79. Vector3 * arg = GetInstance<Vector3,true>(v,2);
  80. // SquirrelObject so = sa.GetObjectHandle(1);
  81. #if 0
  82. SQUserPointer type=0;
  83. so.GetTypeTag(&type);
  84. SQUserPointer reqType = ClassType<Vector3>::type();
  85. if (type != reqType) {
  86. throw SquirrelError(_T("Invalid class type"));
  87. } // if
  88. #endif
  89. // Vector3 * self = (Vector3 *)so.GetInstanceUP(ClassType<Vector3>::type());
  90. // if (!self) throw SquirrelError(_T("Invalid class type"));
  91. Vector3 tv;
  92. tv.x = arg->x + self->x;
  93. tv.y = arg->y + self->y;
  94. tv.z = arg->z + self->z;
  95. return ReturnCopy(v,tv);
  96. }
  97. struct NewTestObj {
  98. ScriptStringVar64 s1;
  99. ScriptStringVar32 s2;
  100. bool b;
  101. int val;
  102. int c1;
  103. ScriptStringVar8 c2; // 8 char plus null (max string is 8 printable chars).
  104. NewTestObj() : val(777) {
  105. s1 = _T("s1=s1");
  106. s2 = _T("s2=s2");
  107. c1 = 996;
  108. c2 = _T("It's a 997"); // Prints: "It's a 9", as only 8 chars in static buffer (plus null).
  109. }
  110. NewTestObj(const SQChar * _s1,int _val,bool _b) {
  111. s1 = _s1;
  112. val = _val;
  113. b = _b;
  114. s2 = _T("s2=s2");
  115. c1 = 993;
  116. c2 = _T("It's a 998"); // Prints: "It's a 9", as only 8 chars in static buffer (plus null).
  117. }
  118. static int construct(HSQUIRRELVM v) {
  119. // StackHandler sa(v);
  120. // SquirrelObject so = sa.GetObjectHandle(1);
  121. return PostConstruct<NewTestObj>(v,new NewTestObj(),release);
  122. } // construct
  123. SQ_DECLARE_RELEASE(NewTestObj) // Required when using a custom constructor.
  124. void newtest(void) {
  125. scprintf(_T("NewTest: %d\n"),val);
  126. }
  127. SQChar * newtestR1(const SQChar * inString) {
  128. scprintf(_T("NewTestR1: Member var val is %d, function arg is %s\n"),val,inString);
  129. return _T("Returned String");
  130. }
  131. int multiArgs(HSQUIRRELVM v) {
  132. StackHandler sa(v);
  133. SquirrelObject so = sa.GetObjectHandle(1);
  134. int paramCount = sa.GetParamCount();
  135. int p1 = sa.GetInt(2);
  136. int p2 = sa.GetInt(3);
  137. int p3 = sa.GetInt(4);
  138. return 0;
  139. } // multiArgs
  140. int _set(HSQUIRRELVM v) {
  141. StackHandler sa(v);
  142. int paramCount = sa.GetParamCount();
  143. const SQChar * el = sa.GetString(2);
  144. val = sa.GetInt(3);
  145. return sa.Return(val);
  146. }
  147. int _get(HSQUIRRELVM v) {
  148. StackHandler sa(v);
  149. int paramCount = sa.GetParamCount();
  150. return sa.Return(val);
  151. }
  152. };
  153. // Using global functions to construct and release classes.
  154. int releaseNewTestObj(SQUserPointer up,SQInteger size) {
  155. SQ_DELETE_CLASS(NewTestObj);
  156. } // releaseNewTestObj
  157. int constructNewTestObj(HSQUIRRELVM v) {
  158. StackHandler sa(v);
  159. int paramCount = sa.GetParamCount();
  160. if (paramCount == 1) {
  161. return PostConstruct<NewTestObj>(v,new NewTestObj(),releaseNewTestObj);
  162. } else if (paramCount == 4) {
  163. return PostConstruct<NewTestObj>(v,new NewTestObj(sa.GetString(2),sa.GetInt(3),sa.GetBool(4)?true:false),releaseNewTestObj);
  164. } // if
  165. return sq_throwerror(v,_T("Invalid Constructor arguments"));
  166. } // constructNewTestObj
  167. // 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).
  168. // SquirrelVM::GetVMPtr() could also be used with PostConstruct(): no HSQUIRRELVM argument would be required.
  169. int constructNewTestObjFixedArgs(const SQChar * s,int val,bool b,HSQUIRRELVM v) {
  170. StackHandler sa(v);
  171. int paramCount = sa.GetParamCount();
  172. return PostConstruct<NewTestObj>(v,new NewTestObj(s,val,b),releaseNewTestObj);
  173. } // constructNewTestObj
  174. // Will be registered in a class namespace.
  175. void globalFunc(const SQChar * s,int val) {
  176. scprintf(_T("globalFunc: s: %s val: %d\n"),s,val);
  177. } // globalFunc
  178. class GlobalClass {
  179. public:
  180. void func(const SQChar * s,int val) {
  181. scprintf(_T("globalClassFunc: s: %s val: %d\n"),s,val);
  182. } // func
  183. } globalClass;
  184. struct CustomTestObj {
  185. ScriptStringVar128 name;
  186. int val;
  187. bool state;
  188. CustomTestObj() : val(0), state(false) { name = _T("empty"); }
  189. CustomTestObj(const SQChar * _name,int _val,bool _state) : val(_val), state(_state) {
  190. name = _name;
  191. }
  192. // Custom variable argument constructor
  193. static int construct(HSQUIRRELVM v) {
  194. StackHandler sa(v);
  195. int paramCount = sa.GetParamCount();
  196. if (paramCount == 1) {
  197. return PostConstruct<CustomTestObj>(v,new CustomTestObj(),release);
  198. } if (paramCount == 4) {
  199. return PostConstruct<CustomTestObj>(v,new CustomTestObj(sa.GetString(2),sa.GetInt(3),sa.GetBool(4)?true:false),release);
  200. } // if
  201. return sq_throwerror(v,_T("Invalid Constructor arguments"));
  202. } // construct
  203. SQ_DECLARE_RELEASE(CustomTestObj) // Required when using a custom constructor.
  204. // Member function that handles variable types.
  205. int varArgTypes(HSQUIRRELVM v) {
  206. StackHandler sa(v);
  207. int paramCount = sa.GetParamCount();
  208. if (sa.GetType(2) == OT_INTEGER) {
  209. val = sa.GetInt(2);
  210. } // if
  211. if (sa.GetType(2) == OT_STRING) {
  212. name = sa.GetString(2);
  213. } // if
  214. if (sa.GetType(3) == OT_INTEGER) {
  215. val = sa.GetInt(3);
  216. } // if
  217. if (sa.GetType(3) == OT_STRING) {
  218. name = sa.GetString(3);
  219. } // if
  220. // return sa.ThrowError(_T("varArgTypes() error"));
  221. return 0;
  222. } // varArgTypes
  223. // Member function that handles variable types and has variable return types+count.
  224. int varArgTypesAndCount(HSQUIRRELVM v) {
  225. StackHandler sa(v);
  226. int paramCount = sa.GetParamCount();
  227. SQObjectType type1 = (SQObjectType)sa.GetType(1); // Always OT_INSTANCE
  228. SQObjectType type2 = (SQObjectType)sa.GetType(2);
  229. SQObjectType type3 = (SQObjectType)sa.GetType(3);
  230. SQObjectType type4 = (SQObjectType)sa.GetType(4);
  231. int returnCount = 0;
  232. if (paramCount == 3) {
  233. sq_pushinteger(v,val);
  234. returnCount = 1;
  235. } else if (paramCount == 4) {
  236. sq_pushinteger(v,val);
  237. sq_pushstring(v,name,-1);
  238. returnCount = 2;
  239. } // if
  240. return returnCount;
  241. } //
  242. int noArgsVariableReturn(HSQUIRRELVM v) {
  243. if (val == 123) {
  244. val++;
  245. return 0; // This will print (null).
  246. } else if (val == 124) {
  247. sq_pushinteger(v,val); // Will return int:124.
  248. val++;
  249. return 1;
  250. } else if (val == 125) {
  251. sq_pushinteger(v,val);
  252. name = _T("Case 125");
  253. sq_pushstring(v,name,-1);
  254. val = 123; // reset
  255. return 2;
  256. } // if
  257. return 0;
  258. } // noArgsVariableReturn
  259. // Registered with func() instead of funcVarArgs(): fixed (single) return type.
  260. const SQChar * variableArgsFixedReturnType(HSQUIRRELVM v) {
  261. StackHandler sa(v);
  262. int paramCount = sa.GetParamCount();
  263. SQObjectType type1 = (SQObjectType)sa.GetType(1); // Always OT_INSTANCE
  264. SQObjectType type2 = (SQObjectType)sa.GetType(2);
  265. SQObjectType type3 = (SQObjectType)sa.GetType(3);
  266. if (paramCount == 1) {
  267. return _T("No Args");
  268. } else if (paramCount == 2) {
  269. return _T("One Arg");
  270. } else if (paramCount == 3) {
  271. return _T("Two Args");
  272. } // if
  273. return _T("More than two args");
  274. } // variableArgsFixedReturnType
  275. void manyArgs(int i,float f,bool b,const SQChar * s) {
  276. scprintf(_T("i: %d, f: %f, b: %s, s: %s\n"),i,f,b?_T("true"):_T("false"),s);
  277. } // manyArgs
  278. float manyArgsR1(int i,float f,bool b,const SQChar * s) {
  279. manyArgs(i,f,b,s);
  280. return i+f;
  281. } // manyArgsR1
  282. };
  283. // === Standard (non member) function ===
  284. int testFunc(HSQUIRRELVM v) {
  285. StackHandler sa(v);
  286. int paramCount = sa.GetParamCount();
  287. scprintf(_T("testFunc: numParams[%d]\n"),paramCount);
  288. for (int i=1; i <= paramCount; i++) {
  289. scprintf(_T("param[%d]: "),i);
  290. switch(sa.GetType(i)) {
  291. case OT_TABLE: scprintf(_T("OT_TABLE[0x%x]\n"),sa.GetObjectHandle(i)); break;
  292. case OT_INTEGER: scprintf(_T("OT_INTEGER[%d]\n"),sa.GetInt(i)); break;
  293. case OT_FLOAT: scprintf(_T("OT_FLOAT[%f]\n"),sa.GetFloat(i)); break;
  294. case OT_STRING: scprintf(_T("OT_STRING[%s]\n"),sa.GetString(i)); break;
  295. default:
  296. scprintf(_T("TYPEID[%d]\n"),sa.GetType(i));
  297. } // switch
  298. } // for
  299. return SQ_OK;
  300. } // testFunc
  301. int globalVar = 5551234;
  302. class Creature {
  303. int health;
  304. public:
  305. enum {MaxHealth=100};
  306. Creature() : health(MaxHealth) {}
  307. int GetMaxHealth(void) {
  308. return MaxHealth;
  309. }
  310. int GetHealth(void) {
  311. return health;
  312. }
  313. void SetHealth(int newHealth) {
  314. health = newHealth;
  315. }
  316. };
  317. DECLARE_INSTANCE_TYPE(Creature)
  318. // === BEGIN Class Instance Test ===
  319. class PlayerManager {
  320. public:
  321. struct Player {
  322. ScriptStringVar64 name;
  323. void printName(void) {
  324. scprintf(_T("Player.name = %s\n"),name.s);
  325. }
  326. };
  327. Player playerVar; // Will be accessed directly.
  328. Player players[2];
  329. Player * GetPlayer(int player) { // Must return pointer: a returned reference will behave the same as return by value.
  330. return &players[player];
  331. }
  332. PlayerManager() {
  333. players[0].name = _T("Player1");
  334. players[1].name = _T("Player2");
  335. playerVar.name = _T("PlayerVar");
  336. }
  337. } playerManager;
  338. DECLARE_INSTANCE_TYPE(PlayerManager)
  339. DECLARE_INSTANCE_TYPE(PlayerManager::Player)
  340. PlayerManager * getPlayerManager(void) { // Must return pointer: a returned reference will behave the same as return by value.
  341. return &playerManager;
  342. }
  343. // Example from forum post question:
  344. class STestScripts {}; // Proxy class
  345. class TestScripts {
  346. public:
  347. int Var_ToBind1,Var_ToBind2;
  348. void InitScript1(void) {
  349. Var_ToBind1 = 808;
  350. RegisterGlobal(*this,&TestScripts::Test1,_T("Test1"));
  351. RegisterGlobal(*this,&TestScripts::Test2,_T("Test2"));
  352. BindVariable(&Var_ToBind1,_T("Var_ToBind1"));
  353. } // InitScript1
  354. void InitScript2(void) {
  355. Var_ToBind2 = 909;
  356. SQClassDef<STestScripts>(_T("STestScripts")).
  357. staticFunc(*this,&TestScripts::Test1,_T("Test1")).
  358. staticFunc(*this,&TestScripts::Test2,_T("Test2")).
  359. staticVar(&Var_ToBind2,_T("Var_ToBind2"));
  360. } // InitScript2
  361. void Test1(void) {
  362. scprintf(_T("Test1 called.\n"));
  363. }
  364. void Test2(void) {
  365. scprintf(_T("Test2 called.\n"));
  366. }
  367. } testScripts;
  368. // From forum questions
  369. #if 1
  370. template<typename T>
  371. struct Point {
  372. Point() {}
  373. Point(T X, T Y) : X(X), Y(Y) {}
  374. T X, Y;
  375. };
  376. template<typename T>
  377. struct Box {
  378. Box() {}
  379. Box(Point<T> UpperLeft, Point<T> LowerRight) : UpperLeft(UpperLeft), LowerRight(LowerRight) {}
  380. Point<T> UpperLeft, LowerRight;
  381. void print(void) {
  382. scprintf(_T("UL.X %f UL.Y %f LR.X %f LR.Y %f\n"),UpperLeft.X,UpperLeft.Y,LowerRight.X,LowerRight.Y);
  383. }
  384. };
  385. template<typename T>
  386. struct Window {
  387. int id;
  388. Box<T> box;
  389. };
  390. typedef Point<float> Pointf;
  391. typedef Box<float> Boxf;
  392. typedef Window<float> Windowf;
  393. #else
  394. struct Pointf {
  395. float X,Y;
  396. Pointf() {}
  397. Pointf(float _X, float _Y) : X(_X), Y(_Y) {}
  398. };
  399. struct Boxf {
  400. Pointf UpperLeft,LowerRight;
  401. Boxf() {}
  402. Boxf(Pointf _UpperLeft,Pointf _LowerRight) : UpperLeft(_UpperLeft), LowerRight(_LowerRight) {}
  403. void print(void) {
  404. scprintf(_T("UL.X %f UL.Y %f LR.X %f LR.Y %f\n"),UpperLeft.X,UpperLeft.Y,LowerRight.X,LowerRight.Y);
  405. }
  406. };
  407. struct Windowf {
  408. int id;
  409. Boxf box;
  410. };
  411. #endif
  412. DECLARE_INSTANCE_TYPE(Pointf)
  413. DECLARE_INSTANCE_TYPE(Boxf)
  414. DECLARE_INSTANCE_TYPE(Windowf)
  415. int constructPointf(float X,float Y,HSQUIRRELVM v) {
  416. return PostConstruct<Pointf>(v,new Pointf(X,Y),ReleaseClassPtr<Pointf>::release);
  417. } // constructPointf
  418. // Must pass by reference or pointer (not copy)
  419. int constructBoxf(Pointf & UpperLeft,Pointf & LowerRight,HSQUIRRELVM v) {
  420. return PostConstruct<Boxf>(v,new Boxf(UpperLeft,LowerRight),ReleaseClassPtr<Boxf>::release);
  421. } // constructBoxf
  422. struct WindowHolder {
  423. static Windowf * currentWindow;
  424. static Windowf * getWindow(void) {
  425. return currentWindow;
  426. } // getWindow
  427. };
  428. Windowf * WindowHolder::currentWindow = 0;
  429. // From forum post: compiler works OK.
  430. void testCompiler(void) {
  431. SquirrelObject test = SquirrelVM::CompileBuffer(_T("\
  432. local SceneManager = getSceneManager() ; \n\
  433. \n\
  434. SceneManager.AddScene(\"Scene1\") ; \n\
  435. SceneManager.AddScene(\"Scene4\") ; \n\
  436. SceneManager.ActivateScene(\"Scene1\") ; \n\
  437. "));
  438. SquirrelVM::RunScript(test);
  439. }
  440. void testPointfBoxf(void) {
  441. // testCompiler();
  442. SQClassDef<Pointf>(_T("Pointf")).
  443. staticFunc(constructPointf,_T("constructor")).
  444. var(&Pointf::X,_T("X")).
  445. var(&Pointf::Y,_T("Y"));
  446. SQClassDef<Boxf>(_T("Boxf")).
  447. staticFunc(constructBoxf,_T("constructor")).
  448. func(&Boxf::print,_T("print")).
  449. var(&Boxf::UpperLeft,_T("UpperLeft")).
  450. var(&Boxf::LowerRight,_T("LowerRight"));
  451. SQClassDef<Windowf>(_T("Windowf")).
  452. var(&Windowf::id,_T("Id")).
  453. var(&Windowf::box,_T("Box"));
  454. RegisterGlobal(WindowHolder::getWindow,_T("getWindow"));
  455. Windowf myWindow;
  456. myWindow.id = 42;
  457. myWindow.box = Boxf(Pointf(1.f,2.f),Pointf(3.f,4.f));
  458. WindowHolder::currentWindow = &myWindow;
  459. // The createWindow() function below creates a new instance on the root table.
  460. // The instance data is a pointer to the C/C++ instance, and will not be freed
  461. // or otherwise managed.
  462. SquirrelObject test = SquirrelVM::CompileBuffer(_T("\
  463. local MyWindow = Windowf(); \n\
  464. MyWindow.Box = Boxf(Pointf(11.,22.),Pointf(33.,44.)); \n\
  465. print(MyWindow.Box.LowerRight.Y); \n\
  466. MyWindow.Box.LowerRight.Y += 1.; \n\
  467. local MyWindow2 = Windowf(); \n\
  468. MyWindow2 = MyWindow; \n\
  469. print(MyWindow2.Box.LowerRight.Y); \n\
  470. local MyBox = Boxf(Pointf(10.,20.),Pointf(30.,40.)); \n\
  471. MyBox.UpperLeft = Pointf(1000.,1000.); \n\
  472. MyBox.UpperLeft.X = 5000. \n\
  473. print(MyBox.UpperLeft.X) \n\
  474. print(MyBox.UpperLeft.Y) \n\
  475. MyWindow2.Box = MyBox; \n\
  476. MyWindow2.Box.print(); \n\
  477. MyWindow2 = getWindow(); \n\
  478. print(\"MyWindow2: \"+MyWindow2.Id); \n\
  479. MyWindow2.Box.print(); \n\
  480. function createWindow(name,instance) { \n\
  481. ::rawset(name,instance); \n\
  482. } \n\
  483. "));
  484. SquirrelVM::RunScript(test);
  485. Windowf window = myWindow;
  486. window.id = 54;
  487. window.box.UpperLeft.X += 1;
  488. window.box.UpperLeft.Y += 1;
  489. window.box.LowerRight.X += 1;
  490. window.box.LowerRight.Y += 1;
  491. // Create a new Window instance "NewWindow" on the root table.
  492. SquirrelFunction<void>(_T("createWindow"))(_T("NewWindow"),&window);
  493. SquirrelObject test2 = SquirrelVM::CompileBuffer(_T("\
  494. print(\"NewWindow: \"+NewWindow.Id); \n\
  495. NewWindow.Box.print(); \n\
  496. "));
  497. SquirrelVM::RunScript(test2);
  498. } // testPointfBoxf
  499. // Example debug hook: called back during script execution.
  500. SQInteger debug_hook(HSQUIRRELVM v) {
  501. SQUserPointer up;
  502. int event_type,line;
  503. const SQChar *src,*func;
  504. sq_getinteger(v,2,&event_type);
  505. sq_getstring(v,3,&src);
  506. sq_getinteger(v,4,&line);
  507. sq_getstring(v,5,&func);
  508. sq_getuserpointer(v,-1,&up);
  509. return 0;
  510. } // debug_hook
  511. // You can add functions/vars here, as well as bind globals to be accessed through this class as shown in the NameSpace example.
  512. // If the class is instantiated in script, the instance is "locked", preventing accidental changes to elements.
  513. // Thus using an instance as the namespace can be a better design for development.
  514. // If variables/constants are bound to the class and/or non-static/non-global functions, the class must be instantiated before use.
  515. struct NamespaceClass {
  516. };
  517. // === END Class Instance Test ===
  518. class TestBase {
  519. public:
  520. int x;
  521. TestBase() : x(0) {
  522. printf("Constructing TestBase[0x%x]\n",(size_t)this);
  523. }
  524. void print(void) {
  525. printf("TestBase[0x%x], x[%d]\n",(size_t)this,x);
  526. }
  527. };
  528. DECLARE_INSTANCE_TYPE(TestBase)
  529. class TestDerivedCPP : public TestBase {
  530. public:
  531. int y;
  532. TestDerivedCPP() {
  533. x = 121;
  534. }
  535. };
  536. typedef void (TestDerivedCPP::*TestDerivedCPP_print)(void);
  537. void testInhertianceCase(void) {
  538. SQClassDef<TestBase>(_T("TestBase")).
  539. var(&TestBase::x,_T("x")).
  540. func(&TestBase::print,_T("print"));
  541. SQClassDef<TestDerivedCPP>(_T("TestDerivedCPP")).
  542. func((TestDerivedCPP_print)&TestDerivedCPP::print,_T("print"));
  543. // Note that the constructor definition and call below is not required for this example.
  544. // (The C/C++ constructor will be called automatically).
  545. SquirrelObject testInheritance2 = SquirrelVM::CompileBuffer(_T("\
  546. class TestDerived extends TestBase { \n\
  547. function print() { \n\
  548. ::TestBase.print(); \n\
  549. ::print(\"Derived: \"+x); \n\
  550. } \n\
  551. constructor() { \n\
  552. TestBase.constructor(); \n\
  553. } \n\
  554. } \n\
  555. local a = TestDerived(); \n\
  556. local b = TestDerived(); \n\
  557. a.x = 1; \n\
  558. b.x = 2; \n\
  559. print(\"a.x = \"+a.x); \n\
  560. print(\"b.x = \"+b.x); \n\
  561. a.print(); \n\
  562. b.print(); \n\
  563. local c = TestDerivedCPP(); \n\
  564. c.print(); \n\
  565. "));
  566. SquirrelVM::RunScript(testInheritance2);
  567. }
  568. // === BEGIN from a forum post by jkleinecke. 8/23/06 jcs ===
  569. namespace Scripting {
  570. class ScriptEntity {
  571. public:
  572. ScriptEntity() {
  573. Bind();
  574. }
  575. static void Bind() {
  576. SqPlus::SQClassDef<ScriptEntity>(_T("ScriptEntity")).
  577. var(&ScriptEntity::m_strName,_T("name"));
  578. } // Bind
  579. SqPlus::ScriptStringVar64 m_strName;
  580. };
  581. }
  582. DECLARE_INSTANCE_TYPE_NAME(Scripting::ScriptEntity,ScriptEntity)
  583. void testScriptingTypeName(void) {
  584. try {
  585. Scripting::ScriptEntity entity ;
  586. SqPlus::BindVariable(&entity,_T("instance"));
  587. SquirrelObject sqObj = SquirrelVM::CompileBuffer(_T("instance.name = \"Testing an instance variable bind: member assignment.\"; print(instance.name);"));
  588. SquirrelVM::RunScript(sqObj);
  589. } // try
  590. catch (SquirrelError e) {
  591. scprintf(_T("testScriptingTypeName: %s\n"),e.desc);
  592. } // catch
  593. }
  594. // === END from a forum post by jkleinecke. 8/23/06 jcs ===
  595. // === BEGIN Interface Test ===
  596. class PureInterface {
  597. public:
  598. virtual void pureFunc1(void)=0;
  599. virtual void pureFunc2(void)=0;
  600. };
  601. class MyImp : public PureInterface {
  602. public:
  603. PureInterface * getInterface(void) { return (PureInterface *)this; }
  604. void pureFunc1(void) {
  605. scprintf(_T("PureFunc1 called [0x%p].\n"),this);
  606. }
  607. void pureFunc2(void) {
  608. scprintf(_T("PureFunc2 called [0x%p].\n"),this);
  609. }
  610. };
  611. class InterfaceHolder {
  612. public:
  613. PureInterface * theInterface;
  614. void setInterface(PureInterface * pureInterface) {
  615. theInterface = pureInterface;
  616. }
  617. PureInterface * getInterface(void) {
  618. return theInterface;
  619. }
  620. };
  621. DECLARE_INSTANCE_TYPE(PureInterface)
  622. DECLARE_INSTANCE_TYPE(MyImp)
  623. DECLARE_INSTANCE_TYPE(InterfaceHolder)
  624. void testPureVirtualInterface(void) {
  625. SQClassDefNoConstructor<PureInterface>(_T("PureInterface")).
  626. func(&PureInterface::pureFunc1,_T("pureFunc1")).
  627. func(&PureInterface::pureFunc2,_T("pureFunc2"));
  628. SQClassDef<InterfaceHolder>(_T("InterfaceHolder")).
  629. func(&InterfaceHolder::setInterface,_T("setInterface")).
  630. func(&InterfaceHolder::getInterface,_T("getInterface"));
  631. SQClassDef<MyImp>(_T("MyImp")).
  632. func(&MyImp::getInterface,_T("getInterface"));
  633. MyImp myImp;
  634. SquirrelObject test = SquirrelVM::CompileBuffer(_T("ih <- InterfaceHolder();"));
  635. SquirrelVM::RunScript(test);
  636. SquirrelObject root = SquirrelVM::GetRootTable();
  637. SquirrelObject ih = root.GetValue(_T("ih"));
  638. InterfaceHolder * ihp = (InterfaceHolder * )ih.GetInstanceUP(ClassType<InterfaceHolder>::type());
  639. ihp->setInterface(&myImp);
  640. test = SquirrelVM::CompileBuffer(_T("\
  641. ih.getInterface().pureFunc1(); \n\
  642. ih.getInterface().pureFunc2(); \n\
  643. ihp <- ih.getInterface(); \n\
  644. ihp.pureFunc1(); \n\
  645. ihp.pureFunc2(); \n\
  646. myIh <- MyImp(); \n\
  647. ih.setInterface(myIh.getInterface()); \n\
  648. ih.getInterface().pureFunc1(); \n\
  649. ih.getInterface().pureFunc2(); \n\
  650. "));
  651. SquirrelVM::RunScript(test);
  652. } // testPureVirtualInterface
  653. // === END Interface Test ===
  654. void testSquirrelObjectSetGet(void) {
  655. // We can pass in arguments:
  656. // by value ('true' arg, required for constant float, int, etc., or when a copy is desired),
  657. // by reference (data will be copied to SquirrelObject and memory managed),
  658. // by pointer (no data copying: pointer is used directly in SquirrelObject; the memory will not be managed).
  659. 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.
  660. float valc = tc.Get<float>();
  661. scprintf(_T("Valc is: %f\n"),valc);
  662. float val = 1.234f;
  663. SquirrelObject t(val); // val is passed by reference, memory will be allocated, and the value copied once.
  664. float val2 = t.Get<float>();
  665. scprintf(_T("Val2 is: %f\n"),val2);
  666. if (1) {
  667. 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.
  668. Vector3 * pv = v.Get<Vector3 *>();
  669. scprintf(_T("Vector3 is: %f %f %f\n"),pv->x,pv->y,pv->z);
  670. pv->z += 1.f;
  671. if (1) {
  672. SquirrelObject v2p(pv); // This is a pointer to v's instance (passed in by pointer: see SquirrelObject.h).
  673. // 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).
  674. pv = v2p.Get<Vector3 *>();
  675. scprintf(_T("Vector3 is: %f %f %f\n"),pv->x,pv->y,pv->z);
  676. } // if
  677. } // if
  678. scprintf(_T("Vector3() instance has been released.\n\n"));
  679. } // testSquirrelObjectSetGet
  680. #define SQDBG_DEBUG_HOOK _T("_sqdebughook_")
  681. class TestSqPlus {
  682. public:
  683. enum {SQ_ENUM_TEST=1234321};
  684. void init(void) {
  685. SquirrelVM::Init();
  686. HSQUIRRELVM _v = SquirrelVM::GetVMPtr();
  687. #if 1
  688. sq_pushregistrytable(_v);
  689. sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1);
  690. sq_pushuserpointer(_v,this);
  691. sq_newclosure(_v,debug_hook,1);
  692. sq_createslot(_v,-3);
  693. // sq_pop(_v,1);
  694. // sq_pushregistrytable(_v);
  695. sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1);
  696. sq_rawget(_v,-2);
  697. sq_setdebughook(_v);
  698. sq_pop(_v,1);
  699. #endif
  700. sq_enabledebuginfo(_v,SQTrue);
  701. } // init
  702. TestSqPlus() {
  703. init();
  704. testPureVirtualInterface();
  705. testScriptingTypeName();
  706. try {
  707. HSQUIRRELVM v = SquirrelVM::GetVMPtr();
  708. SquirrelObject root = SquirrelVM::GetRootTable();
  709. testPointfBoxf();
  710. // Example from forum question:
  711. testScripts.InitScript1();
  712. testScripts.InitScript2();
  713. SquirrelObject testScriptBinding = SquirrelVM::CompileBuffer(_T("\
  714. local testScripts = STestScripts(); \n\
  715. testScripts.Test1(); \n\
  716. testScripts.Test2(); \n\
  717. print(testScripts.Var_ToBind2); \n\
  718. Test1(); \n\
  719. Test2(); \n\
  720. print(Var_ToBind1); \n\
  721. "));
  722. SquirrelVM::RunScript(testScriptBinding);
  723. // === BEGIN Global Function binding tests ===
  724. // Implemented as SquirrelVM::CreateFunction(rootTable,func,name,typeMask). CreateFunctionGlobal() binds a standard SQFUNCTION (stack args).
  725. SquirrelVM::CreateFunctionGlobal(testFunc,_T("testFunc0"));
  726. SquirrelVM::CreateFunctionGlobal(testFunc,_T("testFuncN"),_T("n"));
  727. SquirrelVM::CreateFunctionGlobal(testFunc,_T("testFuncS"),_T("s"));
  728. #if 0
  729. SquirrelObject testStandardFuncs = SquirrelVM::CompileBuffer(_T(" testFunc0(); testFuncN(1.); testFuncS(\"Hello\"); "));
  730. SquirrelVM::RunScript(testStandardFuncs);
  731. #endif
  732. // === Register Standard Functions using template system (function will be directly called with argument auto-marshaling) ===
  733. RegisterGlobal(v,newtest,_T("test"));
  734. RegisterGlobal(v,newtestR1,_T("testR1"));
  735. // === Register Member Functions to existing classes (as opposed to instances of classes) ===
  736. NewTestObj t1,t2,t3;
  737. t1.val = 123;
  738. t2.val = 456;
  739. t3.val = 789;
  740. RegisterGlobal(v,t1,&NewTestObj::newtest,_T("testObj_newtest1"));
  741. RegisterGlobal(v,t2,&NewTestObj::newtest,_T("testObj_newtest2")); // Register newtest() again with different name and object pointer.
  742. SquirrelObject tr = SquirrelVM::GetRootTable(); // Can be any object supporting closures (functions).
  743. Register(v,tr.GetObjectHandle(),t3,&NewTestObj::newtestR1,_T("testObj_newtestR1")); // Return value version.
  744. // === END Global Function binding tests ===
  745. // === BEGIN Namespace examples ===
  746. // Create a namespace using a table.
  747. SquirrelObject nameSpaceTable = SquirrelVM::CreateTable();
  748. root.SetValue(_T("Namespace1"),nameSpaceTable);
  749. Register(v,nameSpaceTable.GetObjectHandle(),globalFunc,_T("namespaceFunc"));
  750. // 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.
  751. // Using the class/instance form also allows extra information to be added to the proxy class, if desired (such as vars/funcs).
  752. // NOTE: If any variables/static-variables/constants are registered to the class, it must be instantiated before use.
  753. SQClassDef<NamespaceClass>(_T("Namespace2")).
  754. staticFunc(globalFunc,_T("namespaceFunc"));
  755. SquirrelObject testNameSpace = SquirrelVM::CompileBuffer(_T("\
  756. Namespace1.namespaceFunc(\"Hello Namespace1 (table),\",321); \n\
  757. Namespace2.namespaceFunc(\"Hello Namespace2 (class),\",654); \n\
  758. local Namespace3 = Namespace2(); \n\
  759. Namespace3.namespaceFunc(\"Hello Namespace3 (instance),\",987); \n\
  760. "));
  761. SquirrelVM::RunScript(testNameSpace);
  762. // === END Namespace examples ===
  763. // === BEGIN Class Instance tests ===
  764. // Example showing two methods for registration.
  765. #if 0
  766. SQClassDef<NewTestObj> sqClass(_T("NewTestObj"));
  767. sqClass.func(NewTestObj::newtestR1,_T("newtestR1"));
  768. sqClass.var(&NewTestObj::val,_T("val"));
  769. sqClass.var(&NewTestObj::s1,_T("s1"));
  770. sqClass.var(&NewTestObj::s2,_T("s2"));
  771. sqClass.var(&NewTestObj::c1,_T("c1"),VAR_ACCESS_READ_ONLY);
  772. sqClass.var(&NewTestObj::c2,_T("c2"),VAR_ACCESS_READ_ONLY);
  773. sqClass.funcVarArgs(NewTestObj::multiArgs,_T("multiArgs"));
  774. #else
  775. SQClassDef<NewTestObj>(_T("NewTestObj")). // If a special constructor+destructor are not needed, the auto-generated versions can be used.
  776. // Example methods for custom constructors:
  777. 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.
  778. // 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.
  779. // staticFuncVarArgs(NewTestObj::construct,_T("constructor")). // Using a static member constructor.
  780. staticFunc(globalFunc,_T("globalFunc")). // Any global function can be registered in a class namespace (no 'this' pointer will be passed to the function).
  781. staticFunc(globalClass,&GlobalClass::func,_T("globalClassFunc")).
  782. func(&NewTestObj::newtestR1,_T("newtestR1")).
  783. var(&NewTestObj::val,_T("val")).
  784. var(&NewTestObj::s1,_T("s1")).
  785. var(&NewTestObj::s2,_T("s2")).
  786. var(&NewTestObj::c1,_T("c1"),VAR_ACCESS_READ_ONLY).
  787. var(&NewTestObj::c2,_T("c2"),VAR_ACCESS_READ_ONLY).
  788. funcVarArgs(&NewTestObj::multiArgs,_T("multiArgs"));
  789. #define SQ_10 10
  790. #define SQ_E 2.71828182845904523536f
  791. #define SQ_PI 3.14159265358979323846264338327950288f
  792. #define SQ_CONST_STRING _T("A constant string")
  793. const int intConstant = 7;
  794. const float floatConstant = 8.765f;
  795. const bool boolConstant = true;
  796. #if 1
  797. SQClassDef<Vector3>(_T("Vector3")).
  798. var(&Vector3::x,_T("x")).
  799. var(&Vector3::y,_T("y")).
  800. var(&Vector3::z,_T("z")).
  801. func(&Vector3::Inc,_T("Inc")).
  802. func(&Vector3::operator+,_T("_add")).
  803. staticFunc(&Add2,_T("Add2")).
  804. staticFuncVarArgs(&Add,_T("Add")).
  805. #if 1
  806. staticVar(&Vector3::staticVar,_T("staticVar")).
  807. #else
  808. staticVar(&Vector3::staticVar,_T("staticVar"),VAR_ACCESS_READ_ONLY).
  809. #endif
  810. staticVar(&globalVar,_T("globalVar")).
  811. constant(SQ_10,_T("SQ_10")).
  812. constant(SQ_E,_T("SQ_E")).
  813. constant(SQ_PI,_T("SQ_PI")).
  814. constant(SQ_CONST_STRING,_T("SQ_CONST_STRING")).
  815. enumInt(SQ_ENUM_TEST,_T("SQ_ENUM_TEST")).
  816. constant(intConstant,_T("intConstant")).
  817. constant(floatConstant,_T("floatConstant")).
  818. constant(true,_T("boolTrue")).
  819. constant(false,_T("boolFalse")).
  820. constant(boolConstant,_T("boolConstant"));
  821. #endif
  822. #endif
  823. testSquirrelObjectSetGet(); // Uses Vector3().
  824. BindConstant(SQ_PI*2,_T("SQ_PI_2"));
  825. BindConstant(SQ_10*2,_T("SQ_10_2"));
  826. BindConstant(_T("Global String"),_T("GLOBAL_STRING"));
  827. 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; "));
  828. SquirrelVM::RunScript(testStaticVars);
  829. SquirrelObject testConstants0 = SquirrelVM::CompileBuffer(_T(" print(\"SQ_PI*2: \"+SQ_PI_2+\" SQ_10_2: \"+SQ_10_2+\" GLOBAL_STRING: \"+GLOBAL_STRING); "));
  830. SquirrelVM::RunScript(testConstants0);
  831. 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);" ));
  832. SquirrelVM::RunScript(testConstants1);
  833. 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\"));" ));
  834. SquirrelVM::RunScript(testConstants2);
  835. 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.
  836. SquirrelVM::RunScript(scriptedBase);
  837. // === BEGIN Instance Test ===
  838. SQClassDef<PlayerManager::Player>(_T("PlayerManager::Player")).
  839. func(&PlayerManager::Player::printName,_T("printName")).
  840. var(&PlayerManager::Player::name,_T("name"));
  841. SQClassDef<PlayerManager>(_T("PlayerManager")).
  842. func(&PlayerManager::GetPlayer,_T("GetPlayer")).
  843. var(&PlayerManager::playerVar,_T("playerVar"));
  844. RegisterGlobal(getPlayerManager,_T("getPlayerManager"));
  845. BindVariable(&playerManager,_T("playerManagerVar"));
  846. SquirrelObject testGetInstance = SquirrelVM::CompileBuffer(_T("\
  847. local PlayerManager = getPlayerManager(); \n\
  848. local oPlayer = PlayerManager.GetPlayer(0); \n\
  849. print(typeof oPlayer); \n\
  850. oPlayer.printName(); \n\
  851. PlayerManager.playerVar.printName(); \n\
  852. print(PlayerManager.playerVar.name); \n\
  853. oPlayer = PlayerManager.playerVar; \n\
  854. oPlayer.name = \"New_Name1\"; \n\
  855. playerManagerVar.playerVar.printName(); \n\
  856. oPlayer.name = \"New_Name2\"; \n\
  857. "));
  858. SquirrelVM::RunScript(testGetInstance);
  859. scprintf(_T("playerManager.playerVar.name: %s\n"),playerManager.playerVar.name.s);
  860. // === END Instance Test ===
  861. // === BEGIN example from forum post ===
  862. SQClassDef<Creature>(_T("Creature")).
  863. func(&Creature::GetMaxHealth,_T("GetMaxHealth")).
  864. func(&Creature::GetHealth,_T("GetHealth")).
  865. func(&Creature::SetHealth,_T("SetHealth"));
  866. SquirrelObject testClass = SquirrelVM::CompileBuffer( _T("function HealthPotionUse(Target) { \n\
  867. local curHealth = Target.GetHealth(); \n\
  868. local maxHealth = Target.GetMaxHealth(); \n\
  869. if ((maxHealth - curHealth) > 15) { \n\
  870. curHealth += 15; \n\
  871. } else { \n\
  872. curHealth = maxHealth; \n\
  873. } \n\
  874. Target.SetHealth(curHealth); \n\
  875. print(typeof Target); \n\
  876. return Target; \n\
  877. }"));
  878. Creature frodo;
  879. frodo.SetHealth(frodo.GetMaxHealth()/2);
  880. SquirrelVM::RunScript(testClass);
  881. Creature newFrodo = SquirrelFunction<Creature &>(_T("HealthPotionUse"))(frodo); // Pass by value and return a copy (Must return by reference due to template system design).
  882. SquirrelFunction<void>(_T("HealthPotionUse"))(&frodo); // Pass the address to directly modify frodo.
  883. scprintf(_T("Frodo's health: %d %d\n"),frodo.GetHealth(),newFrodo.GetHealth());
  884. // === END example from forum post ===
  885. #ifdef SQ_USE_CLASS_INHERITANCE
  886. // Base class constructors, if registered, must use this form: static int construct(HSQUIRRELVM v).
  887. // SQClassDef<CustomTestObj> customClass(_T("CustomTestObj"));
  888. SQClassDef<CustomTestObj> customClass(_T("CustomTestObj"),_T("ScriptedBase"));
  889. // SQClassDef<CustomTestObj> customClass(_T("CustomTestObj"),_T("NewTestObj"));
  890. customClass.staticFuncVarArgs(&CustomTestObj::construct,_T("constructor"),_T("*")); // MUST use this form (or no args) if CustomTestObj will be used as a base class.
  891. // Using the "*" form will allow a single constructor to be used for all cases.
  892. // customClass.staticFuncVarArgs(CustomTestObj::construct,_T("constructor")); // (this form is also OK if used as a base class)
  893. customClass.funcVarArgs(&CustomTestObj::varArgTypesAndCount,_T("multiArgs"),_T("*")); // "*": no type or count checking.
  894. customClass.funcVarArgs(&CustomTestObj::varArgTypesAndCount,_T("varArgTypesAndCount"),_T("*")); // "*": no type or count checking.
  895. #else
  896. SQClassDef<CustomTestObj> customClass(_T("CustomTestObj"));
  897. customClass.staticFuncVarArgs(&CustomTestObj::construct,_T("constructor"),_T("snb")); // string, number, bool (all types must match).
  898. customClass.funcVarArgs(&CustomTestObj::varArgTypesAndCount,_T("varArgTypesAndCount"),_T("*")); // "*": no type or count checking.
  899. #endif
  900. customClass.funcVarArgs(&CustomTestObj::varArgTypes,_T("varArgTypes"),_T("s|ns|ns|ns|n")); // string or number + string or number.
  901. customClass.funcVarArgs(&CustomTestObj::noArgsVariableReturn,_T("noArgsVariableReturn")); // No type string means no arguments allowed.
  902. customClass.func(&CustomTestObj::variableArgsFixedReturnType,_T("variableArgsFixedReturnType")); // Variables args, fixed return type.
  903. customClass.func(&CustomTestObj::manyArgs,_T("manyArgs")); // Many args, type checked.
  904. customClass.func(&CustomTestObj::manyArgsR1,_T("manyArgsR1")); // Many args, type checked, one return value.
  905. #ifdef SQ_USE_CLASS_INHERITANCE
  906. // 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\"); "));
  907. // 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\"); "));
  908. // 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\"); "));
  909. 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); "));
  910. // 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\"); "));
  911. printf("=== BEGIN INHERITANCE ===\n");
  912. testInhertianceCase();
  913. SquirrelVM::RunScript(testInheritance);
  914. printf("=== END INHERITANCE ===\n");
  915. #endif
  916. 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); "));
  917. SquirrelVM::RunScript(testRegV);
  918. #ifdef SQ_USE_CLASS_INHERITANCE
  919. SquirrelObject testReg0 = SquirrelVM::CompileBuffer(_T(" co <- CustomTestObj(\"hello\",123,true); co.varArgTypes(\"str\",123,123,\"str\"); co.varArgTypes(123,\"str\",\"str\",123); "));
  920. SquirrelVM::RunScript(testReg0);
  921. SquirrelObject testReg0a = SquirrelVM::CompileBuffer(_T(" print(co.varArgTypesAndCount(1,true)); print(co.varArgTypesAndCount(2,false,3.)); print(\"\\n\"); "));
  922. SquirrelVM::RunScript(testReg0a);
  923. SquirrelObject testReg0b = SquirrelVM::CompileBuffer(_T(" print(co.noArgsVariableReturn()); print(co.noArgsVariableReturn()); print(co.noArgsVariableReturn()); print(\"\\n\"); "));
  924. SquirrelVM::RunScript(testReg0b);
  925. SquirrelObject testReg0c = SquirrelVM::CompileBuffer(_T(" print(co.variableArgsFixedReturnType(1)); print(co.variableArgsFixedReturnType(1,2)); print(co.variableArgsFixedReturnType(1,2,3)); print(\"\\n\"); "));
  926. SquirrelVM::RunScript(testReg0c);
  927. SquirrelObject testReg0d = SquirrelVM::CompileBuffer(_T(" co.manyArgs(111,222.2,true,\"Hello\"); print(co.manyArgsR1(333,444.3,false,\"World\")); print(\"\\n\"); "));
  928. SquirrelVM::RunScript(testReg0d);
  929. 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; "));
  930. SquirrelVM::RunScript(testReg1a);
  931. // Constant test (read only var). Var can change on C++ side, but not on script side.
  932. try {
  933. SquirrelObject testRegConstant = SquirrelVM::CompileBuffer(_T(" local t = NewTestObj(); t.c1 = 123; "));
  934. SquirrelVM::RunScript(testRegConstant);
  935. } // try
  936. catch (SquirrelError & e) {
  937. scprintf(_T("Error: %s, %s\n"),e.desc,_T("Squirrel::TestConstant"));
  938. } // catch
  939. 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); "));
  940. SquirrelVM::RunScript(testReg1);
  941. 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); "));
  942. SquirrelVM::RunScript(testReg2);
  943. SquirrelObject testReg3 = SquirrelVM::CompileBuffer(_T(" test(); local rv = testR1(\"Hello\"); print(rv); "));
  944. SquirrelVM::RunScript(testReg3);
  945. SquirrelObject testReg4 = SquirrelVM::CompileBuffer(_T(" print(\"\\nMembers:\"); testObj_newtest1(); testObj_newtest2(); print(testObj_newtestR1(\"Hello Again\")); "));
  946. SquirrelVM::RunScript(testReg4);
  947. SquirrelObject defCallFunc = SquirrelVM::CompileBuffer(_T(" function callMe(var) { print(\"I was called by: \"+var); return 123; }"));
  948. SquirrelVM::RunScript(defCallFunc);
  949. SquirrelObject defCallFuncStrRet = SquirrelVM::CompileBuffer(_T(" function callMeStrRet(var) { print(\"I was called by: \"+var); return var; }"));
  950. SquirrelVM::RunScript(defCallFuncStrRet);
  951. SquirrelFunction<void>(_T("callMe"))(_T("Squirrel 1"));
  952. // Get a function from the root table and call it.
  953. #if 1
  954. SquirrelFunction<int> callFunc(_T("callMe"));
  955. int ival = callFunc(_T("Squirrel"));
  956. scprintf(_T("IVal: %d\n"),ival);
  957. SquirrelFunction<const SQChar *> callFuncStrRet(_T("callMeStrRet"));
  958. const SQChar * sval = callFuncStrRet(_T("Squirrel StrRet"));
  959. scprintf(_T("SVal: %s\n"),sval);
  960. #endif
  961. ival = 0;
  962. // Get a function from any table.
  963. SquirrelFunction<int> callFunc2(root.GetObjectHandle(),_T("callMe"));
  964. ival = callFunc(456); // Argument count is checked; type is not.
  965. // === END Class Instance tests ===
  966. 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\");"));
  967. SquirrelVM::RunScript(main);
  968. SquirrelObject table1 = root.GetValue(_T("table1"));
  969. if (table1.Exists(_T("key1"))) {
  970. scprintf(_T("C++: Found it.\n"));
  971. } else {
  972. scprintf(_T("C++: Did not find it.\n"));
  973. } // if
  974. // === BEGIN Simple variable binding tests ===
  975. int iVar = 777;
  976. float fVar = 88.99f;
  977. bool bVar = true;
  978. BindVariable(root,&iVar,_T("iVar"));
  979. BindVariable(root,&fVar,_T("fVar"));
  980. BindVariable(root,&bVar,_T("bVar"));
  981. static ScriptStringVar128 testString;
  982. scsprintf(testString,_T("This is a test string"));
  983. BindVariable(root,&testString,_T("testString"));
  984. // === END Simple variable binding tests ===
  985. // === BEGIN Array Tests ===
  986. SquirrelObject array = SquirrelVM::CreateArray(10);
  987. int i;
  988. for (i = 0; i < 10; i++) array.SetValue(i,i);
  989. array.ArrayAppend(123); // int
  990. array.ArrayAppend(true); // bool (must use bool and not SQBool (SQBool is treated as INT by compiler).
  991. array.ArrayAppend(false); // bool (must use bool and not SQBool (SQBool is treated as INT by compiler).
  992. array.ArrayAppend(123.456f); // float
  993. array.ArrayAppend(_T("string")); // string
  994. array.ArrayAppend(456); // Will be popped and thrown away (below).
  995. array.ArrayAppend((SQUserPointer)0);
  996. // Pop 3 items from array:
  997. array.ArrayPop(SQFalse); // Don't retrieve the popped value (int:123).
  998. SquirrelObject so1 = array.ArrayPop(); // Retrieve the popped value.
  999. const SQChar * val1 = so1.ToString(); // Get string.
  1000. float val2 = array.ArrayPop().ToFloat(); // Pop and get float.
  1001. scprintf(_T("[Popped values] Val1: %s, Val2: %f\n"),val1,val2);
  1002. int startIndex = array.Len();
  1003. array.ArrayExtend(10); // Implemented as: ArrayResize(Len()+amount).
  1004. for (i = startIndex; i < array.Len(); i++) array.SetValue(i,i*10);
  1005. root.SetValue(_T("array"),array);
  1006. SquirrelObject arrayr = array.Clone(); // Get a copy as opposed to another reference.
  1007. arrayr.ArrayReverse();
  1008. root.SetValue(_T("arrayr"),arrayr);
  1009. // === END Array Tests ===
  1010. 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); } } "));
  1011. SquirrelVM::RunScript(define_printArray);
  1012. SquirrelObject test = SquirrelVM::CompileBuffer(_T(" printArray(\"array\",array); printArray(\"arrayr\",arrayr); "));
  1013. SquirrelVM::RunScript(test);
  1014. #endif
  1015. } // try
  1016. catch (SquirrelError & e) {
  1017. scprintf(_T("Error: %s, in %s\n"),e.desc,_T("TestSqPlus"));
  1018. } // catch
  1019. }
  1020. ~TestSqPlus() {
  1021. SquirrelVM::Shutdown();
  1022. }
  1023. };
  1024. void doTest(void) {
  1025. TestSqPlus testSqPlus;
  1026. } // doTest
  1027. int main(int argc,char * argv[]) {
  1028. // Run twice to make sure cleanup/shutdown works OK.
  1029. SCPUTS(_T("Start Pass 1\n"));
  1030. doTest();
  1031. #if 0
  1032. SCPUTS(_T("Start Pass 2\n"));
  1033. doTest();
  1034. #endif
  1035. SCPUTS(_T("Done.\n"));
  1036. scprintf(_T("Press RETURN to exit."));
  1037. getchar();
  1038. return 0;
  1039. }