MainUnit.pas 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. unit MainUnit;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Lion Example
  23. *
  24. * The Initial Developer(s) of the Original Code is:
  25. * Christian-W. Budde <[email protected]>
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2012
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. *
  31. * ***** END LICENSE BLOCK ***** *)
  32. interface
  33. {$include GR32.inc}
  34. uses
  35. {$IFDEF FPC} LCLIntf, LResources, Buttons, {$ENDIF} SysUtils, Classes,
  36. Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, GR32, GR32_Image,
  37. GR32_Polygons, GR32_Paths, GR32_Brushes, GR32_Transforms, GR32_RangeBars,
  38. LionData;
  39. type
  40. TFrmLion = class(TForm)
  41. CbxClearBackground: TCheckBox;
  42. GbrAlpha: TGaugeBar;
  43. GbrWidth: TGaugeBar;
  44. LblAlpha: TLabel;
  45. LblStrokeWidth: TLabel;
  46. PaintBox32: TPaintBox32;
  47. PnlInteraction: TPanel;
  48. PnlSampler: TPanel;
  49. PnlSettings: TPanel;
  50. RgpBrush: TRadioGroup;
  51. RgpMouse: TRadioGroup;
  52. procedure FormCreate(Sender: TObject);
  53. procedure FormDestroy(Sender: TObject);
  54. procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
  55. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  56. procedure CbxClearBackgroundClick(Sender: TObject);
  57. procedure GbrAlphaChange(Sender: TObject);
  58. procedure GbrWidthChange(Sender: TObject);
  59. procedure PaintBox32MouseDown(Sender: TObject; Button: TMouseButton;
  60. Shift: TShiftState; X, Y: Integer);
  61. procedure PaintBox32MouseMove(Sender: TObject; Shift: TShiftState; X,
  62. Y: Integer);
  63. procedure PaintBox32MouseUp(Sender: TObject; Button: TMouseButton;
  64. Shift: TShiftState; X, Y: Integer);
  65. procedure PaintBox32PaintBuffer(Sender: TObject);
  66. procedure PaintBox32Resize(Sender: TObject);
  67. procedure RgpBrushClick(Sender: TObject);
  68. private
  69. FRenderer: TPolygonRenderer32VPR;
  70. FNestedTransformation: TNestedTransformation;
  71. FCenter, FOffset: TFloatPoint;
  72. FLastSqrDistance: TFloat;
  73. FLastAngle: TFloat;
  74. FLastPoint: TPoint;
  75. FCurrentScale: TFloat;
  76. FCurrentAngle: TFloat;
  77. procedure UpdateTransformation;
  78. procedure PaintBox32PaintAlphaBuffer(Sender: TObject);
  79. procedure PaintBox32PaintOutlineAlphaBuffer(Sender: TObject);
  80. procedure UpdateOnPaintBuffer;
  81. end;
  82. var
  83. FrmLion: TFrmLion;
  84. implementation
  85. {$IFDEF FPC}
  86. {$R *.lfm}
  87. {$ELSE}
  88. {$R *.dfm}
  89. {$ENDIF}
  90. uses
  91. Math, Types, GR32_Math, GR32_Geometry, GR32_VectorUtils;
  92. procedure TFrmLion.FormCreate(Sender: TObject);
  93. begin
  94. FNestedTransformation := TNestedTransformation.Create;
  95. FNestedTransformation.Add(TAffineTransformation);
  96. (*
  97. FNestedTransformation.Add(TBloatTransformation);
  98. with TBloatTransformation(FNestedTransformation[1]) do
  99. begin
  100. BloatPower := 1.1;
  101. SrcRect := FloatRect(0, 0, PaintBox32.Width, PaintBox32.Height);
  102. end;
  103. *)
  104. FRenderer := TPolygonRenderer32VPR.Create(PaintBox32.Buffer);
  105. FCurrentScale := 1;
  106. FCurrentAngle := 0;
  107. UpdateTransformation;
  108. end;
  109. procedure TFrmLion.FormDestroy(Sender: TObject);
  110. begin
  111. FRenderer.Free;
  112. FNestedTransformation.Free;
  113. end;
  114. procedure TFrmLion.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  115. WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  116. begin
  117. FCurrentScale := FCurrentScale * Power(2, -0.001 * WheelDelta);
  118. UpdateTransformation;
  119. end;
  120. procedure TFrmLion.GbrAlphaChange(Sender: TObject);
  121. begin
  122. UpdateOnPaintBuffer;
  123. end;
  124. procedure TFrmLion.GbrWidthChange(Sender: TObject);
  125. begin
  126. if RgpBrush.ItemIndex = 1 then
  127. PaintBox32.Invalidate;
  128. end;
  129. procedure TFrmLion.PaintBox32MouseDown(Sender: TObject; Button: TMouseButton;
  130. Shift: TShiftState; X, Y: Integer);
  131. begin
  132. PaintBox32.OnMouseMove := PaintBox32MouseMove;
  133. FLastSqrDistance := SqrDistance(FCenter, FloatPoint(X, Y)) / FCurrentScale;
  134. FLastAngle := ArcTan2(FCenter.Y - Y, FCenter.X - X) + FCurrentAngle;
  135. FLastPoint := GR32.Point(X, Y);
  136. end;
  137. procedure TFrmLion.PaintBox32MouseMove(Sender: TObject; Shift: TShiftState; X,
  138. Y: Integer);
  139. var
  140. Angle, SqrDistance: TFloat;
  141. begin
  142. if ssLeft in Shift then
  143. begin
  144. SqrDistance := GR32_Geometry.SqrDistance(FCenter, FloatPoint(X, Y));
  145. Angle := ArcTan2(FCenter.Y - Y, FCenter.X - X);
  146. FCurrentScale := SqrDistance / FLastSqrDistance;
  147. FCurrentAngle := FLastAngle - Angle;
  148. end;
  149. if ssRight in Shift then
  150. begin
  151. FCenter.X := FCenter.X + (X - FLastPoint.X);
  152. FCenter.Y := FCenter.Y + (Y - FLastPoint.Y);
  153. FLastPoint := GR32.Point(X, Y);
  154. end;
  155. UpdateTransformation;
  156. end;
  157. procedure TFrmLion.PaintBox32MouseUp(Sender: TObject; Button: TMouseButton;
  158. Shift: TShiftState; X, Y: Integer);
  159. begin
  160. PaintBox32.OnMouseMove := nil;
  161. end;
  162. procedure TFrmLion.UpdateTransformation;
  163. begin
  164. with TAffineTransformation(FNestedTransformation[0]) do
  165. begin
  166. Clear;
  167. Translate(-FOffset.X, -FOffset.Y);
  168. Scale(FCurrentScale);
  169. Rotate(RadToDeg(FCurrentAngle));
  170. Translate(FCenter.X, FCenter.Y);
  171. end;
  172. PaintBox32.Invalidate;
  173. end;
  174. procedure TFrmLion.CbxClearBackgroundClick(Sender: TObject);
  175. begin
  176. UpdateOnPaintBuffer;
  177. end;
  178. procedure TFrmLion.PaintBox32PaintBuffer(Sender: TObject);
  179. var
  180. Index: Integer;
  181. begin
  182. PaintBox32.Buffer.Clear($FFFFFFFF);
  183. for Index := 0 to High(GLion.ColoredPolygons) do
  184. begin
  185. FRenderer.Color := GLion.ColoredPolygons[Index].Color;
  186. FRenderer.PolyPolygonFS(GLion.ColoredPolygons[Index].Polygon,
  187. FloatRect(PaintBox32.Buffer.ClipRect), FNestedTransformation);
  188. end;
  189. end;
  190. procedure TFrmLion.PaintBox32PaintAlphaBuffer(Sender: TObject);
  191. var
  192. Index: Integer;
  193. Alpha: Byte;
  194. begin
  195. if CbxClearBackground.Checked then
  196. PaintBox32.Buffer.Clear($FFFFFFFF);
  197. Alpha := GbrAlpha.Position;
  198. for Index := 0 to High(GLion.ColoredPolygons) do
  199. begin
  200. FRenderer.Color := SetAlpha(GLion.ColoredPolygons[Index].Color, Alpha);
  201. FRenderer.PolyPolygonFS(GLion.ColoredPolygons[Index].Polygon,
  202. FloatRect(PaintBox32.Buffer.ClipRect), FNestedTransformation);
  203. end;
  204. end;
  205. procedure TFrmLion.PaintBox32PaintOutlineAlphaBuffer(Sender: TObject);
  206. var
  207. Index: Integer;
  208. Alpha: Byte;
  209. begin
  210. if CbxClearBackground.Checked then
  211. PaintBox32.Buffer.Clear($FFFFFFFF);
  212. Alpha := GbrAlpha.Position;
  213. for Index := 0 to High(GLion.ColoredPolygons) do
  214. with GLion.ColoredPolygons[Index] do
  215. begin
  216. FRenderer.Color := SetAlpha(Color, Alpha);
  217. FRenderer.PolyPolygonFS(BuildPolyPolyLine(Polygon, True,
  218. 0.1 * GbrWidth.Position), FloatRect(PaintBox32.Buffer.ClipRect),
  219. FNestedTransformation);
  220. end;
  221. end;
  222. procedure TFrmLion.PaintBox32Resize(Sender: TObject);
  223. begin
  224. FCenter := FloatPoint(0.5 * PaintBox32.Width, 0.5 * PaintBox32.Height);
  225. FOffset := FloatPoint(0.5 * (GLion.Bounds.Right - GLion.Bounds.Left),
  226. 0.5 * (GLion.Bounds.Bottom - GLion.Bounds.Top));
  227. TAffineTransformation(FNestedTransformation[0]).Translate(FCenter.X - FOffset.X, FCenter.Y - FOffset.Y);
  228. end;
  229. procedure TFrmLion.UpdateOnPaintBuffer;
  230. begin
  231. case RgpBrush.ItemIndex of
  232. 0:
  233. if CbxClearBackground.Checked and (GbrAlpha.Position = $FF) then
  234. PaintBox32.OnPaintBuffer := PaintBox32PaintBuffer
  235. else
  236. PaintBox32.OnPaintBuffer := PaintBox32PaintAlphaBuffer;
  237. 1: PaintBox32.OnPaintBuffer := PaintBox32PaintOutlineAlphaBuffer;
  238. end;
  239. PaintBox32.Invalidate;
  240. end;
  241. procedure TFrmLion.RgpBrushClick(Sender: TObject);
  242. begin
  243. UpdateOnPaintBuffer;
  244. LblStrokeWidth.Visible := RgpBrush.ItemIndex = 1;
  245. GbrWidth.Visible := LblStrokeWidth.Visible;
  246. end;
  247. end.