Quellcode durchsuchen

use point type in script

johann vor 5 Jahren
Ursprung
Commit
af1d13af26

+ 68 - 79
lazpaint/dialog/color/uadjustcurves.pas

@@ -136,7 +136,7 @@ procedure TFAdjustCurves.vsChartRedraw(Sender: TObject; Bitmap: TBGRABitmap);
 var
   i: Integer;
   curve: TVariableSet;
-  XList,YList: TScriptVariableReference;
+  pointList: TScriptVariableReference;
   pointCount: integer;
   pts,symbols: array of TPointF;
   symbolsColor: array of TBGRAPixel;
@@ -164,14 +164,14 @@ begin
   curve := SelectedCurve;
   if Assigned(curve) then
   begin
-    XList := curve.GetVariable('X');
-    YList := curve.GetVariable('Y');
-    pointCount := curve.GetListCount(XList);
+    pointList := curve.GetVariable('Points');
+    pointCount := curve.GetListCount(pointList);
     setlength(symbols, pointCount);
     setlength(symbolsColor, pointCount);
     for i := 0 to pointCount-1 do
     begin
-      symbols[i] := CoordToBitmap(curve.GetFloatAt(XList,i),curve.GetFloatAt(YList,i));
+      with curve.GetPoint2DAt(pointList,i) do
+        symbols[i] := CoordToBitmap(x, y);
       symbolsColor[i] := CurveColor;
     end;
     if curve.Booleans['Posterize'] then
@@ -204,7 +204,7 @@ begin
       hueGradient.Free;
       for i := 0 to pointCount-1 do
       begin
-        hsla.hue := round(curve.GetFloatAt(XList,i)*65535) and 65535;
+        hsla.hue := round(curve.GetPoint2DAt(pointList,i).x*65535) and 65535;
         symbolsColor[i] := HSLAToBGRA(hsla);
         with symbols[i] do Bitmap.FillEllipseAntialias(x,y,FPointSize,FPointSize,symbolsColor[i]);
       end;
@@ -226,7 +226,7 @@ begin
       hueGradient.Free;
       for i := 0 to pointCount-1 do
       begin
-        hsla.saturation := max(0,min(65535,round(curve.GetFloatAt(XList,i)*65535)));
+        hsla.saturation := max(0,min(65535,round(curve.GetPoint2DAt(pointList,i).x*65535)));
         symbolsColor[i] := GSBAToBGRA(hsla);
         with symbols[i] do Bitmap.FillEllipseAntialias(x,y,FPointSize,FPointSize,symbolsColor[i]);
       end;
@@ -249,7 +249,7 @@ begin
       for i := 0 to pointCount-1 do
       begin
         hsla.alpha := 220*$101;
-        hsla.lightness := max(0,min(65535,round(65535 div 8+curve.GetFloatAt(XList,i)*65535*6/8)));
+        hsla.lightness := max(0,min(65535,round(65535 div 8+curve.GetPoint2DAt(pointList,i).x*65535*6/8)));
         c1 := GSBAToBGRA(hsla);
         hsla.alpha := hsla.lightness;
         hsla.lightness:= 65535-hsla.lightness;
@@ -405,7 +405,7 @@ var curve: TVariableSet;
 begin
   curve := SelectedCurve;
   if curve = nil then result := 0
-  else result := curve.GetListCount(curve.GetVariable('X'));
+  else result := curve.GetListCount(curve.GetVariable('Points'));
 end;
 
 function TFAdjustCurves.GetPosterize: boolean;
@@ -572,7 +572,7 @@ end;
 function TFAdjustCurves.NearestPoint(xBmp, yBmp: single): integer;
 var
   curve: TVariableSet;
-  XList,YList: TScriptVariableReference;
+  pointList: TScriptVariableReference;
   i,pointCount: integer;
   minDist,dist: single;
   pt: TPointF;
@@ -580,13 +580,12 @@ begin
   result := -1;
   curve := SelectedCurve;
   if curve = nil then exit;
-  XList := curve.GetVariable('X');
-  YList := curve.GetVariable('Y');
-  pointCount := curve.GetListCount(XList);
+  pointList := curve.GetVariable('Points');
+  pointCount := curve.GetListCount(pointList);
   minDist := sqr(ScaleX(20,96)+0.0);
   for i := 0 to pointCount-1 do
   begin
-    pt := PointF(curve.GetFloatAt(XList,i),curve.GetFloatAt(YList,i));
+    pt := curve.GetPoint2DAt(pointList,i);
     pt := CoordToBitmap(pt.x,pt.y);
     dist := sqr(pt.x-xBmp)+sqr(pt.y-yBmp);
     if dist < minDist then
@@ -600,29 +599,25 @@ end;
 function TFAdjustCurves.InsertPoint(xBmp, yBmp: single): integer;
 var
   curve: TVariableSet;
-  XList,YList: TScriptVariableReference;
+  pointList: TScriptVariableReference;
   i,j,pointCount: integer;
   pt1,pt2,coord: TPointF;
 begin
   result := -1;
   curve := SelectedCurve;
   if curve = nil then exit;
-  XList := curve.GetVariable('X');
-  YList := curve.GetVariable('Y');
-  pointCount := curve.GetListCount(XList);
+  pointList := curve.GetVariable('Points');
+  pointCount := curve.GetListCount(pointList);
   for i := 1 to pointCount-1 do
   begin
-    pt1 := CoordToBitmap(curve.GetFloatAt(XList,i-1),curve.GetFloatAt(YList,i-1));
-    pt2 := CoordToBitmap(curve.GetFloatAt(XList,i),curve.GetFloatAt(YList,i));
+    with curve.GetPoint2DAt(pointList,i-1) do pt1 := CoordToBitmap(x, y);
+    with curve.GetPoint2DAt(pointList,i) do pt2 := CoordToBitmap(x, y);
     if (pt1.x <= xBmp-1) and (pt2.x >= xBmp+1) then
     begin
       coord := BitmapToCoord(xBmp,yBmp);
