浏览代码

connecting filters to script

johann 5 年之前
父节点
当前提交
c149ccffb3

+ 9 - 5
lazpaint/dialog/filter/ucustomblur.pas

@@ -7,7 +7,8 @@ interface
 uses
   Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
   StdCtrls, ExtCtrls, ExtDlgs,  bgrabitmap, LazPaintType, LCScaleDPI,
-  UResourceStrings, UFilterConnector, UFilterThread, ubrowseimages;
+  UResourceStrings, UFilterConnector, UFilterThread, ubrowseimages,
+  UScripting;
 
 type
 
@@ -42,7 +43,7 @@ type
     procedure SetLazPaintInstance(const AValue: TLazPaintCustomInstance);
     procedure OnTaskEvent({%H-}ASender: TObject; AEvent: TThreadManagerEvent);
   public
-    function ShowDlg(AFilterConnector: TObject): boolean;
+    function ShowDlg(AFilterConnector: TObject): TScriptResult;
     property LazPaintInstance: TLazPaintCustomInstance read FLazPaintInstance write SetLazPaintInstance;
   end;
 
@@ -172,16 +173,19 @@ begin
   end;
 end;
 
-function TFCustomBlur.ShowDlg(AFilterConnector: TObject): boolean;
+function TFCustomBlur.ShowDlg(AFilterConnector: TObject): TScriptResult;
 begin
   FFilterConnector := AFilterConnector as TFilterConnector;
   FThreadManager := TFilterThreadManager.Create(FFilterConnector);
   FThreadManager.OnEvent := @OnTaskEvent;
   try
     if FFilterConnector.ActiveLayer <> nil then
-      result:= (ShowModal = mrOk)
+    begin
+      if ShowModal = mrOk then result := srOk
+      else result := srCancelledByUser;
+    end
     else
-      result := false;
+      result := srException;
   finally
     FFilterConnector := nil;
     FThreadManager.Free;

+ 13 - 7
lazpaint/dialog/filter/uemboss.pas

@@ -7,7 +7,7 @@ interface
 uses
   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
   ExtCtrls, StdCtrls, ComCtrls, BGRABitmap, LazPaintType, LCScaleDPI,
-  ufilterconnector;
+  UFilterConnector, UScripting;
 
 type
 
@@ -47,9 +47,10 @@ type
     procedure PreviewNeeded;
   public
     FilterConnector: TFilterConnector;
+    FVars: TVariableSet;
   end;
 
-function ShowEmbossDlg(AFilterConnector: TObject):boolean;
+function ShowEmbossDlg(AFilterConnector: TObject): TScriptResult;
 
 implementation
 
@@ -57,18 +58,21 @@ uses BGRABitmapTypes, math, ugraph, umac;
 
 { TFEmboss }
 
-function ShowEmbossDlg(AFilterConnector: TObject):boolean;
+function ShowEmbossDlg(AFilterConnector: TObject): TScriptResult;
 var
   FEmboss: TFEmboss;
 begin
-  result := false;
   FEmboss:= TFEmboss.create(nil);
   FEmboss.FilterConnector := AFilterConnector as TFilterConnector;
+  FEmboss.FVars := FEmboss.FilterConnector.Parameters;
   try
     if FEmboss.FilterConnector.ActiveLayer <> nil then
-      result:= (FEmboss.showModal = mrOk)
+    begin
+      if FEmboss.showModal = mrOk then result := srOk
+      else result := srCancelledByUser;
+    end
     else
-      result := false;
+      result := srException;
   finally
     FEmboss.free;
   end;
@@ -89,7 +93,9 @@ end;
 
 procedure TFEmboss.FormShow(Sender: TObject);
 begin
-  angle := FilterConnector.LazPaintInstance.Config.DefaultEmbossAngle;
+  if Assigned(FVars) and FVars.IsDefined('Angle') then
+    angle := FVars.Floats['Angle'] else
+    angle := FilterConnector.LazPaintInstance.Config.DefaultEmbossAngle;
   PreviewNeeded;
   Left := FilterConnector.LazPaintInstance.MainFormBounds.Left
 end;

+ 1 - 0
lazpaint/dialog/filter/ufilterfunction.lfm

@@ -10,6 +10,7 @@ object FFilterFunction: TFFilterFunction
   ClientWidth = 430
   OnCreate = FormCreate
   OnDestroy = FormDestroy
+  OnShow = FormShow
   Position = poScreenCenter
   LCLVersion = '1.0.10.0'
   object Button_OK: TButton

+ 64 - 29
lazpaint/dialog/filter/ufilterfunction.pas

@@ -7,7 +7,7 @@ interface
 uses
   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
   StdCtrls, ExtCtrls, ComCtrls, fpexprpars, UFilterConnector, BGRABitmap,
-  BGRABitmapTypes;
+  BGRABitmapTypes, UScripting;
 
 type
 
