GLS.Pythons.Script.pas 5.6 KB

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