GXS.Python.Script.pas 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. //
  2. // The graphics rendering engine GLScene http://glscene.org
  3. //
  4. unit GXS.Python.Script;
  5. (*
  6. Python implementation for the GXScene scripting layer.
  7. This unit is experimental.
  8. *)
  9. interface
  10. uses
  11. System.Classes,
  12. System.SysUtils,
  13. GXS.XCollection,
  14. GXS.ScriptBase,
  15. Stage.Manager,
  16. Python.Engine; // from ... current version of pyscript
  17. type
  18. (* This class only adds manager registration logic to the TPythonEngine
  19. class to enable the XCollection items (ie. TgxScriptPython) retain it's
  20. assigned compiler from design to run -time. *)
  21. TgxPythonEngine = class(TPythonEngine)
  22. public
  23. constructor Create(AOnwer: TComponent); override;
  24. destructor Destroy; override;
  25. end;
  26. // Implements Python scripting functionality through the abstracted GLS.ScriptBase
  27. TgxScriptPython = class(TgxScriptBase)
  28. private
  29. FEngine: TgxPythonEngine;
  30. FEngineName: String;
  31. FCompiled, FStarted: Boolean;
  32. protected
  33. procedure SetEngine(const Value: TgxPythonEngine);
  34. procedure ReadFromFiler(reader: TReader); override;
  35. procedure WriteToFiler(writer: TWriter); override;
  36. procedure Loaded; override;
  37. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  38. function GetState: TgxScriptState; override;
  39. public
  40. destructor Destroy; override;
  41. procedure Assign(Source: TPersistent); override;
  42. procedure Compile; override;
  43. procedure Start; override;
  44. procedure Stop; override;
  45. procedure Execute; override;
  46. procedure Invalidate; override;
  47. function Call(aName: String; aParams: array of Variant): Variant; override;
  48. class function FriendlyName: String; override;
  49. class function FriendlyDescription: String; override;
  50. class function ItemCategory: String; override;
  51. published
  52. property Engine: TgxPythonEngine read FEngine write SetEngine;
  53. end;
  54. procedure Register;
  55. // --------------------------------------------------
  56. implementation
  57. // --------------------------------------------------
  58. // ----------
  59. // ---------- TgxPythonEngine ----------
  60. // ----------
  61. constructor TgxPythonEngine.Create(AOnwer: TComponent);
  62. begin
  63. inherited;
  64. RegisterManager(Self);
  65. end;
  66. destructor TgxPythonEngine.Destroy;
  67. begin
  68. DeregisterManager(Self);
  69. inherited;
  70. end;
  71. // ---------------
  72. // --------------- TgxScriptPython ---------------
  73. // ---------------
  74. destructor TgxScriptPython.Destroy;
  75. begin
  76. Invalidate;
  77. inherited;
  78. end;
  79. procedure TgxScriptPython.Assign(Source: TPersistent);
  80. begin
  81. inherited;
  82. if Source is TgxScriptPython then
  83. begin
  84. Engine := TgxScriptPython(Source).Engine;
  85. end;
  86. end;
  87. procedure TgxScriptPython.ReadFromFiler(reader: TReader);
  88. var
  89. archiveVersion: Integer;
  90. begin
  91. inherited;
  92. archiveVersion := reader.ReadInteger;
  93. Assert(archiveVersion = 0);
  94. with reader do
  95. begin
  96. FEngineName := ReadString;
  97. end;
  98. end;
  99. procedure TgxScriptPython.WriteToFiler(writer: TWriter);
  100. begin
  101. inherited;
  102. writer.WriteInteger(0); // archiveVersion
  103. with writer do
  104. begin
  105. if Assigned(FEngine) then
  106. WriteString(FEngine.GetNamePath)
  107. else
  108. WriteString('');
  109. end;
  110. end;
  111. procedure TgxScriptPython.Loaded;
  112. var
  113. temp: TComponent;
  114. begin
  115. inherited;
  116. if FEngineName <> '' then
  117. begin
  118. temp := FindManager(TGLPythonEngine, FEngineName);
  119. if Assigned(temp) then
  120. Engine := TGLPythonEngine(temp);
  121. FEngineName := '';
  122. end;
  123. end;
  124. procedure TgxScriptPython.Notification(AComponent: TComponent;
  125. Operation: TOperation);
  126. begin
  127. if (AComponent = Engine) and (Operation = opRemove) then
  128. Engine := nil;
  129. end;
  130. class function TgxScriptPython.FriendlyName: String;
  131. begin
  132. Result := 'TgxScriptPython';
  133. end;
  134. class function TgxScriptPython.FriendlyDescription: String;
  135. begin
  136. Result := 'Python script';
  137. end;
  138. class function TgxScriptPython.ItemCategory: String;
  139. begin
  140. Result := '';
  141. end;
  142. procedure TgxScriptPython.Compile;
  143. begin
  144. Invalidate;
  145. if Assigned(Engine) then
  146. begin
  147. Engine.ExecStrings(Text);
  148. FCompiled := True;
  149. FStarted := False;
  150. end
  151. else
  152. raise Exception.Create('No engine assigned!');
  153. end;
  154. procedure TgxScriptPython.Execute;
  155. begin
  156. Compile;
  157. end;
  158. procedure TgxScriptPython.Invalidate;
  159. begin
  160. FStarted := False;
  161. FCompiled := False;
  162. end;
  163. procedure TgxScriptPython.Start;
  164. begin
  165. Compile;
  166. FStarted := True;
  167. end;
  168. procedure TgxScriptPython.Stop;
  169. begin
  170. FStarted := False;
  171. end;
  172. function TgxScriptPython.Call(aName: String; aParams: array of Variant)
  173. : Variant;
  174. var
  175. func: PPyObject;
  176. args: array of TVarRec;
  177. i: Integer;
  178. begin
  179. if State = ssUncompiled then
  180. Start;
  181. if State = ssRunning then
  182. begin
  183. func := Engine.FindFunction('__main__', aName);
  184. if Assigned(func) then
  185. if Length(aParams) > 0 then
  186. begin
  187. SetLength(args, Length(aParams));
  188. for i := 0 to Length(aParams) - 1 do
  189. begin
  190. args[i].VType := vtVariant;
  191. args[i].VVariant := @aParams[i];
  192. end;
  193. Result := Engine.EvalFunction(func, args);
  194. end
  195. else
  196. Result := Engine.EvalFunctionNoArgs(func);
  197. end;
  198. end;
  199. procedure TgxScriptPython.SetEngine(const Value: TgxPythonEngine);
  200. begin
  201. if Value <> FEngine then
  202. begin
  203. FEngine := Value;
  204. Invalidate;
  205. end;
  206. end;
  207. function TgxScriptPython.GetState: TgxScriptState;
  208. begin
  209. Result := ssUncompiled;
  210. if Assigned(Engine) and FCompiled and FStarted then
  211. Result := ssRunning;
  212. end;
  213. procedure Register;
  214. begin
  215. RegisterClasses([TgxPythonEngine, TgxScriptPython]);
  216. RegisterComponents('GXScene Python', [TgxPythonEngine]);
  217. end;
  218. // --------------------------------------------------
  219. initialization
  220. // --------------------------------------------------
  221. RegisterXCollectionItemClass(TgxScriptPython);
  222. // --------------------------------------------------
  223. finalization
  224. // --------------------------------------------------
  225. UnregisterXCollectionItemClass(TgxScriptPython);
  226. end.