@@ -48,13 +48,13 @@ type
     procedure Edit_SaturationChange(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
+    procedure FormShow(Sender: TObject);
     procedure PageControl_ColorChange(Sender: TObject);
     procedure Timer1Timer(Sender: TObject);
   private
     { private declarations }
     FRedExpr,FGreenExpr,FBlueExpr,FAlphaExpr,FHueExpr,FSaturationExpr,FLightnessExpr: TFPExpressionParser;
     FRedError,FGreenError,FBlueError,FAlphaError,FHueError,FSaturationError,FLightnessError: boolean;
-    FExprChanged: boolean;
     FComputing: boolean;
     FComputedImage: TBGRABitmap;
     FComputedLines: integer;
@@ -62,30 +62,43 @@ type
     FInitializing: boolean;
     procedure UpdateExpr(AExpr: TFPExpressionParser; AEdit: TEdit;
       var AError: boolean);
+    procedure InitParams;
     procedure PreviewNeeded;
     function CreateExpr: TFPExpressionParser;
   public
     { public declarations }
   end;
 
-function ShowFilterFunctionDlg(AFilterConnector: TObject):boolean;
+function ShowFilterFunctionDlg(AFilterConnector: TObject): TScriptResult;
 
 implementation
 
 uses LCScaleDPI, UMac, LazPaintType;
 
-function ShowFilterFunctionDlg(AFilterConnector: TObject): boolean;
+function ShowFilterFunctionDlg(AFilterConnector: TObject): TScriptResult;
 var
   FFilterFunction: TFFilterFunction;
 begin
-  result := false;
   FFilterFunction:= TFFilterFunction.create(nil);
   FFilterFunction.FFilterConnector := AFilterConnector as TFilterConnector;
   try
     if FFilterFunction.FFilterConnector.ActiveLayer <> nil then
-      result:= (FFilterFunction.showModal = mrOk)
+    begin
+      if Assigned(FFilterFunction.FFilterConnector.Parameters) and
+        FFilterFunction.FFilterConnector.Parameters.Booleans['Validate'] then
+      begin
+        FFilterFunction.InitParams;
+        FFilterFunction.PreviewNeeded;
+        while FFilterFunction.FComputing do FFilterFunction.Timer1Timer(FFilterFunction);
+        FFilterFunction.FFilterConnector.ValidateAction;
+      end else
+      begin
+        if FFilterFunction.showModal = mrOk then result := srOk
+        else result:= srCancelledByUser;
+      end;
+    end
     else
-      result := false;
+      result := srException;
   finally
     FFilterFunction.free;
   end;
@@ -113,22 +126,6 @@ begin
   FSaturationError := false;
   FLightnessExpr := CreateExpr;
   FLightnessError := false;
-
-  FInitializing := true;
-  Edit_Red.Text := 'red';
-  Edit_RedChange(nil);
-  Edit_Green.Text := 'green';
-  Edit_GreenChange(nil);
-  Edit_Blue.Text := 'blue';
-  Edit_BlueChange(nil);
-  Edit_Alpha.Text := 'alpha';
-  Edit_AlphaChange(nil);
-  Edit_Hue.Text := 'hue';
-  Edit_HueChange(nil);
-  Edit_Saturation.Text := 'saturation';
-  Edit_SaturationChange(nil);
-  Edit_Lightness.Text := 'lightness';
-  Edit_LightnessChange(nil);
   Label_RedEquals.Caption := 'red =';
   Label_GreenEquals.Caption := 'green =';
   Label_BlueEquals.Caption := 'blue =';
@@ -136,10 +133,7 @@ begin
   Label_HueEquals.Caption := 'hue =';
   Label_SaturationEquals.Caption := 'saturation =';
   Label_LightnessEquals.Caption := 'lightness =';
-
-  FExprChanged:= false;
   Label_Variables.Caption := Label_Variables.Caption+' x,y,width,height,random';
-  FInitializing := false;
 end;
 
 procedure TFFilterFunction.FormDestroy(Sender: TObject);
@@ -154,9 +148,15 @@ begin
   FLightnessExpr.Free;
 end;
 
+procedure TFFilterFunction.FormShow(Sender: TObject);
+begin
+  InitParams;
+  PreviewNeeded;
+end;
+
 procedure TFFilterFunction.PageControl_ColorChange(Sender: TObject);
 begin
-  if not FInitializing and FExprChanged then PreviewNeeded;
+  if not FInitializing then PreviewNeeded;
 end;
 
 procedure TFFilterFunction.Timer1Timer(Sender: TObject);
@@ -455,7 +455,6 @@ end;
 procedure TFFilterFunction.UpdateExpr(AExpr: TFPExpressionParser; AEdit: TEdit; var AError: boolean);
 begin
   if AExpr.Expression = Trim(AEdit.Text) then exit;
-  FExprChanged:= true;
   try
     AExpr.Expression := Trim(AEdit.Text);
     AEdit.Color := clWindow;
@@ -488,6 +487,42 @@ begin
   end;
 end;
 
+procedure TFFilterFunction.InitParams;
+begin
+  FInitializing:= true;
+  Edit_Red.Text := 'red';
+  Edit_Green.Text := 'green';
+  Edit_Blue.Text := 'blue';
+  Edit_Alpha.Text := 'alpha';
+  Edit_Hue.Text := 'hue';
+  Edit_Saturation.Text := 'saturation';
+  Edit_Lightness.Text := 'lightness';
+
+  if Assigned(FFilterConnector.Parameters) then
+    with FFilterConnector.Parameters do
+    begin
+      if IsDefined('Red') then Edit_Red.Text := Strings['Red'];
+      if IsDefined('Green') then Edit_Green.Text := Strings['Green'];
+      if IsDefined('Blue') then Edit_Blue.Text := Strings['Blue'];
+      if IsDefined('Alpha') then Edit_Alpha.Text := Strings['Alpha'];
+      if IsDefined('Hue') then Edit_Hue.Text := Strings['Hue'];
+      if IsDefined('Saturation') then Edit_Saturation.Text := Strings['Saturation'];
+      if IsDefined('Lightness') then Edit_Lightness.Text := Strings['Lightness'];
+      if IsDefined('CorrectedHue') then CheckBox_GSBA.Checked:= Booleans['CorrectedHue'];
+      if IsDefined('Hue') or IsDefined('Saturation') or IsDefined('Lightness') then
+        PageControl_Color.ActivePage := TabSheet_HSL;
+    end;
+
+  Edit_RedChange(nil);
+  Edit_GreenChange(nil);
+  Edit_BlueChange(nil);
+  Edit_AlphaChange(nil);
+  Edit_HueChange(nil);
+  Edit_SaturationChange(nil);
+  Edit_LightnessChange(nil);
+  FInitializing:= false;
+end;
+
 function TFFilterFunction.CreateExpr: TFPExpressionParser;
 begin
   result := TFPExpressionParser.Create(nil);
@@ -514,7 +549,7 @@ end;
 
 procedure TFFilterFunction.CheckBox_GSBAChange(Sender: TObject);
 begin
-  if not FInitializing and FExprChanged then PreviewNeeded;
+  if not FInitializing then PreviewNeeded;
 end;
 
 procedure TFFilterFunction.Button_CancelClick(Sender: TObject);

+ 31 - 8
lazpaint/dialog/filter/uformrain.pas

@@ -7,7 +7,7 @@ interface
 uses
   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
   ExtCtrls, StdCtrls, ComCtrls, UFilterConnector, BGRABitmapTypes, BGRABitmap,
-  URainType;
+  URainType, UScripting;
 
 type
 
@@ -43,12 +43,14 @@ type
     InPaintBoxMouseMove: boolean;
     PaintBoxMouseMovePos: TPoint;
     selectingWind: boolean;
+    FVars: TVariableSet;
     function GetRainRenderer: TRainRenderer;
     function GetRainQuantity: single;
     procedure SetRainQuantity(AValue: single);
     procedure ComputeWind(X,{%H-}Y: integer);
     function ComputeFilteredLayer: TBGRABitmap;
     procedure PreviewNeeded;
+    procedure InitParams;
     property RainQuantity: single read GetRainQuantity write SetRainQuantity;
     property RainRenderer: TRainRenderer read GetRainRenderer;
   public
@@ -57,24 +59,36 @@ type
     renderTimeInS: Double;
   end;
 
-function ShowRainDlg(AFilterConnector: TObject):boolean;
+function ShowRainDlg(AFilterConnector: TObject): TScriptResult;
 
 implementation
 
 uses LCScaleDPI, umac, LazPaintType;
 
-function ShowRainDlg(AFilterConnector: TObject):boolean;
+function ShowRainDlg(AFilterConnector: TObject): TScriptResult;
 var
   FRain: TFRain;
 begin
-  result := false;
   FRain := TFRain.create(nil);
   FRain.FilterConnector := AFilterConnector as TFilterConnector;
+  FRain.FVars := FRain.FilterConnector.Parameters;
   try
     if FRain.FilterConnector.ActiveLayer <> nil then
-      result:= (FRain.showModal = mrOk)
+    begin
+      if Assigned(FRain.FVars) and FRain.FVars.Booleans['Validate'] then
+      begin
+        FRain.InitParams;
+        FRain.PreviewNeeded;
+        FRain.FilterConnector.ValidateAction;
+        result := srOk;
+      end else
+      begin
+        if FRain.showModal = mrOk then result := srOk
+        else result := srCancelledByUser;
+      end;
+    end
     else
-      result := false;
+      result := srException;
   finally
     FRain.free;
   end;
@@ -109,8 +123,7 @@ end;
 
 procedure TFRain.FormShow(Sender: TObject);
 begin
-  wind := FilterConnector.LazPaintInstance.Config.DefaultRainWind;
-  RainQuantity := FilterConnector.LazPaintInstance.Config.DefaultRainQuantity;
+  InitParams;
   PreviewNeeded;
   Left := FilterConnector.LazPaintInstance.MainFormBounds.Left;
   Timer1.Enabled := true;
@@ -226,6 +239,16 @@ begin
   FilterConnector.PutImage(ComputeFilteredLayer,False,True);
 end;
 
+procedure TFRain.InitParams;
+begin
+  if Assigned(FVars) and FVars.IsDefined('Wind') then
+    wind := FVars.Floats['Wind']
+  else wind := FilterConnector.LazPaintInstance.Config.DefaultRainWind;
+  if Assigned(FVars) and FVars.IsDefined('Amount') then
+    RainQuantity := FVars.Floats['Amount']
+  else RainQuantity := FilterConnector.LazPaintInstance.Config.DefaultRainQuantity;
+end;
+
 {$R *.lfm}
 
 end.

+ 27 - 9
lazpaint/dialog/filter/umotionblur.pas

@@ -7,7 +7,7 @@ interface
 uses
   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
   StdCtrls, Spin, ExtCtrls, BGRABitmap, LazPaintType, LCScaleDPI,
-  UFilterConnector, UFilterThread;
+  UFilterConnector, UFilterThread, UScripting;
 
 type
 
@@ -41,6 +41,7 @@ type
     { private declarations }
     FFilterConnector: TFilterConnector;
     FThreadManager: TFilterThreadManager;
+    FVars: TVariableSet;
     angle: single;
     selectingAngle: boolean;
     InPaintBoxMouseMove: boolean;
@@ -52,26 +53,29 @@ type
     procedure OnTaskEvent({%H-}ASender: TObject; AEvent: TThreadManagerEvent);
   end;
 
-function ShowMotionBlurDlg(AFilterConnector: TObject):boolean;
+function ShowMotionBlurDlg(AFilterConnector: TObject): TScriptResult;
 
 implementation
 
 uses BGRABitmapTypes, math, ugraph, umac, BGRAFilters;
 
-function ShowMotionBlurDlg(AFilterConnector: TObject):boolean;
+function ShowMotionBlurDlg(AFilterConnector: TObject): TScriptResult;
 var
   FMotionBlur: TFMotionBlur;
 begin
-  result := false;
   FMotionBlur:= TFMotionBlur.create(nil);
   FMotionBlur.FFilterConnector := AFilterConnector as TFilterConnector;
   FMotionBlur.FThreadManager := TFilterThreadManager.Create(FMotionBlur.FFilterConnector);
   FMotionBlur.FThreadManager.OnEvent:= @FMotionBlur.OnTaskEvent;
+  FMotionBlur.FVars := FMotionBlur.FFilterConnector.Parameters;
   try
     if FMotionBlur.FFilterConnector.ActiveLayer <> nil then
-      result:= (FMotionBlur.showmodal = mrOk)
+    begin
+      if FMotionBlur.ShowModal = mrOk then result := srOk
+      else result := srCancelledByUser;
+    end
     else
-      result := false;
+      result := srException;
   finally
     FMotionBlur.FThreadManager.free;
     FMotionBlur.free;
@@ -187,10 +191,24 @@ end;
 procedure TFMotionBlur.FormShow(Sender: TObject);
 begin
   FQuitQuery := false;
-  Checkbox_Oriented.Checked := FFilterConnector.LazPaintInstance.Config.DefaultBlurMotionOriented;
-  SpinEdit_Distance.Value := FFilterConnector.LazPaintInstance.Config.DefaultBlurMotionDistance;
+
+  if Assigned(FVars) and (FVars.IsDefined('Oriented')) then
+    Checkbox_Oriented.Checked := FVars.Booleans['Oriented']
+  else
+    Checkbox_Oriented.Checked := FFilterConnector.LazPaintInstance.Config.DefaultBlurMotionOriented;
+
+  if Assigned(FVars) and (FVars.IsDefined('Distance')) then
+    SpinEdit_Distance.Value := FVars.Floats['Distance']
+  else
+    SpinEdit_Distance.Value := FFilterConnector.LazPaintInstance.Config.DefaultBlurMotionDistance;
+
   UpdateStep;
-  angle := FFilterConnector.LazPaintInstance.Config.DefaultBlurMotionAngle;
+
+  if Assigned(FVars) and (FVars.IsDefined('Angle')) then
+    angle := FVars.Floats['Angle']
+  else
+    angle := FFilterConnector.LazPaintInstance.Config.DefaultBlurMotionAngle;
+
   PreviewNeeded;
   Left := FFilterConnector.LazPaintInstance.MainFormBounds.Left;
 end;

+ 47 - 12
lazpaint/dialog/filter/unoisefilter.pas

@@ -6,7 +6,8 @@ interface
 
 uses
   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
-  StdCtrls, Spin, ExtCtrls, BGRABitmap, BGRABitmapTypes, UFilterConnector;
+  StdCtrls, Spin, ExtCtrls, BGRABitmap, BGRABitmapTypes, UFilterConnector,
+  UScripting;
 
 type
   { TFNoiseFilter }
@@ -33,6 +34,7 @@ type
     { private declarations }
     FComputedLayer: TBGRABitmap;
     FClosing: boolean;
+    procedure InitParams;
   public
     FInitializing: boolean;
     FFilterConnector: TFilterConnector;
@@ -40,24 +42,35 @@ type
     procedure PreviewNeeded(ARecomputeRandom: boolean);
   end;
 
-function ShowNoiseFilterDlg(AFilterConnector: TObject):boolean;
+function ShowNoiseFilterDlg(AFilterConnector: TObject): TScriptResult;
 
 implementation
 
 uses BGRAGradientScanner, umac, LCScaleDPI, LazPaintType;
 
-function ShowNoiseFilterDlg(AFilterConnector: TObject):boolean;
+function ShowNoiseFilterDlg(AFilterConnector: TObject): TScriptResult;
 var
   FNoiseFilter: TFNoiseFilter;
 begin
-  result := false;
   FNoiseFilter:= TFNoiseFilter.create(nil);
   FNoiseFilter.FFilterConnector := AFilterConnector as TFilterConnector;
   try
     if FNoiseFilter.FFilterConnector.ActiveLayer <> nil then
-      result:= (FNoiseFilter.showModal = mrOk)
+    begin
+      if Assigned(FNoiseFilter.FFilterConnector.Parameters) and
+        FNoiseFilter.FFilterConnector.Parameters.Booleans['Validate'] then
+      begin
+        FNoiseFilter.InitParams;
+        FNoiseFilter.PreviewNeeded(true);
+        FNoiseFilter.FFilterConnector.ValidateAction;
+      end else
+      begin
+        if FNoiseFilter.showModal = mrOk then result := srOk
+        else result := srCancelledByUser;
+      end;
+    end
     else
-      result := false;
+      result := srException;
   finally
     FNoiseFilter.free;
   end;
@@ -107,12 +120,8 @@ begin
   FInitializing := true;
   FClosing := false;
   Top := FFilterConnector.LazPaintInstance.MainFormBounds.Top;
-  if FFilterConnector.LazPaintInstance.BlackAndWhite then
-  begin
-    Radio_GrayscaleNoise.Checked := true;
-    Radio_RGBNoise.Enabled := False;
-  end;
   FInitializing := false;
+  InitParams;
   PreviewNeeded(True);
 end;
 
@@ -124,6 +133,27 @@ begin
   PreviewNeeded(False);
 end;
 
+procedure TFNoiseFilter.InitParams;
+begin
+  FInitializing:= true;
+  if FFilterConnector.LazPaintInstance.BlackAndWhite then
+  begin
+    Radio_GrayscaleNoise.Checked := true;
+    Radio_RGBNoise.Enabled := False;
+  end else
+  begin
+    Radio_RGBNoise.Enabled := true;
+    Radio_RGBNoise.Checked := true;
+  end;
+  if Assigned(FFilterConnector.Parameters) then
+  with FFilterConnector.Parameters do
+  begin
+    if Booleans['Grayscale'] then Radio_GrayscaleNoise.Checked:= true;
+    if IsDefined('Opacity') then SpinEdit_Alpha.Value := Integers['Opacity'];
+  end;
+  FInitializing:= false;
+end;
+
 procedure TFNoiseFilter.ComputeFilteredLayer;
 var scan: TBGRARandomScanner;
 begin
@@ -137,7 +167,12 @@ end;
 procedure TFNoiseFilter.PreviewNeeded(ARecomputeRandom: boolean);
 begin
   if ARecomputeRandom or (FComputedLayer = nil) then ComputeFilteredLayer;
-  FFilterConnector.PutImage(FComputedLayer,Radio_RGBNoise.Checked,False);
+  if SpinEdit_Alpha.Value <> 255 then
+  begin
+    FFilterConnector.RestoreBackup;
+    FFilterConnector.PutImage(FComputedLayer,Radio_RGBNoise.Checked,False,dmDrawWithTransparency);
+  end else
+    FFilterConnector.PutImage(FComputedLayer,Radio_RGBNoise.Checked,False,dmSet);
 end;
 
 end.

+ 9 - 6
lazpaint/dialog/filter/uphongfilter.pas

@@ -6,7 +6,8 @@ interface
 
 uses
   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
-  StdCtrls, ExtCtrls, Spin, UFilterConnector, BGRABitmapTypes, BGRABitmap;
+  StdCtrls, ExtCtrls, Spin, UFilterConnector, BGRABitmapTypes, BGRABitmap,
+  UScripting;
 
 type
 
@@ -60,25 +61,27 @@ type
     property CurrentLightPos: TPointF read GetCurrentLightPos;
   end;
 
-function ShowPhongFilterDlg(AFilterConnector: TObject):boolean;
+function ShowPhongFilterDlg(AFilterConnector: TObject): TScriptResult;
 
 implementation
 
 uses LCScaleDPI, UMac, BGRAGradients, LazPaintType;
 
-function ShowPhongFilterDlg(AFilterConnector: TObject): boolean;
+function ShowPhongFilterDlg(AFilterConnector: TObject): TScriptResult;
 var
   FPhongFilter: TFPhongFilter;
 begin
-  result := false;
   FPhongFilter:= TFPhongFilter.create(nil);
   FPhongFilter.FilterConnector := AFilterConnector as TFilterConnector;
   FPhongFilter.FWorkspaceColor:= FPhongFilter.FilterConnector.LazPaintInstance.Config.GetWorkspaceColor;
   try
     if FPhongFilter.FilterConnector.ActiveLayer <> nil then
-      result:= (FPhongFilter.showModal = mrOk)
+    begin
+      if FPhongFilter.showModal = mrOk then result := srOk
+      else result := srCancelledByUser;
+    end
     else
-      result := false;
+      result := srException;
   finally
     FPhongFilter.free;
   end;

+ 55 - 11
lazpaint/dialog/filter/upixelate.pas

@@ -7,7 +7,7 @@ interface
 uses
   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
   StdCtrls, Spin, ExtCtrls, BGRABitmap, LazPaintType, LCScaleDPI,
-  ufilterconnector;
+  UFilterConnector, UScripting;
 
 type
 
@@ -33,28 +33,40 @@ type
     FInitializing: boolean;
     FFilterConnector: TFilterConnector;
     function ComputeFilteredLayer: TBGRABitmap;
+    procedure InitParams;
     procedure PreviewNeeded;
   public
   end;
 
-function ShowPixelateDlg(AFilterConnector: TObject):boolean;
+function ShowPixelateDlg(AFilterConnector: TObject): TScriptResult;
 
 implementation
 
 uses umac, BGRABitmapTypes, uresourcestrings, ugraph;
 
-function ShowPixelateDlg(AFilterConnector: TObject):boolean;
+function ShowPixelateDlg(AFilterConnector: TObject): TScriptResult;
 var
   FPixelate: TFPixelate;
 begin
-  result := false;
   FPixelate:= TFPixelate.create(nil);
   FPixelate.FFilterConnector := AFilterConnector as TFilterConnector;
   try
     if FPixelate.FFilterConnector.ActiveLayer <> nil then
-      result:= (FPixelate.showModal = mrOk)
+    begin
+      if Assigned(FPixelate.FFilterConnector.Parameters) and
+        FPixelate.FFilterConnector.Parameters.Booleans['Validate'] then
+      begin
+        FPixelate.InitParams;
+        FPixelate.PreviewNeeded;
+        FPixelate.FFilterConnector.ValidateAction;
+      end else
+      begin
+        if FPixelate.showModal = mrOk then result := srOk
+        else result := srCancelledByUser;
+      end;
+    end
     else
-      result := false;
+      result := srException;
   finally
     FPixelate.free;
   end;
@@ -80,10 +92,18 @@ begin
 end;
 
 procedure TFPixelate.Button_OKClick(Sender: TObject);
+var
+  qualityStr: TCaption;
 begin
   FFilterConnector.ValidateAction;
   FFilterConnector.LazPaintInstance.Config.SetDefaultPixelateSize(SpinEdit_PixelSize.Value);
-  FFilterConnector.LazPaintInstance.Config.SetDefaultPixelateQuality(ComboBox_Quality.Text);
+  qualityStr := ComboBox_Quality.Text;
+  if qualityStr = rsFast then qualityStr := 'Fast' else
+  if qualityStr = rsLinear then qualityStr := 'Linear' else
+  if qualityStr = rsMitchell then qualityStr := 'Mitchell' else
+  if qualityStr = rsSpline then qualityStr := 'Spline' else
+    qualityStr := '';
+  FFilterConnector.LazPaintInstance.Config.SetDefaultPixelateQuality(qualityStr);
   ModalResult := mrOK;
 end;
 
@@ -94,10 +114,7 @@ end;
 
 procedure TFPixelate.FormShow(Sender: TObject);
 begin
-  FInitializing := true;
-  SpinEdit_PixelSize.Value := FFilterConnector.LazPaintInstance.Config.DefaultPixelateSize;
-  ComboBox_Quality.ItemIndex := ComboBox_Quality.Items.IndexOf(FFilterConnector.LazPaintInstance.Config.DefaultPixelateQuality);
-  FInitializing := false;
+  InitParams;
   PreviewNeeded;
   Top := FFilterConnector.LazPaintInstance.MainFormBounds.Top;
 end;
@@ -112,6 +129,33 @@ begin
   result := DoPixelate(FFilterConnector.BackupLayer,SpinEdit_PixelSize.Value,ComboBox_Quality.Text);
 end;
 
+procedure TFPixelate.InitParams;
+var
+  qualityStr: String;
+begin
+  FInitializing := true;
+  if Assigned(FFilterConnector.Parameters) and
+    FFilterConnector.Parameters.IsDefined('PixelSize') then
+    SpinEdit_PixelSize.Value := FFilterConnector.Parameters.Integers['PixelSize']
+  else
+    SpinEdit_PixelSize.Value := FFilterConnector.LazPaintInstance.Config.DefaultPixelateSize;
+
+  if Assigned(FFilterConnector.Parameters) and
+    FFilterConnector.Parameters.IsDefined('Quality') then
+    qualityStr := FFilterConnector.Parameters.Strings['Quality']
+  else
+    qualityStr := FFilterConnector.LazPaintInstance.Config.DefaultPixelateQuality;
+
+  if qualityStr = 'Fast' then qualityStr := rsFast else
+  if qualityStr = 'Linear' then qualityStr := rsLinear else
+  if qualityStr = 'Mitchell' then qualityStr := rsMitchell else
+  if qualityStr = 'Spline' then qualityStr := rsSpline else
+    qualityStr := '';
+
+  ComboBox_Quality.ItemIndex := ComboBox_Quality.Items.IndexOf(qualityStr);
+  FInitializing := false;
+end;
+
 procedure TFPixelate.PreviewNeeded;
 begin
   FFilterConnector.PutImage(ComputeFilteredLayer,False,true);

+ 17 - 6
lazpaint/dialog/filter/uposterize.pas

@@ -35,13 +35,13 @@ type
     { public declarations }
   end;
 
-function ShowPosterizeDlg(AInstance: TLazPaintCustomInstance; AParameters: TVariableSet):boolean;
+function ShowPosterizeDlg(AInstance: TLazPaintCustomInstance; AParameters: TVariableSet): TScriptResult;
 
 implementation
 
 uses LCScaleDPI, UMac, UColorFilters;
 
-function ShowPosterizeDlg(AInstance: TLazPaintCustomInstance; AParameters: TVariableSet): boolean;
+function ShowPosterizeDlg(AInstance: TLazPaintCustomInstance; AParameters: TVariableSet): TScriptResult;
 var FPosterize: TFPosterize;
   topmostInfo: TTopMostInfo;
 begin
@@ -53,13 +53,16 @@ begin
     on ex: exception do
     begin
       AInstance.ShowError('ShowPosterizeDlg',ex.Message);
-      result := false;
+      result := srException;
       exit;
     end;
   end;
   topmostInfo := AInstance.HideTopmost;
   try
-    result := FPosterize.ShowModal = mrOK;
+    if FPosterize.ShowModal = mrOK then
+      result := srOk
+    else
+      result := srCancelledByUser;
   finally
     AInstance.ShowTopmost(topmostInfo);
     FPosterize.FFilterConnector.OnTryStopAction := nil;
@@ -94,8 +97,16 @@ end;
 procedure TFPosterize.FormShow(Sender: TObject);
 begin
   FInitializing := true;
-  SpinEdit_Levels.Value := FFilterConnector.LazPaintInstance.Config.DefaultPosterizeLevels;
-  CheckBox_ByLightness.Checked := FFilterConnector.LazPaintInstance.Config.DefaultPosterizeByLightness;
+  if Assigned(FFilterConnector.Parameters) and
+     FFilterConnector.Parameters.IsDefined('Levels') then
+    SpinEdit_Levels.Value := FFilterConnector.Parameters.Integers['Levels']
+  else
+    SpinEdit_Levels.Value := FFilterConnector.LazPaintInstance.Config.DefaultPosterizeLevels;
+  if Assigned(FFilterConnector.Parameters) and
+     FFilterConnector.Parameters.IsDefined('ByLightness') then
+    CheckBox_ByLightness.Checked := FFilterConnector.Parameters.Booleans['ByLightness']
+  else
+    CheckBox_ByLightness.Checked := FFilterConnector.LazPaintInstance.Config.DefaultPosterizeByLightness;
   FInitializing := false;
   PreviewNeeded;
   Top := FFilterConnector.LazPaintInstance.MainFormBounds.Top;

+ 16 - 7
lazpaint/dialog/filter/uradialblur.pas

@@ -7,7 +7,7 @@ interface
 uses
   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
   StdCtrls, Spin, ExtCtrls, BGRABitmap, BGRABitmapTypes, LazPaintType, LCScaleDPI,
-  UFilterConnector, UFilterThread;
+  UFilterConnector, UFilterThread, UScripting;
 
 type
 
@@ -34,6 +34,7 @@ type
     FFilterConnector: TFilterConnector;
     FThreadManager: TFilterThreadManager;
     FLastRadius: single;
+    FVars: TVariableSet;
     procedure PreviewNeeded;
     procedure UpdateStep;
     procedure OnTaskEvent({%H-}ASender: TObject; AEvent: TThreadManagerEvent);
@@ -41,25 +42,28 @@ type
     blurType: TRadialBlurType;
   end;
 
-function ShowRadialBlurDlg(AFilterConnector: TObject; blurType:TRadialBlurType; ACaption: string = ''):boolean;
+function ShowRadialBlurDlg(AFilterConnector: TObject; ABlurType:TRadialBlurType;
+  ACaption: string = ''): TScriptResult;
 
 implementation
 
 uses UMac, BGRAFilters;
 
-function ShowRadialBlurDlg(AFilterConnector: TObject; blurType:TRadialBlurType; ACaption: string):boolean;
+function ShowRadialBlurDlg(AFilterConnector: TObject;
+  ABlurType: TRadialBlurType; ACaption: string): TScriptResult;
 var
   RadialBlur: TFRadialBlur;
 begin
-  result := false;
   RadialBlur:= TFRadialBlur.create(nil);
   RadialBlur.FFilterConnector := AFilterConnector as TFilterConnector;
   RadialBlur.FThreadManager := TFilterThreadManager.Create(RadialBlur.FFilterConnector);
   RadialBlur.FThreadManager.OnEvent := @RadialBlur.OnTaskEvent;
+  RadialBlur.FVars := RadialBlur.FFilterConnector.Parameters;
   if ACaption<>'' then RadialBlur.Caption := ACaption;
   try
-    RadialBlur.blurType := blurType;
-    result:= (RadialBlur.ShowModal = mrOk);
+    RadialBlur.blurType := ABlurType;
+    if RadialBlur.ShowModal = mrOk then result := srOk
+    else result := srCancelledByUser;
   finally
     RadialBlur.FThreadManager.Free;
     RadialBlur.free;
@@ -96,7 +100,12 @@ end;
 procedure TFRadialBlur.FormShow(Sender: TObject);
 begin
   FInitializing := True;
-  SpinEdit_Radius.Value := FFilterConnector.LazPaintInstance.Config.DefaultBlurRadius;
+  if Assigned(FVars) and FVars.IsDefined('Radius') then
+    SpinEdit_Radius.Value := FVars.Floats['Radius']
+  else if Assigned(FVars) and FVars.IsDefined('RadiusX') and FVars.IsDefined('RadiusY') then
+    SpinEdit_Radius.Value := (FVars.Floats['RadiusX']+FVars.Floats['RadiusY'])/2
+  else
+    SpinEdit_Radius.Value := FFilterConnector.LazPaintInstance.Config.DefaultBlurRadius;
   UpdateStep;
   FInitializing := False;
   PreviewNeeded;

+ 12 - 6
lazpaint/dialog/filter/usharpen.pas

@@ -6,7 +6,7 @@ interface
 
 uses
   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
-  StdCtrls, Spin, ExtCtrls, UFilterConnector;
+  StdCtrls, Spin, ExtCtrls, UFilterConnector, UScripting;
 
 type
   TSharpenMode = (smSharpen);
@@ -31,16 +31,17 @@ type
     FMode :TSharpenMode;
     FInitializing: boolean;
     FFilterConnector: TFilterConnector;
+    FVars: TVariableSet;
     procedure PreviewNeeded;
   end;
 
-function ShowSharpenDlg(AFilterConnector: TObject; AMode : TSharpenMode):boolean;
+function ShowSharpenDlg(AFilterConnector: TObject; AMode : TSharpenMode): TScriptResult;
 
 implementation
 
 uses LCScaleDPI, UMac, LazPaintType, BGRABitmap, BGRABitmapTypes;
 
-function ShowSharpenDlg(AFilterConnector: TObject; AMode : TSharpenMode): boolean;
+function ShowSharpenDlg(AFilterConnector: TObject; AMode : TSharpenMode): TScriptResult;
 var FSharpen: TFSharpen;
 begin
   FSharpen := TFSharpen.Create(nil);
@@ -48,16 +49,18 @@ begin
   try
     FSharpen.FFilterConnector := AFilterConnector as TFilterConnector;
     FSharpen.FFilterConnector.OnTryStopAction := @FSharpen.OnTryStopAction;
+    FSharpen.FVars:= FSharpen.FFilterConnector.Parameters;
   except
     on ex: exception do
     begin
       (AFilterConnector as TFilterConnector).LazPaintInstance.ShowError('ShowSharpenDlg',ex.Message);
-      result := false;
+      result := srException;
       exit;
     end;
   end;
   try
-    result := FSharpen.ShowModal = mrOK;
+    if FSharpen.ShowModal = mrOK then
+      result := srOk else result := srCancelledByUser;
   finally
     FSharpen.FFilterConnector.OnTryStopAction := nil;
     FSharpen.Free;
@@ -79,7 +82,10 @@ procedure TFSharpen.FormShow(Sender: TObject);
 var idxSlash: integer;
 begin
   FInitializing := true;
-  SpinEdit_Amount.Value := round(FFilterConnector.LazPaintInstance.Config.DefaultSharpenAmount*100);
+  if Assigned(FVars) and FVars.IsDefined('Amount') then
+    SpinEdit_Amount.Value := round(FVars.Floats['Amount']*100)
+  else
+     SpinEdit_Amount.Value := round(FFilterConnector.LazPaintInstance.Config.DefaultSharpenAmount*100);
   FInitializing := false;
   PreviewNeeded;
   idxSlash:= Pos('/',Caption);

+ 9 - 6
lazpaint/dialog/filter/utwirl.pas

@@ -6,7 +6,8 @@ interface
 
 uses
   Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
-  StdCtrls, Spin, ExtCtrls, BGRABitmap, LazPaintType, LCScaleDPI, ufilterconnector, BGRABitmapTypes;
+  StdCtrls, Spin, ExtCtrls, BGRABitmap, LazPaintType, LCScaleDPI,
+  UFilterConnector, BGRABitmapTypes, UScripting;
 
 type
 
@@ -45,24 +46,26 @@ type
     FilterConnector: TFilterConnector;
   end;
 
-function ShowTwirlDlg(AFilterConnector: TObject):boolean;
+function ShowTwirlDlg(AFilterConnector: TObject): TScriptResult;
 
 implementation
 
 uses umac;
 
-function ShowTwirlDlg(AFilterConnector: TObject):boolean;
+function ShowTwirlDlg(AFilterConnector: TObject): TScriptResult;
 var
   FTwirl: TFTwirl;
 begin
-  result := false;
   FTwirl:= TFTwirl.create(nil);
   FTwirl.FilterConnector := AFilterConnector as TFilterConnector;
   try
     if FTwirl.FilterConnector.ActiveLayer <> nil then
-      result:= (FTwirl.showModal = mrOk)
+    begin
+      if FTwirl.showModal = mrOk then result := srOk
+      else result := srCancelledByUser;
+    end
     else
-      result := false;
+      result := srException;
   finally
     FTwirl.free;
   end;

+ 9 - 6
lazpaint/dialog/filter/uwavedisplacement.pas

@@ -6,7 +6,8 @@ interface
 
 uses
   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
-  Spin, UFilterConnector, BGRABitmap, BGRABitmapTypes, LazPaintType;
+  Spin, UFilterConnector, BGRABitmap, BGRABitmapTypes, LazPaintType,
+  UScripting;
 
 type
 
@@ -50,24 +51,26 @@ type
 var
   FWaveDisplacement: TFWaveDisplacement;
 
-function ShowWaveDisplacementDlg(AFilterConnector: TObject):boolean;
+function ShowWaveDisplacementDlg(AFilterConnector: TObject): TScriptResult;
 
 implementation
 
 uses umac, ugraph, LCScaleDPI;
 
-function ShowWaveDisplacementDlg(AFilterConnector: TObject):boolean;
+function ShowWaveDisplacementDlg(AFilterConnector: TObject): TScriptResult;
 var
   FWaveDisplacement: TFWaveDisplacement;
 begin
-  result := false;
   FWaveDisplacement:= TFWaveDisplacement.create(nil);
   FWaveDisplacement.FilterConnector := AFilterConnector as TFilterConnector;
   try
     if FWaveDisplacement.FilterConnector.ActiveLayer <> nil then
-      result:= (FWaveDisplacement.showModal = mrOk)
+    begin
+      if FWaveDisplacement.showModal = mrOk then result := srOk
+      else result := srCancelledByUser;
+    end
     else
-      result := false;
+      result := srException;
   finally
     FWaveDisplacement.free;
   end;

+ 3 - 3
lazpaint/image/uimageaction.pas

@@ -65,7 +65,7 @@ type
     procedure EditSelection(ACallback: TModifyImageCallback);
     procedure Import3DObject(AFilenameUTF8: string);
     function GetPixel(X,Y: Integer): TBGRAPixel;
-    function PutImage(X,Y,AWidth,AHeight: integer; AImage: TBGRACustomBitmap; AMode: TDrawMode; AOpacity: byte): boolean;
+    function PutImage(X,Y: integer; AImage: TBGRACustomBitmap; AMode: TDrawMode; AOpacity: byte): boolean;
     function LayerFill(AColor: TBGRAPixel; AMode: TDrawMode): boolean;
     function TryAddLayerFromFile(AFilenameUTF8: string; ALoadedImage: TBGRABitmap = nil): boolean;
     function AddLayerFromBitmap(ABitmap: TBGRABitmap; AName: string): boolean;
@@ -282,7 +282,7 @@ begin
     end;
     bmp.InvalidateBitmap;
 
-    if PutImage(x,y,width,height,bmp,mode,opacity) then
+    if PutImage(x,y,bmp,mode,opacity) then
     begin
       result := srOk;
       FInstance.UpdateWindows;
@@ -463,7 +463,7 @@ begin
   result := Image.LayerBitmap[Image.CurrentLayerIndex].GetPixel(X-ofs.X,y-ofs.Y);
 end;
 
-function TImageActions.PutImage(X, Y, AWidth, AHeight: integer; AImage: TBGRACustomBitmap;
+function TImageActions.PutImage(X, Y: integer; AImage: TBGRACustomBitmap;
   AMode: TDrawMode; AOpacity: byte): boolean;
 var
   LayerAction: TLayerAction;

+ 1 - 0
lazpaint/lazpaint.lpi

@@ -835,6 +835,7 @@
       <Unit81>
         <Filename Value="uraintype.pas"/>
         <IsPartOfProject Value="True"/>
+        <UnitName Value="URainType"/>
       </Unit81>
       <Unit82>
         <Filename Value="dialog\filter\uformrain.pas"/>

+ 68 - 54
lazpaint/lazpaintdialogs.inc

@@ -176,23 +176,26 @@ begin
   if Assigned(ScriptContext.RecordingFunctionParameters) then AVars := ScriptContext.RecordingFunctionParameters;
   if not Assigned(Image) or not image.CheckCurrentLayerVisible then
   begin result := srException; exit; end;
-  if ShowColorIntensityDlg(AVars) then
-    result := srOk else result := srCancelledByUser;
+  result := ShowColorIntensityDlg(AVars);
 end;
 
-function TLazPaintInstance.ShowColorIntensityDlg(AParameters: TVariableSet
-  ): boolean;
+function TLazPaintInstance.ShowColorIntensityDlg(AParameters: TVariableSet): TScriptResult;
 var oldSelectionNormal: boolean;
 begin
-  result := false;
   FormsNeeded;
   oldSelectionNormal := ShowSelectionNormal;
   ShowSelectionNormal := true;
   try
-    result := FColorIntensity.ShowModal(self,ciIntensity,AParameters) = mrOK;
+    case FColorIntensity.ShowModal(self,ciIntensity,AParameters) of
+    mrOK: result := srOk;
+    else result := srCancelledByUser;
+    end;
   except
     on ex:Exception do
-      ShowError('ShowColorIntensityDlg',ex.Message);
+    begin
+      result := srException;
+      ShowError(FColorIntensity.Caption, ex.Message);
+    end;
   end;
   ShowSelectionNormal := oldSelectionNormal;
 end;
@@ -202,23 +205,27 @@ begin
   if Assigned(ScriptContext.RecordingFunctionParameters) then AVars := ScriptContext.RecordingFunctionParameters;
   if not Assigned(Image) or not image.CheckCurrentLayerVisible then
   begin result := srException; exit; end;
-  if ShowColorLightnessDlg(AVars) then
-    result := srOk else result := srCancelledByUser;
+  result := ShowColorLightnessDlg(AVars);
 end;
 
 function TLazPaintInstance.ShowColorLightnessDlg(AParameters: TVariableSet
-  ): boolean;
+  ): TScriptResult;
 var oldSelectionNormal: boolean;
 begin
-  result := false;
   FormsNeeded;
   oldSelectionNormal := ShowSelectionNormal;
   ShowSelectionNormal := true;
   try
-    result := FColorIntensity.ShowModal(self,ciLightness,AParameters) = mrOk;
+    case FColorIntensity.ShowModal(self,ciLightness,AParameters) of
+    mrOk: result := srOk;
+    else result := srCancelledByUser;
+    end;
   except
     on ex:Exception do
-      ShowError('ShowColorLightnessDlg',ex.Message);
+    begin
+      result := srException;
+      ShowError(FColorIntensity.Caption,ex.Message);
+    end;
   end;
   ShowSelectionNormal := oldSelectionNormal;
 end;
@@ -228,23 +235,26 @@ begin
   if Assigned(ScriptContext.RecordingFunctionParameters) then AVars := ScriptContext.RecordingFunctionParameters;
   if not Assigned(Image) or not image.CheckCurrentLayerVisible then
   begin result := srException; exit; end;
-  if ShowShiftColorsDlg(AVars) then
-    result := srOk else result := srCancelledByUser;
+  result := ShowShiftColorsDlg(AVars);
 end;
 
-function TLazPaintInstance.ShowShiftColorsDlg(AParameters: TVariableSet
-  ): boolean;
+function TLazPaintInstance.ShowShiftColorsDlg(AParameters: TVariableSet): TScriptResult;
 var oldSelectionNormal: boolean;
 begin
-  result := false;
   FormsNeeded;
   oldSelectionNormal := ShowSelectionNormal;
   ShowSelectionNormal := true;
   try
-    result := FShiftColors.ShowModal(self,AParameters) = mrOk;
+    case FShiftColors.ShowModal(self,AParameters) of
+    mrOk: result := srOk;
+    else result := srCancelledByUser;
+    end;
   except
     on ex:Exception do
-      ShowError('ShowShiftColorsDlg',ex.Message);
+    begin
+      result := srException;
+      ShowError(FShiftColors.Caption,ex.Message);
+    end;
   end;
   ShowSelectionNormal := oldSelectionNormal;
 end;
@@ -254,22 +264,26 @@ begin
   if Assigned(ScriptContext.RecordingFunctionParameters) then AVars := ScriptContext.RecordingFunctionParameters;
   if not Assigned(Image) or not image.CheckCurrentLayerVisible then
   begin result := srException; exit; end;
-  if ShowColorizeDlg(AVars) then
-    result := srOk else result := srCancelledByUser;
+  result := ShowColorizeDlg(AVars);
 end;
 
-function TLazPaintInstance.ShowColorizeDlg(AParameters: TVariableSet): boolean;
+function TLazPaintInstance.ShowColorizeDlg(AParameters: TVariableSet): TScriptResult;
 var oldSelectionNormal: boolean;
 begin
-  result := false;
   FormsNeeded;
   oldSelectionNormal := ShowSelectionNormal;
   ShowSelectionNormal := true;
   try
-    result := FColorize.ShowModal(self,AParameters) = mrOk;
+    case FColorize.ShowModal(self,AParameters) of
+    mrOk: result := srOk;
+    else result := srCancelledByUser;
+    end;
   except
     on ex:Exception do
-      ShowError('ShowColorizeDlg',ex.Message);
+    begin
+      result := srException;
+      ShowError(FColorize.Caption, ex.Message);
+    end;
   end;
   ShowSelectionNormal := oldSelectionNormal;
 end;
@@ -279,52 +293,55 @@ begin
   if Assigned(ScriptContext.RecordingFunctionParameters) then AVars := ScriptContext.RecordingFunctionParameters;
   if not Assigned(Image) or not Image.CheckCurrentLayerVisible then
   begin result := srException; exit; end;
-  if ShowColorCurvesDlg(AVars) then
-    result := srOk else result := srCancelledByUser;
+  result := ShowColorCurvesDlg(AVars);
 end;
 
-function TLazPaintInstance.ShowColorCurvesDlg(AParameters: TVariableSet
-  ): boolean;
+function TLazPaintInstance.ShowColorCurvesDlg(AParameters: TVariableSet): TScriptResult;
 var oldSelectionNormal: boolean;
 begin
-  result := false;
   FormsNeeded;
   oldSelectionNormal := ShowSelectionNormal;
   ShowSelectionNormal := true;
   try
-    result := FColorCurves.ShowModal(self,AParameters) = mrOk;
+    case FColorCurves.ShowModal(self,AParameters) of
+    mrOk: result := srOk;
+    else result := srCancelledByUser;
+    end;
   except
     on ex:Exception do
+    begin
+      result := srException;
       ShowError('ShowColorCurvesDlg',ex.Message);
+    end;
   end;
   ShowSelectionNormal := oldSelectionNormal;
 end;
 
-function TLazPaintInstance.ShowRadialBlurDlg(AFilterConnector: TObject; blurType: TRadialBlurType; ACaption: string): boolean;
+function TLazPaintInstance.ShowRadialBlurDlg(AFilterConnector: TObject; blurType: TRadialBlurType; ACaption: string): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
   top := self.HideTopmost;
   oldSelectionNormal := ShowSelectionNormal;
   ShowSelectionNormal := true;
-  result := uradialblur.ShowRadialBlurDlg(AFilterConnector,blurType,ACaption);
+  result := URadialBlur.ShowRadialBlurDlg(AFilterConnector, blurType, ACaption);
   ShowSelectionNormal := oldSelectionNormal;
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowMotionBlurDlg(AFilterConnector: TObject):boolean;
+function TLazPaintInstance.ShowMotionBlurDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
   top := self.HideTopmost;
   oldSelectionNormal := ShowSelectionNormal;
   ShowSelectionNormal := true;
-  result := umotionblur.ShowMotionBlurDlg(AFilterConnector);
+  result := UMotionBlur.ShowMotionBlurDlg(AFilterConnector);
   ShowSelectionNormal := oldSelectionNormal;
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowCustomBlurDlg(AFilterConnector: TObject):boolean;
+function TLazPaintInstance.ShowCustomBlurDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
@@ -336,19 +353,19 @@ begin
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowEmbossDlg(AFilterConnector: TObject): boolean;
+function TLazPaintInstance.ShowEmbossDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
   top := self.HideTopmost;
   oldSelectionNormal := ShowSelectionNormal;
   ShowSelectionNormal := true;
-  result := uemboss.ShowEmbossDlg(AFilterConnector);
+  result := UEmboss.ShowEmbossDlg(AFilterConnector);
   ShowSelectionNormal := oldSelectionNormal;
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowRainDlg(AFilterConnector: TObject): boolean;
+function TLazPaintInstance.ShowRainDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
@@ -360,20 +377,19 @@ begin
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowPixelateDlg(AFilterConnector: TObject): boolean;
+function TLazPaintInstance.ShowPixelateDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
   top := self.HideTopmost;
   oldSelectionNormal := ShowSelectionNormal;
   ShowSelectionNormal := true;
-  result := upixelate.ShowPixelateDlg(AFilterConnector);
+  result := UPixelate.ShowPixelateDlg(AFilterConnector);
   ShowSelectionNormal := oldSelectionNormal;
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowNoiseFilterDlg(AFilterConnector: TObject
-  ): boolean;
+function TLazPaintInstance.ShowNoiseFilterDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
@@ -385,7 +401,7 @@ begin
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowTwirlDlg(AFilterConnector: TObject): boolean;
+function TLazPaintInstance.ShowTwirlDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
@@ -397,7 +413,7 @@ begin
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowWaveDisplacementDlg(AFilterConnector: TObject): boolean;
+function TLazPaintInstance.ShowWaveDisplacementDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
@@ -409,7 +425,7 @@ begin
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowPhongFilterDlg(AFilterConnector: TObject): boolean;
+function TLazPaintInstance.ShowPhongFilterDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
@@ -421,8 +437,7 @@ begin
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowFunctionFilterDlg(AFilterConnector: TObject
-  ): boolean;
+function TLazPaintInstance.ShowFunctionFilterDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
@@ -434,14 +449,14 @@ begin
   self.ShowTopmost(top);
 end;
 
-function TLazPaintInstance.ShowSharpenDlg(AFilterConnector: TObject): boolean;
+function TLazPaintInstance.ShowSharpenDlg(AFilterConnector: TObject): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin
   top := self.HideTopmost;
   oldSelectionNormal := ShowSelectionNormal;
   ShowSelectionNormal := true;
-  result := USharpen.ShowSharpenDlg(AFilterConnector,smSharpen);
+  result := USharpen.ShowSharpenDlg(AFilterConnector, smSharpen);
   ShowSelectionNormal := oldSelectionNormal;
   self.ShowTopmost(top);
 end;
@@ -451,11 +466,10 @@ begin
   if Assigned(ScriptContext.RecordingFunctionParameters) then AVars := ScriptContext.RecordingFunctionParameters;
   if not Assigned(Image) or not Image.CheckCurrentLayerVisible then
   begin result := srException; exit; end;
-  if ShowPosterizeDlg(AVars) then
-    result := srOk else result := srCancelledByUser;
+  result := ShowPosterizeDlg(AVars);
 end;
 
-function TLazPaintInstance.ShowPosterizeDlg(AParameters: TVariableSet): boolean;
+function TLazPaintInstance.ShowPosterizeDlg(AParameters: TVariableSet): TScriptResult;
 var oldSelectionNormal: boolean;
     top: TTopMostInfo;
 begin

+ 23 - 23
lazpaint/lazpaintinstance.pas

@@ -161,29 +161,29 @@ type
     procedure NotifyImageChange(RepaintNow: boolean; ARect: TRect); override;
     procedure NotifyImageChangeCompletely(RepaintNow: boolean); override;
     function TryOpenFileUTF8(filename: string; skipDialogIfSingleImage: boolean = false): boolean; override;
-    function ExecuteFilter(filter: TPictureFilter; skipDialog: boolean = false): boolean; override;
+    function ExecuteFilter(filter: TPictureFilter; skipDialog: boolean = false): TScriptResult; override;
     function RunScript(AFilename: string): boolean; override;
     procedure ColorFromFChooseColor; override;
     procedure ColorToFChooseColor; override;
     function ShowSaveOptionDlg({%H-}AParameters: TVariableSet; AOutputFilenameUTF8: string; ASkipOptions: boolean): boolean; override;
-    function ShowColorIntensityDlg(AParameters: TVariableSet): boolean; override;
-    function ShowColorLightnessDlg(AParameters: TVariableSet): boolean; override;
-    function ShowShiftColorsDlg(AParameters: TVariableSet): boolean; override;
-    function ShowColorizeDlg(AParameters: TVariableSet): boolean; override;
-    function ShowColorCurvesDlg(AParameters: TVariableSet): boolean; override;
-    function ShowRadialBlurDlg(AFilterConnector: TObject;blurType:TRadialBlurType; ACaption: string = ''):boolean; override;
-    function ShowMotionBlurDlg(AFilterConnector: TObject):boolean; override;
-    function ShowCustomBlurDlg(AFilterConnector: TObject):boolean; override;
-    function ShowEmbossDlg(AFilterConnector: TObject):boolean; override;
-    function ShowRainDlg(AFilterConnector: TObject):boolean; override;
-    function ShowPixelateDlg(AFilterConnector: TObject):boolean; override;
-    function ShowNoiseFilterDlg(AFilterConnector: TObject):boolean; override;
-    function ShowTwirlDlg(AFilterConnector: TObject):boolean; override;
-    function ShowWaveDisplacementDlg(AFilterConnector: TObject):boolean; override;
-    function ShowPhongFilterDlg(AFilterConnector: TObject): boolean; override;
-    function ShowFunctionFilterDlg(AFilterConnector: TObject): boolean; override;
-    function ShowSharpenDlg(AFilterConnector: TObject):boolean; override;
-    function ShowPosterizeDlg(AParameters: TVariableSet):boolean; override;
+    function ShowColorIntensityDlg(AParameters: TVariableSet): TScriptResult; override;
+    function ShowColorLightnessDlg(AParameters: TVariableSet): TScriptResult; override;
+    function ShowShiftColorsDlg(AParameters: TVariableSet): TScriptResult; override;
+    function ShowColorizeDlg(AParameters: TVariableSet): TScriptResult; override;
+    function ShowColorCurvesDlg(AParameters: TVariableSet): TScriptResult; override;
+    function ShowRadialBlurDlg(AFilterConnector: TObject; blurType:TRadialBlurType; ACaption: string = ''): TScriptResult; override;
+    function ShowMotionBlurDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowCustomBlurDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowEmbossDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowRainDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowPixelateDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowNoiseFilterDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowTwirlDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowWaveDisplacementDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowPhongFilterDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowFunctionFilterDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowSharpenDlg(AFilterConnector: TObject): TScriptResult; override;
+    function ShowPosterizeDlg(AParameters: TVariableSet): TScriptResult; override;
     procedure ApplyDocking; override;
     procedure ShowPrintDlg; override;
     function HideTopmost: TTopMostInfo; override;
@@ -216,8 +216,8 @@ implementation
 
 uses LCLType, Types, Forms, Dialogs, FileUtil, StdCtrls, LCLIntf, Math,
 
-     uradialblur, umotionblur, uemboss, UTwirl, UWaveDisplacement,
-     unewimage, uresample, upixelate, unoisefilter, ufilters,
+     URadialBlur, UMotionBlur, UEmboss, UTwirl, UWaveDisplacement,
+     unewimage, uresample, UPixelate, unoisefilter, ufilters,
      UImageAction, USharpen, uposterize, UPhongFilter, UFilterFunction,
      uprint, USaveOption, UFormRain,
 
@@ -1278,12 +1278,12 @@ begin
 end;
 
 function TLazPaintInstance.ExecuteFilter(filter: TPictureFilter;
-  skipDialog: boolean): boolean;
+  skipDialog: boolean): TScriptResult;
 var vars: TVariableSet;
 begin
   if filter = pfNone then
   begin