-      curve.AppendFloat(XList, curve.GetFloatAt(XList, pointCount-1));
-      for j := pointCount-1 downto i do curve.AssignFloatAt(XList, j+1, curve.GetFloatAt(XList, j));
-      curve.AssignFloatAt(XList, i, coord.x);
-      curve.AppendFloat(YList, curve.GetFloatAt(YList, pointCount-1));
-      for j := pointCount-1 downto i do curve.AssignFloatAt(YList, j+1, curve.GetFloatAt(YList, j));
-      curve.AssignFloatAt(YList, i, coord.y);
+      curve.AppendPoint(pointList, curve.GetPoint2DAt(pointList, pointCount-1));
+      for j := pointCount-1 downto i do curve.AssignPointAt(pointList, j+1, curve.GetPoint2DAt(pointList, j));
+      curve.AssignPointAt(pointList, i, coord);
       result := i;
       FEffectUpdated := false;
     end;
@@ -631,8 +626,7 @@ begin
       coord := BitmapToCoord(xBmp,yBmp);
       if coord.x <= 1 then
       begin
-        curve.AppendFloat(XList, coord.x);
-        curve.AppendFloat(YList, coord.y);
+        curve.AppendPoint(pointList, coord);
         result := i+1;
         FEffectUpdated := false;
       end;
@@ -643,7 +637,7 @@ end;
 procedure TFAdjustCurves.EnsureCurveExist(AParameters: TVariableSet;
   AName: string);
 var
-  listX, listY: TScriptVariableReference;
+  pointList: TScriptVariableReference;
   post: Boolean;
   cnt: NativeInt;
   i: Integer;
@@ -654,34 +648,21 @@ begin
   with AParameters.Subsets[AName] do
   begin
     post := Booleans['Posterize'];
-    listX := GetVariable('X');
-    listY := GetVariable('Y');
-    if not IsList(listX) or (GetListCount(listX)<=integer(not post)) then Remove(listX);
-    if not IsList(listY) or (GetListCount(listY)<=integer(not post)) then Remove(listY);
+    pointList := GetVariable('Points');
+    if not IsList(pointList) or (GetListCount(pointList)<=integer(not post)) then Remove(pointList);
 
-    if IsReferenceDefined(listX) then cnt := GetListCount(listX)
-    else if IsReferenceDefined(listY) then cnt := GetListCount(listY)
+    if IsReferenceDefined(pointList) then cnt := GetListCount(pointList)
     else cnt := 2;
 
-    if not IsReferenceDefined(listX) then
+    if not IsReferenceDefined(pointList) then
     begin
-      listX := AddFloatList('X');
+      pointList := AddPointList('Points');
       if Booleans['Posterize'] then
         for i := 0 to cnt-1 do
-          AppendFloat(listX, i/cnt)
+          AppendPoint(pointList, PointF(i/cnt, i/(cnt-1)) )
       else
         for i := 0 to cnt-1 do
-          AppendFloat(listX, i/(cnt-1));
-    end;
-
-    if not IsReferenceDefined(listY) then
-    begin
-      listY := AddFloatList('Y');
-      if cnt > 0 then
-        for i := 0 to cnt-1 do
-          AppendFloat(listY, i/(cnt-1))
-      else
-        AppendFloat(listY, 0);
+          AppendPoint(pointList, PointF(i/(cnt-1), i/(cnt-1)) );
     end;
   end;
 end;
@@ -689,53 +670,50 @@ end;
 procedure TFAdjustCurves.SetPointCoord(AIndex: integer; ACoord: TPointF);
 var
   curve: TVariableSet;
-  XList,YList: TScriptVariableReference;
+  pointList: TScriptVariableReference;
   pointCount: integer;
 begin
   curve := SelectedCurve;
   if curve = nil then exit;
-  XList := curve.GetVariable('X');
-  YList := curve.GetVariable('Y');
-  pointCount := curve.GetListCount(XList);
+  pointList := curve.GetVariable('Points');
+  pointCount := curve.GetListCount(pointList);
   if (AIndex < 0) or (AIndex >= pointCount) then exit;
   if AIndex = 0 then ACoord.x := 0 else
-    ACoord.x := max(ACoord.x, curve.GetFloatAt(XList, AIndex-1));
+    ACoord.x := max(ACoord.x, curve.GetPoint2DAt(pointList, AIndex-1).X);
   if AIndex = pointCount-1 then
   begin
     if not Posterize then ACoord.x := 1 else
       if ACoord.x > 1 then ACoord.x := 1;
   end else
-    ACoord.x := min(ACoord.x, curve.GetFloatAt(XList, AIndex+1));
+    ACoord.x := min(ACoord.x, curve.GetPoint2DAt(pointList, AIndex+1).X);
   if ACoord.y < 0 then ACoord.y := 0;
   if ACoord.y > 1 then ACoord.y := 1;
-  curve.AssignFloatAt(XList, AIndex, ACoord.x);
-  curve.AssignFloatAt(YList, AIndex, ACoord.y);
+  curve.AssignPointAt(pointList, AIndex, ACoord);
   FEffectUpdated:= false;
 end;
 
 function TFAdjustCurves.RemovePoint(AIndex: integer): boolean;
 var
   curve: TVariableSet;
-  XList,YList: TScriptVariableReference;
+  pointList: TScriptVariableReference;
   pointCount: integer;
 begin
   result := false;
   curve := SelectedCurve;
   if curve = nil then exit;
-  XList := curve.GetVariable('X');
-  YList := curve.GetVariable('Y');
-  pointCount := curve.GetListCount(XList);
+  pointList := curve.GetVariable('Points');
+  pointCount := curve.GetListCount(pointList);
   if (AIndex <= 0) or (AIndex >= pointCount-1) then exit;
-  if curve.RemoveAt(XList, AIndex) then result := true;
-  if curve.RemoveAt(YList, AIndex) then result := true;
+  if curve.RemoveAt(pointList, AIndex) then result := true;
   if result then FEffectUpdated:= false;
 end;
 
 procedure TFAdjustCurves.SetPosterize(AValue: boolean);
 var
   curve: TVariableSet;
