- Changed rendering to build the draw list for the whole range

- Added CanBeEdited flag to TWorldItem
- Changed list sorting from custom heap sort implementation to the FCL standard (QuickSort)
This commit is contained in:
2009-05-15 23:37:10 +02:00
parent c20a160543
commit 2f560a7738
6 changed files with 627 additions and 664 deletions

View File

@@ -21,7 +21,7 @@
* CDDL HEADER END
*
*
* Portions Copyright 2007 Andreas Schneider
* Portions Copyright 2009 Andreas Schneider
*)
unit ULandscape;
@@ -103,6 +103,7 @@ type
constructor Create(AWidth, AHeight: Word);
destructor Destroy; override;
protected
{ Members }
FWidth: Word;
FHeight: Word;
FCellWidth: Word;
@@ -110,7 +111,7 @@ type
FBlockCache: TCacheManager;
FOnChange: TLandscapeChangeEvent;
FOpenRequests: array of Boolean;
function Compare(left, right: TObject): Integer;
{ Methods }
function GetNormals(AX, AY: Word): TNormals;
function GetMapCell(AX, AY: Word): TMapCell;
function GetStaticList(AX, AY: Word): TList;
@@ -118,7 +119,6 @@ type
function GetStaticBlock(AX, AY: Word): TSeperatedStaticBlock;
procedure UpdateStaticsPriority(AStaticItem: TStaticItem;
APrioritySolver: Integer);
procedure OnBlockChanged(ABlock: TMulBlock);
procedure OnRemoveCachedObject(AObject: TObject);
procedure OnBlocksPacket(ABuffer: TEnhancedMemoryStream);
@@ -129,6 +129,7 @@ type
procedure OnMoveStaticPacket(ABuffer: TEnhancedMemoryStream);
procedure OnHueStaticPacket(ABuffer: TEnhancedMemoryStream);
public
{ Fields }
property Width: Word read FWidth;
property Height: Word read FHeight;
property CellWidth: Word read FCellWidth;
@@ -137,10 +138,11 @@ type
property StaticList[X, Y: Word]: TList read GetStaticList;
property Normals[X, Y: Word]: TNormals read GetNormals;
property OnChange: TLandscapeChangeEvent read FOnChange write FOnChange;
function GetDrawList(AX, AY: Word; AMinZ, AMaxZ: ShortInt;
{ Methods }
function GetDrawList(AX, AY, AWidth, AHeight: Word; AMinZ, AMaxZ: ShortInt;
AGhostTile: TWorldItem; AVirtualLayer: TStaticItem; AMap,
AStatics: Boolean; ANoDraw:Boolean; AStaticsFilter: TStaticFilter): TList;
procedure UpdateDrawListItems(AList: TList);
function GetEffectiveAltitude(ATile: TMapCell): ShortInt;
function GetLandAlt(AX, AY: Word; ADefault: ShortInt): ShortInt;
@@ -204,15 +206,6 @@ begin
Result := ((AX and $7FFF) shl 15) or (AY and $7FFF);
end;
{operator=(AStaticItem: TStaticItem; AStaticInfo: TStaticInfo): Boolean;
begin
Result := (AStaticItem.X = AStaticInfo.X) and
(AStaticItem.Y = AStaticInfo.Y) and
(AStaticItem.Z = AStaticInfo.Z) and
(AStaticItem.TileID = AStaticInfo.TileID) and
(AStaticItem.Hue = AStaticInfo.Hue);
end;}
{ TLandTextureManager }
constructor TLandTextureManager.Create;
@@ -410,88 +403,113 @@ begin
end;
end;
function TLandscape.Compare(left, right: TObject): Integer;
function Compare(AItem1, AItem2: Pointer): Integer;
begin
Result := TWorldItem(right).Priority - TWorldItem(left).Priority;
if TWorldItem(AItem1).X <> TWorldItem(AItem2).X then
Exit(TWorldItem(AItem1).X - TWorldItem(AItem2).X);
if TWorldItem(AItem1).Y <> TWorldItem(AItem2).Y then
Exit(TWorldItem(AItem1).Y - TWorldItem(AItem2).Y);
Result := TWorldItem(AItem1).Priority - TWorldItem(AItem2).Priority;
if Result = 0 then
begin
if (left is TMapCell) and (right is TStaticItem) then
Result := 1
else if (left is TStaticItem) and (right is TMapCell) then
Result := -1;
if (TObject(AItem1) is TMapCell) and (TObject(AItem2) is TStaticItem) then
Result := -1
else if (TObject(AItem1) is TStaticItem) and (TObject(AItem2) is TMapCell) then
Result := 1;
end;
if Result = 0 then
Result := TWorldItem(right).PriorityBonus - TWorldItem(left).PriorityBonus;
Result := TWorldItem(AItem1).PriorityBonus - TWorldItem(AItem2).PriorityBonus;
if Result = 0 then
Result := TWorldItem(right).PrioritySolver - TWorldItem(left).PrioritySolver;
Result := TWorldItem(AItem1).PrioritySolver - TWorldItem(AItem2).PrioritySolver;
end;
function TLandscape.GetDrawList(AX, AY: Word; AMinZ, AMaxZ: ShortInt;
AGhostTile: TWorldItem; AVirtualLayer: TStaticItem; AMap,
AStatics: Boolean; ANoDraw:Boolean; AStaticsFilter: TStaticFilter): TList;
function TLandscape.GetDrawList(AX, AY, AWidth, AHeight: Word;
AMinZ, AMaxZ: ShortInt; AGhostTile: TWorldItem; AVirtualLayer: TStaticItem;
AMap, AStatics: Boolean; ANoDraw: Boolean;
AStaticsFilter: TStaticFilter): TList;
var
landAlt: ShortInt;
drawMapCell: TMapCell;
drawStatics: TList;
i: Integer;
i, x, y: Integer;
begin
Result := TList.Create;
if AMap then
begin
landAlt := GetLandAlt(AX, AY, 0);
if (landAlt >= AMinZ) and (landAlt <= AMaxZ) then
for x := AX to AX + AWidth do
for y := AY to AY + AWidth do
begin
drawMapCell := GetMapCell(AX, AY);
if (drawMapCell <> nil) and (ANoDraw or (drawMapCell.TileID > 2)) then
if AMap then
begin
drawMapCell.Priority := GetEffectiveAltitude(drawMapCell);
drawMapCell.PriorityBonus := 0;
drawMapCell.PrioritySolver := 0;
Result.Add(drawMapCell);
end;
if AGhostTile is TMapCell then
begin
AGhostTile.X := AX;
AGhostTile.Y := AY;
AGhostTile.Priority := GetEffectiveAltitude(TMapCell(AGhostTile));
AGhostTile.PriorityBonus := 0;
AGhostTile.PrioritySolver := 0;
Result.Add(AGhostTile);
end;
end;
end;
if AStatics then
begin
drawStatics := GetStaticList(AX, AY);
if drawStatics <> nil then
for i := 0 to drawStatics.Count - 1 do
if (TStaticItem(drawStatics[i]).Z >= AMinZ) and
(TStaticItem(drawStatics[i]).Z <= AMaxZ) and
((AStaticsFilter = nil) or AStaticsFilter(TStaticItem(drawStatics[i]))) then
landAlt := GetLandAlt(x, y, 0);
if (landAlt >= AMinZ) and (landAlt <= AMaxZ) then
begin
UpdateStaticsPriority(TStaticItem(drawStatics[i]), i + 1);
Result.Add(Pointer(drawStatics[i]));
end;
drawMapCell := GetMapCell(x, y);
if (drawMapCell <> nil) and (ANoDraw or (drawMapCell.TileID > 2)) then
begin
drawMapCell.Priority := GetEffectiveAltitude(drawMapCell);
drawMapCell.PriorityBonus := 0;
drawMapCell.PrioritySolver := 0;
Result.Add(drawMapCell);
end;
if AGhostTile is TStaticItem then
begin
UpdateStaticsPriority(TStaticItem(AGhostTile), MaxInt);
Result.Add(AGhostTile);
if AGhostTile is TMapCell then
begin
AGhostTile.X := x;
AGhostTile.Y := y;
AGhostTile.Priority := GetEffectiveAltitude(TMapCell(AGhostTile));
AGhostTile.PriorityBonus := 0;
AGhostTile.PrioritySolver := 0;
Result.Add(AGhostTile);
end;
end;
end;
if AStatics then
begin
drawStatics := GetStaticList(x, y);
if drawStatics <> nil then
for i := 0 to drawStatics.Count - 1 do
if (TStaticItem(drawStatics[i]).Z >= AMinZ) and
(TStaticItem(drawStatics[i]).Z <= AMaxZ) and
((AStaticsFilter = nil) or AStaticsFilter(TStaticItem(drawStatics[i]))) then
begin
UpdateStaticsPriority(TStaticItem(drawStatics[i]), i + 1);
Result.Add(Pointer(drawStatics[i]));
end;
if AGhostTile is TStaticItem then
begin
UpdateStaticsPriority(TStaticItem(AGhostTile), MaxInt);
Result.Add(AGhostTile);
end;
end;
//TODO : re add virtual layer
{if AVirtualLayer <> nil then
begin
UpdateStaticsPriority(AVirtualLayer, MaxInt-1);
Result.Add(AVirtualLayer);
end;}
end;
end;
if AVirtualLayer <> nil then
Result.Sort(@Compare);
//ListSort(Result, @Compare);
end;
procedure TLandscape.UpdateDrawListItems(AList: TList);
var
worldItem: TWorldItem;
i: Integer;
begin
for i := 0 to AList.Count - 1 do
begin
UpdateStaticsPriority(AVirtualLayer, MaxInt-1);
Result.Add(AVirtualLayer);
worldItem := TWorldItem(AList.Items[i]);
worldItem.CanBeEdited := dmNetwork.CanWrite(worldItem.X, worldItem.Y);
end;
ListSort(Result, @Compare);
end;
function TLandscape.GetEffectiveAltitude(ATile: TMapCell): ShortInt;
@@ -591,37 +609,6 @@ begin
Result[3] := VectorNorm(VectorAdd(VectorAdd(VectorAdd(north, west), east), south));
end;
procedure TLandscape.OnBlockChanged(ABlock: TMulBlock);
var
block, old: TWorldBlock;
mode: Byte;
id, blockID: Integer;
begin
{block := ABlock as TWorldBlock;
if block <> nil then
begin
if block is TSeperatedStaticBlock then
mode := mStatics
else
mode := mMap;
id := GetID(block.X, block.Y, mode);
blockID := (block.X * FHeight) + block.Y;
if block.Changed or (block.RefCount > 0) then
begin
if FPersistentBlocks[blockID][mode] = nil then
begin
FPersistentBlocks[blockID][mode] := block;
FBlockCache.DiscardID(id);
end;
end else
begin
FPersistentBlocks[blockID][mode] := nil;
if not FBlockCache.QueryID(id, TObject(old)) then
FBlockCache.StoreID(id, block);
end;
end;}
end;
procedure TLandscape.MoveStatic(AStatic: TStaticItem; AX, AY: Word);
var
sourceBlock, targetBlock: TSeperatedStaticBlock;
@@ -639,7 +626,8 @@ begin
targetStaticList.Add(AStatic);
for i := 0 to targetStaticList.Count - 1 do
UpdateStaticsPriority(TStaticItem(targetStaticList.Items[i]), i);
ListSort(targetStaticList, @Compare);
targetStaticList.Sort(@Compare);
//ListSort(targetStaticList, @Compare);
AStatic.UpdatePos(AX, AY, AStatic.Z);
AStatic.Owner := targetBlock;
end;
@@ -788,7 +776,8 @@ begin
targetStaticList.Add(staticItem);
for i := 0 to targetStaticList.Count - 1 do
UpdateStaticsPriority(TStaticItem(targetStaticList.Items[i]), i);
ListSort(targetStaticList, @Compare);
targetStaticList.Sort(@Compare);
//ListSort(targetStaticList, @Compare);
staticItem.Owner := block;
if Assigned(FOnChange) then FOnChange;
end;
@@ -846,7 +835,8 @@ begin
staticItem.Z := ABuffer.ReadShortInt;
for j := 0 to statics.Count - 1 do
UpdateStaticsPriority(TStaticItem(statics.Items[j]), j);
ListSort(statics, @Compare);
statics.Sort(@Compare);
//ListSort(statics, @Compare);
if Assigned(FOnChange) then FOnChange;
Break;
end;
@@ -906,7 +896,8 @@ begin
statics.Add(staticItem);
for i := 0 to statics.Count - 1 do
UpdateStaticsPriority(TStaticItem(statics.Items[i]), i);
ListSort(statics, @Compare);
statics.Sort(@Compare);
//ListSort(statics, @Compare);
staticItem.Owner := targetBlock;
end;
@@ -987,7 +978,6 @@ var
pixel: TColor32Rec;
begin
Result := False;
//writeln(FGraphic.Width, ',', FGraphic.Height, ',', AX, ',', AY);
if InRange(AX, 0, FGraphic.Width - 1) and
InRange(AY, 0, FGraphic.Height - 1) then
begin