-    result := false;
+    result := srInvalidParameters;
     exit;
   end;
   vars := TVariableSet.Create('Filter');

+ 30 - 18
lazpaint/lazpaintmainform.pas

@@ -1698,7 +1698,6 @@ begin
           delete(filterName,1,6);
     params := TVariableSet.Create('Filter');
     params.AddString('Name', filterName);
-    params.AddString('Caption', RemoveTrail((Sender as TAction).Caption));
     CallScriptFunction(params);
     params.Free;
   end;
@@ -2055,16 +2054,23 @@ end;
 
 function TFMain.ScriptFilter(AVars: TVariableSet): TScriptResult;
 var filter: TPictureFilter;
+  a: TContainedAction;
+  defaultCaption: String;
 begin
-  filter := StrToPictureFilter(AVars.GetString(AVars.GetVariable('Name')));
+  filter := StrToPictureFilter(AVars.Strings['Name']);
   if filter = pfNone then
      result := srInvalidParameters
   else
   begin
-    if ExecuteFilter(LazPaintInstance, filter, AVars) then
-      result := srOk
+    defaultCaption := '';
+
+    a := ActionList1.ActionByName('Filter'+AVars.Strings['Name']);
+    if Assigned(a) then
+      defaultCaption := RemoveTrail((a as TAction).Caption)
     else
