diff --git a/Source/script/imports/simba.import_async.pas b/Source/script/imports/simba.import_async.pas index 97580887e..4c197e30b 100644 --- a/Source/script/imports/simba.import_async.pas +++ b/Source/script/imports/simba.import_async.pas @@ -16,6 +16,9 @@ implementation lptypes, ffi, simba.target, simba.http_async, simba.input_async, simba.fs_async; +type + PSimbaTarget = ^TSimbaTarget; + (* ASync ===== @@ -96,14 +99,14 @@ procedure _LapeASyncHTTP_Post2(const Params: PParamArray); LAPE_WRAPPER_CALLING_ ASync.MouseMove --------------- ``` -procedure ASync.MouseMove(Target: TTarget; Dest: TPoint; Accuracy: Double = 1); -procedure ASync.MouseMove(Dest: TPoint; Accuracy: Double = 1); +procedure ASync.MouseMove(Target: TTarget; Dest: TPoint; Accuracy: Single = 1); +procedure ASync.MouseMove(Dest: TPoint; Accuracy: Single = 1); ``` Moves the mouse on another thread, so the script can do other things such as updating the destination. *) procedure _LapeASyncMouse_Move(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - ASyncMouse.Move(PSimbaTarget(Params^[0])^, PPoint(Params^[1])^, PDouble(Params^[2])^); + ASyncMouse.Move(PSimbaTarget(Params^[0])^, PPoint(Params^[1])^, PSingle(Params^[2])^); end; (* @@ -211,8 +214,8 @@ procedure ImportASync(Script: TSimbaScript); // namespace addGlobalType('record end;', 'ASync'); - addGlobalFunc('procedure ASync.MouseMove(constref Target: TTarget; Dest: TPoint; Accuracy: Double = 1); static; overload;', @_LapeASyncMouse_Move); - addGlobalFunc('procedure ASync.MouseMove(Dest: TPoint; Accuracy: Double = 1); static; overload;', [ + addGlobalFunc('procedure ASync.MouseMove(constref Target: TTarget; Dest: TPoint; Accuracy: Single = 0.5); static; overload;', @_LapeASyncMouse_Move); + addGlobalFunc('procedure ASync.MouseMove(Dest: TPoint; Accuracy: Single = 0.5); static; overload;', [ 'begin', ' ASync.MouseMove(System.Target, Dest, Accuracy);', 'end;' diff --git a/Source/script/imports/simba.import_imagebox.pas b/Source/script/imports/simba.import_imagebox.pas index 7f7320275..04a2033a7 100644 --- a/Source/script/imports/simba.import_imagebox.pas +++ b/Source/script/imports/simba.import_imagebox.pas @@ -20,6 +20,7 @@ implementation simba.target; type + PSimbaTarget = ^TSimbaTarget; PComponent = ^TComponent; PBitmap = ^TBitmap; diff --git a/Source/script/imports/simba.import_misc.pas b/Source/script/imports/simba.import_misc.pas index cd3dfebde..959fde1fb 100644 --- a/Source/script/imports/simba.import_misc.pas +++ b/Source/script/imports/simba.import_misc.pas @@ -21,6 +21,7 @@ implementation simba.finder_color, simba.finder_image, simba.matchtemplate; type + PSimbaTarget = ^TSimbaTarget; PProcessID = ^TProcessID; (* diff --git a/Source/script/imports/simba.import_target.pas b/Source/script/imports/simba.import_target.pas index 42134fa9b..2447d27b9 100644 --- a/Source/script/imports/simba.import_target.pas +++ b/Source/script/imports/simba.import_target.pas @@ -19,6 +19,7 @@ implementation simba.image, simba.target, simba.externalcanvas, simba.finder_image, simba.finder_color; type + PSimbaTarget = ^TSimbaTarget; PMouseButton = ^EMouseButton; PKeyCode = ^EKeyCode; @@ -107,7 +108,7 @@ procedure _LapeTarget_SetPlugin1(const Params: PParamArray); LAPE_WRAPPER_CALLIN TTarget.SetPlugin ----------------- ``` -procedure TTarget.SetPlugin(FileName, Args: String; out DebugImage: TExternalCanvas); +procedure TTarget.SetPlugin(FileName, Args: String; out Canvas: TExternalCanvas); ``` Overloaded version that returns a "external canvas" to draw on. @@ -117,42 +118,6 @@ procedure _LapeTarget_SetPlugin2(const Params: PParamArray); LAPE_WRAPPER_CALLIN PSimbaTarget(Params^[0])^.SetPlugin(PString(Params^[1])^, PString(Params^[2])^, TSimbaExternalCanvas(Params^[3]^)); end; -(* -TTarget.RemoveTargetInvalidEvent --------------------------------- -``` -procedure TTarget.RemoveTargetInvalidEvent(Event: TTargetEvent); -``` -*) -procedure _Lape_Target_RemoveTargetInvalidEvent(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV -begin - PSimbaTarget(Params^[0])^.RemoveTargetInvalidEvent(TTargetEvent(Params^[1]^)); -end; - -(* -TTarget.AddTargetChangeEvent ----------------------------- -``` -function TTarget.AddTargetChangeEvent(Event: TTargetEvent): TTargetEvent; -``` -*) -procedure _Lape_Target_AddTargetChangeEvent(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV -begin - TTargetEvent(Result^) := PSimbaTarget(Params^[0])^.AddTargetChangeEvent(TTargetEvent(Params^[1]^)); -end; - -(* -TTarget.RemoveTargetChangeEvent -------------------------------- -``` -procedure TTarget.RemoveTargetChangeEvent(Event: TTargetEvent); -``` -*) -procedure _Lape_Target_RemoveTargetChangeEvent(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV -begin - PSimbaTarget(Params^[0])^.RemoveTargetChangeEvent(TTargetEvent(Params^[1]^)); -end; - (* TTarget.FreezeImage ------------------- @@ -290,8 +255,6 @@ procedure _LapeTarget_GetTargetImage(const Params: PParamArray; const Result: Po ------------------------ ``` property TTarget.CustomClientArea: TBox; -``` -``` property TTarget.CustomClientArea(Value: TBox); ``` @@ -317,8 +280,6 @@ procedure _LapeTarget_GetCustomClientArea(const Params: PParamArray; const Resul ----------------- ``` property TTarget.AutoFocus(Value: Boolean); -``` -``` property TTarget.AutoFocus: Boolean; ``` *) @@ -383,59 +344,27 @@ procedure _LapeTarget_Size(const Params: PParamArray; const Result: Pointer); LA end; (* -TTarget.AddMouseEvent ---------------------- -``` -function TTarget.AddMouseEvent(Event: TMouseButtonEvent): TMouseButtonEvent; -``` -``` -function TTarget.AddMouseEvent(Event: TMouseTeleportEvent): TMouseTeleportEvent; -``` +TTarget.AddEvent +---------------- ``` -function TTarget.AddMouseEvent(Event: TMouseMovingEvent): TMouseMovingEvent; +function TTarget.AddEvent(EventType: ETargetEventType; Event: TMouseEvent): TMouseEvent; ``` *) -procedure _LapeTarget_AddMouseEvent1(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV +procedure _LapeTarget_AddEvent(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV begin - TMouseTeleportEvent(Result^) := PSimbaTarget(Params^[0])^.AddMouseEvent(TMouseTeleportEvent(Params^[1]^)); -end; - -procedure _LapeTarget_AddMouseEvent2(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV -begin - TMouseButtonEvent(Result^) := PSimbaTarget(Params^[0])^.AddMouseEvent(TMouseButtonEvent(Params^[1]^)); -end; - -procedure _LapeTarget_AddMouseEvent3(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV -begin - TMouseMovingEvent(Result^) := PSimbaTarget(Params^[0])^.AddMouseEvent(TMouseMovingEvent(Params^[1]^)); + TSimbaTarget.TEvent(Result^) := PSimbaTarget(Params^[0])^.AddEvent(ETargetEventType(Params^[1]^), TSimbaTarget.TEvent(Params^[2]^)); end; (* -TTarget.RemoveMouseEvent ------------------------- -``` -procedure TTarget.RemoveMouseEvent(Event: TMouseButtonEvent); overload; -``` -``` -procedure TTarget.RemoveMouseEvent(Event: TMouseTeleportEvent); overload; -``` +TTarget.RemoveEvent +------------------- ``` -procedure TTarget.RemoveMouseEvent(Event: TMouseMovingEvent); overload; +procedure TTarget.RemoveEvent(EventType: ETargetEventType; Event: TMouseEvent); ``` *) -procedure _LapeTarget_RemoveMouseEvent1(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV -begin - PSimbaTarget(Params^[0])^.RemoveMouseEvent(TMouseTeleportEvent(Params^[1]^)); -end; - -procedure _LapeTarget_RemoveMouseEvent2(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV +procedure _LapeTarget_RemoveEvent(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PSimbaTarget(Params^[0])^.RemoveMouseEvent(TMouseButtonEvent(Params^[1]^)); -end; - -procedure _LapeTarget_RemoveMouseEvent3(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV -begin - PSimbaTarget(Params^[0])^.RemoveMouseEvent(TMouseMovingEvent(Params^[1]^)); + PSimbaTarget(Params^[0])^.RemoveEvent(ETargetEventType(Params^[1]^), TSimbaTarget.TEvent(Params^[2]^)); end; (* @@ -537,8 +466,6 @@ procedure _LapeTarget_MouseMove1(const Params: PParamArray); LAPE_WRAPPER_CALLIN ----------------- ``` procedure MouseMove(Box: TBox; ForcedMove: Boolean = False); overload; -``` -``` procedure MouseMove(Quad: TQuad; ForcedMove: Boolean = False); overload; ``` @@ -560,8 +487,6 @@ procedure _LapeTarget_MouseMove3(const Params: PParamArray); LAPE_WRAPPER_CALLIN --------------- ``` property TTarget.MouseXY: TPoint; -``` -``` property TTarget.MouseXY(Value: TPoint); ``` *) @@ -580,8 +505,6 @@ procedure _LapeTarget_MouseXY_Write(const Params: PParamArray); LAPE_WRAPPER_CAL -------------- ``` property TTarget.MouseX: Integer; -``` -``` property TTarget.MouseX(Value: Integer); ``` *) @@ -600,8 +523,6 @@ procedure _LapeTarget_MouseX_Write(const Params: PParamArray); LAPE_WRAPPER_CALL -------------- ``` property TTarget.MouseY: Integer; -``` -``` property TTarget.MouseY(Value: Integer); ``` *) @@ -615,18 +536,6 @@ procedure _LapeTarget_MouseY_Write(const Params: PParamArray); LAPE_WRAPPER_CALL PSimbaTarget(Params^[0])^.MouseY := PInteger(Params^[1])^; end; -(* -TTarget.AddTargetInvalidEvent ------------------------------ -``` -function TTarget.AddTargetInvalidEvent(Event: TTargetEvent): TTargetEvent; -``` -*) -procedure _Lape_Target_AddTargetInvalidEvent(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV -begin - TTargetEvent(Result^) := PSimbaTarget(Params^[0])^.AddTargetInvalidEvent(TTargetEvent(Params^[1]^)); -end; - (* TTarget.KeySend --------------- @@ -1110,24 +1019,20 @@ procedure ImportTarget(Script: TSimbaScript); ' DataWidth: Integer;', ' Data: array of TColorBGRA;', ' end;', - ' FInvalidEvents: array of TMethod;', - ' FChangeEvents: array of TMethod;', + ' FEvents: array of record', + ' EventType: Integer;', + ' Method: TMethod;', + ' end;', ' FCustomClientArea: TBox;', ' FAutoFocus: Boolean;', ' {%CODETOOLS ON}', '', ' MouseOptions: record', - ' {%CODETOOLS OFF}', - ' MouseButtonEvents: array of TMethod;', - ' MouseTeleportEvents: array of TMethod;', - ' MouseMovingEvents: array of TMethod;', - ' {%CODETOOLS ON}', ' MinClickTime: Integer;', ' MaxClickTime: Integer;', ' Speed: Double;', ' Gravity: Double;', ' Wind: Double;', - ' Accuracy: Double;', ' Timeout: Integer;', ' end;', '', @@ -1139,35 +1044,54 @@ procedure ImportTarget(Script: TSimbaScript); 'TTarget' ); - addGlobalVar('TTarget', @Script.Target, 'Target'); - - //with addGlobalVar('TTarget', '[]', 'Target') do - //begin - // Used := duTrue; - // if (Size <> SizeOf(TSimbaTarget)) then - // SimbaException('SizeOf(TTarget)=%d should be %d', [Size, SizeOf(TSimbaTarget)]); - //end; + with addGlobalVar('TTarget', @Script.Target, 'Target') do + begin + Used := duTrue; + if (Size <> SizeOf(TSimbaTarget)) then + SimbaException('SizeOf(TTarget)=%d should be %d', [Size, SizeOf(TSimbaTarget)]); + end; addGlobalType(specialize GetEnumDecl(True, False), 'ETargetKind'); + addGlobalType(specialize GetEnumDecl(True, False), 'ETargetEventType'); addGlobalType(specialize GetEnumDecl(True, False), 'EMouseButton'); addGlobalType(specialize GetEnumDecl(True, True), 'EKeyCode'); - addGlobalType('procedure(var Input: TTarget; P: TPoint) of object', 'TMouseTeleportEvent', FFI_DEFAULT_ABI); - addGlobalType('procedure(var Input: TTarget; Button: EMouseButton; Down: Boolean) of object', 'TMouseButtonEvent', FFI_DEFAULT_ABI); - addGlobalType('procedure(var Input: TTarget; var X, Y, DestX, DestY: Double; var Stop: Boolean) of object', 'TMouseMovingEvent', FFI_DEFAULT_ABI); - addGlobalType('procedure(var Target: TTarget) of object', 'TTargetEvent', FFI_DEFAULT_ABI); + addGlobalType([ + 'record', + ' EventType: ETargetEventType;', + '', + ' TargetChange: record', + ' { nothing }', + ' end;', + '', + ' TargetInvalid: record', + ' { nothing }', + ' end;', + '', + ' MouseButton: record', + ' Button: EMouseButton;', + ' Down: Boolean;', + ' end;', + '', + ' MouseTeleport: record', + ' X: Integer;', + ' Y: Integer;', + ' end;', + 'end;'], + 'TTargetEventData' + ); + + addGlobalType('procedure(var Target: TTarget; Data: TTargetEventData) of object', 'TTargetEvent', FFI_DEFAULT_ABI); + + addGlobalFunc('function TTarget.AddEvent(EventType: ETargetEventType; Event: TTargetEvent): TTargetEvent', @_LapeTarget_AddEvent); + addGlobalFunc('procedure TTarget.RemoveEvent(EventType: ETargetEventType; Event: TTargetEvent)', @_LapeTarget_RemoveEvent); addGlobalFunc('procedure TTarget.SetDesktop', @_LapeTarget_SetDesktop); addGlobalFunc('procedure TTarget.SetImage(TImage: TImage)', @_LapeTarget_SetImage); addGlobalFunc('procedure TTarget.SetWindow(Window: TWindowHandle)', @_LapeTarget_SetWindow); addGlobalFunc('procedure TTarget.SetEIOS(Plugin, Args: String)', @_LapeTarget_SetEIOS); addGlobalFunc('procedure TTarget.SetPlugin(Plugin, Args: String); overload', @_LapeTarget_SetPlugin1); - addGlobalFunc('procedure TTarget.SetPlugin(Plugin, Args: String; out DebugImage: TExternalCanvas); overload', @_LapeTarget_SetPlugin2); - - addGlobalFunc('function TTarget.AddTargetChangeEvent(Event: TTargetEvent): TTargetEvent', @_Lape_Target_AddTargetChangeEvent); - addGlobalFunc('function TTarget.AddTargetInvalidEvent(Event: TTargetEvent): TTargetEvent', @_Lape_Target_AddTargetInvalidEvent); - addGlobalFunc('procedure TTarget.RemoveTargetChangeEvent(Event: TTargetEvent)', @_Lape_Target_RemoveTargetChangeEvent); - addGlobalFunc('procedure TTarget.RemoveTargetInvalidEvent(Event: TTargetEvent)', @_Lape_Target_RemoveTargetInvalidEvent); + addGlobalFunc('procedure TTarget.SetPlugin(Plugin, Args: String; out Canvas: TExternalCanvas); overload', @_LapeTarget_SetPlugin2); addGlobalFunc('procedure TTarget.FreezeImage(Bounds: TBox = [-1,-1,-1,-1]);', @_LapeTarget_FreezeImage); addGlobalFunc('procedure TTarget.UnFreezeImage;', @_LapeTarget_UnFreezeImage); @@ -1192,14 +1116,7 @@ procedure ImportTarget(Script: TSimbaScript); addProperty('TTarget', 'TargetWindow', 'TWindowHandle', @_LapeTarget_GetTargetWindow); addProperty('TTarget', 'TargetImage', 'TImage', @_LapeTarget_GetTargetImage); - addGlobalFunc('function TTarget.AddMouseEvent(Event: TMouseTeleportEvent): TMouseTeleportEvent; overload', @_LapeTarget_AddMouseEvent1); - addGlobalFunc('function TTarget.AddMouseEvent(Event: TMouseButtonEvent): TMouseButtonEvent; overload', @_LapeTarget_AddMouseEvent2); - addGlobalFunc('function TTarget.AddMouseEvent(Event: TMouseMovingEvent): TMouseMovingEvent; overload', @_LapeTarget_AddMouseEvent3); - - addGlobalFunc('procedure TTarget.RemoveMouseEvent(Event: TMouseTeleportEvent); overload', @_LapeTarget_RemoveMouseEvent1); - addGlobalFunc('procedure TTarget.RemoveMouseEvent(Event: TMouseButtonEvent); overload', @_LapeTarget_RemoveMouseEvent2); - addGlobalFunc('procedure TTarget.RemoveMouseEvent(Event: TMouseMovingEvent); overload', @_LapeTarget_RemoveMouseEvent3); - + // MOUSE addGlobalFunc('procedure TTarget.MouseTeleport(P: TPoint)', @_LapeTarget_MouseTeleport); addGlobalFunc('procedure TTarget.MouseClick(Button: EMouseButton)', @_LapeTarget_MouseClick); addGlobalFunc('procedure TTarget.MouseDown(Button: EMouseButton)', @_LapeTarget_MouseDown); @@ -1222,6 +1139,7 @@ procedure ImportTarget(Script: TSimbaScript); addGlobalFunc('function TTarget.KeyPressed(Key: EKeyCode): Boolean', @_LapeTarget_KeyPressed); addGlobalFunc('function TTarget.KeyCodeFromChar(C: Char): EKeyCode', @_LapeTarget_KeyCodeFromChar); + // COLORS addGlobalFunc('function TTarget.MatchColor(Color: TColor; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; Bounds: TBox= [-1,-1,-1,-1]): TSingleMatrix;', @_LapeTarget_MatchColor); addGlobalFunc('function TTarget.FindColor(Color: TColor; Tolerance: Single; Bounds: TBox = [-1,-1,-1,-1]): TPointArray; overload', @_LapeTarget_FindColor1); diff --git a/Source/script/simba.script.pas b/Source/script/simba.script.pas index fba33f478..416bff645 100644 --- a/Source/script/simba.script.pas +++ b/Source/script/simba.script.pas @@ -290,14 +290,7 @@ constructor TSimbaScript.Create(FileName: String; Communication: TSimbaScriptCom destructor TSimbaScript.Destroy; begin if (FCompiler <> nil) then - begin - if (FCompiler.Globals['HTTPClient'] <> nil) then - TObject(FCompiler.Globals['HTTPClient'].Ptr^).Free(); - if (FCompiler.Globals['ASyncMouse'] <> nil) then - TObject(FCompiler.Globals['ASyncMouse'].Ptr^).Free(); - FreeAndNil(FCompiler); - end; FreeAndNil(FPlugins); FreeAndNil(FSimbaCommunication); FreeAndNil(FCodeRunner); diff --git a/Source/simba.input_async.pas b/Source/simba.input_async.pas index e8f019846..b8a5248da 100644 --- a/Source/simba.input_async.pas +++ b/Source/simba.input_async.pas @@ -33,8 +33,9 @@ TSimbaASyncMouse = class(TObject) FTarget: TSimbaTarget; FDest: TPoint; FStop: Boolean; + FAccuracy: Single; - procedure DoMouseMoving(Target: Pointer; var X, Y, DestX, DestY: Double; var Stop: Boolean); + procedure DoMouseMoving(var X, Y, DestX, DestY: Double; out Stop: Boolean); procedure Execute; public constructor Create; @@ -45,7 +46,7 @@ TSimbaASyncMouse = class(TObject) procedure WaitMoving; procedure Stop; - procedure Move(constref Target: TSimbaTarget; Dest: TPoint; Accuracy: Double = 1); + procedure Move(constref Target: TSimbaTarget; Dest: TPoint; Accuracy: Single = 0.5); end; var @@ -53,6 +54,10 @@ TSimbaASyncMouse = class(TObject) implementation +uses + Math, + simba.target_movemouse; + procedure TSimbaASyncMouseThread.Execute; begin while (not Terminated) do @@ -87,17 +92,18 @@ procedure TSimbaASyncMouseThread.Wake; FLock.Unlock(); end; -procedure TSimbaASyncMouse.DoMouseMoving(Target: Pointer; var X, Y, DestX, DestY: Double; var Stop: Boolean); +procedure TSimbaASyncMouse.DoMouseMoving(var X, Y, DestX, DestY: Double; out Stop: Boolean); begin DestX := FDest.X; DestY := FDest.Y; - - Stop := FStop; + if (Hypot(X - DestX, Y - DestY) <= FAccuracy) then + FStop := True; + Stop := FStop; end; procedure TSimbaASyncMouse.Execute; begin - FTarget.MouseMove(FDest); + MoveMouseOnTarget(FTarget, FDest, @DoMouseMoving); end; constructor TSimbaASyncMouse.Create; @@ -136,14 +142,12 @@ procedure TSimbaASyncMouse.WaitMoving; Sleep(15); end; -procedure TSimbaASyncMouse.Move(constref Target: TSimbaTarget; Dest: TPoint; Accuracy: Double); +procedure TSimbaASyncMouse.Move(constref Target: TSimbaTarget; Dest: TPoint; Accuracy: Single); begin + FTarget := Target; FStop := False; FDest := Dest; - - FTarget := Target.Copy(); // ensure arrays are copies - FTarget.MouseOptions.Accuracy := Accuracy; - FTarget.AddMouseEvent(@DoMouseMoving); + FAccuracy := Max(0.5, Accuracy); FThread.Wake(); end; diff --git a/Source/simba.target.pas b/Source/simba.target.pas index f6263a920..d56d079ab 100644 --- a/Source/simba.target.pas +++ b/Source/simba.target.pas @@ -65,13 +65,38 @@ TSimbaTargetInfo = record MouseScroll: procedure(Target: Pointer; Scrolls: Integer); end; - TMouseButtonEvent = procedure(Target: Pointer; Button: EMouseButton; Down: Boolean) of object; - TMouseTeleportEvent = procedure(Target: Pointer; P: TPoint) of object; - TMouseMovingEvent = procedure(Target: Pointer; var X, Y, DestX, DestY: Double; var Stop: Boolean) of object; - TTargetEvent = procedure(Target: Pointer) of object; + {$scopedenums on} + ETargetEventType = ( + TARGET_CHANGE, TARGET_INVALID, + MOUSE_TELEPORT, MOUSE_BUTTON + ); + {$scopedenums off} + + TTargetEventData = record + EventType: ETargetEventType; + + TargetChange: record + { nothing } + end; + TargetInvalid: record + { nothing } + end; + + MouseButton: record + Button: EMouseButton; + Down: Boolean; + end; + + MouseTeleport: record + X: Integer; + Y: Integer; + end; + end; - PSimbaTarget = ^TSimbaTarget; TSimbaTarget = record + public + type + TEvent = procedure(var Target: TSimbaTarget; Data: TTargetEventData) of object; private FTarget: TSimbaTargetInfo; FFrozen: record @@ -79,11 +104,16 @@ TSimbaTarget = record DataWidth: Integer; Data: array of TColorBGRA; end; - FInvalidEvents: array of TMethod; - FChangeEvents: array of TMethod; + FEvents: array of record + EventType: ETargetEventType; + Method: TEvent; + end; FCustomClientArea: TBox; FAutoFocus: Boolean; + function HasEvent(EventType: ETargetEventType): Boolean; + procedure CallEvent(var Data: TTargetEventData); + function ValidateBounds(var ABounds: TBox): Boolean; procedure ChangeTarget(Kind: ESimbaTargetKind); @@ -106,17 +136,12 @@ TSimbaTarget = record procedure SetMouseXY(Value: TPoint); public MouseOptions: record - ButtonEvents: array of TMethod; - TeleportEvents: array of TMethod; - MovingEvents: array of TMethod; - MinClickTime: Integer; MaxClickTime: Integer; Speed: Double; Gravity: Double; Wind: Double; - Accuracy: Double; Timeout: Integer; end; @@ -125,6 +150,9 @@ TSimbaTarget = record MaxPressTime: Integer; end; + function AddEvent(EventType: ETargetEventType; Method: TEvent): TEvent; + procedure RemoveEvent(EventType: ETargetEventType; Method: TEvent); + // target procedure SetDesktop; procedure SetWindow(Window: TWindowHandle); @@ -133,11 +161,6 @@ TSimbaTarget = record procedure SetPlugin(FileName, Args: String); overload; procedure SetPlugin(FileName, Args: String; out DebugImage: TSimbaExternalCanvas); overload; - function AddTargetChangeEvent(Event: TTargetEvent): TTargetEvent; - function AddTargetInvalidEvent(Event: TTargetEvent): TTargetEvent; - procedure RemoveTargetChangeEvent(Event: TTargetEvent); - procedure RemoveTargetInvalidEvent(Event: TTargetEvent); - function GetImageDataAsImage(var ABounds: TBox; out Image: TSimbaImage): Boolean; function GetImageData(var ABounds: TBox; var Data: PColorBGRA; var DataWidth: Integer): Boolean; procedure FreeImageData(var Data: PColorBGRA); @@ -152,7 +175,6 @@ TSimbaTarget = record function IsFocused: Boolean; function Focus: Boolean; - function Copy: TSimbaTarget; function ToString: String; property TargetKind: ESimbaTargetKind read FTarget.Kind; @@ -167,15 +189,6 @@ TSimbaTarget = record property CustomClientArea: TBox read FCustomClientArea write FCustomClientArea; property AutoFocus: Boolean read FAutoFocus write FAutoFocus; - // Mouse - function AddMouseEvent(Event: TMouseButtonEvent): TMouseButtonEvent; overload; - function AddMouseEvent(Event: TMouseTeleportEvent): TMouseTeleportEvent; overload; - function AddMouseEvent(Event: TMouseMovingEvent): TMouseMovingEvent; overload; - - procedure RemoveMouseEvent(Event: TMouseButtonEvent); overload; - procedure RemoveMouseEvent(Event: TMouseTeleportEvent); overload; - procedure RemoveMouseEvent(Event: TMouseMovingEvent); overload; - procedure MouseMove(Dest: TPoint); overload; procedure MouseMove(Box: TBox; ForcedMove: Boolean = False); overload; procedure MouseMove(Quad: TQuad; ForcedMove: Boolean = False); overload; @@ -256,31 +269,6 @@ implementation simba.nativeinterface, simba.vartype_box, simba.vartype_quad, simba.target_movemouse, simba.random, simba.finder_color, simba.finder_image, simba.finder_dtm; -type - TEventArray = array of TMethod; - -function AppendEvent(var Arr: TEventArray; Event: TMethod): TMethod; -var - I: Integer; -begin - Result := Event; - - // check duplicate - for I := 0 to High(Arr) do - if (Arr[I].Code = Event.Code) and (Arr[I].Data = Event.Data) then - Exit; - Arr += [Event]; -end; - -procedure DeleteEvent(var Arr: TEventArray; Event: TMethod); -var - I: Integer; -begin - for I := High(Arr) downto 0 do - if (Arr[I].Code = Event.Code) and (Arr[I].Data = Event.Data) then - Delete(Arr, I, 1); -end; - function TSimbaTarget.MousePressed(Button: EMouseButton): Boolean; begin CheckMethod(FTarget.MousePressed, 'MousePressed'); @@ -321,35 +309,49 @@ procedure TSimbaTarget.MouseClick(Button: EMouseButton); procedure TSimbaTarget.MouseTeleport(P: TPoint); var - I: Integer; + EventData: TTargetEventData; begin CheckMethod(FTarget.MouseTeleport, 'MouseTeleport'); - for I := 0 to High(MouseOptions.TeleportEvents) do - TMouseTeleportEvent(MouseOptions.TeleportEvents[I])(@Self, P); + + EventData := Default(TTargetEventData); + EventData.EventType := ETargetEventType.MOUSE_TELEPORT; + EventData.MouseTeleport.X := P.X; + EventData.MouseTeleport.Y := P.Y; + CallEvent(EventData); FTarget.MouseTeleport(FTarget.Target, P); end; procedure TSimbaTarget.MouseDown(Button: EMouseButton); var - I: Integer; + EventData: TTargetEventData; begin CheckMethod(FTarget.MouseDown, 'MouseDown'); CheckAutoFocus(); - for I := 0 to High(MouseOptions.ButtonEvents) do - TMouseButtonEvent(MouseOptions.ButtonEvents[I])(@Self, Button, True); + + EventData := Default(TTargetEventData); + EventData.EventType := ETargetEventType.MOUSE_BUTTON; + EventData.MouseButton.Button := Button; + EventData.MouseButton.Down := True; + + CallEvent(EventData); FTarget.MouseDown(FTarget.Target, Button); end; procedure TSimbaTarget.MouseUp(Button: EMouseButton); var - I: Integer; + EventData: TTargetEventData; begin CheckMethod(FTarget.MouseUp, 'MouseUp'); CheckAutoFocus(); - for I := 0 to High(MouseOptions.ButtonEvents) do - TMouseButtonEvent(MouseOptions.ButtonEvents[I])(@Self, Button, False); + + EventData := Default(TTargetEventData); + EventData.EventType := ETargetEventType.MOUSE_BUTTON; + EventData.MouseButton.Button := Button; + EventData.MouseButton.Down := False; + + CallEvent(EventData); FTarget.MouseUp(FTarget.Target, Button); end; @@ -708,26 +710,6 @@ function TSimbaTarget.FindEdges(MinDiff: Single; ABounds: TBox): TPointArray; Result := FindEdgesOnTarget(Self, ABounds, MinDiff, DefaultColorSpace, DefaultMultipliers); end; -function TSimbaTarget.AddTargetChangeEvent(Event: TTargetEvent): TTargetEvent; -begin - Result := TTargetEvent(AppendEvent(FChangeEvents, TMethod(Event))); -end; - -function TSimbaTarget.AddTargetInvalidEvent(Event: TTargetEvent): TTargetEvent; -begin - Result := TTargetEvent(AppendEvent(FInvalidEvents, TMethod(Event))); -end; - -procedure TSimbaTarget.RemoveTargetChangeEvent(Event: TTargetEvent); -begin - DeleteEvent(FChangeEvents, TMethod(Event)); -end; - -procedure TSimbaTarget.RemoveTargetInvalidEvent(Event: TTargetEvent); -begin - DeleteEvent(FInvalidEvents, TMethod(Event)); -end; - procedure TSimbaTarget.CheckMethod(Method: Pointer; Name: String); begin if (Method = nil) then @@ -766,34 +748,41 @@ procedure TSimbaTarget.SetMouseXY(Value: TPoint); MouseTeleport(Value); end; -function TSimbaTarget.AddMouseEvent(Event: TMouseButtonEvent): TMouseButtonEvent; -begin - Result := TMouseButtonEvent(AppendEvent(MouseOptions.ButtonEvents, TMethod(Event))); -end; - -function TSimbaTarget.AddMouseEvent(Event: TMouseTeleportEvent): TMouseTeleportEvent; +function TSimbaTarget.HasEvent(EventType: ETargetEventType): Boolean; +var + I: Integer; begin - Result := TMouseTeleportEvent(AppendEvent(MouseOptions.TeleportEvents, TMethod(Event))); + for I := 0 to High(FEvents) do + if (FEvents[I].EventType = EventType) then + Exit(True); + Result := False; end; -function TSimbaTarget.AddMouseEvent(Event: TMouseMovingEvent): TMouseMovingEvent; +procedure TSimbaTarget.CallEvent(var Data: TTargetEventData); +var + I: Integer; begin - Result := TMouseMovingEvent(AppendEvent(MouseOptions.MovingEvents, TMethod(Event))); + for I := 0 to High(FEvents) do + if (FEvents[I].EventType = Data.EventType) then + FEvents[I].Method(Self, Data); end; -procedure TSimbaTarget.RemoveMouseEvent(Event: TMouseButtonEvent); +function TSimbaTarget.AddEvent(EventType: ETargetEventType; Method: TEvent): TEvent; begin - DeleteEvent(MouseOptions.ButtonEvents, TMethod(Event)); -end; + SetLength(FEvents, Length(FEvents) + 1); + FEvents[High(FEvents)].EventType := EventType; + FEvents[High(FEvents)].Method := Method; -procedure TSimbaTarget.RemoveMouseEvent(Event: TMouseTeleportEvent); -begin - DeleteEvent(MouseOptions.TeleportEvents, TMethod(Event)); + Result := Method; end; -procedure TSimbaTarget.RemoveMouseEvent(Event: TMouseMovingEvent); +procedure TSimbaTarget.RemoveEvent(EventType: ETargetEventType; Method: TEvent); +var + I: Integer; begin - DeleteEvent(MouseOptions.MovingEvents, TMethod(Event)); + for I := High(FEvents) downto 0 do + if (FEvents[I].EventType = EventType) and (FEvents[I].Method = Method) then + Delete(FEvents, I, 1); end; procedure TSimbaTarget.ChangeTarget(Kind: ESimbaTargetKind); @@ -804,31 +793,36 @@ procedure TSimbaTarget.ChangeTarget(Kind: ESimbaTargetKind); procedure TSimbaTarget.TargetChanged; var - I: Integer; + EventData: TTargetEventData; begin - for I := 0 to High(FChangeEvents) do - TTargetEvent(FChangeEvents[I])(@Self); + EventData := Default(TTargetEventData); + EventData.EventType := ETargetEventType.TARGET_CHANGE; + + CallEvent(EventData); end; procedure TSimbaTarget.CheckInvalidTarget; var Attempt, I: Integer; + EventData: TTargetEventData; begin if IsValid() then Exit; - if (Length(FInvalidEvents) > 0) then + if HasEvent(ETargetEventType.TARGET_INVALID) then + begin + EventData := Default(TTargetEventData); + EventData.EventType := ETargetEventType.TARGET_INVALID; + for Attempt := 1 to 5 do begin Sleep(100); - for I := 0 to High(FInvalidEvents) do - begin - TTargetEvent(FInvalidEvents[I])(@Self); - if IsValid() then - Exit; - end; + CallEvent(EventData); + if IsValid() then + Exit; end; + end; SimbaException('Target is invalid: %s', [ToString()]); end; @@ -1148,24 +1142,6 @@ procedure TSimbaTarget.UnFreezeImage; FFrozen.Data := []; end; -function TSimbaTarget.Copy: TSimbaTarget; - - procedure MakeUnique(var Arr: TEventArray); - begin - if (Pointer(Arr) <> nil) then - Arr := System.Copy(Arr); - end; - -begin - Result := Self; - - MakeUnique(Result.FInvalidEvents); - MakeUnique(Result.FChangeEvents); - MakeUnique(Result.MouseOptions.ButtonEvents); - MakeUnique(Result.MouseOptions.TeleportEvents); - MakeUnique(Result.MouseOptions.MovingEvents); -end; - function TSimbaTarget.ToString: String; begin Result := 'ESimbaTargetKind.' + TargetName[FTarget.Kind]; diff --git a/Source/simba.target_movemouse.pas b/Source/simba.target_movemouse.pas index dd1ee797d..b6e78dd0f 100644 --- a/Source/simba.target_movemouse.pas +++ b/Source/simba.target_movemouse.pas @@ -20,7 +20,10 @@ interface Classes, SysUtils, simba.base, simba.target; -procedure MoveMouseOnTarget(constref Target: TSimbaTarget; Dest: TPoint); +type + TMoveMouseEvent = procedure(var X, Y, DestX, DestY: Double; out Stop: Boolean) of object; + +procedure MoveMouseOnTarget(constref Target: TSimbaTarget; Dest: TPoint; MouseMoveEvent: TMoveMouseEvent = nil); implementation @@ -28,7 +31,7 @@ implementation Math, simba.math, simba.random, simba.nativeinterface; -procedure MoveMouseOnTarget(constref Target: TSimbaTarget; Dest: TPoint); +procedure MoveMouseOnTarget(constref Target: TSimbaTarget; Dest: TPoint; MouseMoveEvent: TMoveMouseEvent); procedure Move(const X, Y, Idle: Double); var @@ -41,25 +44,11 @@ procedure MoveMouseOnTarget(constref Target: TSimbaTarget; Dest: TPoint); SimbaNativeInterface.PreciseSleep(Round(Idle)); end; - procedure DoMovingEvent(var X, Y, DestX, DestY: Double; out Stop: Boolean); - var - I: Integer; - begin - Stop := False; - - for I := 0 to High(Target.MouseOptions.MovingEvents) do - begin - TMouseMovingEvent(Target.MouseOptions.MovingEvents[I])(@Target, X, Y, DestX, DestY, Stop); - if Stop then - Exit; - end; - end; - procedure WindMouse(X1, Y1, X2, Y2, Gravity, Wind, MinWait, MaxWait, MaxStep, TargetArea: Double; Timeout: Integer); var X, Y, DestX, DestY: Double; VeloX, VeloY, WindX, WindY, VeloMag, RandomDist, Idle: Double; - RemainingDist, Acc, Step: Double; + RemainingDist, Step: Double; T: UInt64; Stop: Boolean; begin @@ -71,18 +60,20 @@ procedure MoveMouseOnTarget(constref Target: TSimbaTarget; Dest: TPoint); DestX := X2; DestY := Y2; - Acc := Target.MouseOptions.Accuracy + 0.5; Step := MaxStep; T := GetTickCount64() + Timeout; while (T > GetTickCount64()) do begin - DoMovingEvent(X, Y, X2, Y2, Stop); - if Stop then - Exit; + if Assigned(MouseMoveEvent) then + begin + MouseMoveEvent(X, Y, X2, Y2, Stop); + if Stop then + Exit; + end; RemainingDist := Hypot(X - X2, Y - Y2); - if (RemainingDist <= Acc) then + if (RemainingDist <= 0.5) then Break; // If destination changed ensure Step is appropriate diff --git a/Tests/target_invalid.simba b/Tests/target_invalid.simba index 5a8080483..113c03785 100644 --- a/Tests/target_invalid.simba +++ b/Tests/target_invalid.simba @@ -1,19 +1,21 @@ {$assertions on} -procedure DoInvalidTarget(var Target: TTarget); +procedure DoInvalidTarget(var Target: TTarget; Data: TTargetEventData); begin + Assert(Target.TargetKind = ETargetKind.IMAGE); + Assert(Target.TargetImage = nil); Target.SetImage(TImage.Create(100,100)); end; var Event: TTargetEvent; var Err: String; begin - Event := Target.AddTargetInvalidEvent(@DoInvalidTarget); + Event := Target.AddEvent(ETargetEventType.TARGET_INVALID, @DoInvalidTarget); Target.SetImage(nil); Assert(Target.Width = 100); Assert(Target.Height = 100); Target.TargetImage.Free(); - Target.RemoveTargetInvalidEvent(Event); + Target.RemoveEvent(ETargetEventType.TARGET_INVALID, Event); Target.SetImage(nil); try Target.Width;