-  XList: TScriptVariableReference;
+  pointList: TScriptVariableReference;
   pointCount: integer;
+  lastCoord: TPointF;
 begin
   curve := SelectedCurve;
   if curve = nil then exit;
@@ -744,13 +722,20 @@ begin
     curve.Booleans['Posterize'] := AValue; //try to set it
     if curve.Booleans['Posterize'] <> AValue then exit;
 
-    XList := curve.GetVariable('X');
-    pointCount := curve.GetListCount(XList);
+    pointList := curve.GetVariable('Points');
+    pointCount := curve.GetListCount(pointList);
 
-    if AValue then
-      curve.AssignFloatAt(XList, pointCount-1, (curve.GetFloatAt(XList, pointCount-1)+curve.GetFloatAt(XList, pointCount-2))/2)
-    else
-      curve.AssignFloatAt(XList, pointCount-1, 1);
+    if pointCount >= 2 then
+    begin
+      lastCoord := curve.GetPoint2DAt(pointList, pointCount-1);
+
+      if AValue then
+        lastCoord.x := (lastCoord.x + curve.GetPoint2DAt(pointList, pointCount-2).x)/2
+      else
+        lastCoord.x := 1;
+
+      curve.AssignPointAt(pointList, pointCount-1, lastCoord);
+    end;
 
     FEffectUpdated:= false;
     vsChart.RedrawBitmap;
@@ -826,22 +811,26 @@ var
 
   procedure CopyCurveIfNonTrivial(ASource: TVariableSet; AName: string);
   var subset: TVariableSet;
-    XList,YList: TScriptVariableReference;
+    pointList: TScriptVariableReference;
     pointCount,i: integer;
     trivial: boolean;
   begin
     subset := asource.Subsets[AName];
     if Assigned(subset) then
     begin
-      XList := subset.GetVariable('X');
-      YList := subset.GetVariable('Y');
-      if subset.IsReferenceDefined(XList) and
-        subset.IsReferenceDefined(YList) then
+      pointList := subset.GetVariable('Points');
+      if subset.IsReferenceDefined(pointList) then
       begin
-        pointCount := subset.GetListCount(XList);
-        trivial := true;
-        for i := 0 to pointCount-1 do
-          if abs(subset.GetFloatAt(XList, i)-subset.GetFloatAt(YList, i)) > 1e-6 then trivial := false;
+        pointCount := subset.GetListCount(pointList);
+        if subset.Booleans['Posterize'] then
+          trivial := false
+        else
+        begin
+          trivial := true;
+          for i := 0 to pointCount-1 do
+            with subset.GetPoint2DAt(pointList, i) do
+              if abs(x-y) > 1e-6 then trivial := false;
+        end;
         if not trivial or AParameters.IsDefined(AName) then
           AParameters.Subsets[AName] := subset;
       end;

+ 4 - 8
lazpaint/dialog/filter/uposterize.pas