-      result := srException;
+      defaultCaption := AVars.Strings['Name'];
+
+    result := ExecuteFilter(LazPaintInstance, filter, AVars, false, defaultCaption);
   end;
 end;
 
@@ -3288,23 +3294,29 @@ end;
 procedure TFMain.FileRunScriptExecute(Sender: TObject);
 var
   dlg: TOpenDialog;
+  tmi: TTopMostInfo;
 begin
-  dlg := TOpenDialog.Create(nil);
+  tmi := LazPaintInstance.HideTopmost;
   try
-    dlg.Title := FileRunScript.Caption;
-    dlg.InitialDir:= Config.DefaultScriptDirectory;
-    dlg.DefaultExt:= 'py';
-    dlg.Filter:= 'Python (*.py)|*.py';
-    if dlg.Execute then
-    begin
-      Config.SetDefaultScriptDirectory(ExtractFilePath(dlg.FileName));
-      LazPaintInstance.RunScript(dlg.FileName);
+    dlg := TOpenDialog.Create(nil);
+    try
+      dlg.Title := FileRunScript.Caption;
+      dlg.InitialDir:= Config.DefaultScriptDirectory;
+      dlg.DefaultExt:= 'py';
+      dlg.Filter:= 'Python (*.py)|*.py';
+      if dlg.Execute then
+      begin
+        Config.SetDefaultScriptDirectory(ExtractFilePath(dlg.FileName));
+        LazPaintInstance.RunScript(dlg.FileName);
+      end;
+    except
+      on ex:exception do
+        LazPaintInstance.ShowError(RemoveTrail(FileRunScript.Caption), ex.Message);
     end;
