Place UOA design #4
| @ -322,6 +322,19 @@ type | |||||||
| 
 | 
 | ||||||
|   TGhostTile = class(TStaticItem); |   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; | operator enumerator(AScreenBuffer: TScreenBuffer): TScreenBufferItemEnumerator; | ||||||
| 
 | 
 | ||||||
| implementation | implementation | ||||||
|  | |||||||
| @ -368,6 +368,7 @@ type | |||||||
|     FUoaDesigns: TUoaDesigns; |     FUoaDesigns: TUoaDesigns; | ||||||
|     FCurrentUoaDesign: TUoaDesign; |     FCurrentUoaDesign: TUoaDesign; | ||||||
|     FCurrentUoaDesignAnchor: TWorldItem; |     FCurrentUoaDesignAnchor: TWorldItem; | ||||||
|  |     FCurrentUoaTiles: TStaticItemList; | ||||||
|     { Methods } |     { Methods } | ||||||
|     procedure BuildTileList; |     procedure BuildTileList; | ||||||
|     function  ConfirmAction: Boolean; |     function  ConfirmAction: Boolean; | ||||||
| @ -383,6 +384,7 @@ type | |||||||
|     procedure LoadRandomPresets; |     procedure LoadRandomPresets; | ||||||
|     procedure LoadUoaDesigns; |     procedure LoadUoaDesigns; | ||||||
|     procedure MoveBy(AOffsetX, AOffsetY: Integer); inline; |     procedure MoveBy(AOffsetX, AOffsetY: Integer); inline; | ||||||
|  |     procedure MoveUoaDesign(AX, AY: Word; AZ: ShortInt); | ||||||
|     procedure PlaceUoaDesign(AWorldItem: TWorldItem); |     procedure PlaceUoaDesign(AWorldItem: TWorldItem); | ||||||
|     procedure PrepareMapCell(AMapCell: TMapCell); |     procedure PrepareMapCell(AMapCell: TMapCell); | ||||||
|     procedure PrepareScreenBlock(ABlockInfo: PBlockInfo); |     procedure PrepareScreenBlock(ABlockInfo: PBlockInfo); | ||||||
| @ -2006,6 +2008,8 @@ end; | |||||||
| procedure TfrmMain.vstUoaDesignsDblClick(Sender: TObject); | procedure TfrmMain.vstUoaDesignsDblClick(Sender: TObject); | ||||||
| var | var | ||||||
|   selectedNode: PVirtualNode; |   selectedNode: PVirtualNode; | ||||||
|  |   designTile: TStaticItem; | ||||||
|  |   virtualTile: TMovableGhostTile; | ||||||
| begin | begin | ||||||
|   // Make sure to reset the current view first. |   // Make sure to reset the current view first. | ||||||
|   PreviewUoaDesign(nil); |   PreviewUoaDesign(nil); | ||||||
| @ -2020,7 +2024,25 @@ begin | |||||||
|     Exit; |     Exit; | ||||||
| 
 | 
 | ||||||
|   FreeAndNil(FCurrentUoaDesign); |   FreeAndNil(FCurrentUoaDesign); | ||||||
|  |   FreeAndNil(FCurrentUoaTiles); | ||||||
|   FCurrentUoaDesign := FUoaDesigns.LoadDesign(FUoaDesigns.Headers[selectedNode^.Index]); |   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); |   RegisterSelectionListener(@PlaceUoaDesign); | ||||||
|   RegisterHoverListener(@PreviewUoaDesign); |   RegisterHoverListener(@PreviewUoaDesign); | ||||||
| @ -2328,6 +2350,39 @@ begin | |||||||
|   UpdateCurrentTile; |   UpdateCurrentTile; | ||||||
| end; | 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); | procedure TfrmMain.PlaceUoaDesign(AWorldItem: TWorldItem); | ||||||
| var | var | ||||||
|   selectedNode: PVirtualNode; |   selectedNode: PVirtualNode; | ||||||
| @ -2338,6 +2393,7 @@ begin | |||||||
|   UnregisterSelectionListener(@PlaceUoaDesign); |   UnregisterSelectionListener(@PlaceUoaDesign); | ||||||
|   UnregisterHoverListener(@PreviewUoaDesign); |   UnregisterHoverListener(@PreviewUoaDesign); | ||||||
|   FreeAndNil(FCurrentUoaDesign); |   FreeAndNil(FCurrentUoaDesign); | ||||||
|  |   FreeAndNil(FCurrentUoaTiles); | ||||||
|   FCurrentUoaDesignAnchor := nil; |   FCurrentUoaDesignAnchor := nil; | ||||||
|   vstUoaDesigns.Enabled := True; |   vstUoaDesigns.Enabled := True; | ||||||
|   btnCancelUOAPlacement.Visible := False; |   btnCancelUOAPlacement.Visible := False; | ||||||
| @ -2637,59 +2693,20 @@ begin | |||||||
| end; | end; | ||||||
| 
 | 
 | ||||||
| procedure TfrmMain.PreviewUoaDesign(AWorldItem: TWorldItem); | procedure TfrmMain.PreviewUoaDesign(AWorldItem: TWorldItem); | ||||||
| var |  | ||||||
|   offsetX, offsetY, offsetZ: Integer; |  | ||||||
|   newX, newY, newZ: Integer; |  | ||||||
|   i: Integer; |  | ||||||
|   designTile, virtualTile: TStaticItem; |  | ||||||
|   blockInfo: PBlockInfo; |  | ||||||
| begin | begin | ||||||
|   // If nothing has changed, we can keep this short. |   // If nothing has changed, we can keep this short. | ||||||
|   if FCurrentUoaDesignAnchor = AWorldItem then |   if FCurrentUoaDesignAnchor = AWorldItem then | ||||||
|     Exit; |     Exit; | ||||||
|  |   FCurrentUoaDesignAnchor := AWorldItem; | ||||||
| 
 | 
 | ||||||
|   // No design selected? Well then. |   // No design selected? Well then. | ||||||
|   if FCurrentUoaDesign = nil then |   if FCurrentUoaDesign = nil then | ||||||
|     Exit; |     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 |   if AWorldItem = nil then | ||||||
|     Exit; |     Exit; | ||||||
| 
 | 
 | ||||||
|   offsetX := AWorldItem.X - FCurrentUoaDesign.Header.Width div 2; |   MoveUoaDesign(AWorldItem.X, AWorldItem.Y, AWorldItem.Z); | ||||||
|   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; |  | ||||||
| end; | end; | ||||||
| 
 | 
 | ||||||
| procedure TfrmMain.Render; | procedure TfrmMain.Render; | ||||||
| @ -3404,9 +3421,11 @@ var | |||||||
| begin | begin | ||||||
|   //Logger.EnterMethod([lcClient, lcDebug], 'UpdateSelection'); |   //Logger.EnterMethod([lcClient, lcDebug], 'UpdateSelection'); | ||||||
| 
 | 
 | ||||||
|   //If the current tile is nil, but we still have a selected tile, the |   // If the current tile is nil, but we still have a selected tile, the | ||||||
|   //procedure is pointless - the selection should stay intact. |   // procedure is pointless - the selection should stay intact. | ||||||
|   if (CurrentTile <> nil) or (SelectedTile = nil) then |   // 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 |   begin | ||||||
|     if CurrentTile = nil then |     if CurrentTile = nil then | ||||||
|       selectedRect := Rect(-1, -1, -1, -1) |       selectedRect := Rect(-1, -1, -1, -1) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user