Skip to content

Commit

Permalink
Fix target image freezing when a region is frozen
Browse files Browse the repository at this point in the history
  • Loading branch information
ollydev committed Jan 15, 2025
1 parent baaaa37 commit e7f572b
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 28 deletions.
39 changes: 27 additions & 12 deletions Source/simba.target.pas
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ TSimbaTargetInfo = record
Plugin: TSimbaPluginTarget;

GetDimensions: procedure(Target: Pointer; out W, H: Integer);
GetImageData: function(Target: Pointer; X, Y, Width, Height: Integer; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
GetImageData: function(Target: Pointer; X, Y, Width, Height: Integer; out Data: PColorBGRA; out DataWidth: Integer): Boolean;

IsValid: function(Target: Pointer): Boolean;
IsFocused: function(Target: Pointer): Boolean;
Expand Down Expand Up @@ -163,7 +163,7 @@ TSimbaTarget = record
procedure SetPlugin(FileName, Args: String; out DebugImage: TSimbaExternalCanvas); overload;

function GetImageDataAsImage(var ABounds: TBox; out Image: TSimbaImage): Boolean;
function GetImageData(var ABounds: TBox; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
function GetImageData(var ABounds: TBox; out Data: PColorBGRA; out DataWidth: Integer): Boolean;
procedure FreeImageData(var Data: PColorBGRA);

function IsImageFrozen: Boolean;
Expand Down Expand Up @@ -1074,26 +1074,41 @@ function TSimbaTarget.GetImageDataAsImage(var ABounds: TBox; out Image: TSimbaIm
end;
end;

function TSimbaTarget.GetImageData(var ABounds: TBox; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
begin
CheckMethod(FTarget.GetImageData, 'GetImageData');
if IsImageFrozen() then
begin
Data := @FFrozen.Data[0];
DataWidth := FFrozen.DataWidth;
ABounds := FFrozen.Bounds;
function TSimbaTarget.GetImageData(var ABounds: TBox; out Data: PColorBGRA; out DataWidth: Integer): Boolean;

Exit(True);
function GetFrozenData: Boolean;
begin
// constrain to our frozen bounds
if (ABounds.X1 = -1) and (ABounds.Y1 = -1) and (ABounds.X2 = -1) and (ABounds.Y2 = -1) then
ABounds := FFrozen.Bounds
else
ABounds := ABounds.Clip(FFrozen.Bounds);

Result := (ABounds.Width > 0) and (ABounds.Height > 0);
if Result then
begin
Data := @FFrozen.Data[(ABounds.Y1 - FFrozen.Bounds.Y1) * FFrozen.DataWidth + (ABounds.X1 - FFrozen.Bounds.X1)];
DataWidth := FFrozen.DataWidth;
end;
end;

begin
Data := nil;
Result := ValidateBounds(ABounds) and FTarget.GetImageData(FTarget.Target, ABounds.X1, ABounds.Y1, ABounds.Width, ABounds.Height, Data, DataWidth);
DataWidth := 0;

CheckMethod(FTarget.GetImageData, 'GetImageData');
if IsImageFrozen() then
Result := GetFrozenData()
else
Result := ValidateBounds(ABounds) and FTarget.GetImageData(FTarget.Target, ABounds.X1, ABounds.Y1, ABounds.Width, ABounds.Height, Data, DataWidth);
end;

procedure TSimbaTarget.FreeImageData(var Data: PColorBGRA);
begin
// never free frozen data
if IsImageFrozen() and (Data = @FFrozen.Data[0]) then
Exit;
// Only free window since rest of targets are references to buffers or image data.
if (FTarget.Kind in [ESimbaTargetKind.WINDOW]) then
FreeMem(Data);
end;
Expand Down
4 changes: 2 additions & 2 deletions Source/simba.target_eios.pas
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ TEIOSTarget = record

function LoadEIOS(FileName, Args: String): TEIOSTarget;

function EIOSTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
function EIOSTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; out Data: PColorBGRA; out DataWidth: Integer): Boolean;
procedure EIOSTarget_GetDimensions(Target: Pointer; out Width, Height: Integer);

procedure EIOSTarget_KeyDown(Target: Pointer; Key: EKeyCode);
Expand Down Expand Up @@ -155,7 +155,7 @@ function LoadEIOS(FileName, Args: String): TEIOSTarget;
end;
end;

function EIOSTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
function EIOSTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; out Data: PColorBGRA; out DataWidth: Integer): Boolean;
var
BufferWidth, BufferHeight: Integer;
begin
Expand Down
4 changes: 2 additions & 2 deletions Source/simba.target_image.pas
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface
simba.base;

procedure ImageTarget_GetDimensions(Target: Pointer; out W, H: Integer);
function ImageTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
function ImageTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; out Data: PColorBGRA; out DataWidth: Integer): Boolean;
function ImageTarget_IsValid(Target: Pointer): Boolean;

implementation
Expand All @@ -30,7 +30,7 @@ procedure ImageTarget_GetDimensions(Target: Pointer; out W, H: Integer);
H := Image.Height;
end;

function ImageTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
function ImageTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; out Data: PColorBGRA; out DataWidth: Integer): Boolean;
var
Image: TSimbaImage absolute Target;
begin
Expand Down
4 changes: 2 additions & 2 deletions Source/simba.target_plugin.pas
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function LoadPluginTarget(FileName, Args: String): TSimbaPluginTarget; overload;
function LoadPluginTarget(FileName, Args: String; out DebugImage: TSimbaExternalCanvas): TSimbaPluginTarget; overload;

