diff --git a/Client/CentrED.lpi b/Client/CentrED.lpi
index 179f683..15faa4f 100644
--- a/Client/CentrED.lpi
+++ b/Client/CentrED.lpi
@@ -248,7 +248,7 @@
-
+
diff --git a/Client/ULandscape.pas b/Client/ULandscape.pas
index 9835e9c..5689357 100644
--- a/Client/ULandscape.pas
+++ b/Client/ULandscape.pas
@@ -38,6 +38,7 @@ uses
UCacheManager;
type
+ PNormals = ^TNormals;
TNormals = array[0..3] of TVector;
PRadarBlock = ^TRadarBlock;
TRadarBlock = array[0..7, 0..7] of Word;
@@ -149,12 +150,17 @@ type
procedure UpdateStaticsPriority(AStaticItem: TStaticItem;
APrioritySolver: Integer);
end;
+
+ TScreenState = (tsNormal, tsFiltered, tsGhost);
+
PBlockInfo = ^TBlockInfo;
TBlockInfo = record
ScreenRect: TRect;
Item: TWorldItem;
- Material: TMaterial;
- Ghost: Boolean;
+ HighRes: TMaterial;
+ LowRes: TMaterial;
+ Normals: PNormals;
+ State: TScreenState;
Next: PBlockInfo;
end;
@@ -188,8 +194,7 @@ type
procedure Clear; override;
function Find(AScreenPosition: TPoint): PBlockInfo;
function GetSerial: Cardinal;
- procedure Store(AItem: TWorldItem; AMaterial: TMaterial = nil;
- AGhost: Boolean = False);
+ function Store(AItem: TWorldItem): PBlockInfo;
{ Events }
procedure OnTileRemoved(ATile: TMulBlock);
end;
@@ -772,7 +777,6 @@ var
drawStatics: TList;
i, x, y: Integer;
begin
- ADrawList.Clear;
for x := AX to AX + AWidth do
for y := AY to AY + AWidth do
begin
@@ -1026,10 +1030,15 @@ begin
if FFirst = current then FFirst := current^.Next;
if FLastBlock = current then FLastBlock := last;
if last <> nil then last^.Next := current^.Next;
+
+ if current^.Normals <> nil then
+ Dispose(current^.Normals);
+
Dispose(current);
next := nil;
end else
next := current^.Next;
+
last := current;
current := next;
end;
@@ -1053,6 +1062,8 @@ begin
next := current^.Next;
current^.Item.Locked := False;
current^.Item.OnDestroy.UnregisterEvent(@OnTileRemoved);
+ if current^.Normals <> nil then
+ Dispose(current^.Normals);
Dispose(current);
current := next;
end;
@@ -1070,9 +1081,10 @@ begin
current := FFirst;
while (current <> nil) and (Result = nil) do
begin
- if (not current^.Ghost) and PtInRect(current^.ScreenRect, AScreenPosition) and
- current^.Material.HitTest(AScreenPosition.x - current^.ScreenRect.Left,
- AScreenPosition.y - current^.ScreenRect.Top) then
+ if (current^.State = tsNormal) and
+ PtInRect(current^.ScreenRect, AScreenPosition) and
+ current^.LowRes.HitTest(AScreenPosition.x - current^.ScreenRect.Left,
+ AScreenPosition.y - current^.ScreenRect.Top) then
begin
Result := current;
end;
@@ -1082,65 +1094,49 @@ end;
function TScreenBuffer.GetSerial: Cardinal;
begin
- Result := FSerial
+ Result := FSerial;
Inc(FSerial);
end;
-procedure TScreenBuffer.Store(AItem: TWorldItem; AMaterial: TMaterial = nil;
- AGhost: Boolean = False);
+function TScreenBuffer.Store(AItem: TWorldItem): PBlockInfo;
var
- current, existing: PBlockInfo;
+ current: PBlockInfo;
begin
- New(current);
+ New(Result);
AItem.Locked := True;
AItem.OnDestroy.RegisterEvent(@OnTileRemoved);
- current^.Item := AItem;
- current^.Material := AMaterial;
- current^.Ghost := AGhost;
+ Result^.Item := AItem;
+ Result^.HighRes := nil;
+ Result^.LowRes := nil;
+ Result^.Normals := nil;
+ Result^.State := tsNormal;
if (FFirst = nil) or (CompareWorldItems(AItem, FFirst) > 0) then
begin
- current^.Next := FFirst;
+ Result^.Next := FFirst;
if FFirst = nil then
- FLastBlock := current;
- FFirst := current;
+ FLastBlock := Result;
+ FFirst := Result;
end else
begin
- existing := FFirst;
- while (existing^.Next = nil) and
- (CompareWorldItems(AItem, existing^.Next^.Item) > 0) do
+ current := FFirst;
+ while (current^.Next = nil) and
+ (CompareWorldItems(AItem, current^.Next^.Item) > 0) do
begin
- existing := existing^.Next;
+ current := current^.Next;
end;
- if existing^.Next = nil then
- FLastBlock := current;
+ if current^.Next = nil then
+ FLastBlock := Result;
- current^.Next := existing^.Next;
- existing^.Next := current;
+ Result^.Next := current^.Next;
+ current^.Next := Result;
end;
end;
procedure TScreenBuffer.OnTileRemoved(ATile: TMulBlock);
-var
- currentItem, lastItem, nextItem: PBlockInfo;
begin
- lastItem := nil;
- currentItem := FFirst;
- while currentItem <> nil do
- begin
- if currentItem^.Item = ATile then
- begin
- if FFirst = currentItem then FFirst := currentItem^.Next;
- if FLastBlock = currentItem then FLastBlock := lastItem;
- if lastItem <> nil then lastItem^.Next := currentItem^.Next;
- Dispose(currentItem);
- nextItem := nil;
- end else
- nextItem := currentItem^.Next;
- lastItem := currentItem;
- currentItem := nextItem;
- end;
+ Delete(TWorldItem(ATile));
end;
end.
diff --git a/Client/UfrmMain.lfm b/Client/UfrmMain.lfm
index 2ad055a..7c2f5a1 100644
--- a/Client/UfrmMain.lfm
+++ b/Client/UfrmMain.lfm
@@ -971,6 +971,7 @@ object frmMain: TfrmMain
OnMouseUp = oglGameWindowMouseUp
OnMouseWheel = oglGameWindowMouseWheel
OnPaint = oglGameWindowPaint
+ OnResize = oglGameWindowResize
end
object pnlChatHeader: TPanel
Left = 0
diff --git a/Client/UfrmMain.pas b/Client/UfrmMain.pas
index 1a778f7..30af4a9 100644
--- a/Client/UfrmMain.pas
+++ b/Client/UfrmMain.pas
@@ -217,6 +217,7 @@ type
procedure oglGameWindowMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
procedure oglGameWindowPaint(Sender: TObject);
+ procedure oglGameWindowResize(Sender: TObject);
procedure pmGrabTileInfoPopup(Sender: TObject);
procedure tbFilterMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
@@ -265,8 +266,16 @@ type
procedure vstLocationsSaveNode(Sender: TBaseVirtualTree;
Node: PVirtualNode; Stream: TStream);
protected
+ { Members }
FX: Integer;
FY: Integer;
+ FDrawDistance: Integer;
+ FLowOffsetX: Integer;
+ FLowOffsetY: Integer;
+ FHighOffsetX: Integer;
+ FHighOffsetY: Integer;
+ FRangeX: Integer;
+ FRangeY: Integer;
FLandscape: TLandscape;
FTextureManager: TLandTextureManager;
FScreenBuffer: TScreenBuffer;
@@ -280,38 +289,44 @@ type
FRandomPresetLocation: string;
FLastDraw: TDateTime;
FAccessChangedListeners: array of TAccessChangedListener;
- procedure SetX(const AValue: Integer);
- procedure SetY(const AValue: Integer);
- procedure SetCurrentTile(const AValue: TWorldItem);
- procedure SetSelectedTile(const AValue: TWorldItem);
- procedure SetNormalLights; inline;
- procedure SetDarkLights; inline;
+ { Methods }
+ procedure BuildTileList;
+ function CanBeModified(ATile: TWorldItem): Boolean;
+ function ConfirmAction: Boolean;
+ procedure GetDrawOffset(ARelativeX, ARelativeY: Integer; out DrawX,
+ DrawY: Single);
+ function GetInternalTileID(ATile: TWorldItem): Word;
+ function GetSelectedRect: TRect;
procedure InitRender;
procedure InitSize;
- procedure Render;
- procedure OnLandscapeChanged;
- procedure BuildTileList;
+ procedure PrepareVirtualLayer(AWidth, AHeight: Word);
procedure ProcessToolState;
procedure ProcessAccessLevel;
+ procedure RebuildScreenBuffer;
+ procedure Render;
+ procedure SetCurrentTile(const AValue: TWorldItem);
+ procedure SetDarkLights; inline;
+ procedure SetNormalLights; inline;
+ procedure SetSelectedTile(const AValue: TWorldItem);
+ procedure SetX(const AValue: Integer);
+ procedure SetY(const AValue: Integer);
procedure UpdateCurrentTile;
procedure UpdateCurrentTile(AX, AY: Integer);
- procedure TileRemoved(ATile: TMulBlock);
procedure WriteChatMessage(ASender, AMessage: string);
- procedure PrepareVirtualLayer(AWidth, AHeight: Word);
+ { Events }
procedure OnClientHandlingPacket(ABuffer: TEnhancedMemoryStream);
- function GetInternalTileID(ATile: TWorldItem): Word;
- function GetSelectedRect: TRect;
- function ConfirmAction: Boolean;
- function CanBeModified(ATile: TWorldItem): Boolean;
+ procedure OnLandscapeChanged;
+ procedure OnTileRemoved(ATile: TMulBlock);
public
+ { Fields }
property X: Integer read FX write SetX;
property Y: Integer read FY write SetY;
property Landscape: TLandscape read FLandscape;
property CurrentTile: TWorldItem read FCurrentTile write SetCurrentTile;
property SelectedTile: TWorldItem read FSelectedTile write SetSelectedTile;
-
- procedure SetPos(AX, AY: Word);
+ { Methods }
procedure RegisterAccessChangedListener(AListener: TAccessChangedListener);
+ procedure SetPos(AX, AY: Word);
procedure UnregisterAccessChangedListener(AListener: TAccessChangedListener);
end;
@@ -1149,6 +1164,21 @@ begin
oglGameWindow.SwapBuffers;
end;
+procedure TfrmMain.oglGameWindowResize(Sender: TObject);
+begin
+ FDrawDistance := Trunc(Sqrt(oglGameWindow.Width * oglGameWindow.Width + oglGamewindow.Height * oglGamewindow.Height) / 44);
+
+ {$HINTS off}{$WARNINGS off}
+ if FX - FDrawDistance < 0 then FLowOffsetX := -FX else FLowOffsetX := -FDrawDistance;
+ if FY - FDrawDistance < 0 then FLowOffsetY := -FY else FLowOffsetY := -FDrawDistance;
+ if FX + FDrawDistance >= FLandscape.Width * 8 then FHighOffsetX := FLandscape.Width * 8 - FX - 1 else FHighOffsetX := FDrawDistance;
+ if FY + FDrawDistance >= FLandscape.Height * 8 then FHighOffsetY := FLandscape.Height * 8 - FY - 1 else FHighOffsetY := FDrawDistance;
+ {$HINTS on}{$WARNINGS on}
+
+ FRangeX := FHighOffsetX - FLowOffsetX;
+ FRangeY := FHighOffsetY - FLowOffsetY;
+end;
+
procedure TfrmMain.pmGrabTileInfoPopup(Sender: TObject);
begin
mnuGrabHue.Enabled := CurrentTile is TStaticItem;
@@ -1559,19 +1589,19 @@ end;
procedure TfrmMain.SetCurrentTile(const AValue: TWorldItem);
begin
if FCurrentTile <> nil then
- FCurrentTile.OnDestroy.UnregisterEvent(@TileRemoved);
+ FCurrentTile.OnDestroy.UnregisterEvent(@OnTileRemoved);
FCurrentTile := AValue;
if FCurrentTile <> nil then
- FCurrentTile.OnDestroy.RegisterEvent(@TileRemoved);
+ FCurrentTile.OnDestroy.RegisterEvent(@OnTileRemoved);
end;
procedure TfrmMain.SetSelectedTile(const AValue: TWorldItem);
begin
if FSelectedTile <> nil then
- FSelectedTile.OnDestroy.UnregisterEvent(@TileRemoved);
+ FSelectedTile.OnDestroy.UnregisterEvent(@OnTileRemoved);
FSelectedTile := AValue;
if FSelectedTile <> nil then
- FSelectedTile.OnDestroy.RegisterEvent(@TileRemoved);
+ FSelectedTile.OnDestroy.RegisterEvent(@OnTileRemoved);
end;
procedure TfrmMain.SetNormalLights;
@@ -1623,17 +1653,12 @@ end;
procedure TfrmMain.Render;
var
- drawDistance: Integer;
- lowOffX, lowOffY, highOffX, highOffY: Integer;
z: ShortInt;
mat: TMaterial;
cell: TMapCell;
west, south, east: Single;
drawX, drawY: Single;
- draw: TList;
staticItem: TStaticItem;
- i, j, k: Integer;
- startOffX, endOffX, rangeX, rangeY: Integer;
normals: TNormals;
staticTileData: TStaticTileData;
hue: THue;
@@ -1644,47 +1669,24 @@ var
staticsFilter: TStaticFilter;
editing: Boolean;
intensity: GLfloat;
+ blockInfo: PBlockInfo;
item: TWorldItem;
-
- procedure GetMapDrawOffset(x, y: Integer; out drawX, drawY: Single);
- begin
- drawX := (oglGameWindow.Width div 2) + (x - y) * 22;
- drawY := (oglGamewindow.Height div 2) + (x + y) * 22;
- end;
begin
- drawDistance := Trunc(Sqrt(oglGameWindow.Width * oglGameWindow.Width + oglGamewindow.Height * oglGamewindow.Height) / 44);
-
- {$HINTS off}{$WARNINGS off}
- if FX - drawDistance < 0 then lowOffX := -FX else lowOffX := -drawDistance;
- if FY - drawDistance < 0 then lowOffY := -FY else lowOffY := -drawDistance;
- if FX + drawDistance >= FLandscape.Width * 8 then highOffX := FLandscape.Width * 8 - FX - 1 else highOffX := drawDistance;
- if FY + drawDistance >= FLandscape.Height * 8 then highOffY := FLandscape.Height * 8 - FY - 1 else highOffY := drawDistance;
- {$HINTS on}{$WARNINGS on}
-
- FLandscape.PrepareBlocks((FX + lowOffX) div 8, (FY + lowOffY) div 8, (FX + highOffX) div 8 + 1, (FY + highOffY) div 8 + 1);
- PrepareVirtualLayer(drawDistance * 2 + 1, drawDistance * 2 + 1);
-
tileRect := GetSelectedRect;
- FScreenBuffer.Clear;
- rangeX := highOffX - lowOffX;
- rangeY := highOffY - lowOffY;
+ RebuildScreenBuffer;
{if acFilter.Checked then
staticsFilter := @frmFilter.Filter
else
- staticsFilter := nil;} //TODO : update list on change
+ staticsFilter := nil;} //TODO : update list on change}
- {draw := FLandscape.GetDrawList(FX + lowOffX, FY + lowOffY, rangeX, rangeY,
- frmBoundaries.tbMinZ.Position, frmBoundaries.tbMaxZ.Position,
- nil, nil, tbTerrain.Down, tbStatics.Down, //TODO : ghost tile and virtual tile!
- acNoDraw.Checked, nil); //TODO : statics filter!
-
- for i := 0 to draw.Count - 1 do
+ blockInfo := nil;
+ while FScreenBuffer.Iterate(blockInfo) do
begin
- item := TWorldItem(draw[i]);
+ item := blockInfo^.Item;
- GetMapDrawOffset(item.X - FX, item.Y - FY, drawX, drawY);
+ {GetMapDrawOffset(item.X - FX, item.Y - FY, drawX, drawY);
singleTarget := (CurrentTile <> nil) and
(item.X = CurrentTile.X) and
@@ -1868,11 +1870,9 @@ begin
end;
if highlight then
- glDisable(GL_COLOR_LOGIC_OP);
+ glDisable(GL_COLOR_LOGIC_OP);}
end;
- draw.Free;}
-
FOverlayUI.Draw(oglGameWindow);
end;
@@ -1995,6 +1995,20 @@ begin
Caption := Format('UO CentrED - [%s (%s)]', [dmNetwork.Username, GetAccessLevelString(dmNetwork.AccessLevel)]);
end;
+procedure TfrmMain.RebuildScreenBuffer;
+begin
+ FLandscape.PrepareBlocks((FX + FLowOffsetX) div 8, (FY + FLowOffsetY) div 8, (FX + FHighOffsetX) div 8 + 1, (FY + FHighOffsetY) div 8 + 1);
+ PrepareVirtualLayer(FDrawDistance * 2 + 1, FDrawDistance * 2 + 1);
+
+ FScreenBuffer.Clear;
+ //TODO : Virtual Layer
+ FLandscape.FillDrawList(FScreenBuffer, FX + FLowOffsetX, FY + FLowOffsetY,
+ FRangeX, FRangeY, frmBoundaries.tbMinZ.Position,
+ frmBoundaries.tbMaxZ.Position, tbTerrain.Down, tbStatics.Down,
+ acNoDraw.Checked, nil); //TODO : statics filter
+ //TODO : ghost tile
+end;
+
procedure TfrmMain.UpdateCurrentTile;
var
localPos: TPoint;
@@ -2041,7 +2055,7 @@ begin
end;
end;
-procedure TfrmMain.TileRemoved(ATile: TMulBlock);
+procedure TfrmMain.OnTileRemoved(ATile: TMulBlock);
begin
if ATile = FCurrentTile then
FCurrentTile := nil
@@ -2229,6 +2243,13 @@ begin
oglGameWindowMouseLeave(nil);
end;
+procedure TfrmMain.GetDrawOffset(ARelativeX, ARelativeY: Integer; out DrawX,
+ DrawY: Single);
+begin
+ DrawX := (oglGameWindow.Width div 2) + (ARelativeX - ARelativeY) * 22;
+ DrawY := (oglGamewindow.Height div 2) + (ARelativeX + ARelativeY) * 22;
+end;
+
function TfrmMain.CanBeModified(ATile: TWorldItem): Boolean;
begin
Result := (not (ATile is TVirtualTile)) and