-  except
-    on ex:exception do
-      LazPaintInstance.ShowError(RemoveTrail(FileRunScript.Caption), ex.Message);
+    dlg.Free;
+  finally
+    LazPaintInstance.ShowTopmost(tmi);
   end;
-  dlg.Free;
 end;
 
 procedure TFMain.FileSaveAsInSameFolderExecute(Sender: TObject);

+ 19 - 19
lazpaint/lazpainttype.pas

@@ -230,29 +230,29 @@ type
     procedure NotifyImageChangeCompletely(RepaintNow: boolean); virtual; abstract;
     procedure NotifyStackChange; virtual; abstract;
     function TryOpenFileUTF8(filename: string; skipDialogIfSingleImage: boolean = false): boolean; virtual; abstract;
-    function ExecuteFilter(filter: TPictureFilter; skipDialog: boolean = false): boolean; virtual; abstract;
+    function ExecuteFilter(filter: TPictureFilter; skipDialog: boolean = false): TScriptResult; virtual; abstract;
     function RunScript(AFilename: string): boolean; virtual; abstract;
     procedure ColorFromFChooseColor; virtual; abstract;
     procedure ColorToFChooseColor; virtual; abstract;
     function ShowSaveOptionDlg(AParameters: TVariableSet; AOutputFilenameUTF8: string; ASkipOptions: boolean): boolean; virtual; abstract;