@@ -40,7 +40,7 @@ function ShowPosterizeDlg(AInstance: TLazPaintCustomInstance; AParameters: TVari
 
 implementation
 
-uses LCScaleDPI, UMac, UColorFilters;
+uses BGRABitmapTypes, LCScaleDPI, UMac, UColorFilters;
 
 function ShowPosterizeDlg(AInstance: TLazPaintCustomInstance; AParameters: TVariableSet): TScriptResult;
 var FPosterize: TFPosterize;
@@ -144,19 +144,15 @@ var params:TVariableSet;
 
   procedure AddPosterize(AChannel :string);
   var
-    XList,YList: TScriptVariableReference;
+    pointList: TScriptVariableReference;
     i: integer;
   begin
     with params.AddSubset(AChannel) do
     begin
       Booleans['Posterize'] := true;
-      XList := AddFloatList('X');
-      YList := AddFloatList('Y');
+      pointList := AddPointList('Points');
       for i := 0 to levels-1 do
-      begin
-        AppendFloat(XList, i/levels);
-        AppendFloat(YList, i/(levels-1));
-      end;
+        AppendPoint(pointList, PointF(i/levels, i/(levels-1)));
     end;
   end;
 

+ 5 - 7
lazpaint/lazpaintmainform.pas

@@ -3107,7 +3107,7 @@ end;
 
 function TFMain.ScriptToolMouse(AVars: TVariableSet): TScriptResult;
 var
-  state, x, y, pressure: TScriptVariableReference;
+  state, xy, pressure: TScriptVariableReference;
   nb, i: integer;
   ptF: TPointF;
   shiftState: TShiftState;
@@ -3116,14 +3116,12 @@ var
   keyCode: word;
 begin
   state := AVars.GetVariable('State');
-  x := AVars.GetVariable('X');
-  y := AVars.GetVariable('Y');
+  xy := AVars.GetVariable('Coords');
   pressure := AVars.GetVariable('Pressure');
-  if not TVariableSet.IsReferenceDefined(x) or
-     not TVariableSet.IsReferenceDefined(y) or
+  if not TVariableSet.IsReferenceDefined(xy) or
      not TVariableSet.IsReferenceDefined(pressure) then
        exit(srInvalidParameters);
-  nb := min(min(AVars.GetListCount(x), AVars.GetListCount(y)), AVars.GetListCount(pressure));
+  nb := min(AVars.GetListCount(xy), AVars.GetListCount(pressure));
   if nb < 1 then
     exit(srInvalidParameters);
   shiftState := [];
@@ -3151,7 +3149,7 @@ begin
 
   for i := 0 to nb-1 do
   begin
-    ptF := PointF(AVars.GetFloatAt(x, i), AVars.GetFloatAt(y, i));
+    ptF := AVars.GetPoint2DAt(xy, i);
     p := AVars.GetFloatAt(pressure, i);
     if ToolManager.ToolMove(ptF,p) then needUpdate := true;
     if (ssLeft in ShiftState) or (ssRight in shiftState) then

+ 9 - 9
lazpaint/ucolorfilters.pas

@@ -340,7 +340,7 @@ type
     result:= ACurve.x <> nil;
   end;
   function GetCurve(ASubset: TVariableSet; AFactor: NativeInt): TCurveInfo;
-  var XList,YList: TScriptVariableReference;
+  var pointList: TScriptVariableReference;
       i,pointCount: NativeInt;
       trivial: boolean;
       slopeValue,slopeX,slopeY: double;
@@ -349,18 +349,17 @@ type
     result.maxValue := 0;
     if Assigned(ASubset) then
     begin
-      XList := ASubset.GetVariable('X');
-      YList := ASubset.GetVariable('Y');
-      if ASubset.IsReferenceDefined(XList) and
-        ASubset.IsReferenceDefined(YList) then
+      pointList := ASubset.GetVariable('Points');
+      if ASubset.IsReferenceDefined(pointList) then
       begin
-        pointCount := ASubset.GetListCount(XList);
+        pointCount := ASubset.GetListCount(pointList);
         if ASubset.Booleans['Posterize'] then trivial := false
         else
           begin
             trivial := true;
             for i := 0 to pointCount-1 do
-              if abs(ASubset.GetFloatAt(XList, i)-ASubset.GetFloatAt(YList, i)) > 1e-6 then trivial := false;
+              with ASubset.GetPoint2DAt(pointList, i) do
+                if abs(x - y) > 1e-6 then trivial := false;
           end;
         if not trivial then
         begin
@@ -368,9 +367,10 @@ type
           setlength(result.y,pointCount);
           setlengtH(result.slope,pointCount-1);
           for i := 0 to pointCount-1 do
+          with ASubset.GetPoint2DAt(pointList, i) do
           begin
-            result.x[i] := trunc(ASubset.GetFloatAt(XList, i)*AFactor+0.5);
-            result.y[i] := trunc(ASubset.GetFloatAt(YList, i)*AFactor+0.5);
+            result.x[i] := trunc(x*AFactor+0.5);
+            result.y[i] := trunc(y*AFactor+0.5);
           end;
           if ASubset.Booleans['Posterize'] then
           begin

+ 229 - 12
lazpaint/uscripting.pas

@@ -50,6 +50,8 @@ type
     function GetFloatByName(const AName: string): double;
     function GetIntegerByName(const AName: string): TScriptInteger;
     function GetPixelByName(const AName: string): TBGRAPixel;
+    function GetPoint2DByName(const AName: string): TPointF;
+    function GetPoint3DByName(const AName: string): TPoint3D;
     function GetStringByName(const AName: string): string;
     function GetSubsetByName(const AName: string): TVariableSet;
     function GetListByName(const AName: string): string;
@@ -60,6 +62,8 @@ type
     procedure SetIntegerByName(const AName: string; AValue: TScriptInteger);
     procedure SetListByName(const AName: string; AValue: string);
     procedure SetPixelByName(const AName: string; AValue: TBGRAPixel);
+    procedure SetPoint2DByName(const AName: string; AValue: TPointF);
+    procedure SetPoint3DByName(const AName: string; AValue: TPoint3D);
     procedure SetStringByName(const AName: string; AValue: string);
     procedure SetSubSetByName(const AName: string; AValue: TVariableSet);
     function GetStrListAsString(AIndex: NativeInt): string;
@@ -77,6 +81,8 @@ type
     destructor Destroy; override;
     function AddFloat(const AName: string; AValue: double): boolean;
     function AddInteger(const AName: string; AValue: TScriptInteger): boolean;
+    function AddPoint(const AName: string; AValue: TPoint3D): boolean; overload;
+    function AddPoint(const AName: string; AValue: TPointF): boolean; overload;
     function AddBoolean(const AName: string; AValue: boolean): boolean;
     function AddPixel(const AName: string; const AValue: TBGRAPixel): boolean;
     function AddString(const AName: string; AValue: string): boolean;
@@ -86,6 +92,7 @@ type
     function AddBooleanList(const AName: string): TScriptVariableReference;
     function AddIntegerList(const AName: string): TScriptVariableReference;
     function AddFloatList(const AName: string): TScriptVariableReference;
+    function AddPointList(const AName: string): TScriptVariableReference;
     function AddPixelList(const AName: string): TScriptVariableReference;
     function AddStringList(const AName: string): TScriptVariableReference;
     function GetVariable(const AName: string): TScriptVariableReference;
@@ -97,6 +104,12 @@ type
     class function AppendInteger(const ADest: TScriptVariableReference; AValue: TScriptInteger): boolean; overload; static;
     class function AssignInteger(const ADest: TScriptVariableReference; AValue: TScriptInteger): boolean; overload; static;
     class function AssignIntegerAt(const ADest: TScriptVariableReference; AIndex: NativeInt; AValue: TScriptInteger): boolean; static;
+    class function AppendPoint(const ADest: TScriptVariableReference; const AValue: TPoint3D): boolean; overload; static;
+    class function AssignPoint(const ADest: TScriptVariableReference; const AValue: TPoint3D): boolean; overload; static;
+    class function AssignPointAt(const ADest: TScriptVariableReference; AIndex: NativeInt; const AValue: TPoint3D): boolean; overload; static;
+    class function AppendPoint(const ADest: TScriptVariableReference; const AValue: TPointF): boolean; overload; static;
+    class function AssignPoint(const ADest: TScriptVariableReference; const AValue: TPointF): boolean; overload; static;
+    class function AssignPointAt(const ADest: TScriptVariableReference; AIndex: NativeInt; const AValue: TPointF): boolean; overload; static;
     class function AppendBoolean(const ADest: TScriptVariableReference; AValue: boolean): boolean; overload; static;
     class function AssignBoolean(const ADest: TScriptVariableReference; AValue: boolean): boolean; overload; static;
     class function AppendString(const ADest: TScriptVariableReference; AValue: string): boolean; overload; static;
@@ -110,6 +123,8 @@ type
     class function IsSubSet(const AReference: TScriptVariableReference): boolean; static;
     class function GetFloat(const ASource: TScriptVariableReference) : double; static;
     class function GetInteger(const ASource: TScriptVariableReference) : TScriptInteger; static;
+    class function GetPoint2D(const ASource: TScriptVariableReference) : TPointF; static;
+    class function GetPoint3D(const ASource: TScriptVariableReference) : TPoint3D; static;
     class function GetBoolean(const ASource: TScriptVariableReference) : boolean; static;
     class function GetString(const ASource: TScriptVariableReference) : string; static;
     class function GetPixel(const ASource: TScriptVariableReference) : TBGRAPixel; static;
@@ -118,6 +133,9 @@ type
     class function GetListCount(const ASource: TScriptVariableReference) : NativeInt; static;
     class function GetFloatAt(const ASource: TScriptVariableReference; AIndex: NativeInt) : double; static;
     class function GetIntegerAt(const ASource: TScriptVariableReference; AIndex: NativeInt) : TScriptInteger; static;
+    class function GetPoint2DAt(const ASource: TScriptVariableReference; AIndex: NativeInt) : TPointF; static;
+    class function GetPoint3DAt(const ASource: TScriptVariableReference; AIndex: NativeInt): TPoint3D; static;
+    class function GetPoint3DAt(const ASource: TScriptVariableReference; AIndex: NativeInt; ADefaultZ: single): TPoint3D; static;
     class function GetBooleanAt(const ASource: TScriptVariableReference; AIndex: NativeInt) : boolean; static;
     class function GetStringAt(const ASource: TScriptVariableReference; AIndex: NativeInt) : string; static;
     class function GetPixelAt(const ASource: TScriptVariableReference; AIndex: NativeInt) : TBGRAPixel; static;
@@ -130,6 +148,8 @@ type
     property VariablesAsString: string read GetVariablesAsString;
     property Floats[const AName: string]: double read GetFloatByName write SetFloatByName;
     property Integers[const AName: string]: TScriptInteger read GetIntegerByName write SetIntegerByName;
+    property Points2D[const AName: string]: TPointF read GetPoint2DByName write SetPoint2DByName;
+    property Points3D[const AName: string]: TPoint3D read GetPoint3DByName write SetPoint3DByName;
     property Booleans[const AName: string]: boolean read GetBooleanByName write SetBooleanByName;
     property Strings[const AName: string]: string read GetStringByName write SetStringByName;
     property Pixels[const AName: string]: TBGRAPixel read GetPixelByName write SetPixelByName;
@@ -346,6 +366,16 @@ begin
   result := GetPixel(GetVariable(AName));
 end;
 
+function TVariableSet.GetPoint2DByName(const AName: string): TPointF;
+begin
+  result := GetPoint2D(GetVariable(AName));
+end;
+
+function TVariableSet.GetPoint3DByName(const AName: string): TPoint3D;
+begin
+  result := GetPoint3D(GetVariable(AName));
+end;
+
 function TVariableSet.GetStringByName(const AName: string): string;
 begin
   result := GetString(GetVariable(AName));
@@ -570,6 +600,7 @@ begin
       case litteral.valueType of
         svtInteger: if not AddInteger(varName,litteral.valueInt) then result := result + [ieDuplicateIdentifier];
         svtFloat: if not AddFloat(varName,litteral.valueFloat) then result := result + [ieDuplicateIdentifier];
+        svtPoint: if not AddPoint(varName,litteral.valuePoint) then result := result + [ieDuplicateIdentifier];
         svtString: if not AddString(varName, litteral.valueStr) then result := result + [ieDuplicateIdentifier];
         svtBoolean: if not AddBoolean(varName,litteral.valueBool) then result := result + [ieDuplicateIdentifier];
         svtPixel: if not AddPixel(varName,litteral.valuePixel) then result := result + [ieDuplicateIdentifier];
@@ -669,6 +700,20 @@ begin
   if IsReferenceDefined(v) then AssignPixel(v,AValue) else AddPixel(AName,AValue);
 end;
 
+procedure TVariableSet.SetPoint2DByName(const AName: string; AValue: TPointF);
+var v: TScriptVariableReference;
+begin
+  v := GetVariable(AName);
+  if IsReferenceDefined(v) then AssignPoint(v,AValue) else AddPoint(AName,AValue);
+end;
+
+procedure TVariableSet.SetPoint3DByName(const AName: string; AValue: TPoint3D);
+var v: TScriptVariableReference;
+begin
+  v := GetVariable(AName);
+  if IsReferenceDefined(v) then AssignPoint(v,AValue) else AddPoint(AName,AValue);
+end;
+
 procedure TVariableSet.SetStringByName(const AName: string; AValue: string);
 var v: TScriptVariableReference;
 begin
@@ -819,6 +864,17 @@ begin
   if result then FScalars[FNbScalars-1].valueInt := AValue;
 end;
 
+function TVariableSet.AddPoint(const AName: string; AValue: TPoint3D): boolean;
+begin
+  result := AddScalar(AName, svtPoint);
+  if result then FScalars[FNbScalars-1].valuePoint := AValue;
+end;
+
+function TVariableSet.AddPoint(const AName: string; AValue: TPointF): boolean;
+begin
+  result := AddPoint(AName, Point3D(AValue.X, AValue.Y, EmptySingle));
+end;
+
 function TVariableSet.AddBoolean(const AName: string; AValue: boolean): boolean;
 begin
   result := AddScalar(AName, svtBoolean);
@@ -939,6 +995,12 @@ begin
   result := AddScalarList(AName, svtFloatList);
 end;
 
+function TVariableSet.AddPointList(const AName: string
+  ): TScriptVariableReference;
+begin
+  result := AddScalarList(AName, svtPointList);
+end;
+
 function TVariableSet.AddPixelList(const AName: string
   ): TScriptVariableReference;
 begin
@@ -1036,16 +1098,18 @@ class procedure TVariableSet.ClearList(const ADest: TScriptVariableReference);
 begin
   if ADest.variableSet <> nil then
   begin
+    if ADest.variableType in ScriptScalarListTypes then
+      with ADest.variableSet.FScalarLists[ADest.variableIndex] do
+      begin
+        count := 0;
+        size := 0;
+        freemem(list);
+        list := nil;
+      end
+    else
     case ADest.variableType of
       svtBoolList: with ADest.variableSet.FBoolLists[ADest.variableIndex] do
                    begin count := 0; list.Size := 0; end;
-      svtIntList,svtFloatList,svtPixList: with ADest.variableSet.FScalarLists[ADest.variableIndex] do
-                    begin
-                      count := 0;
-                      size := 0;
-                      freemem(list);
-                      list := nil;
-                    end;
       svtStrList: with ADest.variableSet.FStrLists[ADest.variableIndex] do
                   begin count := 0; list := nil; end;
     end;
@@ -1187,6 +1251,86 @@ begin
   result := true;
 end;
 
+class function TVariableSet.AppendPoint(const ADest: TScriptVariableReference;
+  const AValue: TPoint3D): boolean;
+begin
+  result := false;
+  if ADest.variableSet = nil then exit;
+  case ADest.variableType of
+    svtPointList:
+      with ADest.variableSet.FScalarLists[ADest.variableIndex] do
+      begin
+        if count = ListMaxLength then exit;
+        if size = count then
+        begin
+          if count = 0 then size := 4 else size := count*2;
+          ReAllocMem(list,size*sizeof(TPoint3D));
+        end;
+        (PPoint3D(list)+count)^ := AValue;
+        inc(count);
+        result := true;
+      end;
+    svtStrList: result := AppendString(ADest, ScalarToStr(svtPoint, AValue));
+  end;
+end;
+
+class function TVariableSet.AssignPoint(const ADest: TScriptVariableReference;
+  const AValue: TPoint3D): boolean;
+begin
+  if ADest.variableSet = nil then
+  begin
+    result := false;
+    exit;
+  end;
+  case ADest.variableType of
+    svtPoint: ADest.variableSet.FScalars[ADest.variableIndex].valuePoint := AValue;
+    svtString: ADest.variableSet.FStrings[ADest.variableIndex].value := ScalarToStr(svtPoint, AValue);
+    else
+    begin
+      result := false;
+      exit;
+    end;
+  end;
+  result := true;
+end;
+
+class function TVariableSet.AssignPointAt(
+  const ADest: TScriptVariableReference; AIndex: NativeInt;
+  const AValue: TPoint3D): boolean;
+begin
+  result := false;
+  if (ADest.variableSet = nil) or (AIndex < 0) then exit;
+  if not (Adest.variableType in ScriptVariableListTypes) then exit;
+  if AIndex >= GetListCount(ADest) then exit;
+  case ADest.variableType of
+    svtPointList: with ADest.variableSet.FScalarLists[ADest.variableIndex] do
+                    (PPoint3D(list)+AIndex)^ := AValue;
+    svtStrList: with ADest.variableSet.FStrLists[ADest.variableIndex] do
+                    list[AIndex] := ScalarToStr(svtPoint, AValue);
+    else exit;
+  end;
+  result := true;
+end;
+
+class function TVariableSet.AppendPoint(const ADest: TScriptVariableReference;
+  const AValue: TPointF): boolean;
+begin
+  result := AppendPoint(ADest, Point3D(AValue.X, AValue.y, EmptySingle));
+end;
+
+class function TVariableSet.AssignPoint(const ADest: TScriptVariableReference;
+  const AValue: TPointF): boolean;
+begin
+  result := AssignPoint(ADest, Point3D(AValue.X, AValue.y, EmptySingle));
+end;
+
+class function TVariableSet.AssignPointAt(
+  const ADest: TScriptVariableReference; AIndex: NativeInt;
+  const AValue: TPointF): boolean;
+begin
+  result := AssignPointAt(ADest, AIndex, Point3D(AValue.X, AValue.y, EmptySingle));
+end;
+
 class function TVariableSet.AppendBoolean(
   const ADest: TScriptVariableReference; AValue: boolean): boolean;
 begin
@@ -1388,6 +1532,7 @@ class function TVariableSet.AssignList(const ADest: TScriptVariableReference;
 var
   tilde,expectingValue: boolean;
   inQuote: char;
+  inPar: integer;
   escaping: boolean;
   start,cur: integer;
 
@@ -1402,6 +1547,7 @@ var
       svtBoolean: AppendBoolean(ADest, litteral.valueBool);
       svtInteger: AppendInteger(ADest, litteral.valueInt);
       svtFloat: AppendFloat(ADest, litteral.valueFloat);
+      svtPoint: AppendPoint(ADest, litteral.valuePoint);
       svtString: AppendString(ADest, litteral.valueStr);
       svtPixel: AppendPixel(ADest, litteral.valuePixel);
     end;
@@ -1426,6 +1572,7 @@ begin
     cur := 1;
   tilde := false;
   inQuote:= #0;
+  inPar := 0;
   escaping := false;
   start := 0;
   expectingValue := false;
@@ -1444,7 +1591,13 @@ begin
     begin
       if (start = 0) and not (AListExpr[cur] in IgnoredWhitespaces) then start := cur;
       if AListExpr[cur] in StringDelimiters then inQuote:= AListExpr[cur] else
-      if AListExpr[cur]=',' then
+      if AListExpr[cur] = '(' then inc(inPar) else
+      if AListExpr[cur] = ')' then
+      begin
+        if inPar > 0 then dec(inPar)
+        else include(result, ieTooManyClosingBrackets);
+      end else
+      if (AListExpr[cur]=',') and (inPar = 0) then
       begin
         if start = 0 then result += [ieMissingValue]
         else
@@ -1485,6 +1638,7 @@ begin
       svtBoolList: for i := 0 to sourceCount-1 do AppendBoolean(ADest, GetBooleanAt(ASource,i));
       svtIntList: for i := 0 to sourceCount-1 do AppendInteger(ADest, GetIntegerAt(ASource,i));
       svtFloatList: for i := 0 to sourceCount-1 do AppendFloat(ADest, GetFloatAt(ASource,i));
+      svtPointList: for i := 0 to sourceCount-1 do AppendPoint(ADest, GetPoint3DAt(ASource,i));
       svtPixList: for i := 0 to sourceCount-1 do AppendPixel(ADest, GetPixelAt(ASource,i));
       svtStrList: for i := 0 to sourceCount-1 do AppendString(ADest, GetStringAt(ASource,i));
     end;
@@ -1492,7 +1646,8 @@ begin
   if ADest.variableType = ASource.variableType then //no conversion
   begin
     case ASource.variableType of
-      svtBoolean,svtFloat,svtInteger,svtPixel: ADest.variableSet.FScalars[ADest.variableIndex].valueBytes := ASource.variableSet.FScalars[ASource.variableIndex].valueBytes;
+      svtBoolean, svtFloat, svtInteger, svtPixel, svtPoint:
+        ADest.variableSet.FScalars[ADest.variableIndex].valueBytes := ASource.variableSet.FScalars[ASource.variableIndex].valueBytes;
       svtString: ADest.variableSet.FStrings[ADest.variableIndex].value := ASource.variableSet.FStrings[ASource.variableIndex].value;
       svtSubset: ADest.variableSet.FSubsets[ASource.variableIndex].value.CopyValuesTo(ASource.variableSet.FSubsets[ASource.variableIndex].value);
       else
@@ -1508,6 +1663,7 @@ begin
     svtBoolean: AssignBoolean(ADest, ASource.variableSet.FScalars[ASource.variableIndex].valueBool);
     svtFloat: AssignFloat(ADest, ASource.variableSet.FScalars[ASource.variableIndex].valueFloat);
     svtInteger: AssignInteger(ADest, ASource.variableSet.FScalars[ASource.variableIndex].valueInt);
+    svtPoint: AssignPoint(ADest, ASource.variableSet.FScalars[ASource.variableIndex].valuePoint);
     svtPixel: AssignPixel(ADest, ASource.variableSet.FScalars[ASource.variableIndex].valuePix);
     svtString: AssignString(ADest, ASource.variableSet.FStrings[ASource.variableIndex].value);
     else
@@ -1528,7 +1684,7 @@ end;
 class function TVariableSet.IsList(const AReference: TScriptVariableReference
   ): boolean;
 begin
-  result := AReference.variableType in [svtFloatList, svtIntList, svtBoolList, svtStrList, svtPixList];
+  result := AReference.variableType in ScriptVariableListTypes;
 end;
 
 class function TVariableSet.IsSubSet(const AReference: TScriptVariableReference
@@ -1601,6 +1757,28 @@ begin
   result := 0;
 end;
 
+class function TVariableSet.GetPoint2D(const ASource: TScriptVariableReference
+  ): TPointF;
+begin
+  with GetPoint3D(ASource) do
+    result := PointF(x,y);
+end;
+
+class function TVariableSet.GetPoint3D(const ASource: TScriptVariableReference
+  ): TPoint3D;
+begin
+  if ASource.variableSet <> nil then
+  begin
+    case ASource.variableType of
+      svtPoint: begin
+        result := ASource.variableSet.FScalars[ASource.variableIndex].valuePoint;
+        exit;
+      end;
+    end;
+  end;
+  result := Point3D(0,0,EmptySingle);
+end;
+
 class function TVariableSet.GetBoolean(const ASource: TScriptVariableReference
   ): boolean;
 begin
@@ -1688,9 +1866,11 @@ class function TVariableSet.GetList(const ASource: TScriptVariableReference
 begin
   if ASource.variableSet <> nil then
   begin
+    if ASource.variableType in ScriptScalarListTypes then
+      result := ASource.variableSet.GetScalarListAsString(ASource.variableIndex)
+    else
     case ASource.variableType of
       svtBoolList: result := ASource.variableSet.GetBoolListAsString(ASource.variableIndex);
-      svtFloatList,svtIntList,svtPixList: result := ASource.variableSet.GetScalarListAsString(ASource.variableIndex);
       svtStrList: result := ASource.variableSet.GetStrListAsString(ASource.variableIndex);
     else
       result := '';
@@ -1703,9 +1883,11 @@ class function TVariableSet.GetListCount(const ASource: TScriptVariableReference
 begin
   if ASource.variableSet <> nil then
   begin
+    if ASource.variableType in ScriptScalarListTypes then
+      result := ASource.variableSet.FScalarLists[ASource.variableIndex].count
+    else
     case ASource.variableType of
       svtBoolList: result := ASource.variableSet.FBoolLists[ASource.variableIndex].count;
-      svtFloatList,svtIntList,svtPixList: result := ASource.variableSet.FScalarLists[ASource.variableIndex].count;
       svtStrList: result := ASource.variableSet.FStrLists[ASource.variableIndex].count;
     else
       result := 0;
@@ -1762,6 +1944,41 @@ begin
     end;
 end;
 
+class function TVariableSet.GetPoint2DAt(
+  const ASource: TScriptVariableReference; AIndex: NativeInt): TPointF;
+var
+  result3D: TPoint3D;
+begin
+  result3D := GetPoint3DAt(ASource, AIndex);
+  result := PointF(result3D.x, result3D.y);
+end;
+
+class function TVariableSet.GetPoint3DAt(
+  const ASource: TScriptVariableReference; AIndex: NativeInt): TPoint3D;
+begin
+  result := GetPoint3DAt(ASource, AIndex, EmptySingle);
+end;
+
+class function TVariableSet.GetPoint3DAt(
+  const ASource: TScriptVariableReference; AIndex: NativeInt; ADefaultZ: single
+  ): TPoint3D;
+begin
+  result := Point3D(0,0, ADefaultZ);
+  if (ASource.variableSet = nil) or (AIndex < 0) then exit;
+  if not (ASource.variableType in ScriptVariableListTypes) then exit;
+  if ASource.variableType in ScriptScalarListTypes then
+    with ASource.variableSet.FScalarLists[ASource.variableIndex] do
+    begin
+      if AIndex >= count then exit;
+      case ASource.variableType of
+        svtPointList: begin
+          result := (PPoint3D(list)+AIndex)^;
+          if result.z = EmptySingle then result.z := ADefaultZ;
+        end;
+      end;
+    end;
+end;
+
 class function TVariableSet.GetBooleanAt(
   const ASource: TScriptVariableReference; AIndex: NativeInt): boolean;
 begin

+ 14 - 7
lazpaint/uscripttype.pas

@@ -41,10 +41,10 @@ type
     valueType: TScriptVariableType;
     valueFloat: double;
     valueInt: TScriptInteger;
+    valuePoint: TPoint3D;
     valueBool: boolean;
     valueStr: string;
     valuePixel: TBGRAPixel;
-    valuePoint: TPoint3D;
   end;
 
   TScalarVariable = record
@@ -52,11 +52,11 @@ type
     varType: TScriptVariableType;
     case TScriptVariableType of
       svtFloat: (valueFloat: double);
-      svtPoint: (valuePoint: TPoint3D);
       svtInteger: (valueInt: TScriptInteger);
+      svtPoint: (valuePoint: TPoint3D);
       svtBoolean: (valueBool: boolean);
       svtPixel: (valuePix: TBGRAPixel);
-      svtUndefined: (valueBytes: packed array[0..7] of byte);
+      svtUndefined: (valueBytes: packed array[0..11] of byte);
   end;
 
 const
@@ -83,7 +83,7 @@ function ScriptUnquote(const S: string): string;
 function UnescapeString(const S: string): string;
 function TryScriptUnquote(const S: String; out unquotedS: string): TInterpretationErrors;
 function FloatToStrUS(AValue: double): string;
-function ScalarToStr(AVarType: TScriptVariableType; var AValue): string;
+function ScalarToStr(AVarType: TScriptVariableType; const AValue): string;
 function ParseLitteral(var cur: integer; expr: string; var errors: TInterpretationErrors): TParsedLitteral;
 function ParseListType(s: string): TScriptVariableType;
 function FloatToPixel(AValue: double): TBGRAPixel;
@@ -144,7 +144,7 @@ begin
   if (idxE = 0) and (idxPt = 0) then result := result+'.0';
 end;
 
-function ScalarToStr(AVarType: TScriptVariableType; var AValue): string;
+function ScalarToStr(AVarType: TScriptVariableType; const AValue): string;
 begin
   case AVarType of
     svtFloat: result := FloatToStrUS(double(AValue));
@@ -385,7 +385,7 @@ begin
 end;
 
 function ParseListType(s: string): TScriptVariableType;
-var cur,start: integer;
+var cur,start,inPar: integer;
   inQuote: boolean;
   firstVal: TParsedLitteral;
   errors: TInterpretationErrors;
@@ -396,6 +396,7 @@ begin
   if (cur <= length(s)) and (s[cur]='~') then inc(cur);
   while (cur <= length(s)) and (s[cur] in IgnoredWhitespaces) do inc(cur);
   inQuote:= false;
+  inPar := 0;
   start := cur;
   while (cur <= length(s)) do
   begin
@@ -405,7 +406,12 @@ begin
     end else
     begin
       if s[cur]='"' then inQuote:= true else
-      if s[cur] in ['[',']',','] then break;
+      if s[cur]='(' then inc(inPar) else
+      if s[cur]=')' then
+      begin
+        if inPar > 0 then dec(inPar) else break;
+      end else
+      if (inPar = 0) and (s[cur] in ['[',']',',']) then break;
     end;
     inc(cur);
   end;
@@ -416,6 +422,7 @@ begin
   case firstval.valueType of
   svtBoolean: result := svtBoolList;
   svtFloat: result := svtFloatList;
+  svtPoint: result := svtPointList;
   svtInteger: result := svtIntList;
   svtPixel: result := svtPixList;
   svtString: result := svtStrList;

+ 1 - 1
scripts/lazpaint/colors.py

@@ -71,7 +71,7 @@ OLIVE = RGB(128,128,0)
 SILVER = RGB(192,192,192)
 
 def get_curve(points, posterize=False):
-  return {'X': [float(pt[0]) for pt in points], 'Y': [float(pt[1]) for pt in points], 'Posterize': posterize}
+  return {'Points': points, 'Posterize': posterize}
 
 def curves(red=[], red_posterize=False, green=[], green_posterize=False, blue=[], blue_posterize=False, hue=[], hue_posterize=False, saturation=[], saturation_posterize=False, lightness=[], lightness_posterize=False, validate=True):
   command.send('ColorCurves', Red=get_curve(red, red_posterize), Green=get_curve(green, green_posterize), Blue=get_curve(blue, blue_posterize), Hue=get_curve(hue, hue_posterize), Saturation=get_curve(saturation, saturation_posterize), Lightness=get_curve(lightness, lightness_posterize), Validate=validate)

+ 3 - 5
scripts/lazpaint/tools.py

@@ -138,17 +138,15 @@ def choose(name):
 
 def mouse(coords, state=[STATE_LEFT], default_pressure=1.0):
   if not isinstance(coords, list):
-      x = [float(coords[0])]
-      y = [float(coords[1])]
+      xy = [(float(coords[0]), float(coords[1]))]
       if len(coords)>2:
         pressure = [float(coords[2])]
       else:
         pressure = [default_pressure]
   else:
-      x = [float(c[0]) for c in coords]
-      y = [float(c[1]) for c in coords]
+      xy = [(float(c[0]), float(c[1])) for c in coords]
       pressure = [float(c[2]) if len(c)>2 else default_pressure for c in coords]      
-  command.send("ToolMouse", X=x, Y=y, State=state, Pressure=pressure)
+  command.send("ToolMouse", Coords=xy, State=state, Pressure=pressure)
 
 def keys(keys, state=[]):
   if isinstance(keys, str):