From 6aa6496429eb228e2a41d5b78b98758fee0a61cc Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 20 Jul 2022 20:22:42 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Speed=20up=20preview=20ren?= =?UTF-8?q?dering?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Client/ULandscape.pas | 13 +++++ Client/UfrmMain.pas | 107 +++++++++++++++++++++++++----------------- 2 files changed, 76 insertions(+), 44 deletions(-) diff --git a/Client/ULandscape.pas b/Client/ULandscape.pas index 3026df9..2816128 100644 --- a/Client/ULandscape.pas +++ b/Client/ULandscape.pas @@ -322,6 +322,19 @@ type TGhostTile = class(TStaticItem); + { TMovableGhostTile } + + TMovableGhostTile = class(TGhostTile) + private + FOriginalX: Word; + FOriginalY: Word; + FOriginalZ: ShortInt; + public + property OriginalX: Word read FOriginalX write FOriginalX; + property OriginalY: Word read FOriginalY write FOriginalY; + property OriginalZ: ShortInt read FOriginalZ write FOriginalZ; + end; + operator enumerator(AScreenBuffer: TScreenBuffer): TScreenBufferItemEnumerator; implementation diff --git a/Client/UfrmMain.pas b/Client/UfrmMain.pas index c6afe76..0cdef58 100644 --- a/Client/UfrmMain.pas +++ b/Client/UfrmMain.pas @@ -368,6 +368,7 @@ type FUoaDesigns: TUoaDesigns; FCurrentUoaDesign: TUoaDesign; FCurrentUoaDesignAnchor: TWorldItem; + FCurrentUoaTiles: TStaticItemList; { Methods } procedure BuildTileList; function ConfirmAction: Boolean; @@ -383,6 +384,7 @@ type procedure LoadRandomPresets; procedure LoadUoaDesigns; procedure MoveBy(AOffsetX, AOffsetY: Integer); inline; + procedure MoveUoaDesign(AX, AY: Word; AZ: ShortInt); procedure PlaceUoaDesign(AWorldItem: TWorldItem); procedure PrepareMapCell(AMapCell: TMapCell); procedure PrepareScreenBlock(ABlockInfo: PBlockInfo); @@ -2006,6 +2008,8 @@ end; procedure TfrmMain.vstUoaDesignsDblClick(Sender: TObject); var selectedNode: PVirtualNode; + designTile: TStaticItem; + virtualTile: TMovableGhostTile; begin // Make sure to reset the current view first. PreviewUoaDesign(nil); @@ -2020,7 +2024,25 @@ begin Exit; FreeAndNil(FCurrentUoaDesign); + FreeAndNil(FCurrentUoaTiles); FCurrentUoaDesign := FUoaDesigns.LoadDesign(FUoaDesigns.Headers[selectedNode^.Index]); + FCurrentUoaTiles := TStaticItemList.Create(False); + + for designTile in FCurrentUoaDesign.Tiles do + begin + virtualTile := TMovableGhostTile.Create(nil, nil, 0, 0); + virtualTile.X := designTile.X; + virtualTile.Y := designTile.Y; + virtualTile.Z := designTile.Z; + virtualTile.OriginalX := designTile.X; + virtualTile.OriginalY := designTile.Y; + virtualTile.OriginalZ := designTile.Z; + virtualTile.TileID := designTile.TileID; + virtualTile.Hue := designTile.Hue; + FCurrentUoaTiles.Add(virtualTile); + FVirtualTiles.Add(virtualTile); + end; + MoveUoaDesign(FX, FY, FLandscape.GetLandAlt(FX, FY, 0)); RegisterSelectionListener(@PlaceUoaDesign); RegisterHoverListener(@PreviewUoaDesign); @@ -2328,6 +2350,39 @@ begin UpdateCurrentTile; end; +procedure TfrmMain.MoveUoaDesign(AX, AY: Word; AZ: ShortInt); +var + offsetX, offsetY, offsetZ, maxZ: Integer; + item: TStaticItem; +begin + maxZ := Low(Integer); + for item in FCurrentUoaDesign.Tiles do + if item.Z > maxZ then + maxZ := item.Z; + + offsetX := AX - FCurrentUoaDesign.Header.Width div 2; + offsetY := AY - FCurrentUoaDesign.Header.Height div 2; + offsetZ := EnsureRange(AZ, -128, 127); + + if offsetX < 0 then offsetX := 0; + if offsetX + FCurrentUoaDesign.Header.Width > FLandscape.CellWidth then + offsetX := FLandscape.CellWidth - FCurrentUoaDesign.Header.Width; + if offsetY < 0 then offsetY := 0; + if offsetY + FCurrentUoaDesign.Header.Height > FLandscape.CellHeight then + offsetY := FLandscape.CellHeight - FCurrentUoaDesign.Header.Height; + if offsetZ + maxZ > 127 then + offsetZ := 127 - maxZ; + + for item in FCurrentUoaTiles do + begin + item.X := TMovableGhostTile(item).OriginalX + offsetX; + item.Y := TMovableGhostTile(item).OriginalY + offsetY; + item.Z := TMovableGhostTile(item).OriginalZ + offsetZ; + end; + + InvalidateScreenBuffer; +end; + procedure TfrmMain.PlaceUoaDesign(AWorldItem: TWorldItem); var selectedNode: PVirtualNode; @@ -2338,6 +2393,7 @@ begin UnregisterSelectionListener(@PlaceUoaDesign); UnregisterHoverListener(@PreviewUoaDesign); FreeAndNil(FCurrentUoaDesign); + FreeAndNil(FCurrentUoaTiles); FCurrentUoaDesignAnchor := nil; vstUoaDesigns.Enabled := True; btnCancelUOAPlacement.Visible := False; @@ -2637,59 +2693,20 @@ begin end; procedure TfrmMain.PreviewUoaDesign(AWorldItem: TWorldItem); -var - offsetX, offsetY, offsetZ: Integer; - newX, newY, newZ: Integer; - i: Integer; - designTile, virtualTile: TStaticItem; - blockInfo: PBlockInfo; begin // If nothing has changed, we can keep this short. if FCurrentUoaDesignAnchor = AWorldItem then Exit; + FCurrentUoaDesignAnchor := AWorldItem; // No design selected? Well then. if FCurrentUoaDesign = nil then Exit; - for i := FVirtualTiles.Count - 1 downto 0 do - begin - if FVirtualTiles[i] is TGhostTile then - begin - FScreenBuffer.Delete(FVirtualTiles[i]); - FVirtualTiles.Delete(i); - end; - end; - if AWorldItem = nil then Exit; - offsetX := AWorldItem.X - FCurrentUoaDesign.Header.Width div 2; - offsetY := AWorldItem.Y - FCurrentUoaDesign.Header.Height div 2; - offsetZ := AWorldItem.Z; - - for designTile in FCurrentUoaDesign.Tiles do - begin - newX := designTile.X + offsetX; - newY := designTile.Y + offsetY; - newZ := designTile.Z + offsetZ; - - if (newX < 0) or (newX >= FLandscape.CellWidth) or - (newY < 0) or (newY >= FLandscape.CellHeight) or - (newZ < -128) or (newZ > 127) then - // We can't render this tile. Skip it. - continue; - - virtualTile := TGhostTile.Create(nil, nil, 0, 0); - virtualTile.X := newX; - virtualTile.Y := newY; - virtualTile.Z := newZ; - virtualTile.TileID := designTile.TileID; - virtualTile.Hue := designTile.Hue; - FVirtualTiles.Add(virtualTile); - end; - - InvalidateScreenBuffer; + MoveUoaDesign(AWorldItem.X, AWorldItem.Y, AWorldItem.Z); end; procedure TfrmMain.Render; @@ -3404,9 +3421,11 @@ var begin //Logger.EnterMethod([lcClient, lcDebug], 'UpdateSelection'); - //If the current tile is nil, but we still have a selected tile, the - //procedure is pointless - the selection should stay intact. - if (CurrentTile <> nil) or (SelectedTile = nil) then + // If the current tile is nil, but we still have a selected tile, the + // procedure is pointless - the selection should stay intact. + // Same if we are currently placing a UOA design, since we reuse the virtual + // tile and just update its position. + if ((CurrentTile <> nil) or (SelectedTile = nil)) and (FCurrentUoaTiles = nil) then begin if CurrentTile = nil then selectedRect := Rect(-1, -1, -1, -1)