2011-07-21 15:10:27 +00:00
|
|
|
unit lazeyes2form;
|
|
|
|
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
|
|
|
Classes, Math, SysUtils,
|
|
|
|
Graphics, Forms, LResources, StdCtrls, ExtCtrls,
|
|
|
|
Controls, LCLType, LCLIntf,
|
|
|
|
lazeyes2painter;
|
|
|
|
|
|
|
|
type
|
|
|
|
{ TMainForm }
|
|
|
|
|
|
|
|
TMainForm = class(TForm)
|
|
|
|
public
|
|
|
|
MyTimer: TTimer;
|
2011-07-28 12:20:06 +00:00
|
|
|
FirstOnTimer: Boolean;
|
2011-07-21 15:10:27 +00:00
|
|
|
WindowDragMousePos, WindowDragTopLeft: TPoint;
|
|
|
|
WindowDragStarted: Boolean;
|
|
|
|
Painter: TLazEye2Painter;
|
|
|
|
constructor Create(AOwner: TComponent); override;
|
|
|
|
destructor Destroy; override;
|
|
|
|
function CalculateEyePosition(
|
|
|
|
EyeXc, EyeYc: Integer): TPoint;
|
|
|
|
procedure HandleOnTimer(ASender: TObject);
|
|
|
|
procedure HandleOnMouseDown(Sender: TObject;
|
|
|
|
Button: TMouseButton; Shift: TShiftState;
|
|
|
|
X, Y: Integer);
|
|
|
|
procedure HandleOnMouseMove(Sender: TObject;
|
|
|
|
Shift: TShiftState; X, Y: Integer);
|
|
|
|
procedure HandleOnMouseUp(Sender: TObject;
|
|
|
|
Button: TMouseButton; Shift: TShiftState;
|
|
|
|
X, Y: Integer);
|
2011-07-28 12:20:06 +00:00
|
|
|
procedure SetWindowRegion();
|
2011-07-21 15:10:27 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
|
|
MainForm: TMainForm;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
{ TMainForm }
|
|
|
|
|
|
|
|
constructor TMainForm.Create(AOwner: TComponent);
|
|
|
|
begin
|
|
|
|
inherited Create(AOwner);
|
|
|
|
|
|
|
|
// basic initial data
|
|
|
|
MousePos := Mouse.CursorPos;
|
|
|
|
|
|
|
|
// create child objects
|
|
|
|
MyTimer := TTimer.Create(Self);
|
|
|
|
MyTimer.Interval := 1000 div 60;
|
|
|
|
MyTimer.OnTimer := @HandleOnTimer;
|
|
|
|
MyTimer.Enabled := True;
|
2011-07-28 12:20:06 +00:00
|
|
|
FirstOnTimer := True;
|
2011-07-21 15:10:27 +00:00
|
|
|
|
|
|
|
Painter := TLazEye2Painter.Create(Self);
|
|
|
|
Painter.Parent := Self;
|
|
|
|
Painter.Align := alClient;
|
|
|
|
Painter.DoubleBuffered := True;
|
|
|
|
|
|
|
|
// set events
|
|
|
|
OnMouseMove := @HandleOnMouseMove;
|
|
|
|
OnMouseDown := @HandleOnMouseDown;
|
|
|
|
OnMouseUp := @HandleOnMouseUp;
|
|
|
|
Painter.OnMouseMove := @HandleOnMouseMove;
|
|
|
|
Painter.OnMouseDown := @HandleOnMouseDown;
|
|
|
|
Painter.OnMouseUp := @HandleOnMouseUp;
|
|
|
|
|
|
|
|
// set window properties
|
|
|
|
BorderStyle := bsNone;
|
|
|
|
Position := poScreenCenter;
|
|
|
|
|
|
|
|
// set window transparency
|
2011-07-28 12:20:06 +00:00
|
|
|
SetWindowRegion();
|
2011-07-21 15:10:27 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TMainForm.Destroy;
|
|
|
|
begin
|
|
|
|
// free child object
|
|
|
|
MyTimer.Free;
|
|
|
|
|
|
|
|
inherited Destroy;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ Calculates where the eye should be painted
|
|
|
|
EyeXc, EyeYc is the center of the eye ellipse
|
|
|
|
The size of the ellipse is given by the constants
|
|
|
|
INT_EYE_WIDTH and INT_EYE_HEIGHT }
|
|
|
|
function TMainForm.CalculateEyePosition(
|
|
|
|
EyeXc, EyeYc: Integer): TPoint;
|
|
|
|
var
|
|
|
|
RelMousePos: TPoint;
|
|
|
|
MousePosAngle: Double;
|
|
|
|
DeltaX, DeltaY: Double;
|
|
|
|
AbsEyeXc, AbsEyeYc: Integer;
|
|
|
|
begin
|
|
|
|
// Get the mouse position relative to the window
|
|
|
|
RelMousePos.X := MousePos.X - Left;
|
|
|
|
RelMousePos.Y := MousePos.Y - Top;
|
|
|
|
|
|
|
|
// Get the eye center absolute position in the screen
|
|
|
|
AbsEyeXc := EyeXc + Left;
|
|
|
|
AbsEyeYc := EyeYc + Top;
|
|
|
|
|
|
|
|
// First check if the cursor is inside the eye, in a
|
|
|
|
// position that it will fall right over the eye pupil
|
|
|
|
// eye pupil elipse area equation:
|
|
|
|
// (X - Xc)^2 / A^2 + (Y - Yc)^2 / B^2 <= 1
|
|
|
|
// (Xc, Yc) is the center of the elipse
|
|
|
|
// A and B are the half axis of the elipse
|
|
|
|
if (Sqr(RelMousePos.X - EyeXc) / INT_EYE_HALFWIDTH_SQR)
|
|
|
|
+ (Sqr(RelMousePos.Y - EyeYc) / INT_EYE_HALFHEIGHT_SQR)
|
|
|
|
<= 1 then
|
|
|
|
begin
|
|
|
|
Result.X := RelMousePos.X;
|
|
|
|
Result.Y := RelMousePos.Y;
|
|
|
|
Exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
// Calculate the position of the eye, by calculating how
|
|
|
|
// many grads the cursor is forming with the center of
|
|
|
|
// the eye. The polar equation of the elipse is:
|
|
|
|
// X = Xc + A * cos(t)
|
|
|
|
// Y = Yc + B * sen(t)
|
|
|
|
if MousePos.X - AbsEyeXc = 0 then
|
|
|
|
MousePosAngle := Pi / 2
|
|
|
|
else
|
|
|
|
MousePosAngle := arctan(Abs(MousePos.Y - AbsEyeYc)
|
|
|
|
/ Abs(MousePos.X - AbsEyeXc));
|
|
|
|
|
|
|
|
DeltaX := INT_EYE_HALFWIDTH * Cos(MousePosAngle);
|
|
|
|
DeltaY := INT_EYE_HALFHEIGHT * Sin(MousePosAngle);
|
|
|
|
|
|
|
|
// 1st quadrant
|
|
|
|
if (MousePos.X >= AbsEyeXc) and
|
|
|
|
(MousePos.Y <= AbsEyeYc) then
|
|
|
|
begin
|
|
|
|
Result.X := Round(EyeXc + DeltaX);
|
|
|
|
Result.Y := Round(EyeYc - DeltaY);
|
|
|
|
end
|
|
|
|
// 2nd quadrant
|
|
|
|
else if (MousePos.X >= AbsEyeXc) and
|
|
|
|
(MousePos.Y >= AbsEyeYc) then
|
|
|
|
begin
|
|
|
|
Result.X := Round(EyeXc + DeltaX);
|
|
|
|
Result.Y := Round(EyeYc + DeltaY);
|
|
|
|
end
|
|
|
|
// 3rd quadrant
|
|
|
|
else if (MousePos.X <= AbsEyeXc) and
|
|
|
|
(MousePos.Y >= AbsEyeYc) then
|
|
|
|
begin
|
|
|
|
Result.X := Round(EyeXc - DeltaX);
|
|
|
|
Result.Y := Round(EyeYc + DeltaY);
|
|
|
|
end
|
|
|
|
// 4th quadrant
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
Result.X := Round(EyeXc - DeltaX);
|
|
|
|
Result.Y := Round(EyeYc - DeltaY);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ Timer event - Updates the eyes if the mouse moved }
|
|
|
|
procedure TMainForm.HandleOnTimer(ASender: TObject);
|
|
|
|
begin
|
2011-07-28 12:20:06 +00:00
|
|
|
{$ifdef LCLGtk2}
|
|
|
|
if FirstOnTimer then SetWindowRegion();
|
|
|
|
FirstOnTimer := False;
|
|
|
|
{$endif}
|
|
|
|
|
2011-07-21 15:10:27 +00:00
|
|
|
// Check if mouse position changed
|
|
|
|
if (MousePos.X = Mouse.CursorPos.X) and
|
|
|
|
(MousePos.Y = Mouse.CursorPos.Y) then Exit;
|
|
|
|
|
|
|
|
MousePos := Mouse.CursorPos;
|
|
|
|
|
|
|
|
// Calculate the position of the eyes
|
|
|
|
LeftEyePos := CalculateEyePosition(
|
|
|
|
INT_EYE_HALFWIDTH + INT_BORDER_WIDTH,
|
|
|
|
INT_EYE_HALFHEIGHT + INT_BORDER_WIDTH);
|
|
|
|
RightEyePos := CalculateEyePosition(
|
|
|
|
INT_OUTER_EYE_WIDTH + INT_INTEREYE_SPACE +
|
|
|
|
INT_EYE_HALFWIDTH + INT_BORDER_WIDTH,
|
|
|
|
INT_EYE_HALFHEIGHT + INT_BORDER_WIDTH);
|
|
|
|
|
|
|
|
// Redraw the eye
|
|
|
|
Invalidate;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ MouseDown - Code to drag the main window using the mouse}
|
|
|
|
procedure TMainForm.HandleOnMouseDown(Sender: TObject;
|
|
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
|
|
begin
|
|
|
|
WindowDragStarted := True;
|
|
|
|
WindowDragMousePos := Mouse.CursorPos;
|
|
|
|
WindowDragTopLeft.X := Left;
|
|
|
|
WindowDragTopLeft.Y := Top;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ MouseMove - Code to drag the main window using the mouse}
|
|
|
|
procedure TMainForm.HandleOnMouseMove(Sender: TObject;
|
|
|
|
Shift: TShiftState; X, Y: Integer);
|
|
|
|
begin
|
|
|
|
if WindowDragStarted then
|
|
|
|
begin
|
|
|
|
Left := WindowDragTopLeft.X +
|
|
|
|
(Mouse.CursorPos.X - WindowDragMousePos.X);
|
|
|
|
Top := WindowDragTopLeft.Y +
|
|
|
|
(Mouse.CursorPos.Y - WindowDragMousePos.Y);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
{ MouseUp - Code to drag the main window using the mouse }
|
|
|
|
procedure TMainForm.HandleOnMouseUp(Sender: TObject;
|
|
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
|
|
begin
|
|
|
|
WindowDragStarted := False;
|
|
|
|
end;
|
|
|
|
|
2011-07-28 12:20:06 +00:00
|
|
|
procedure TMainForm.SetWindowRegion();
|
|
|
|
var
|
|
|
|
Rgn1, Rgn2, TotalRgn: HRGN;
|
|
|
|
begin
|
|
|
|
Rgn1 := CreateEllipticRgn(
|
|
|
|
0, 0,
|
|
|
|
INT_OUTER_EYE_WIDTH, INT_OUTER_EYE_HEIGHT);
|
|
|
|
Rgn2 := CreateEllipticRgn(
|
|
|
|
INT_OUTER_EYE_WIDTH + INT_INTEREYE_SPACE, 0,
|
|
|
|
2*INT_OUTER_EYE_WIDTH + INT_INTEREYE_SPACE,
|
|
|
|
INT_OUTER_EYE_HEIGHT);
|
|
|
|
// The dest region needs to exist before calling
|
|
|
|
// CombineRgn, so we create it with dummy values
|
|
|
|
TotalRgn := CreateEllipticRgn(0, 0, 10, 10);
|
|
|
|
LCLIntf.CombineRgn(TotalRgn, Rgn1, Rgn2, RGN_OR);
|
|
|
|
LCLIntf.SetWindowRgn(Handle, TotalRgn, True);
|
|
|
|
end;
|
|
|
|
|
2011-07-21 15:10:27 +00:00
|
|
|
end.
|
|
|
|
|