procedure PluginTarget_GetDimensions(Target: Pointer; out W, H: Integer);
function PluginTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
function PluginTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; out Data: PColorBGRA; out DataWidth: Integer): Boolean;

function PluginTarget_MousePressed(Target: Pointer; Button: EMouseButton): Boolean;
function PluginTarget_MousePosition(Target: Pointer): TPoint;
Expand Down Expand Up @@ -190,7 +190,7 @@ procedure PluginTarget_GetDimensions(Target: Pointer; out W, H: Integer);
end;
end;

function PluginTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
function PluginTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; out Data: PColorBGRA; out DataWidth: Integer): Boolean;
begin
with PSimbaPluginTarget(Target)^ do
begin
Expand Down
4 changes: 2 additions & 2 deletions Source/simba.target_window.pas
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface
simba.base;

procedure WindowTarget_GetDimensions(Target: Pointer; out W, H: Integer);
function WindowTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
function WindowTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; out Data: PColorBGRA; out DataWidth: Integer): Boolean;

function WindowTarget_Focus(Target: Pointer): Boolean;
function WindowTarget_IsFocused(Target: Pointer): Boolean;
Expand Down Expand Up @@ -47,7 +47,7 @@ procedure WindowTarget_GetDimensions(Target: Pointer; out W, H: Integer);
end;
end;

function WindowTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; var Data: PColorBGRA; var DataWidth: Integer): Boolean;
function WindowTarget_GetImageData(Target: Pointer; X, Y, Width, Height: Integer; out Data: PColorBGRA; out DataWidth: Integer): Boolean;
begin
Result := SimbaNativeInterface.GetWindowImage(PWindowHandle(Target)^, X, Y, Width, Height, Data);
if Result then
Expand Down
30 changes: 22 additions & 8 deletions Tests/target_imagefreeze.simba
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,34 @@
var
img: TImage := TImage.Create(50, 50);
begin
// test entire client
img.FreeOnTerminate := True;
img.Fill(Colors.RED);

Target.SetImage(img);
Target.FreezeImage([5,5,25,25]);
Target.FreezeImage();

img.Fill(Colors.GREEN); // draw green, but frozen image is still red
img.Fill(Colors.GREEN); // draw green but frozen target is still red
Assert(Target.IsImageFrozen());
Assert(Target.CountColor(Colors.GREEN, 0) = 0);
Assert(Target.FindColor(Colors.RED, 0).Bounds.Area = 21*21);
Assert(Target.CountColor(Colors.RED, 0) = 50*50);

Target.UnFreezeImage();
Assert(not Target.IsImageFrozen());
Assert(Target.CountColor(Colors.GREEN, 0) = (50*50));
Assert(Target.CountColor(Colors.RED, 0) = 0);
Target.UnFreezeImage(); // test unfreeze
Assert(Target.CountColor(Colors.GREEN, 0) = 50*50);

img.Free();
// test area
img.Fill(0);
img.DrawColor := Colors.RED;
img.DrawBox([10,10,35,45]);

Target.FreezeImage([15,15,40,50]);
img.Clear(); // clear image but target is frozen

// search the entire frozen
Assert(Target.FindColor(Colors.RED, 0).Bounds = [15,15,35,45]);
Assert(Target.FindColor(Colors.RED, 0, [0,0,1000,1000]).Bounds = [15,15,35,45]);

// search a sub region of frozen
Assert(Target.CountColor(Colors.RED, 0, [20,20,25,30]) = 0);
Assert(Target.FindColor(Colors.RED, 0, [20,20,45,40]).Bounds = [35,20,35,40]);
end.

0 comments on commit e7f572b

Please sign in to comment.