Lua_Object.pas 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421
  1. //******************************************************************************
  2. //*** LUA SCRIPT FUNCTIONS ***
  3. //*** ***
  4. //*** (c) Massimo Magnano 2006 ***
  5. //*** ***
  6. //*** ***
  7. //******************************************************************************
  8. // File : Lua_Object.pas (rev. 1.0)
  9. //
  10. // Description : Access from Lua scripts to TObject Classes
  11. // (at this time only Properties and methods)
  12. //
  13. //******************************************************************************
  14. // Exported functions :
  15. //
  16. // CreateObject(string className, bool CanFree [, param1, ..paramN]) return a new TObject.
  17. // GetObject(string Name) return an existing TObject.
  18. //
  19. // TObject.PropertyName return Property Value as Variant.
  20. // TObject.PropertyName = (variant Value) set Property Value.
  21. // TObject:<method name>([param1, .., paramN]) call <method name>, return Result as Variant.
  22. // TObject:Free() free the object, return True on success.
  23. // TO-DO :
  24. // funzioni lua da esportare :
  25. // enumval(Type :???, value :string) enumstr(Type :???, value :Integer???)
  26. // nei metodi dove c'è var, come lo torno in Lua?
  27. // Eventi degli oggetti (una classe per ogni evento + lista con il nome della funzione lua)
  28. // Gestione delle property di Tipo Record Vedi cos'è PFieldTable
  29. // + Metodo x avere le property publiche??? invece di usare SetElement
  30. // * gestione del garbage collector (metafunction _gc)
  31. // * Gestione di TComponent.<componentname> come se fosse una property tkClass
  32. // ++ Migliorare la gestione delle property che sono degli array (se possibile???)
  33. // * Migliorare la registrazione delle classi, andare sempre alla ricerca dell' ancestor
  34. // COMMENTARE IL CODICE MENTRO ME LO RICORDO
  35. unit Lua_Object;
  36. {$J+}
  37. interface
  38. uses TypInfo, SysUtils, ScriptableObject, Lua, LuaUtils, lauxlib, Variants;
  39. type
  40. {$METHODINFO ON}
  41. TLuaObject = class(TObject)
  42. protected
  43. rInstanceObj :TObject;
  44. Owned :Boolean;
  45. class function GetPublicPropertyAccessClass :TClass; virtual; abstract;
  46. public
  47. constructor Create(AInstanceObj :TObject; AOwned :Boolean);
  48. destructor Destroy; override;
  49. function CallMethod(MethodName :String; const Args : array of variant;
  50. NeedResult: Boolean): Variant;
  51. //WARNING : if you want parameters when creating an Object you must write
  52. // a function with the following form that create the object.
  53. // You must change every parameter or result of type TClass, TObject
  54. // with type integer (ObjComAuto do not support this types?????)
  55. //
  56. function LuaCreate(ObjClass :Integer) :Integer; overload;
  57. function GetDefaultArrayProp :String; virtual; abstract;
  58. function GetArrayPropType(Name :String; index :Variant) :PTypeInfo; virtual; abstract;
  59. function GetArrayProp(Name :String; index :Variant) :Variant; virtual; abstract;
  60. procedure SetArrayProp(Name :String; index :Variant; Value :Variant); virtual; abstract;
  61. //If the ElementType is tkSet or tkEnumeration (except the boolean) you may return the Value
  62. // in GetElement as a String
  63. function GetElementType(Name :String) :PTypeInfo; virtual; abstract;
  64. function GetElement(Name :String) :Variant; virtual; abstract;
  65. procedure SetElement(Name :String; Value :Variant); virtual; abstract;
  66. function GetPublicPropInfo(Name :String) :PPropInfo;
  67. function GetPublicPropValue(Name :String; AsString :Boolean) :Variant;
  68. procedure SetPublicPropValue(Name :String; Value :Variant);
  69. property InstanceObj :TObject read rInstanceObj;
  70. end;
  71. {$METHODINFO OFF}
  72. TLuaObjectClass = class of TLuaObject;
  73. const
  74. TypeInfoArray : TTypeInfo = (Kind : tkArray; Name :'');
  75. TypeInfoClass : TTypeInfo = (Kind : tkClass; Name :'');
  76. procedure RegisterFunctions(L: Plua_State);
  77. procedure RegisterClass(ObjClass :TClass; LuaClass :TLuaObjectClass=nil);
  78. procedure RegisterObject(Obj :TObject; Name :String; LuaClass :TLuaObjectClass=nil);
  79. function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean): string;
  80. function StringToSet(EnumInfo: PTypeInfo; const Value: string): Integer;
  81. implementation
  82. uses MGList, Classes, Controls;
  83. const
  84. OBJHANDLE_STR ='Lua_TObjectHandle';
  85. ARRAYPROP_STR ='Lua_TObjectArrayProp';
  86. ARRAYPROPNAME_STR ='Lua_TObjectArrayPropName';
  87. SETPROP_VALUE ='Lua_TObjectSetPropvalue';
  88. SETPROP_INFO ='Lua_TObjectSetPropINFO';
  89. type
  90. //Record stored in lua stack to mantain TLuaObject
  91. TLuaObjectData = packed record
  92. ID : String[20];
  93. Obj :TLuaObject;
  94. end;
  95. PLuaObjectData =^TLuaObjectData;
  96. TLuaArrayPropData = record
  97. ID : String[20];
  98. Obj :TLuaObject;
  99. PropName :string;
  100. end;
  101. TLuaSetPropData = record
  102. ID :String[20];
  103. Info :PTypeInfo;
  104. Value :string;
  105. end;
  106. PLuaSetPropData = ^TLuaSetPropData;
  107. //This List associate an Object Class with a LuaObject Class
  108. TLuaClassesListData = record
  109. ObjClass :TClass;
  110. LuaClass :TLuaObjectClass;
  111. end;
  112. PLuaClassesListData =^TLuaClassesListData;
  113. TLuaClassesList = class(TMGList)
  114. protected
  115. InternalData :TLuaClassesListData;
  116. function allocData :Pointer; override;
  117. procedure deallocData(pData :Pointer); override;
  118. function internalFind(ObjClassName :String) :PLuaClassesListData; overload;
  119. function internalFind(ObjClass :TClass) :PLuaClassesListData; overload;
  120. public
  121. function Add(ObjClass :TClass; LuaClass :TLuaObjectClass=nil) :PLuaClassesListData; overload;
  122. function FindAncestor(ObjClass :TClass) :TLuaObjectClass;
  123. function Find(ObjClassName :String) :PLuaClassesListData; overload;
  124. function Find(ObjClass :TClass) :PLuaClassesListData; overload;
  125. end;
  126. //This List associate an Existing Object Instance with a Name in the Lua script
  127. TLuaExistingObjListData = record
  128. Obj :TObject;
  129. Name :String;
  130. end;
  131. PLuaExistingObjListData =^TLuaExistingObjListData;
  132. TLuaExistingObjList = class(TMGList)
  133. protected
  134. function allocData :Pointer; override;
  135. procedure deallocData(pData :Pointer); override;
  136. public
  137. function Add(Obj :TObject; Name :String) :PLuaExistingObjListData; overload;
  138. function Find(Name :String) :PLuaExistingObjListData; overload;
  139. end;
  140. Var
  141. LuaClassesList :TLuaClassesList =nil;
  142. LuaExistingObjList :TLuaExistingObjList =nil;
  143. procedure MySetPropValue(Instance: TObject; PropInfo: PPropInfo;
  144. const Value: Variant);
  145. begin
  146. //SetPropValue raise an exception when i try to set a class property...
  147. // even if it's value is a simple Integer (infact GetPropValue return it as Integer)
  148. if PropInfo^.PropType^.Kind = tkClass
  149. then SetOrdProp(Instance, PropInfo, Value)
  150. else SetPropValue(Instance, PropInfo, Value);
  151. end;
  152. constructor TLuaObject.Create(AInstanceObj :TObject; AOwned :Boolean);
  153. begin
  154. inherited Create;
  155. rInstanceObj :=AInstanceObj;
  156. Owned :=AOwned;
  157. end;
  158. destructor TLuaObject.Destroy;
  159. begin
  160. if Owned then rInstanceObj.Free;
  161. inherited Destroy;
  162. end;
  163. function TLuaObject.LuaCreate(ObjClass :Integer) :Integer;
  164. begin
  165. Result :=Integer(TClass(ObjClass).Create);
  166. end;
  167. function TLuaObject.CallMethod(MethodName :String; const Args : array of variant;
  168. NeedResult: Boolean): Variant;
  169. Var
  170. scripter :TScriptableObject;
  171. pRes :PVariant;
  172. begin
  173. Result :=NULL;
  174. scripter :=nil;
  175. try
  176. //Try with My Methods
  177. scripter :=TScriptableObject.Create(Self, false);
  178. pRes :=scripter.CallMethod(scripter.NameToDispID(MethodName), Args, NeedResult);
  179. if (pRes<>nil)
  180. then Result :=pRes^;
  181. scripter.Free;
  182. except
  183. scripter.Free;
  184. Result :=NULL;
  185. try
  186. //Try with InstanceObj Methods
  187. scripter :=TScriptableObject.Create(rInstanceObj, false);
  188. pRes :=scripter.CallMethod(scripter.NameToDispID(MethodName), Args, NeedResult);
  189. if (pRes<>nil)
  190. then Result :=pRes^;
  191. scripter.Free;
  192. except
  193. scripter.Free;
  194. Result :=NULL;
  195. end;
  196. end;
  197. end;
  198. function TLuaObject.GetPublicPropInfo(Name :String) :PPropInfo;
  199. Var
  200. _parent :TLuaObjectClass;
  201. begin
  202. _parent :=TLuaObjectClass(Self.ClassType);
  203. repeat
  204. Result :=GetPropInfo(_parent.GetPublicPropertyAccessClass, Name, tkProperties);
  205. if (Result=nil)
  206. then _parent := TLuaObjectClass(_parent.ClassParent);
  207. //IF the Property is not public in this Class, try in ancestors.
  208. // This method avoid to redeclare property as published in every TXXXAccess class,
  209. // for example :
  210. // TLuaControl <- TLuaWinControl
  211. // TControl <- TWinControl
  212. // Without this method, in TLuaWinControl, you might declare every public property
  213. // of TWinControl including every public property of TControl.
  214. // With this method, in TLuaWinControl, you can declare only public property of TWinControl
  215. until (_parent=TLuaObject) or (Result<>nil);
  216. end;
  217. (*
  218. begin
  219. Result :=GetPropInfo(GetPublicPropertyAccessClass, Name, tkProperties);
  220. end;
  221. *)
  222. function TLuaObject.GetPublicPropValue(Name :String; AsString :Boolean) :Variant;
  223. Var
  224. PropInfo :PPropInfo;
  225. begin
  226. PropInfo :=GetPublicPropInfo(Name);
  227. if (PropInfo<>nil)
  228. then Result :=GetPropValue(rInstanceObj, PropInfo, AsString);
  229. end;
  230. procedure TLuaObject.SetPublicPropValue(Name :String; Value :Variant);
  231. Var
  232. PropInfo :PPropInfo;
  233. begin
  234. PropInfo :=GetPublicPropInfo(Name);
  235. if (PropInfo<>nil)
  236. then MySetPropValue(rInstanceObj, PropInfo, Value);
  237. end;
  238. //==============================================================================
  239. //
  240. function TLuaClassesList.allocData :Pointer;
  241. begin
  242. GetMem(Result, sizeof(TLuaClassesListData));
  243. fillchar(Result^, sizeof(TLuaClassesListData), 0);
  244. end;
  245. procedure TLuaClassesList.deallocData(pData :Pointer);
  246. begin
  247. FreeMem(pData, sizeof(TLuaClassesListData));
  248. end;
  249. function TLuaClassesList.Add(ObjClass :TClass; LuaClass :TLuaObjectClass=nil) :PLuaClassesListData;
  250. begin
  251. Result :=Find(ObjClass.ClassName);
  252. if (Result=nil)
  253. then Result :=Self.Add;
  254. if (Result<>nil)
  255. then begin
  256. Result^.ObjClass :=ObjClass;
  257. (*if (LuaClass=nil)
  258. then Result^.LuaClass :=TLuaObject
  259. else*) Result^.LuaClass :=LuaClass;
  260. end;
  261. end;
  262. function TLuaClassesList.FindAncestor(ObjClass :TClass) :TLuaObjectClass;
  263. Var
  264. _parent :TClass;
  265. Data :PLuaClassesListData;
  266. begin
  267. _parent :=ObjClass.ClassParent;
  268. Data :=nil;
  269. while (_parent<>nil) and (Data=nil) do
  270. begin
  271. Data :=internalFind(_parent);
  272. if (Data<>nil)
  273. then Result :=Data^.LuaClass
  274. else _parent := _parent.ClassParent;
  275. end;
  276. if (Data=nil)
  277. then Result :=TLuaObject;
  278. end;
  279. function TLuaClassesList.internalFind(ObjClassName :String) :PLuaClassesListData;
  280. function CompByClassName(Tag :Integer; ptData1, ptData2 :Pointer) :Boolean;
  281. begin
  282. Result := String(PChar(ptData1)) = Uppercase(PLuaClassesListData(ptData2)^.ObjClass.Classname);
  283. end;
  284. begin
  285. Result :=Self.ExtFind(PChar(Uppercase(ObjClassName)), 0, @CompByClassName);
  286. end;
  287. function TLuaClassesList.internalFind(ObjClass :TClass) :PLuaClassesListData;
  288. function CompByClass(Tag :Integer; ptData1, ptData2 :Pointer) :Boolean;
  289. begin
  290. Result := TClass(ptData1) = PLuaClassesListData(ptData2)^.ObjClass;
  291. end;
  292. begin
  293. Result :=Self.ExtFind(ObjClass, 0, @CompByClass);
  294. end;
  295. function TLuaClassesList.Find(ObjClass :TClass) :PLuaClassesListData;
  296. begin
  297. Result :=Self.internalFind(ObjClass);
  298. if (Result<>nil)
  299. then begin
  300. if (Result^.LuaClass=nil) //The Class is registered, but have no LuaClass,
  301. //try to find a registered ancestor class
  302. then Result^.LuaClass :=FindAncestor(Result^.ObjClass);
  303. end
  304. else begin
  305. //The Class is not registered, try to find a registered ancestor class
  306. InternalData.ObjClass :=ObjClass;
  307. InternalData.LuaClass :=FindAncestor(ObjClass);
  308. if (InternalData.LuaClass<>nil)
  309. then Result :=@InternalData
  310. else Result :=nil;
  311. end;
  312. end;
  313. function TLuaClassesList.Find(ObjClassName :String) :PLuaClassesListData;
  314. begin
  315. Result :=Self.internalFind(ObjClassName);
  316. if (Result<>nil)
  317. then begin
  318. if (Result^.LuaClass=nil) //The Class is registered, but have no LuaClass,
  319. //try to find a registered ancestor class
  320. then Result^.LuaClass :=FindAncestor(Result^.ObjClass);
  321. end
  322. else begin
  323. Result :=Self.internalFind(FindClass(ObjClassName));
  324. if (Result<>nil)
  325. then begin
  326. if (Result^.LuaClass=nil) //The Class is registered in VCL, but have no LuaClass,
  327. //try to find a registered ancestor class
  328. then Result^.LuaClass :=FindAncestor(Result^.ObjClass);
  329. end
  330. end;
  331. end;
  332. //==============================================================================
  333. //
  334. function TLuaExistingObjList.allocData :Pointer;
  335. begin
  336. GetMem(Result, sizeof(TLuaExistingObjListData));
  337. fillchar(Result^, sizeof(TLuaExistingObjListData), 0);
  338. end;
  339. procedure TLuaExistingObjList.deallocData(pData :Pointer);
  340. begin
  341. PLuaExistingObjListData(pData)^.Name :='';
  342. FreeMem(pData, sizeof(TLuaExistingObjListData));
  343. end;
  344. function TLuaExistingObjList.Add(Obj :TObject; Name :String) :PLuaExistingObjListData;
  345. begin
  346. Result :=Find(Name);
  347. if (Result=nil)
  348. then Result :=Self.Add;
  349. if (Result<>nil)
  350. then begin
  351. Result^.Obj :=Obj;
  352. Result^.Name :=Uppercase(Name);
  353. end;
  354. end;
  355. function TLuaExistingObjList.Find(Name :String) :PLuaExistingObjListData;
  356. function CompByClass(Tag :Integer; ptData1, ptData2 :Pointer) :Boolean;
  357. begin
  358. Result := String(PChar(ptData1)) = PLuaExistingObjListData(ptData2)^.Name;
  359. end;
  360. begin
  361. Result :=Self.ExtFind(PChar(Uppercase(Name)), 0, @CompByClass);
  362. end;
  363. //==============================================================================
  364. function GetPropertyArrayObject(var Data : TLuaArrayPropData; L: Plua_State; Index: Integer): boolean; forward;
  365. function LuaPush_TLuaObject(L :Plua_State; theParams :array of Variant;
  366. Obj :TObject=nil; ObjClassName :String='';
  367. CanFree :Boolean=True) :boolean; forward;
  368. function LuaPushPropertyArrayObject(L: Plua_State; Obj :TLuaObject; PropName :string): boolean; forward;
  369. function LuaPushPropertySet(L: Plua_State; TypeInfo :PTypeInfo; PropValue :Variant): boolean; forward;
  370. function PushProperty(L :Plua_State; scripter :TLuaObject;
  371. PropName :string; PropValue :Variant; PropType :PTypeInfo) :Integer;
  372. begin
  373. Result :=0;
  374. if (PropType^.Kind = tkClass)
  375. then begin
  376. //If this property is a class, push a TLuaObject in the stack
  377. if LuaPush_TLuaObject(L, [], TObject(Integer(PropValue)))
  378. then Result := 1;
  379. end
  380. else
  381. if (PropType^.Kind =tkArray)
  382. then begin //If this property is an array, push an ArrayPropObject in the stack
  383. if LuaPushPropertyArrayObject(L, scripter, PropName)
  384. then Result := 1;
  385. end
  386. else
  387. if (PropType^.Kind =tkSet)
  388. then begin //If this property is an array, push an ArrayPropObject in the stack
  389. if LuaPushPropertySet(L, PropType, PropValue)
  390. then Result := 1;
  391. end
  392. else
  393. begin //Push the PropValue
  394. LuaPushVariant(L, PropValue);
  395. Result := 1;
  396. end;
  397. end;
  398. //==============================================================================
  399. // Array Properties Support
  400. function Lua_IsPropertyArrayObject(L: Plua_State; Index: Integer): boolean;
  401. begin
  402. Result :=False;
  403. try
  404. Result :=(LuaGetTableString(L, Index, 'ID')=ARRAYPROP_STR);
  405. except
  406. end;
  407. end;
  408. function GetPropertyArrayObject(var Data : TLuaArrayPropData; L: Plua_State; Index: Integer): boolean;
  409. begin
  410. Result :=false;
  411. try
  412. Data.Obj :=TLuaObject(LuaGetTableLightUserData(L, Index, ARRAYPROP_STR));
  413. Data.PropName :=LuaGetTableString(L, Index, ARRAYPROPNAME_STR);
  414. Result :=true;
  415. except
  416. end;
  417. end;
  418. function Lua_ArrayProp_Get(L: Plua_State): Integer; cdecl;
  419. Var
  420. indice,
  421. PropValue :Variant;
  422. PropType :PTypeInfo;
  423. GetPropOK :Boolean;
  424. NParams :Integer;
  425. Data :TLuaArrayPropData;
  426. begin
  427. Result := 0;
  428. NParams := lua_gettop(L);
  429. if (NParams=2) then
  430. try
  431. GetPropertyArrayObject(Data, L, 1);
  432. indice :=LuaToVariant(L, 2);
  433. if (indice<>NULL)
  434. then begin
  435. PropType :=Data.Obj.GetArrayPropType(Data.PropName, indice);
  436. GetPropOK := (PropType<>nil);
  437. if GetPropOK
  438. then PropValue :=Data.Obj.GetArrayProp(Data.PropName, indice)
  439. else PropValue :=NULL;
  440. Result :=PushProperty(L, Data.Obj, Data.PropName, PropValue, PropType);
  441. end
  442. else raise Exception.CreateFmt('Trying to index %s.%s with a NULL index', [Data.Obj.InstanceObj.ClassName, Data.PropName]);
  443. except
  444. On E:Exception do begin
  445. LuaError(L, ERR_Script+E.Message);
  446. end;
  447. end;
  448. end;
  449. function Lua_ArrayProp_Set(L: Plua_State): Integer; cdecl;
  450. begin
  451. end;
  452. function LuaPushPropertyArrayObject(L: Plua_State; Obj :TLuaObject; PropName :string): boolean;
  453. begin
  454. lua_newtable(L);
  455. LuaSetTableString(L, -1, 'ID', ARRAYPROP_STR);
  456. LuaSetTableLightUserData(L, -1, ARRAYPROP_STR, Obj);
  457. LuaSetTableString(L, -1, ARRAYPROPNAME_STR, PropName);
  458. LuaSetTablePropertyFuncs(L, -1, Lua_ArrayProp_Get, Lua_ArrayProp_Set);
  459. Result :=true;
  460. end;
  461. //==============================================================================
  462. //Set Properties Support
  463. function Lua_IsPropertySet(L: Plua_State; Index: Integer): boolean;
  464. begin
  465. Result :=False;
  466. try
  467. Result :=lua_istable(L, Index) and (LuaGetTableString(L, Index, 'ID')=SETPROP_VALUE);
  468. except
  469. end;
  470. end;
  471. function GetPropertySet(Data :PLuaSetPropData; L: Plua_State; Index: Integer): String;
  472. begin
  473. Result :='';
  474. if Data<>nil then FillChar(Data^, Sizeof(TLuaSetPropData), 0);
  475. try
  476. if lua_istable(L, Index)
  477. then begin
  478. Result :=LuaGetTableString(L, Index, SETPROP_VALUE);
  479. if Data<>nil then
  480. begin
  481. Data^.ID :=LuaGetTableString(L, Index, 'ID');
  482. Data^.Info :=LuaGetTableLightUserData(L, Index, SETPROP_INFO);
  483. end;
  484. end
  485. else begin
  486. if (lua_isString(L, Index)=1)
  487. then Result :=LuaToString(L, Index);
  488. end;
  489. if Data<>nil
  490. then Data^.Value :=Result;
  491. except
  492. end;
  493. end;
  494. function SetToString(TypeInfo: PTypeInfo; Value: Integer; Brackets: Boolean): string;
  495. var
  496. S: TIntegerSet;
  497. I: Integer;
  498. EnumInfo :PTypeInfo;
  499. begin
  500. Result := '';
  501. Integer(S) := Value;
  502. EnumInfo := GetTypeData(TypeInfo)^.CompType^;
  503. for I := 0 to SizeOf(Integer) * 8 - 1 do
  504. if I in S then
  505. begin
  506. if Result <> '' then
  507. Result := Result + ',';
  508. Result := Result + GetEnumName(EnumInfo, I);
  509. end;
  510. if Brackets then
  511. Result := '[' + Result + ']';
  512. end;
  513. // grab the next enum name
  514. function SetNextWord(var P: PChar): string;
  515. var
  516. i: Integer;
  517. begin
  518. i := 0;
  519. // scan til whitespace
  520. while not (P[i] in [',', ' ', #0,']']) do
  521. Inc(i);
  522. SetString(Result, P, i);
  523. // skip whitespace
  524. while P[i] in [',', ' ',']'] do
  525. Inc(i);
  526. Inc(P, i);
  527. end;
  528. function StringToSet(EnumInfo: PTypeInfo; const Value: string): Integer;
  529. var
  530. P: PChar;
  531. EnumName: string;
  532. EnumValue: Longint;
  533. begin
  534. Result := 0;
  535. if Value = '' then Exit;
  536. P := PChar(Value);
  537. // skip leading bracket and whitespace
  538. while P^ in ['[',' '] do
  539. Inc(P);
  540. EnumName := SetNextWord(P);
  541. while EnumName <> '' do
  542. begin
  543. EnumValue := GetEnumValue(EnumInfo, EnumName);
  544. if EnumValue < 0 then
  545. raise EPropertyConvertError.CreateFmt('Invalid Property Element %s', [EnumName]);
  546. Include(TIntegerSet(Result), EnumValue);
  547. EnumName := SetNextWord(P);
  548. end;
  549. end;
  550. function Lua_SetProp_Add(L: Plua_State): Integer; cdecl;
  551. Var
  552. Val1, Val2,
  553. EnumName,
  554. xResult :String;
  555. NParams :Integer;
  556. pVal2 :PChar;
  557. begin
  558. Result := 0;
  559. NParams := lua_gettop(L);
  560. if (NParams=2) then
  561. try
  562. Val1 :=GetPropertySet(nil, L, 1);
  563. if (Val1='')
  564. then raise Exception.Create('Left Side is Not a Set');
  565. Val2 :=GetPropertySet(nil, L, 2);
  566. if (Val2='')
  567. then raise Exception.Create('Right Side is Not a Set');
  568. xResult :=Val1;
  569. pVal2 :=PChar(Val2);
  570. EnumName := SetNextWord(pVal2);
  571. while (EnumName<>'') do
  572. begin
  573. if (Pos(EnumName, Val1)<1)
  574. then xResult :=xResult+','+EnumName;
  575. EnumName := SetNextWord(pVal2);
  576. end;
  577. LuaPushPropertySet(L, nil, xResult);
  578. Result :=1;
  579. except
  580. On E:Exception do begin
  581. LuaError(L, ERR_Script+E.Message);
  582. end;
  583. end;
  584. end;
  585. function Lua_SetProp_Sub(L: Plua_State): Integer; cdecl;
  586. Var
  587. Val1, Val2,
  588. EnumName,
  589. xResult :String;
  590. NParams :Integer;
  591. pVal2 :PChar;
  592. xPos :Integer;
  593. begin
  594. Result := 0;
  595. NParams := lua_gettop(L);
  596. if (NParams=2) then
  597. try
  598. Val1 :=GetPropertySet(nil, L, 1);
  599. if (Val1='')
  600. then raise Exception.Create('Left Side is Not a Set');
  601. Val2 :=GetPropertySet(nil, L, 2);
  602. if (Val1='')
  603. then raise Exception.Create('Right Side is Not a Set');
  604. xResult :=Val1;
  605. pVal2 :=PChar(Val2);
  606. EnumName := SetNextWord(pVal2);
  607. while (EnumName<>'') do
  608. begin
  609. xPos := Pos(EnumName, xResult);
  610. while (xPos>0) do
  611. begin
  612. Delete(xResult, xPos, Length(EnumName)+1);
  613. xPos := Pos(EnumName, xResult);
  614. end;
  615. EnumName := SetNextWord(pVal2);
  616. end;
  617. LuaPushPropertySet(L, nil, xResult);
  618. Result :=1;
  619. except
  620. On E:Exception do begin
  621. LuaError(L, ERR_Script+E.Message);
  622. end;
  623. end;
  624. end;
  625. function LuaPushPropertySet(L: Plua_State; TypeInfo :PTypeInfo; PropValue :Variant): boolean;
  626. begin
  627. lua_newtable(L);
  628. LuaSetTableString(L, -1, 'ID', SETPROP_INFO);
  629. LuaSetTableLightUserData(L, -1, SETPROP_INFO, TypeInfo);
  630. if (TVarData(PropValue).VType = varString) or
  631. (TVarData(PropValue).VType = varOleStr)
  632. then LuaSetTableString(L, -1, SETPROP_VALUE, PropValue)
  633. else LuaSetTableString(L, -1, SETPROP_VALUE, SetToString(TypeInfo, PropValue, false));
  634. LuaSetMetaFunction(L, -1, '__add', Lua_SetProp_Add);
  635. LuaSetMetaFunction(L, -1, '__sub', Lua_SetProp_Sub);
  636. Result :=true;
  637. end;
  638. //==============================================================================
  639. function GetTLuaObject(L: Plua_State; Index: Integer): TLuaObject;
  640. Var
  641. pObjData :PLuaObjectData;
  642. begin
  643. //Result := TLuaObject(LuaGetTableLightUserData(L, Index, OBJHANDLE_STR));
  644. Result :=nil;
  645. try
  646. if (lua_isuserdata(L, Index)=1) then
  647. begin
  648. pObjData :=lua_touserdata(L, Index);
  649. if (pObjData^.ID=OBJHANDLE_STR)
  650. then Result :=pObjData^.Obj;
  651. end;
  652. except
  653. end;
  654. end;
  655. //=== Methods Access methods ===================================================
  656. function Lua_TObject_Methods(L: Plua_State): Integer; cdecl;
  657. var
  658. NParams,
  659. iParams,
  660. invParams :Integer;
  661. theParams :array of Variant;
  662. xResult :Variant;
  663. ParamISOBJ :Boolean;
  664. MethodName :String;
  665. curComponent :TObject;
  666. NewObj,
  667. LuaObj :TLuaObject;
  668. PropSetData :TLuaSetPropData;
  669. retValue :Variant;
  670. begin
  671. Result :=0;
  672. NParams := lua_gettop(L);
  673. try
  674. LuaObj :=GetTLuaObject(L, 1);
  675. MethodName :=LuaGetCurrentFuncName(L);
  676. //Fill Params for Method call in inverse sequense (why???)
  677. SetLength(theParams, (NParams-1));
  678. invParams :=0;
  679. for iParams :=NParams downto 2 do
  680. begin
  681. //If Param[iParams] is an Object get it's real value
  682. ParamISOBJ :=false;
  683. NewObj :=GetTLuaObject(L, iParams);
  684. ParamISOBJ :=(NewObj<>nil);
  685. if ParamISOBJ
  686. then xResult :=Integer(NewObj.InstanceObj)
  687. else begin
  688. if Lua_IsPropertySet(L, iParams)
  689. then begin
  690. xResult :=GetPropertySet(@PropSetData, L, iParams);
  691. //try to convert string value to Real Set Value
  692. if (PropSetData.Info<>nil)
  693. then xResult :=StringToSet(PropSetData.Info, xResult);
  694. end
  695. else xResult :=LuaToVariant(L, iParams);
  696. end;
  697. theParams[invParams] :=xResult;
  698. inc(invParams);
  699. end;
  700. retValue := LuaObj.CallMethod(MethodName, theParams, true);
  701. if (retValue<>NULL)
  702. then begin
  703. //TO-DO : PushVariant è riduttivo, potrebbe tornare un oggetto etc...
  704. // Fare una procedura simile a PushProperty
  705. LuaPushVariant(L, retValue);
  706. Result :=1;
  707. end;
  708. except
  709. On E:Exception do begin
  710. LuaError(L, ERR_Script+E.Message);
  711. end;
  712. end;
  713. end;
  714. function Lua_TObject_GetProp(L: Plua_State): Integer; cdecl; forward;
  715. function Lua_TObject_SetProp(L: Plua_State): Integer; cdecl; forward;
  716. function Lua_TObject_Free(L: Plua_State): Integer; cdecl; forward;
  717. function LuaPush_TLuaObject(L :Plua_State; theParams :array of Variant;
  718. Obj :TObject=nil; ObjClassName :String='';
  719. CanFree :Boolean=True) :boolean;
  720. var
  721. NParams,
  722. iParams :Integer;
  723. xResult :Variant;
  724. retValue :Variant;
  725. ClassData :PLuaClassesListData;
  726. LuaObj :TLuaObject;
  727. NewObj :TObject;
  728. CanCreate :Boolean;
  729. LuaClass :TLuaObjectClass;
  730. pObjData :PLuaObjectData;
  731. scripter :TScriptableObject;
  732. begin
  733. Result :=false;
  734. CanCreate := (Obj=nil);
  735. if CanCreate
  736. then ClassData :=LuaClassesList.Find(ObjClassName)
  737. else ClassData :=LuaClassesList.Find(Obj.ClassType);
  738. if (ClassData=nil)
  739. then LuaClass :=TLuaObject
  740. else LuaClass :=ClassData^.LuaClass;
  741. //lua_newtable(L);
  742. pObjData :=lua_newuserdata(L, sizeof(TLuaObjectData));
  743. if CanCreate
  744. then begin
  745. if (LuaClass<>nil)
  746. then begin
  747. LuaObj :=LuaClass.Create(nil, false);
  748. theParams[High(theParams)] :=Integer(ClassData^.ObjClass);
  749. try
  750. retValue :=LuaObj.CallMethod('LuaCreate', theParams, true);
  751. if (retValue<>NULL)
  752. then NewObj :=TObject(Integer(retValue))
  753. else NewObj :=ClassData^.ObjClass.Create;
  754. except
  755. NewObj :=ClassData^.ObjClass.Create;
  756. end;
  757. LuaObj.Free;
  758. LuaObj :=LuaClass.Create(NewObj, CanFree);
  759. end
  760. else begin
  761. NewObj :=ClassData^.ObjClass.Create;
  762. LuaObj :=LuaClass.Create(NewObj, CanFree);
  763. end;
  764. end
  765. else begin
  766. if (LuaClass<>nil)
  767. then LuaObj :=LuaClass.Create(Obj, false)
  768. else LuaObj :=TLuaObject.Create(Obj, false);
  769. end;
  770. pObjData^.ID :=OBJHANDLE_STR;
  771. pObjData^.Obj :=LuaObj;
  772. LuaSetTablePropertyFuncs(L, -1, Lua_TObject_GetProp, Lua_TObject_SetProp);
  773. LuaSetMetaFunction(L, -1, '__gc', Lua_TObject_Free);
  774. Result :=true;
  775. end;
  776. //=== Properties Access methods ================================================
  777. //NON FUNZIONA!!!!!!! PERCHE' FA LA LISTA SOLO DELLE PROPERTY PUBLISHED
  778. function FindPredefArrayProp(AComponent :TObject):String;
  779. Var
  780. Props :PPropList;
  781. i, n :Integer;
  782. curPropInfo :PPropInfo;
  783. begin
  784. Result :='';
  785. n :=GetPropList(AComponent, Props);
  786. for i:=0 to n-1 do
  787. begin
  788. curPropInfo :=PPropInfo(Props^[i]);
  789. if ((curPropInfo^.Default and $80000000)<>0) and
  790. (curPropInfo^.PropType^^.Kind = tkArray)
  791. then begin
  792. Result :=curPropInfo^.Name;
  793. end;
  794. end;
  795. end;
  796. function Lua_TObject_GetProp(L: Plua_State): Integer; cdecl;
  797. Var
  798. ty :Integer;
  799. PropName :String;
  800. PropValue :Variant;
  801. PropInfo :PPropInfo;
  802. PropType :PTypeInfo;
  803. GetPropOK :Boolean;
  804. NParams :Integer;
  805. ClassData :PLuaClassesListData;
  806. LuaObj :TLuaObject;
  807. NewObj :TObject;
  808. function TryGetProp(AComponent :TObject; PropName :String; PropKind :TTypeKinds):Boolean;
  809. Var
  810. AsString :Boolean;
  811. begin
  812. Result :=false;
  813. try
  814. PropInfo :=GetPropInfo(AComponent, PropName, PropKind);
  815. if (PropInfo<>nil)
  816. then begin //This Name is a Property
  817. PropType :=PropInfo^.PropType^;
  818. //Return as String only if the property is a Set or an Enum, exclude the Boolean
  819. if (PropType^.Kind=tkEnumeration)
  820. then AsString := not(GetTypeData(PropType)^.BaseType^ = TypeInfo(Boolean))
  821. else AsString := (PropType^.Kind=tkSet);
  822. PropValue :=GetPropValue(AComponent, PropInfo, AsString);
  823. Result :=true;
  824. end;
  825. except
  826. end;
  827. end;
  828. function TryGetPublicProp:Boolean;
  829. Var
  830. AsString :Boolean;
  831. begin
  832. Result :=false;
  833. try
  834. PropInfo :=LuaObj.GetPublicPropInfo(PropName);
  835. if (PropInfo<>nil)
  836. then begin //This Name is a Property
  837. PropType :=PropInfo^.PropType^;
  838. //Return as String only if the property is a Set or an Enum, exclude the Boolean
  839. if (PropType^.Kind=tkEnumeration)
  840. then AsString := not(GetTypeData(PropType)^.BaseType^ = TypeInfo(Boolean))
  841. else AsString := (PropType^.Kind=tkSet);
  842. if (PropType^.Kind<>tkArray)
  843. then PropValue :=GetPropValue(LuaObj.InstanceObj, PropInfo, AsString);
  844. Result :=true;
  845. end;
  846. except
  847. end;
  848. end;
  849. procedure GetPredefArrayProp(Index: Integer);
  850. var
  851. indice :Variant;
  852. begin
  853. GetPropOK :=false;
  854. try
  855. indice :=LuaToVariant(L, Index);
  856. PropName :=LuaObj.GetDefaultArrayProp;
  857. PropType :=LuaObj.GetArrayPropType(PropName, indice);
  858. GetPropOK := (PropType<>nil);
  859. except
  860. end;
  861. if GetPropOK
  862. then PropValue :=LuaObj.GetArrayProp(PropName, indice)
  863. else PropValue :=NULL;
  864. end;
  865. begin
  866. Result := 0;
  867. GetPropOK := false;
  868. NParams := lua_gettop(L);
  869. if (NParams>0) then
  870. try
  871. LuaObj :=GetTLuaObject(L, 1);
  872. ty := lua_type(L, 2);
  873. if (ty = LUA_TNUMBER)
  874. then GetPredefArrayProp(2)
  875. else begin
  876. PropName :=LuaToString(L, 2);
  877. GetPropOK :=TryGetProp(LuaObj, PropName, tkProperties);
  878. if not(GetPropOK)
  879. then begin //Is not a Property published in the TLuaObject, try the TObject
  880. GetPropOK :=TryGetProp(LuaObj.InstanceObj, PropName, tkProperties);
  881. if not(GetPropOK)
  882. then begin //Try with public Properties using scripter.GetPublicXXX
  883. GetPropOK :=TryGetPublicProp;
  884. end;
  885. if not(GetPropOK)
  886. then begin //Try with public elements using scripter.GetElementXXX
  887. try
  888. PropType :=LuaObj.GetElementType(PropName);
  889. GetPropOK := (PropType<>nil);
  890. except
  891. end;
  892. if GetPropOK and (PropType^.Kind<>tkArray)
  893. then PropValue :=LuaObj.GetElement(PropName);
  894. end;
  895. end;
  896. end;
  897. if (GetPropOK)
  898. then begin //This Name is a Property
  899. Result :=PushProperty(L, LuaObj, PropName, PropValue, PropType);
  900. end
  901. else begin //This Name may be a Method or an Event ???????????
  902. //TO-DO : Testare se è un evento (OnXXXX), in questo caso
  903. // tornare l' eventuale nome della funzione lua
  904. // (this code is for method)
  905. LuaRawSetTableNil(L, 1, PropName);
  906. LuaRawSetTableFunction(L, 1, PropName, Lua_TObject_Methods);
  907. lua_pushcfunction(L, Lua_TObject_Methods);
  908. Result := 1;
  909. end;
  910. except
  911. On E:Exception do begin
  912. LuaError(L, ERR_Script+E.Message);
  913. end;
  914. end;
  915. end;
  916. // TObject:SetProp(string PropName, variant Value) set Property Value.
  917. function Lua_TObject_SetProp(L: Plua_State): Integer; cdecl;
  918. Var
  919. curComponent :TObject;
  920. ty :Integer;
  921. PropName :String;
  922. PropInfo :PPropInfo;
  923. PropType :PTypeInfo;
  924. SetPropOK :Boolean;
  925. NewVal :Variant;
  926. NParams :Integer;
  927. ClassData :PLuaClassesListData;
  928. LuaObj :TLuaObject;
  929. NewObj :TLuaObject;
  930. NewValISPropertySet,
  931. NewValISOBJ :Boolean;
  932. PropertySetData :TLuaSetPropData;
  933. function TrySetProp(AComponent :TObject; PropName :String; PropKind :TTypeKinds):Boolean;
  934. begin
  935. Result :=false;
  936. try
  937. PropInfo :=GetPropInfo(AComponent, PropName, PropKind);
  938. if (PropInfo<>nil)
  939. then begin //This Name is a Property
  940. curComponent :=AComponent;
  941. PropType :=PropInfo^.PropType^;
  942. Result :=true;
  943. end;
  944. except
  945. end;
  946. end;
  947. function TrySetPublicProp:Boolean;
  948. begin
  949. Result :=false;
  950. try
  951. PropInfo :=LuaObj.GetPublicPropInfo(PropName);
  952. if (PropInfo<>nil)
  953. then begin //This Name is a Property
  954. curComponent :=LuaObj.InstanceObj;
  955. PropType :=PropInfo^.PropType^;
  956. Result :=true;
  957. end;
  958. except
  959. end;
  960. end;
  961. procedure SetPredefArray(Index: Integer);
  962. var
  963. indice :Variant;
  964. begin
  965. indice :=LuaToVariant(L, Index);
  966. PropName :=LuaObj.GetDefaultArrayProp;
  967. PropType :=LuaObj.GetArrayPropType(PropName, indice);
  968. if (PropType^.Kind=tkClass)
  969. then begin
  970. if NewValISOBJ
  971. then LuaObj.SetArrayProp(PropName, indice, Integer(NewObj.InstanceObj))
  972. else raise Exception.Createfmt('Cannot assign %s to %s.%s', [NewVal, curComponent.ClassName, PropName]);
  973. end
  974. else LuaObj.SetArrayProp(PropName, indice, NewVal);
  975. end;
  976. begin
  977. Result := 0;
  978. ty :=lua_type(L, 3);
  979. if (ty <> LUA_TFUNCTION) then
  980. try
  981. LuaObj :=GetTLuaObject(L, 1);
  982. //If the new Value is an Object get it's real value
  983. NewValISOBJ :=false;
  984. NewObj :=GetTLuaObject(L, 3);
  985. NewValISOBJ :=(NewObj<>nil);
  986. if not(NewValISOBJ)
  987. then begin
  988. NewValISPropertySet :=Lua_IsPropertySet(L, 3);
  989. if NewValISPropertySet
  990. then NewVal :=GetPropertySet(@PropertySetData, L, 3)
  991. else NewVal :=LuaToVariant(L, 3);
  992. end;
  993. ty := lua_type(L, 2);
  994. if (ty = LUA_TNUMBER)
  995. then SetPredefArray(2)
  996. else begin
  997. PropName :=LuaToString(L, 2);
  998. SetPropOK :=TrySetProp(LuaObj, PropName, tkProperties);
  999. if not(SetPropOK)
  1000. then begin //Is not a Property published in the TLuaObject, try the TObject
  1001. SetPropOK :=TrySetProp(LuaObj.InstanceObj, PropName, tkProperties);
  1002. if not(SetPropOK)
  1003. then begin //Try with public Properties using scripter.GetPublicPropInfo
  1004. SetPropOK :=TrySetPublicProp;
  1005. end;
  1006. if not(SetPropOK)
  1007. then begin //Try with public elements using scripter.SetElementXXX
  1008. try
  1009. PropType :=LuaObj.GetElementType(PropName);
  1010. SetPropOK := (PropType<>nil);
  1011. except
  1012. end;
  1013. if SetPropOK then
  1014. begin
  1015. if (PropType^.Kind=tkClass)
  1016. then begin
  1017. if NewValISOBJ
  1018. then LuaObj.SetElement(PropName, Integer(NewObj.InstanceObj))
  1019. else raise Exception.Createfmt('Cannot assign %s to %s.%s', [NewVal, LuaObj.InstanceObj.ClassName, PropName]);
  1020. end
  1021. else begin
  1022. if NewValISPropertySet //convert string to real Value
  1023. then NewVal :=StringToSet(PropertySetData.Info, NewVal);
  1024. LuaObj.SetElement(PropName, NewVal);
  1025. end;
  1026. Exit;
  1027. end;
  1028. end;
  1029. end;
  1030. if SetPropOK
  1031. then begin
  1032. if (PropType^.Kind=tkClass)
  1033. then begin
  1034. if NewValISOBJ
  1035. then MySetPropValue(curComponent, PropInfo, Integer(NewObj.InstanceObj))
  1036. else raise Exception.Createfmt('Cannot assign %s to %s.%s', [NewVal, curComponent.ClassName, PropName]);
  1037. end
  1038. else MySetPropValue(curComponent, PropInfo, NewVal);
  1039. end
  1040. else begin //This Name may be a Method or an Event ???????????
  1041. //TO-DO : se è un evento potremmo mantenere una Lista
  1042. // che associa un oggetto con il nome di una
  1043. // funzione Lua. Settiamo come evento un
  1044. // nostro metodo che cerca nella Lista l' oggetto
  1045. // e chiama la relativa funzione lua
  1046. end;
  1047. end;
  1048. except
  1049. On E:Exception do begin
  1050. LuaError(L, ERR_Script+E.Message);
  1051. end;
  1052. end;
  1053. end;
  1054. // TObject:Free() free the object.
  1055. function Lua_TObject_Free(L: Plua_State): Integer; cdecl;
  1056. Var
  1057. theObject :TLuaObject;
  1058. NParams :Integer;
  1059. begin
  1060. Result := 0;
  1061. NParams := lua_gettop(L);
  1062. if (NParams=1)
  1063. then begin
  1064. try
  1065. theObject :=GetTLuaObject(L, 1);
  1066. //LuaEventsList.Del(theObject.InstanceObj);
  1067. theObject.Free;
  1068. //LuaSetTableClear(L, 1);
  1069. except
  1070. On E:Exception do begin
  1071. LuaError(L, ERR_Script+E.Message);
  1072. end;
  1073. end;
  1074. end;
  1075. end;
  1076. //==============================================================================
  1077. // Main Functions
  1078. function Lua_CreateObject(L: Plua_State): Integer; cdecl;
  1079. var
  1080. NParams,
  1081. iParams,
  1082. invParams :Integer;
  1083. theParams :array of Variant;
  1084. xResult :Variant;
  1085. retValue :PVariant;
  1086. ObjClassName :String;
  1087. ClassData :PLuaClassesListData;
  1088. scripter :TLuaObject;
  1089. NewObj :TLuaObject;
  1090. CanFree,
  1091. ParamISOBJ :Boolean;
  1092. PropSetData :TLuaSetPropData;
  1093. begin
  1094. Result :=0;
  1095. NParams := lua_gettop(L);
  1096. if (NParams>1)
  1097. then begin
  1098. try
  1099. ObjClassName :=LuaToString(L, 1);
  1100. CanFree :=LuaToBoolean(L, 2);
  1101. //Fill Params for Create call in inverse sequense (why???)
  1102. SetLength(theParams, NParams-1);
  1103. invParams :=0;
  1104. for iParams :=NParams downto 3 do
  1105. begin
  1106. //If Param[iParams] is an Object get it's real value
  1107. ParamISOBJ :=false;
  1108. NewObj :=GetTLuaObject(L, iParams);
  1109. ParamISOBJ :=(NewObj<>nil);
  1110. if ParamISOBJ
  1111. then xResult :=Integer(NewObj.InstanceObj)
  1112. else begin
  1113. if Lua_IsPropertySet(L, iParams)
  1114. then begin
  1115. xResult :=GetPropertySet(@PropSetData, L, iParams);
  1116. //try to convert string value to Real Set Value
  1117. if (PropSetData.Info<>nil)
  1118. then xResult :=StringToSet(PropSetData.Info, xResult);
  1119. end
  1120. else xResult :=LuaToVariant(L, iParams);
  1121. end;
  1122. theParams[invParams] :=xResult;
  1123. inc(invParams);
  1124. end;
  1125. //LuaPush_TLuaObject sets the last parameter with the Class
  1126. theParams[invParams] :=1234;
  1127. if LuaPush_TLuaObject(L, theParams, nil, ObjClassName, CanFree)
  1128. then Result :=1
  1129. else raise Exception.Createfmt('Cannot Create class %s', [ObjClassName])
  1130. except
  1131. On E:Exception do begin
  1132. LuaError(L, ERR_Script+E.Message);
  1133. end;
  1134. end;
  1135. end;
  1136. end;
  1137. function Lua_GetObject(L: Plua_State): Integer; cdecl;
  1138. var
  1139. NParams,
  1140. iParams,
  1141. invParams :Integer;
  1142. theParams :array of Variant;
  1143. xResult :Variant;
  1144. retValue :PVariant;
  1145. ObjName :String;
  1146. ObjData :PLuaExistingObjListData;
  1147. scripter :TLuaObject;
  1148. NewObj :TObject;
  1149. begin
  1150. Result :=0;
  1151. NParams := lua_gettop(L);
  1152. if (NParams>0)
  1153. then begin
  1154. try
  1155. ObjName :=LuaToString(L, 1);
  1156. ObjData := LuaExistingObjList.Find(ObjName);
  1157. if (ObjData<>nil)
  1158. then begin
  1159. if LuaPush_TLuaObject(L, [], ObjData^.Obj)
  1160. then Result :=1
  1161. else raise Exception.Createfmt('Cannot Interface with class %s', [ObjData^.Obj.ClassName]);
  1162. end
  1163. else raise Exception.Createfmt('Object "%s" not found', [ObjName]);
  1164. except
  1165. On E:Exception do begin
  1166. LuaError(L, ERR_Script+E.Message);
  1167. end;
  1168. end;
  1169. end;
  1170. end;
  1171. procedure RegisterFunctions(L: Plua_State);
  1172. begin
  1173. LuaRegister(L, 'CreateObject', Lua_CreateObject);
  1174. LuaRegister(L, 'GetObject', Lua_GetObject);
  1175. end;
  1176. procedure RegisterClass(ObjClass :TClass; LuaClass :TLuaObjectClass=nil);
  1177. begin
  1178. LuaClassesList.Add(ObjClass, LuaClass);
  1179. end;
  1180. procedure RegisterObject(Obj :TObject; Name :String; LuaClass :TLuaObjectClass=nil);
  1181. begin
  1182. LuaExistingObjList.Add(Obj, Name);
  1183. LuaClassesList.Add(Obj.ClassType, LuaClass);
  1184. end;
  1185. initialization
  1186. LuaClassesList :=TLuaClassesList.Create;
  1187. LuaExistingObjList :=TLuaExistingObjList.Create;
  1188. finalization
  1189. LuaClassesList.Free;
  1190. LuaExistingObjList.Free;
  1191. end.