home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 November / CDVD1105.ISO / Software / Freeware / programare / graphics32 / Examples / Clx / GradLines_Ex / MainUnit.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2004-07-16  |  7.5 KB  |  320 lines

  1. unit MainUnit;
  2.  
  3. (* ***** BEGIN LICENSE BLOCK *****
  4.  * Version: MPL 1.1
  5.  *
  6.  * The contents of this file are subject to the Mozilla Public License Version
  7.  * 1.1 (the "License"); you may not use this file except in compliance with
  8.  * the License. You may obtain a copy of the License at
  9.  * http://www.mozilla.org/MPL/
  10.  *
  11.  * Software distributed under the License is distributed on an "AS IS" basis,
  12.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13.  * for the specific language governing rights and limitations under the
  14.  * License.
  15.  *
  16.  * The Original Code is Graphics32
  17.  *
  18.  * The Initial Developer of the Original Code is
  19.  * Alex A. Denisov
  20.  *
  21.  * Portions created by the Initial Developer are Copyright (C) 2000-2004
  22.  * the Initial Developer. All Rights Reserved.
  23.  *
  24.  * Contributor(s):
  25.  *   Mattias Andersson <mattias@centaurix.com>
  26.  *
  27.  * ***** END LICENSE BLOCK ***** *)
  28.  
  29. // TPaintBox32 and DrawLineFSP example
  30. // Author: Alex Denissov
  31. // http://g32.org
  32.  
  33.  
  34. interface
  35.  
  36. uses
  37.   SysUtils, Classes, QGraphics, QControls, QForms, QDialogs,
  38.   QStdCtrls, QExtCtrls, GR32, GR32_Blend, GR32_Image;
  39.  
  40. type
  41.   TVector2f = record
  42.     X, Y: Single;
  43.   end;
  44.  
  45.   TLine = class
  46.   public
  47.     Bitmap: TBitmap32;
  48.     P1, P2: TVector2f;     // positions
  49.     V1, V2: TVector2f;     // velocities
  50.     C1, C2, C3: TColor32;  // colors that define gradient pattern
  51.     t1, t2, t3: Single;
  52.     MaxVelocity: Single;
  53.     constructor Create(ABitmap: TBitmap32);
  54.     procedure Advance(DeltaT: Single);
  55.     function GetLength: Single;
  56.     procedure Paint;
  57.   end;
  58.  
  59.   TForm1 = class(TForm)
  60.     PaintBox: TPaintBox32;
  61.     Button1: TButton;
  62.     Button2: TButton;
  63.     Button3: TButton;
  64.     RadioGroup1: TRadioGroup;
  65.     RadioGroup2: TRadioGroup;
  66.     Label1: TLabel;
  67.     Panel1: TPanel;
  68.     procedure Button1Click(Sender: TObject);
  69.     procedure FormCreate(Sender: TObject);
  70.     procedure Button2Click(Sender: TObject);
  71.     procedure Button3Click(Sender: TObject);
  72.     procedure BitmapLayerMouseDown(Sender: TObject;
  73.       Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  74.     procedure BitmapLayerMouseUp(Sender: TObject; Button: TMouseButton;
  75.       Shift: TShiftState; X, Y: Integer);
  76.     procedure RadioGroup1Click(Sender: TObject);
  77.     procedure RadioGroup2Click(Sender: TObject);
  78.   protected
  79.     Lines: array of TLine;
  80.     P: TPoint; // mouse shift
  81.     M: Boolean; // mouse down flag
  82.     FadeCount: Integer;
  83.     Pass: Integer;
  84.     DrawPasses: Integer;
  85.     procedure AppEventsIdle(Sender: TObject; var Done: Boolean);
  86.   public
  87.     procedure AddLine;
  88.     procedure AddLines(N: Integer);
  89.   end;
  90.  
  91. var
  92.   Form1: TForm1;
  93.  
  94. implementation
  95.  
  96. uses Math;
  97.  
  98. function vAdd(const A, B: TVector2f): TVector2f;
  99. begin
  100.   Result.X := A.X + B.X;
  101.   Result.Y := A.Y + B.Y;
  102. end;
  103.  
  104. function vSub(const A, B: TVector2f): TVector2f;
  105. begin
  106.   Result.X := A.X - B.X;
  107.   Result.Y := A.Y - B.Y;
  108. end;
  109.  
  110. function vLen(const A: TVector2f): Single;
  111. begin
  112.   Result := SqRt(SqR(A.X) + SqR(A.Y));
  113. end;
  114.  
  115. function vDot(const A, B: TVector2f): Single;
  116. begin
  117.   Result := A.X * B.X + A.Y * B.Y;
  118. end;
  119.  
  120. function vScale(const A: TVector2f; Factor: Single): TVector2f;
  121. begin
  122.   Result.X := A.X * Factor;
  123.   Result.Y := A.Y * Factor;
  124. end;
  125.  
  126. {$R *.xfm}
  127.  
  128.  
  129. { TLine }
  130.  
  131. procedure TLine.Advance(DeltaT: Single);
  132.  
  133. {}procedure AdvancePoint(var P, V: TVector2f; t: Single);
  134.   begin
  135.     { apply velocities }
  136.     P.X := P.X + V.X * t;
  137.     P.Y := P.Y + V.Y * t;
  138.  
  139.     { reflect from walls }
  140.     if P.X < 0 then
  141.     begin
  142.       P.X := 0;
  143.       V.X := -V.X;
  144.     end;
  145.     if P.X >= Form1.PaintBox.Width then
  146.     begin
  147.       P.X := Form1.PaintBox.Width - 1;
  148.       V.X := - V.X;
  149.     end;
  150.     if P.Y < 0 then
  151.     begin
  152.       P.Y := 0;
  153.       V.Y := -V.Y;
  154.     end;
  155.     if P.Y >= Form1.PaintBox.Height then
  156.     begin
  157.       P.Y := Form1.PaintBox.Height - 1;
  158.       V.Y := - V.Y
  159.     end;
  160.  
  161.     { change velocity a little bit }
  162.     V.X := V.X + t * (Random - 0.5) / 4;
  163.     V.Y := V.Y + t * (Random - 0.5) / 4;
  164.  
  165.     { limit velocity }
  166.     if vLen(V1) > MaxVelocity then V1 := vScale(V1, 1 / vLen(V1));
  167.     if vLen(V2) > MaxVelocity then V2 := vScale(V2, 1 / vLen(V2));
  168.   end;
  169. begin
  170.   AdvancePoint(P1, V1, DeltaT);
  171.   AdvancePoint(P2, V2, DeltaT);
  172.  
  173.   C1 := HSLtoRGB(t1, Sin(t1 / 1.8) * 0.4 + 0.6, 0.5);
  174.   C1 := SetAlpha(C1, Round(Sin(t1) * 25 + 50));
  175.   t1 := t1 + Random / 300;
  176.  
  177.   C2 := HSLtoRGB(t2, Sin(t2 / 1.8) * 0.4 + 0.6, 0.5);
  178.   C2 := SetAlpha(C2, Round(Sin(t2) * 25 + 50));
  179.   t2 := t2 + Random / 400;
  180.  
  181.   C3 := HSLtoRGB(t3, Sin(t3 / 1.8) * 0.4 + 0.6, 0.5);
  182.   C3 := SetAlpha(C3, Round(Sin(t3) * 25 + 50));
  183.   t3 := t3 + Random / 400;
  184. end;
  185.  
  186. constructor TLine.Create(ABitmap: TBitmap32);
  187. begin
  188.   Bitmap := ABitmap;
  189.   MaxVelocity := 1;
  190. end;
  191.  
  192. function TLine.GetLength: Single;
  193. begin
  194.   Result := vLen(vSub(P1, P2));
  195. end;
  196.  
  197. procedure TLine.Paint;
  198. var
  199.   L: Single;
  200. begin
  201.   // this shows how to draw a gradient line
  202.   L := GetLength;
  203.   if L < 1 then Exit;
  204.   Bitmap.SetStipple([C1, C2, C3]);
  205.   Bitmap.StippleStep := 2 / L; {2 = 3 - 1 = Number of colors in a pattern - 1}
  206.   Bitmap.StippleCounter := 0;             
  207.   Bitmap.LineFSP(P1.X, P1.Y, P2.X, P2.Y);
  208. end;
  209.  
  210. { TForm1 }
  211.  
  212. procedure TForm1.AddLine;
  213. var
  214.   L: TLine;
  215. begin
  216.   SetLength(Lines, Length(Lines) + 1);
  217.   L := TLine.Create(PaintBox.Buffer);
  218.   Lines[High(Lines)] := L;
  219.   L.t1 := Random * 3;
  220.   L.t2 := Random * 3;
  221.   L.t3 := Random * 3;
  222.   L.P1.X := Random(PaintBox.Buffer.Width - 1);
  223.   L.P2.X := Random(PaintBox.Buffer.Width - 1);
  224.   L.P1.Y := Random(PaintBox.Buffer.Height - 1);
  225.   L.P2.Y := Random(PaintBox.Buffer.Height - 1);
  226.   Panel1.Caption := IntToStr(Length(Lines));
  227. end;
  228.  
  229. procedure TForm1.AddLines(N: Integer);
  230. var
  231.   i: Integer;
  232. begin
  233.   for i := 0 to N - 1 do AddLine;
  234. end;
  235.  
  236. procedure TForm1.AppEventsIdle(Sender: TObject; var Done: Boolean);
  237. var
  238.   I, J: Integer;
  239.   P: PColor32;
  240. begin
  241.   for J := 0 to DrawPasses - 1 do
  242.     for I := 0 to High(Lines) do
  243.     begin
  244.       Lines[I].Advance(1);
  245.       Lines[I].Paint;
  246.     end;
  247.  
  248.   if FadeCount > 0 then
  249.   begin
  250.     if Pass = 0 then with PaintBox.Buffer do
  251.     begin
  252.       P := @Bits[0];
  253.       for I := 0 to Width * Height - 1 do
  254.       begin
  255.         BlendMem($10000000, P^);
  256.         Inc(P);
  257.       end;
  258.       EMMS;
  259.     end;
  260.     Dec(Pass);
  261.     if (Pass < 0) or (Pass > FadeCount) then Pass := FadeCount;
  262.   end;
  263.   PaintBox.Invalidate;
  264. end;
  265.  
  266. procedure TForm1.FormCreate(Sender: TObject);
  267. begin
  268.   FadeCount := 7;
  269.   DrawPasses := 2;
  270.   Application.OnIdle := AppEventsIdle;
  271. end;
  272.  
  273. procedure TForm1.Button1Click(Sender: TObject);
  274. begin
  275.   AddLine;
  276. end;
  277.  
  278. procedure TForm1.Button2Click(Sender: TObject);
  279. begin
  280.   AddLines(10);
  281. end;
  282.  
  283. procedure TForm1.Button3Click(Sender: TObject);
  284. var
  285.   I: Integer;
  286. begin
  287.   for I := High(Lines) downto 0 do Lines[I].Free;
  288.   Lines := nil;
  289.   PaintBox.Buffer.Clear;
  290.   Panel1.Caption := '0';
  291. end;
  292.  
  293. procedure TForm1.BitmapLayerMouseDown(Sender: TObject;
  294.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  295. begin
  296.   // X and Y here are relative to layer origin
  297.   P := Point(X, Y);
  298.   M := True;
  299. end;
  300.  
  301. procedure TForm1.BitmapLayerMouseUp(Sender: TObject;
  302.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  303. begin
  304.   M := False;
  305. end;
  306.  
  307. procedure TForm1.RadioGroup1Click(Sender: TObject);
  308. const
  309.   FC: array [0..2] of Integer = (0, 7, 1);
  310. begin
  311.   FadeCount := FC[RadioGroup1.ItemIndex];
  312. end;
  313.  
  314. procedure TForm1.RadioGroup2Click(Sender: TObject);
  315. begin
  316.   DrawPasses := (RadioGroup2.ItemIndex + 1) * 3 - 2;
  317. end;
  318.  
  319. end.
  320.