-    function ShowColorIntensityDlg(AParameters: TVariableSet): boolean; virtual; abstract;
-    function ShowColorLightnessDlg(AParameters: TVariableSet): boolean; virtual; abstract;
-    function ShowShiftColorsDlg(AParameters: TVariableSet): boolean; virtual; abstract;
-    function ShowColorizeDlg(AParameters: TVariableSet): boolean; virtual; abstract;
-    function ShowColorCurvesDlg(AParameters: TVariableSet): boolean; virtual; abstract;
-    function ShowRadialBlurDlg(AFilterConnector: TObject;blurType:TRadialBlurType; ACaption: string = ''):boolean; virtual; abstract;
-    function ShowMotionBlurDlg(AFilterConnector: TObject):boolean; virtual; abstract;
-    function ShowCustomBlurDlg(AFilterConnector: TObject):boolean; virtual; abstract;
-    function ShowEmbossDlg(AFilterConnector: TObject):boolean; virtual; abstract;
-    function ShowRainDlg(AFilterConnector: TObject):boolean; virtual; abstract;
-    function ShowPixelateDlg(AFilterConnector: TObject):boolean; virtual; abstract;
-    function ShowNoiseFilterDlg(AFilterConnector: TObject):boolean; virtual; abstract;
-    function ShowTwirlDlg(AFilterConnector: TObject):boolean; virtual; abstract;
-    function ShowWaveDisplacementDlg(AFilterConnector: TObject):boolean; virtual; abstract;
-    function ShowPhongFilterDlg(AFilterConnector: TObject): boolean; virtual; abstract;
-    function ShowFunctionFilterDlg(AFilterConnector: TObject): boolean; virtual; abstract;
-    function ShowSharpenDlg(AFilterConnector: TObject):boolean; virtual; abstract;
-    function ShowPosterizeDlg(AParameters: TVariableSet):boolean; virtual; abstract;
+    function ShowColorIntensityDlg(AParameters: TVariableSet): TScriptResult; virtual; abstract;
+    function ShowColorLightnessDlg(AParameters: TVariableSet): TScriptResult; virtual; abstract;
+    function ShowShiftColorsDlg(AParameters: TVariableSet): TScriptResult; virtual; abstract;
+    function ShowColorizeDlg(AParameters: TVariableSet): TScriptResult; virtual; abstract;
+    function ShowColorCurvesDlg(AParameters: TVariableSet): TScriptResult; virtual; abstract;
+    function ShowRadialBlurDlg(AFilterConnector: TObject; blurType:TRadialBlurType; ACaption: string = ''): TScriptResult; virtual; abstract;
+    function ShowMotionBlurDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowCustomBlurDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowEmbossDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowRainDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowPixelateDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowNoiseFilterDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowTwirlDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowWaveDisplacementDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowPhongFilterDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowFunctionFilterDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowSharpenDlg(AFilterConnector: TObject): TScriptResult; virtual; abstract;
+    function ShowPosterizeDlg(AParameters: TVariableSet): TScriptResult; virtual; abstract;
     procedure ShowPrintDlg; virtual; abstract;
     function OpenImage (FileName: string; AddToRecent: Boolean= True): boolean; virtual; abstract;
     procedure AddToImageList(const FileNames: array of String); virtual; abstract;

