🚧 Preview design placement
This commit is contained in:
parent
cd983844fa
commit
1753c38eea
|
@ -320,6 +320,8 @@ type
|
||||||
Hue: Word;
|
Hue: Word;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TGhostTile = class(TStaticItem);
|
||||||
|
|
||||||
operator enumerator(AScreenBuffer: TScreenBuffer): TScreenBufferItemEnumerator;
|
operator enumerator(AScreenBuffer: TScreenBuffer): TScreenBufferItemEnumerator;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
@ -996,6 +998,7 @@ var
|
||||||
i, x, y: Integer;
|
i, x, y: Integer;
|
||||||
tempDrawList: TWorldItemList;
|
tempDrawList: TWorldItemList;
|
||||||
staticTileData: TStaticTiledata;
|
staticTileData: TStaticTiledata;
|
||||||
|
blockInfo: PBlockInfo;
|
||||||
begin
|
begin
|
||||||
ADrawList.Clear;
|
ADrawList.Clear;
|
||||||
tempDrawList := TWorldItemList.Create(False);;
|
tempDrawList := TWorldItemList.Create(False);;
|
||||||
|
@ -1042,7 +1045,11 @@ begin
|
||||||
|
|
||||||
tempDrawList.Sort(@CompareWorldItems);
|
tempDrawList.Sort(@CompareWorldItems);
|
||||||
for i := 0 to tempDrawList.Count - 1 do
|
for i := 0 to tempDrawList.Count - 1 do
|
||||||
ADrawList.Add(TWorldItem(tempDrawList[i]));
|
begin
|
||||||
|
blockInfo := ADrawList.Add(TWorldItem(tempDrawList[i]));
|
||||||
|
if tempDrawList[i] is TGhostTile then
|
||||||
|
blockInfo^.State := ssGhost;
|
||||||
|
end;
|
||||||
tempDrawList.Free;
|
tempDrawList.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,19 @@ type
|
||||||
constructor CreateFromStream(AStream: TStream);
|
constructor CreateFromStream(AStream: TStream);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TUoaDesign = class
|
||||||
|
private
|
||||||
|
FHeader: TUoaDesignHeader;
|
||||||
|
FTiles: TStaticItemList;
|
||||||
|
|
||||||
|
constructor Create(AHeader: TUoaDesignHeader; AData: TStream);
|
||||||
|
public
|
||||||
|
property Header: TUoaDesignHeader read FHeader;
|
||||||
|
property Tiles: TStaticItemList read Ftiles;
|
||||||
|
|
||||||
|
destructor Destroy; override;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TUoaDesigns }
|
{ TUoaDesigns }
|
||||||
|
|
||||||
TUoaDesigns = class
|
TUoaDesigns = class
|
||||||
|
@ -42,8 +55,7 @@ type
|
||||||
constructor Create(AIdxFile, ABinFile: String);
|
constructor Create(AIdxFile, ABinFile: String);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
function LoadTiles(AHeader: TUoaDesignHeader; AOffsetX, AOffsetY: Word;
|
function LoadDesign(AHeader: TUoaDesignHeader): TUoaDesign;
|
||||||
AOffsetZ: ShortInt): TStaticItemList;
|
|
||||||
public
|
public
|
||||||
property Headers: TUoaDesignHeaders read FHeaders;
|
property Headers: TUoaDesignHeaders read FHeaders;
|
||||||
end;
|
end;
|
||||||
|
@ -65,6 +77,49 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TUoaDesign }
|
||||||
|
|
||||||
|
constructor TUoaDesign.Create(AHeader: TUoaDesignHeader; AData: TStream);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
tile: TStaticItem;
|
||||||
|
version: Int32;
|
||||||
|
|
||||||
|
function ReadInt: Int32;
|
||||||
|
begin
|
||||||
|
AData.Read(Result, SizeOf(Result));
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
FHeader := AHeader;
|
||||||
|
FTiles := TStaticItemList.Create(True);
|
||||||
|
AData.Seek(FHeader.FilePosition, soFromBeginning);
|
||||||
|
for i := 0 to FHeader.TileCount - 1 do
|
||||||
|
begin
|
||||||
|
AData.Read(version, SizeOf(version));
|
||||||
|
if (version < 0) or (version > 1) then
|
||||||
|
raise Exception.Create('Unsupported binary version');
|
||||||
|
|
||||||
|
tile := TStaticItem.Create(nil);
|
||||||
|
tile.TileID := ReadInt;
|
||||||
|
tile.X := ReadInt;
|
||||||
|
tile.Y := ReadInt;
|
||||||
|
tile.Z := ReadInt;
|
||||||
|
ReadInt; // Level; unused
|
||||||
|
|
||||||
|
if version = 1 then
|
||||||
|
tile.Hue := ReadInt;
|
||||||
|
|
||||||
|
FTiles.Add(tile);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TUoaDesign.Destroy;
|
||||||
|
begin
|
||||||
|
FTiles.Free;
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TUoaDesignHeaders }
|
{ TUoaDesignHeaders }
|
||||||
|
|
||||||
constructor TUoaDesignHeaders.CreateFromStream(AStream: TStream);
|
constructor TUoaDesignHeaders.CreateFromStream(AStream: TStream);
|
||||||
|
@ -120,39 +175,9 @@ begin
|
||||||
Headers.Free;
|
Headers.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TUoaDesigns.LoadTiles(AHeader: TUoaDesignHeader; AOffsetX,
|
function TUoaDesigns.LoadDesign(AHeader: TUoaDesignHeader): TUoaDesign;
|
||||||
AOffsetY: Word; AOffsetZ: ShortInt): TStaticItemList;
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
tile: TStaticItem;
|
|
||||||
version: Int32;
|
|
||||||
|
|
||||||
function ReadInt: Int32;
|
|
||||||
begin
|
begin
|
||||||
FData.Read(Result, SizeOf(Result));
|
Result := TUoaDesign.Create(AHeader, FData);
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
Result := TStaticItemList.Create(True);
|
|
||||||
FData.Seek(AHeader.FilePosition, soFromBeginning);
|
|
||||||
for i := 0 to AHeader.TileCount - 1 do
|
|
||||||
begin
|
|
||||||
FData.Read(version, SizeOf(version));
|
|
||||||
if (version < 0) or (version > 1) then
|
|
||||||
raise Exception.Create('Unsupported binary version');
|
|
||||||
|
|
||||||
tile := TStaticItem.Create(nil);
|
|
||||||
tile.TileID := ReadInt;
|
|
||||||
tile.X := AOffsetX + ReadInt;
|
|
||||||
tile.Y := AOffsetY + ReadInt;
|
|
||||||
tile.Z := AOffsetZ + ReadInt;
|
|
||||||
ReadInt; // TODO: Level??
|
|
||||||
|
|
||||||
if version = 1 then
|
|
||||||
tile.Hue := ReadInt;
|
|
||||||
|
|
||||||
Result.Add(tile);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
|
@ -47,7 +47,6 @@ type
|
||||||
|
|
||||||
TBlockInfoList = specialize TFPGList<PBlockInfo>;
|
TBlockInfoList = specialize TFPGList<PBlockInfo>;
|
||||||
|
|
||||||
TGhostTile = class(TStaticItem);
|
|
||||||
TPacketList = specialize TFPGObjectList<TPacket>;
|
TPacketList = specialize TFPGObjectList<TPacket>;
|
||||||
TAccessChangedListeners = specialize TFPGList<TAccessChangedListener>;
|
TAccessChangedListeners = specialize TFPGList<TAccessChangedListener>;
|
||||||
TSelectionListeners = specialize TFPGList<TSelectionListener>;
|
TSelectionListeners = specialize TFPGList<TSelectionListener>;
|
||||||
|
@ -360,10 +359,13 @@ type
|
||||||
FUndoList: TPacketList;
|
FUndoList: TPacketList;
|
||||||
FGLFont: TGLFont;
|
FGLFont: TGLFont;
|
||||||
FSelectionListeners: TSelectionListeners;
|
FSelectionListeners: TSelectionListeners;
|
||||||
|
FHoverListeners: TSelectionListeners;
|
||||||
FTileHint: TTileHintInfo;
|
FTileHint: TTileHintInfo;
|
||||||
FLightManager: TLightManager;
|
FLightManager: TLightManager;
|
||||||
FTileFilter: TTileDataFlags;
|
FTileFilter: TTileDataFlags;
|
||||||
FUoaDesigns: TUoaDesigns;
|
FUoaDesigns: TUoaDesigns;
|
||||||
|
FCurrentUoaDesign: TUoaDesign;
|
||||||
|
FCurrentUoaDesignAnchor: TWorldItem;
|
||||||
{ Methods }
|
{ Methods }
|
||||||
procedure BuildTileList;
|
procedure BuildTileList;
|
||||||
function ConfirmAction: Boolean;
|
function ConfirmAction: Boolean;
|
||||||
|
@ -381,6 +383,7 @@ type
|
||||||
procedure PlaceUoaDesign(AWorldItem: TWorldItem);
|
procedure PlaceUoaDesign(AWorldItem: TWorldItem);
|
||||||
procedure PrepareMapCell(AMapCell: TMapCell);
|
procedure PrepareMapCell(AMapCell: TMapCell);
|
||||||
procedure PrepareScreenBlock(ABlockInfo: PBlockInfo);
|
procedure PrepareScreenBlock(ABlockInfo: PBlockInfo);
|
||||||
|
procedure PreviewUoaDesign(AWorldItem: TWorldItem);
|
||||||
procedure ProcessToolState;
|
procedure ProcessToolState;
|
||||||
procedure ProcessAccessLevel;
|
procedure ProcessAccessLevel;
|
||||||
procedure RebuildScreenBuffer;
|
procedure RebuildScreenBuffer;
|
||||||
|
@ -420,10 +423,12 @@ type
|
||||||
procedure InvalidateFilter;
|
procedure InvalidateFilter;
|
||||||
procedure InvalidateScreenBuffer;
|
procedure InvalidateScreenBuffer;
|
||||||
procedure RegisterAccessChangedListener(AListener: TAccessChangedListener);
|
procedure RegisterAccessChangedListener(AListener: TAccessChangedListener);
|
||||||
|
procedure RegisterHoverListener(AListener: TSelectionListener);
|
||||||
procedure RegisterSelectionListener(AListener: TSelectionListener);
|
procedure RegisterSelectionListener(AListener: TSelectionListener);
|
||||||
procedure SetPos(AX, AY: Word);
|
procedure SetPos(AX, AY: Word);
|
||||||
procedure SwitchToSelection;
|
procedure SwitchToSelection;
|
||||||
procedure UnregisterAccessChangedListener(AListener: TAccessChangedListener);
|
procedure UnregisterAccessChangedListener(AListener: TAccessChangedListener);
|
||||||
|
procedure UnregisterHoverListener(AListener: TSelectionListener);
|
||||||
procedure UnregisterSelectionListener(AListener: TSelectionListener);
|
procedure UnregisterSelectionListener(AListener: TSelectionListener);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1038,6 +1043,7 @@ begin
|
||||||
pnlBottom.DoubleBuffered := True;
|
pnlBottom.DoubleBuffered := True;
|
||||||
|
|
||||||
FAccessChangedListeners := TAccessChangedListeners.Create;
|
FAccessChangedListeners := TAccessChangedListeners.Create;
|
||||||
|
FHoverListeners := TSelectionListeners.Create;
|
||||||
FSelectionListeners := TSelectionListeners.Create;
|
FSelectionListeners := TSelectionListeners.Create;
|
||||||
|
|
||||||
FLastDraw := Now;
|
FLastDraw := Now;
|
||||||
|
@ -1408,6 +1414,7 @@ begin
|
||||||
FreeAndNil(FGLFont);
|
FreeAndNil(FGLFont);
|
||||||
FreeAndNil(FRandomPresetsDoc);
|
FreeAndNil(FRandomPresetsDoc);
|
||||||
FreeAndNil(FAccessChangedListeners);
|
FreeAndNil(FAccessChangedListeners);
|
||||||
|
FreeAndNil(FHoverListeners);
|
||||||
FreeAndNil(FSelectionListeners);
|
FreeAndNil(FSelectionListeners);
|
||||||
FreeAndNil(FUoaDesigns);
|
FreeAndNil(FUoaDesigns);
|
||||||
|
|
||||||
|
@ -1989,8 +1996,24 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.vstUoaDesignsDblClick(Sender: TObject);
|
procedure TfrmMain.vstUoaDesignsDblClick(Sender: TObject);
|
||||||
|
var
|
||||||
|
selectedNode: PVirtualNode;
|
||||||
begin
|
begin
|
||||||
|
// Make sure to reset the current view first.
|
||||||
|
PreviewUoaDesign(nil);
|
||||||
|
|
||||||
|
UnregisterSelectionListener(@PlaceUoaDesign);
|
||||||
|
UnregisterHoverListener(@PreviewUoaDesign);
|
||||||
|
|
||||||
|
selectedNode := vstUoaDesigns.GetFirstSelected();
|
||||||
|
if selectedNode = nil then
|
||||||
|
Exit;
|
||||||
|
|
||||||
|
FreeAndNil(FCurrentUoaDesign);
|
||||||
|
FCurrentUoaDesign := FUoaDesigns.LoadDesign(FUoaDesigns.Headers[selectedNode^.Index]);
|
||||||
|
|
||||||
RegisterSelectionListener(@PlaceUoaDesign);
|
RegisterSelectionListener(@PlaceUoaDesign);
|
||||||
|
RegisterHoverListener(@PreviewUoaDesign);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.vstUoaDesignsGetText(Sender: TBaseVirtualTree;
|
procedure TfrmMain.vstUoaDesignsGetText(Sender: TBaseVirtualTree;
|
||||||
|
@ -2065,6 +2088,12 @@ begin
|
||||||
FAccessChangedListeners.Add(AListener);
|
FAccessChangedListeners.Add(AListener);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.RegisterHoverListener(AListener: TSelectionListener);
|
||||||
|
begin
|
||||||
|
if FHoverListeners.IndexOf(AListener) = -1 then
|
||||||
|
FHoverListeners.Add(AListener);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.RegisterSelectionListener(AListener: TSelectionListener);
|
procedure TfrmMain.RegisterSelectionListener(AListener: TSelectionListener);
|
||||||
begin
|
begin
|
||||||
if FSelectionListeners.IndexOf(AListener) = -1 then
|
if FSelectionListeners.IndexOf(AListener) = -1 then
|
||||||
|
@ -2077,6 +2106,11 @@ begin
|
||||||
FAccessChangedListeners.Remove(AListener);
|
FAccessChangedListeners.Remove(AListener);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TfrmMain.UnregisterHoverListener(AListener: TSelectionListener);
|
||||||
|
begin
|
||||||
|
FHoverListeners.Remove(Alistener);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.UnregisterSelectionListener(AListener: TSelectionListener);
|
procedure TfrmMain.UnregisterSelectionListener(AListener: TSelectionListener);
|
||||||
begin
|
begin
|
||||||
FSelectionListeners.Remove(AListener);
|
FSelectionListeners.Remove(AListener);
|
||||||
|
@ -2294,7 +2328,9 @@ begin
|
||||||
if selectedNode = nil then
|
if selectedNode = nil then
|
||||||
Exit;
|
Exit;
|
||||||
|
|
||||||
header := FUoaDesigns.Headers[selectedNode^.Index];
|
vstUoaDesigns.ClearSelection;
|
||||||
|
|
||||||
|
{header := FUoaDesigns.Headers[selectedNode^.Index];
|
||||||
tiles := FUoaDesigns.LoadTiles(header, AWorldItem.X, AWorldItem.Y, AWorldItem.Z);
|
tiles := FUoaDesigns.LoadTiles(header, AWorldItem.X, AWorldItem.Y, AWorldItem.Z);
|
||||||
try
|
try
|
||||||
FUndoList.Clear;
|
FUndoList.Clear;
|
||||||
|
@ -2305,7 +2341,7 @@ begin
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
tiles.Free;
|
tiles.Free;
|
||||||
end;
|
end;}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.PrepareMapCell(AMapCell: TMapCell);
|
procedure TfrmMain.PrepareMapCell(AMapCell: TMapCell);
|
||||||
|
@ -2568,6 +2604,62 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
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;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.Render;
|
procedure TfrmMain.Render;
|
||||||
var
|
var
|
||||||
highlight: Boolean;
|
highlight: Boolean;
|
||||||
|
@ -3060,6 +3152,7 @@ end;
|
||||||
procedure TfrmMain.UpdateCurrentTile(AX, AY: Integer);
|
procedure TfrmMain.UpdateCurrentTile(AX, AY: Integer);
|
||||||
var
|
var
|
||||||
blockInfo: PBlockInfo;
|
blockInfo: PBlockInfo;
|
||||||
|
listener: TSelectionListener;
|
||||||
begin
|
begin
|
||||||
//Logger.EnterMethod([lcClient, lcDebug], 'UpdateCurrentTile');
|
//Logger.EnterMethod([lcClient, lcDebug], 'UpdateCurrentTile');
|
||||||
FOverlayUI.ActiveArrow := FOverlayUI.HitTest(AX, AY);
|
FOverlayUI.ActiveArrow := FOverlayUI.HitTest(AX, AY);
|
||||||
|
@ -3077,6 +3170,9 @@ begin
|
||||||
else
|
else
|
||||||
CurrentTile := nil;
|
CurrentTile := nil;
|
||||||
|
|
||||||
|
for listener in FHoverListeners do
|
||||||
|
listener(CurrentTile);
|
||||||
|
|
||||||
//Logger.ExitMethod([lcClient, lcDebug], 'UpdateCurrentTile');
|
//Logger.ExitMethod([lcClient, lcDebug], 'UpdateCurrentTile');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue