


MODULE  MouseWatcher;


(*  Öffnet ein Fenster auf dem Workbench-Bildschirm und zeichnet in diesem  *)
(*  ein Gesicht mit zwei Kulleraugen, die der Bewegung der Maus folgen.     *)
(*                                                                          *)
(*  von Ernst Heinz  /  12.08.1989                                          *)



FROM  Arts         IMPORT  TermProcedure;

FROM  Dos          IMPORT  Delay;

FROM  Intuition    IMPORT  OpenWorkBench;

FROM  MathLib0     IMPORT  arctan, cos, sin;

FROM  ScreenLib    IMPORT  GetScrMouse;

FROM  WindowLib    IMPORT  CloseWin, FillWin, GetGzzDim, gzz, noBack, noSize,
                           SimpleWin;

FROM  WinGraphics  IMPORT  Circle, Rectangle;

FROM  WinIOLib     IMPORT  check, InspClose, ReportClose, wait;

FROM  SYSTEM       IMPORT  ADDRESS, ADR;




VAR  WinX, WinY, WinWidth, WinHeight      : INTEGER;
     LeftEyeX, LeftEyeY, EyeRadius        : INTEGER;
     LeftPupilX, LeftPupilY, PupilRadius  : INTEGER;
     DeltaX, DeltaY, NewDeltaX, NewDeltaY : INTEGER;
     MouseX, MouseY                       : INTEGER; 
     WBench, Win                          : ADDRESS;




PROCEDURE  RedrawPupils;

(*  Löscht die alten Pupillen und bestimmt die neue Pupillenposition. Dabei  *)
(*  werden die globalen Variablen "LeftPupilX" und "LeftPupilY" automatisch  *)
(*  angeglichen. Natürlich werden die neuen Pupillen auch gezeichnet !       *)


VAR  SignDX, SignDY : INTEGER;
     Phi            : REAL;


BEGIN
 (*  Vorzeichen der beiden Komponenten des Differenzvektors bestimmen.  *)
 SignDX := 1;
 SignDY := 1;
 IF DeltaX<0 THEN
  SignDX := -1
 END;
 IF DeltaY<0 THEN
  SignDY := -1
 END;
 
 (*  Neue Pupillenposition relativ zur Augenmitte berechnen.  *)
 IF DeltaX#0 THEN
  Phi := arctan(REAL(ABS(DeltaY))/REAL(ABS(DeltaX)))
 ELSE
  Phi := 0.0
 END;
 NewDeltaX := SignDX*TRUNC(cos(Phi)*REAL(EyeRadius));
 NewDeltaY := SignDY*TRUNC(sin(Phi)*REAL(EyeRadius));
 
 (*  Alte Pupillen jetzt zunächst löschen.  *)
 Rectangle(Win,LeftPupilX-PupilRadius,LeftPupilY-PupilRadius,
           2*PupilRadius,2*PupilRadius,0,TRUE);
 Rectangle(Win,2*LeftEyeX+LeftPupilX-PupilRadius,LeftPupilY-PupilRadius,
           2*PupilRadius,2*PupilRadius,0,TRUE);

 (*  Neue absolute Pupillenposition bestimmen und Pupillen zeichnen.  *)
 LeftPupilX := LeftEyeX+NewDeltaX;
 LeftPupilY := LeftEyeY+NewDeltaY;
 Circle(Win,           LeftPupilX,LeftPupilY,PupilRadius,1,TRUE);
 Circle(Win,2*LeftEyeX+LeftPupilX,LeftPupilY,PupilRadius,1,TRUE)
END  RedrawPupils;




PROCEDURE  CloseWindow;

(*  Die private Abschlußprozedur, die das Fenster schließt.  *)

BEGIN
 IF Win#NIL THEN
  ReportClose(Win,FALSE);
  CloseWin(Win);
  Win := NIL
 END
END  CloseWindow;




BEGIN
 Win := NIL;
 WBench := OpenWorkBench();
 TermProcedure(CloseWindow);
 
 (*  Neues GZZ-Fenster öffnen und mit Vordergrundfarbe füllen.  *)
 Win := SimpleWin(NIL,"MouseWatcher",0,11,160,80,noBack+noSize+gzz);
 FillWin(Win,1);
 
 (*  Dimension der Zeichenfläche und Koordinaten der Augen bestimmen.  *)
 GetGzzDim(Win,WinX,WinY,WinWidth,WinHeight);
 LeftEyeX := WinWidth DIV 4;
 LeftEyeY := WinHeight DIV 2;
 EyeRadius := 4*(LeftEyeX DIV 5);
 
 (*  Beide Augen in das Fenster einzeichnen.  *)
 Circle(Win,  LeftEyeX,LeftEyeY,EyeRadius,0,TRUE);
 Circle(Win,3*LeftEyeX,LeftEyeY,EyeRadius,0,TRUE);

 (*  Anfängliche Bezugskoordinaten der Maus und des Fensters bestimmen.  *)
 GetGzzDim(Win,WinX,WinY,WinWidth,WinHeight);
 GetScrMouse(WBench,MouseX,MouseY);

 (*  Ab sofort die Schließung des Fensters verfolgen.  *)
 ReportClose(Win,TRUE);
 
 (*  Ausgangskoordinaten der Pupille berechnen und diese dann zeichnen.  *)
 LeftPupilX := LeftEyeX;
 LeftPupilY := LeftEyeY;
 PupilRadius := LeftEyeX DIV 6;
 DEC(EyeRadius,3*(PupilRadius DIV 2));   (*  "EyeRadius" für Pupillenkreis  *)

 (*  Differenzvektor zwischen linker Pupille und Mausposition bestimmen.  *)
 DeltaX := MouseX-(WinX+LeftEyeX);
 DeltaY := MouseY-(WinY+LeftEyeY);
 
 RedrawPupils;
 
 (*  Jetzt die Mausbewegung solange verfolgen, bis Close-Gadget geklickt.  *)
 
 WHILE NOT InspClose(Win,check) DO
  Delay(15);
  
  (*  Neue Mausposition und neue Fensterposition bestimmen.  *)
  GetScrMouse(WBench,MouseX,MouseY);
  GetGzzDim(Win,WinX,WinY,WinWidth,WinHeight);
  
  (*  Neuen Differenzvektor zwischen linker Pupille und Maus berechnen.  *)
  NewDeltaX := MouseX-(WinX+LeftEyeX);
  NewDeltaY := MouseY-(WinY+LeftEyeY);
  
  IF (NewDeltaX#DeltaX) OR (NewDeltaY#DeltaY) THEN
   DeltaX := NewDeltaX;
   DeltaY := NewDeltaY;
   RedrawPupils
  END
 END;

 ReportClose(Win,FALSE);
 CloseWindow
END  MouseWatcher.