+ 2 - 2
lazpaint/ucommandline.pas

@@ -13,7 +13,7 @@ implementation
 
 uses
   SysUtils, BGRAUTF8, LazFileUtils, BGRABitmap, BGRABitmapTypes, Dialogs, uparse,
-  UImage, UImageAction, ULayerAction;
+  UImage, UImageAction, ULayerAction, UScripting;
 
 function ParamStrUTF8(AIndex: integer): string;
 begin
@@ -81,7 +81,7 @@ begin
       Filter := StrToPictureFilter(CommandStr);
       if Filter <> pfNone then
       begin
-        if not instance.ExecuteFilter(Filter,True) then
+        if instance.ExecuteFilter(Filter,True) <> srOk then
         begin
           instance.ShowError(CommandStr, rsUnableToApplyFilter+CommandStr);
           errorEncountered := true;

+ 8 - 8
lazpaint/ufilterconnector.pas

@@ -6,7 +6,7 @@ interface
 
 uses
   Classes, SysUtils, UImage, ULayerAction, UImageType, Forms,
-  LazPaintType, BGRABitmap, uscripting;
+  LazPaintType, BGRABitmap, BGRABitmapTypes, uscripting;
 
 type
   TFilterConnector = class;
@@ -43,8 +43,8 @@ type
     procedure ValidateAction;
     procedure InvalidateActiveLayer; overload;
     procedure InvalidateActiveLayer(ARect: TRect); overload;
-    procedure PutImage(AFilteredLayer: TBGRABitmap; AMayBeColored: boolean; AOwner: boolean);
-    procedure PutImage(AFilteredLayer: TBGRABitmap; AModifiedRect: TRect; AMayBeColored: boolean; AOwner: boolean);
+    procedure PutImage(AFilteredLayer: TBGRABitmap; AMayBeColored: boolean; AOwner: boolean; ADrawMode: TDrawMode = dmSet);
+    procedure PutImage(AFilteredLayer: TBGRABitmap; AModifiedRect: TRect; AMayBeColored: boolean; AOwner: boolean; ADrawMode: TDrawMode = dmSet);
     procedure RestoreBackup;
     property BackupLayer: TBGRABitmap read GetBackupLayer;
     property CurrentSelection: TBGRABitmap read GetCurrentSelection;
@@ -59,7 +59,7 @@ type
 
 implementation
 
-uses Types, BGRABitmapTypes;
+uses Types;
 
 { TFilterConnector }
 
@@ -206,13 +206,13 @@ begin
   end;
 end;
 
-procedure TFilterConnector.PutImage(AFilteredLayer: TBGRABitmap; AMayBeColored: boolean; AOwner: boolean);
+procedure TFilterConnector.PutImage(AFilteredLayer: TBGRABitmap; AMayBeColored: boolean; AOwner: boolean; ADrawMode: TDrawMode);
 begin
-  PutImage(AFilteredLayer,FWorkArea,AMayBeColored,AOwner);
+  PutImage(AFilteredLayer,FWorkArea,AMayBeColored,AOwner,ADrawMode);
 end;
 
 procedure TFilterConnector.PutImage(AFilteredLayer: TBGRABitmap;
-  AModifiedRect: TRect; AMayBeColored: boolean; AOwner: boolean);
+  AModifiedRect: TRect; AMayBeColored: boolean; AOwner: boolean; ADrawMode: TDrawMode);
 var AMine: boolean;
   imgRect: TRect;
 begin
@@ -237,7 +237,7 @@ begin
       end;
       ApplySelectionMaskOn(AFilteredLayer);
     end;
-    ActiveLayer.PutImagePart(AModifiedRect.Left,AModifiedRect.Top,AFilteredLayer,AModifiedRect,dmSet);
+    ActiveLayer.PutImagePart(AModifiedRect.Left,AModifiedRect.Top,AFilteredLayer,AModifiedRect,ADrawMode);
     if AMine then AFilteredLayer.Free;
     imgRect := AModifiedRect;
     with ActiveLayerOffset do

+ 101 - 40
lazpaint/ufilters.pas

@@ -7,22 +7,35 @@ interface
 uses
   Classes, SysUtils, LazPaintType, uscripting;
 
-function ExecuteFilter(AInstance: TLazPaintCustomInstance; filter: TPictureFilter; AParameters: TVariableSet; skipDialog: boolean = false): boolean;
+function ExecuteFilter(AInstance: TLazPaintCustomInstance; filter: TPictureFilter;
+  AParameters: TVariableSet; skipDialog: boolean = false; defaultCaption: string = ''): TScriptResult;
 
 implementation
 
 uses UFilterConnector, BGRABitmap, BGRABitmapTypes, UGraph, BGRAGradients, Dialogs, UColorFilters;
 
-function ExecuteFilter(AInstance: TLazPaintCustomInstance;filter: TPictureFilter; AParameters: TVariableSet; skipDialog: boolean = false): boolean;
+function ExecuteFilter(AInstance: TLazPaintCustomInstance; filter: TPictureFilter;
+  AParameters: TVariableSet; skipDialog: boolean = false; defaultCaption: string = ''): TScriptResult;
 var
     FilterConnector: TFilterConnector;
     filteredLayer: TBGRABitmap;
 
+  function GetCaption: string;
+  begin
+    result := Trim(AParameters.Strings['Caption']);
+    if result = '' then result := defaultCaption;
+  end;
+
+  function GetSkip: boolean;
+  begin
+    result := skipDialog or AParameters.Booleans['Validate'];
+  end;
+
   procedure DoBlurCustom;
   var
     blurMask,blurMaskCopy: TBGRABitmap;
   begin
-    if skipDialog and (AInstance.Config.DefaultCustomBlurMaskUTF8 <> '') then
+    if GetSkip and (AInstance.Config.DefaultCustomBlurMaskUTF8 <> '') then
     begin
       try
         blurMask := TBGRABitmap.Create(AInstance.Config.DefaultCustomBlurMaskUTF8,True);
@@ -38,12 +51,13 @@ var
       end;
     end
     else
-      AInstance.ShowCustomBlurDlg(FilterConnector);
+      result := AInstance.ShowCustomBlurDlg(FilterConnector);
   end;
 
   procedure DoSimpleBlur;
   var
     blurType: TRadialBlurType;
+    radiusX,radiusY: single;
   begin
     case filter of
       pfBlurPrecise: blurType := rbPrecise;
@@ -55,10 +69,54 @@ var
     else
       exit;
     end;
-    if skipDialog then
-      filteredLayer := FilterConnector.ActiveLayer.FilterBlurRadial(FilterConnector.WorkArea, AInstance.Config.DefaultBlurRadius,blurType) as TBGRABitmap
+
+    if GetSkip then
+    begin
+      if AParameters.IsDefined('Radius') then
+      begin
+        radiusX := AParameters.Floats['Radius'];
+        radiusY := radiusX;
+      end else
+      begin
+        if AParameters.IsDefined('RadiusX') then
+          radiusX := AParameters.Floats['RadiusX']
+        else radiusX := AInstance.Config.DefaultBlurRadius;
+
+        if AParameters.IsDefined('RadiusY') then
+          radiusY := AParameters.Floats['RadiusY']
+        else radiusY := AInstance.Config.DefaultBlurRadius;
+      end;
+
+      filteredLayer := FilterConnector.ActiveLayer.FilterBlurRadial(FilterConnector.WorkArea, radiusX,radiusY,blurType) as TBGRABitmap
+    end
+    else
+      result := AInstance.ShowRadialBlurDlg(FilterConnector, blurType, GetCaption);
+  end;
+
+  procedure DoBlurMotion;
+  var
+    oriented: Boolean;
+    distance, angle: Double;
+  begin
+    if GetSkip then
+    begin
+      if AParameters.IsDefined('Oriented') then
+        oriented := AParameters.Booleans['Oriented']
+      else oriented := AInstance.Config.DefaultBlurMotionOriented;
+
+      if AParameters.IsDefined('Distance') then
+        distance := AParameters.Floats['Distance']
+      else distance := AInstance.Config.DefaultBlurMotionDistance;
+
+      if AParameters.IsDefined('Angle') then
+        angle := AParameters.Floats['Angle']
+      else angle := AInstance.Config.DefaultBlurMotionAngle;
+
+      filteredLayer := FilterConnector.ActiveLayer.FilterBlurMotion(FilterConnector.WorkArea,
+                          distance,angle,oriented) as TBGRABitmap
+    end
     else
-      AInstance.ShowRadialBlurDlg(FilterConnector,blurType,AParameters.Strings['Caption']);
+      result := AInstance.ShowMotionBlurDlg(FilterConnector);
   end;
 
   procedure DoMetalFloor;
