// // This unit is part of the GLScene Engine, http://glscene.org // (* Python implementation for the GLScene scripting layer. This unit is experimental. *) unit GLScriptPython; interface uses System.Classes, System.SysUtils, XCollection, GLScriptBase, GLManager, PythonEngine; type (* This class only adds manager registration logic to the TPythonEngine class to enable the XCollection items (ie. TGLScriptPython) retain it's assigned compiler from design to run -time. *) TGLPythonEngine = class(TPythonEngine) public constructor Create(AOnwer : TComponent); override; destructor Destroy; override; end; { Implements Python scripting functionality through the abstracted GLScriptBase } TGLScriptPython = class(TGLScriptBase) private FEngine : TGLPythonEngine; FEngineName : String; FCompiled, FStarted : Boolean; protected procedure SetEngine(const Value : TGLPythonEngine); procedure ReadFromFiler(reader : TReader); override; procedure WriteToFiler(writer : TWriter); override; procedure Loaded; override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; function GetState : TGLScriptState; override; public destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure Compile; override; procedure Start; override; procedure Stop; override; procedure Execute; override; procedure Invalidate; override; function Call(aName : String; aParams : array of Variant) : Variant; override; class function FriendlyName : String; override; class function FriendlyDescription : String; override; class function ItemCategory : String; override; published property Engine : TGLPythonEngine read FEngine write SetEngine; end; procedure Register; // -------------------------------------------------- implementation // -------------------------------------------------- // ---------- // ---------- TGLPythonEngine ---------- // ---------- constructor TGLPythonEngine.Create(AOnwer : TComponent); begin inherited; RegisterManager(Self); end; destructor TGLPythonEngine.Destroy; begin DeregisterManager(Self); inherited; end; // --------------- // --------------- TGLScriptPython --------------- // --------------- destructor TGLScriptPython.Destroy; begin Invalidate; inherited; end; procedure TGLScriptPython.Assign(Source: TPersistent); begin inherited; if Source is TGLScriptPython then begin Engine:=TGLScriptPython(Source).Engine; end; end; procedure TGLScriptPython.ReadFromFiler(reader : TReader); var archiveVersion : Integer; begin inherited; archiveVersion:=reader.ReadInteger; Assert(archiveVersion = 0); with reader do begin FEngineName:=ReadString; end; end; procedure TGLScriptPython.WriteToFiler(writer : TWriter); begin inherited; writer.WriteInteger(0); // archiveVersion with writer do begin if Assigned(FEngine) then WriteString(FEngine.GetNamePath) else WriteString(''); end; end; procedure TGLScriptPython.Loaded; var temp : TComponent; begin inherited; if FEngineName<>'' then begin temp:=FindManager(TGLPythonEngine, FEngineName); if Assigned(temp) then Engine:=TGLPythonEngine(temp); FEngineName:=''; end; end; procedure TGLScriptPython.Notification(AComponent: TComponent; Operation: TOperation); begin if (AComponent = Engine) and (Operation = opRemove) then Engine:=nil; end; class function TGLScriptPython.FriendlyName : String; begin Result:='TGLScriptPython'; end; class function TGLScriptPython.FriendlyDescription : String; begin Result:='Python script'; end; class function TGLScriptPython.ItemCategory : String; begin Result:=''; end; procedure TGLScriptPython.Compile; begin Invalidate; if Assigned(Engine) then begin Engine.ExecStrings(Text); FCompiled:=True; FStarted:=False; end else raise Exception.Create('No engine assigned!'); end; procedure TGLScriptPython.Execute; begin Compile; end; procedure TGLScriptPython.Invalidate; begin FStarted:=False; FCompiled:=False; end; procedure TGLScriptPython.Start; begin Compile; FStarted:=True; end; procedure TGLScriptPython.Stop; begin FStarted:=False; end; function TGLScriptPython.Call(aName: String; aParams: array of Variant) : Variant; var func : PPyObject; args : array of TVarRec; i : Integer; begin if State = ssUncompiled then Start; if State = ssRunning then begin func:=Engine.FindFunction('__main__', aName); if Assigned(func) then if Length(aParams)>0 then begin SetLength(args, Length(aParams)); for i:=0 to Length(aParams)-1 do begin args[i].VType:=vtVariant; args[i].VVariant:=@aParams[i]; end; Result:=Engine.EvalFunction(func, args); end else Result:=Engine.EvalFunctionNoArgs(func); end; end; procedure TGLScriptPython.SetEngine(const Value : TGLPythonEngine); begin if Value<>FEngine then begin FEngine:=Value; Invalidate; end; end; function TGLScriptPython.GetState : TGLScriptState; begin Result:=ssUncompiled; if Assigned(Engine) and FCompiled and FStarted then Result:=ssRunning; end; procedure Register; begin RegisterClasses([TGLPythonEngine, TGLScriptPython]); RegisterComponents('GLScene Python', [TGLPythonEngine]); end; // -------------------------------------------------- initialization // -------------------------------------------------- RegisterXCollectionItemClass(TGLScriptPython); // -------------------------------------------------- finalization // -------------------------------------------------- UnregisterXCollectionItemClass(TGLScriptPython); end.