@@ -71,18 +129,32 @@ var
 
   procedure DoSharpen;
   var
-    amountDefined: boolean;
     amount: single;
   begin
-    amountDefined := AParameters.IsDefined('Amount');
-    if skipDialog or amountDefined then
+    if GetSkip then
     begin
-      amount := AInstance.Config.DefaultSharpenAmount;
-      if amountDefined then amount := AParameters.Floats['Amount'];
+      if AParameters.IsDefined('Amount') then
+        amount := AParameters.Floats['Amount']
+      else amount := AInstance.Config.DefaultSharpenAmount;
       filteredLayer := FilterConnector.ActiveLayer.FilterSharpen(FilterConnector.WorkArea,amount) as TBGRABitmap;
       AParameters.Floats['Amount'] := amount;
     end
-    else AInstance.ShowSharpenDlg(FilterConnector);
+    else result := AInstance.ShowSharpenDlg(FilterConnector);
+  end;
+
+  procedure DoEmboss;
+  var
+    angle: Double;
+  begin
+    if GetSkip then
+    begin
+      if AParameters.IsDefined('Angle') then
+        angle := AParameters.Floats['Angle']
+      else angle := AInstance.Config.DefaultEmbossAngle;
+      filteredLayer := FilterConnector.ActiveLayer.FilterEmboss(angle, FilterConnector.WorkArea) as TBGRABitmap
+    end
+    else
+      result := AInstance.ShowEmbossDlg(FilterConnector);
   end;
 
 var
@@ -90,14 +162,14 @@ var
   applyOfsBefore: Boolean;
 
 begin
-  result := false;
-  if filter = pfNone then exit;
+  result := srException;
+  if filter = pfNone then exit(srInvalidParameters);
   if not AInstance.Image.CheckNoAction then exit;
   if not AInstance.image.CheckCurrentLayerVisible then exit;
   if (filter = pfLinearNegative) and AInstance.Image.SelectionMaskEmpty and (AInstance.Image.NbLayers = 1) then
   begin
       AInstance.Image.LinearNegativeAll;
-      result := true;
+      result := srOk;
       exit;
   end;
 
@@ -138,36 +210,24 @@ begin
         FilterComplementaryColor(filteredLayer,FilterConnector.WorkArea);
       end;
     pfBlurPrecise, pfBlurRadial, pfBlurCorona, pfBlurDisk, pfBlurFast, pfBlurBox: DoSimpleBlur;
-    pfBlurMotion:
-        if skipDialog then
-          filteredLayer := layer.FilterBlurMotion(FilterConnector.WorkArea, AInstance.Config.DefaultBlurMotionDistance,AInstance.Config.DefaultBlurMotionAngle,AInstance.Config.DefaultBlurMotionOriented) as TBGRABitmap
-        else
-          AInstance.ShowMotionBlurDlg(FilterConnector);
+    pfBlurMotion: DoBlurMotion;
     pfBlurCustom: DoBlurCustom;
-    pfEmboss:
-        if skipDialog then
-          filteredLayer := layer.FilterEmboss(AInstance.Config.DefaultEmbossAngle,FilterConnector.WorkArea) as TBGRABitmap
-        else
-          AInstance.ShowEmbossDlg(FilterConnector);
-    pfRain: AInstance.ShowRainDlg(FilterConnector);
-    pfPhong: AInstance.ShowPhongFilterDlg(FilterConnector);
-    pfFunction: AInstance.ShowFunctionFilterDlg(FilterConnector);
-    pfNoise: AInstance.ShowNoiseFilterDlg(FilterConnector);
-    pfPixelate:
-        if skipDialog then
-          filteredLayer := DoPixelate(layer,AInstance.Config.DefaultPixelateSize,AInstance.config.DefaultPixelateQuality)
-        else
-          AInstance.ShowPixelateDlg(FilterConnector);
+    pfEmboss: DoEmboss;
+    pfRain: result := AInstance.ShowRainDlg(FilterConnector);
+    pfPhong: result := AInstance.ShowPhongFilterDlg(FilterConnector);
+    pfFunction: result := AInstance.ShowFunctionFilterDlg(FilterConnector);
+    pfNoise: result := AInstance.ShowNoiseFilterDlg(FilterConnector);
+    pfPixelate: result := AInstance.ShowPixelateDlg(FilterConnector);
     pfTwirl:
-        if skipDialog then
+        if GetSkip then
           filteredLayer := layer.FilterTwirl(FilterConnector.WorkArea, Point(layer.Width div 2,layer.Height div 2), AInstance.Config.DefaultTwirlRadius, AInstance.Config.DefaultTwirlTurn ) as TBGRABitmap
         else
-          AInstance.ShowTwirlDlg(FilterConnector);
+          result := AInstance.ShowTwirlDlg(FilterConnector);
     pfWaveDisplacement:
-        if skipDialog then
+        if GetSkip then
           filteredLayer := ugraph.WaveDisplacementFilter(layer,FilterConnector.WorkArea, PointF(layer.Width/2,layer.Height/2), AInstance.Config.DefaultWaveDisplacementWavelength, AInstance.Config.DefaultWaveDisplacementAmount, AInstance.Config.DefaultWaveDisplacementPhase ) as TBGRABitmap
         else
-          AInstance.ShowWaveDisplacementDlg(FilterConnector);
+          result := AInstance.ShowWaveDisplacementDlg(FilterConnector);
     pfContour: filteredLayer := layer.FilterContour as TBGRABitmap;
     pfGrayscale: filteredLayer := layer.FilterGrayscale(FilterConnector.WorkArea) as TBGRABitmap;
     pfPerlinNoise: filteredLayer := CreatePerlinNoiseMap(layer.Width,layer.Height,layer.Width/256,layer.Height/256,1,rfBestQuality);
@@ -208,7 +268,8 @@ begin
     on ex: Exception do
       AInstance.ShowError(PictureFilterStr[filter],ex.Message);
   end;
-  result:= FilterConnector.ActionDone;
+  if FilterConnector.ActionDone then
+    result := srOk;
   FilterConnector.Free;
 end;
 

+ 86 - 0
lazpaintscripts/lazpaint/filter.py

@@ -0,0 +1,86 @@
+from lazpaint import command, dialog
+
+if __name__ == "__main__":
+  dialog.show_message("Library to execute filters on the current layer.")
+
+BLUR_PRECISE = 'BlurPrecise'
+BLUR_RADIAL = 'BlurRadial'
+BLUR_FAST = 'BlurFast'
+BLUR_BOX = 'BlurBox'
+BLUR_CORONA = 'BlurCorona'
+BLUR_DISK = 'BlurDisk'
+BLUR_MOTION = 'BlurMotion'
+BLUR_CUSTOM = 'BlurCustom'
+SHARPEN = 'Sharpen'
+SMOOTH = 'Smooth'
+MEDIAN = 'Median'
+NOISE = 'Noise'
+PIXELATE = 'Pixelate'
+CLEAR_TYPE = 'ClearType'
+CLEAR_TYPE_INVERSE = 'ClearTypeInverse'
+FILTER_FUNCTION = 'Function'
+EMBOSS = 'Emboss'
+PHONG = 'Phong'
+CONTOUR = 'Contour'
+GRAYSCALE = 'Grayscale'
+NEGATIVE = 'Negative'
+LINEAR_NEGATIVE = 'LinearNegative'
+COMPLEMENTARY_COLOR = 'ComplementaryColor'
+NORMALIZE = 'Normalize'
+SPHERE = 'Sphere'
+TWIRL = 'Twirl'
+WAVE_DISPLACEMENT = 'WaveDisplacement'
+CYLINDER = 'Cylinder'
+PLANE = 'Plane'
+PERLIN_NOISE = 'PerlinNoise'
+CYCLIC_PERLIN_NOISE = 'CyclicPerlinNoise'
+CLOUDS = 'Clouds'
+CUSTOM_WATER = 'CustomWater'
+WATER = 'Water'
+RAIN = 'Rain'
+WOOD = 'Wood'
+WOOD_VERTICAL = 'WoodVertical'
+PLASTIK = 'Plastik'
+METAL_FLOOR = 'MetalFloor'
+CAMOUFLAGE = 'Camouflage'
+SNOW_PRINT = 'SnowPrint'
+STONE = 'Stone'
+ROUND_STONE = 'RoundStone'
+MARBLE = 'Marble'
+
+PIXELATE_QUALITY_FAST = 'Fast'
+PIXELATE_QUALITY_LINEAR = 'Linear'
+PIXELATE_QUALITY_MITCHELL = 'Mitchell'
+PIXELATE_QUALITY_SPLINE = 'Spline'
+PIXELATE_QUALITY_BEST = PIXELATE_QUALITY_MITCHELL
+
+def run(name, validate=True):
+  command.send("Filter", Name=name, Validate=validate)
+
+def blur(name, radius=None, radius_x=None, radius_y=None, validate=True):
+  command.send("Filter", Name=name, Radius=radius, RadiusX=radius_x, RadiusY=radius_y, Validate=validate)
+
+def blur_motion(distance=None, angle=None, oriented=None, validate=True):
+  command.send("Filter", Name=BLUR_MOTION, Distance=distance, Angle=angle, Oriented=oriented, Validate=validate)
+
+def sharpen(amount=None, validate=True):
+  command.send("Filter", Name=SHARPEN, Amount=amount, Validate=validate)
+
+def noise(grayscale=None, opacity=None, validate=True):
+  command.send("Filter", Name=NOISE, Grayscale=grayscale, Opacity=opacity, Validate=validate)
+
+def pixelate(pixel_size=None, quality=None, validate=True):
+  command.send("Filter", Name=PIXELATE, PixelSize=pixel_size, Quality=quality, Validate=validate)
+
+def filter_function(red=None, green=None, blue=None, alpha=None, hue=None, saturation=None, lightness=None, validate=True):
+  command.send("Filter", Name=FILTER_FUNCTION, Red=red, Green=green, Blue=blue, Alpha=alpha, Hue=hue, Saturation=saturation, Lightness=lightness, Validate=validate)
+
+def emboss(angle=None, validate=True):
+  command.send("Filter", Name=EMBOSS, Angle=angle, Validate=validate)
+
+def rain(amount=None, wind=None, validate=True):
+  command.send("Filter", Name=RAIN, Amount=amount, Wind=wind, Validate=validate)
+
+def posterize(levels=None, by_lightness=None, validate=True):
+  command.send("Filter", Name=POSTERIZE, Levels=levels, ByLightness=by_lightness, Validate=validate)
+

+ 6 - 0
lazpaintscripts/test_filter.py

@@ -0,0 +1,6 @@
+from lazpaint import filter
+
+filter.filter_function(green="green*2")
+filter.noise(grayscale=True, opacity=128)
+filter.pixelate(20, filter.PIXELATE_QUALITY_BEST)
+