diff --git a/Client/ULandscape.pas b/Client/ULandscape.pas index e84cf38..a95b37a 100644 --- a/Client/ULandscape.pas +++ b/Client/ULandscape.pas @@ -73,7 +73,8 @@ type constructor Create; destructor Destroy; override; function GetArtMaterial(ATileID: Word): TMaterial; overload; - function GetArtMaterial(ATileID: Word; AHue: THue; APartialHue: Boolean): TMaterial; overload; + function GetArtMaterial(ATileID: Word; AHue: THue; + APartialHue: Boolean): TMaterial; overload; function GetFlatLandMaterial(ATileID: Word): TMaterial; function GetTexMaterial(ATileID: Word): TMaterial; protected @@ -114,6 +115,8 @@ type end; TLandscapeChangeEvent = procedure of object; + TNewBlockEvent = procedure(ABlock: TBlock) of object; + TStaticChangedEvent = procedure(AStaticItem: TStaticItem) of object; TStaticFilter = function(AStatic: TStaticItem): Boolean of object; TScreenBuffer = class; @@ -131,6 +134,11 @@ type FCellHeight: Word; FBlockCache: TCacheManager; FOnChange: TLandscapeChangeEvent; + FOnNewBlock: TNewBlockEvent; + FOnStaticInserted: TStaticChangedEvent; + FOnStaticDeleted: TStaticChangedEvent; + FOnStaticElevated: TStaticChangedEvent; + FOnStaticHued: TStaticChangedEvent; FOpenRequests: array of Boolean; { Methods } function GetMapBlock(AX, AY: Word): TMapBlock; @@ -157,6 +165,15 @@ type property StaticList[X, Y: Word]: TList read GetStaticList; property Normals[X, Y: Word]: TNormals read GetNormals; property OnChange: TLandscapeChangeEvent read FOnChange write FOnChange; + property OnNewBlock: TNewBlockEvent read FOnNewBlock write FOnNewBlock; + property OnStaticInserted: TStaticChangedEvent read FOnStaticInserted + write FOnStaticInserted; + property OnStaticDeleted: TStaticChangedEvent read FOnStaticDeleted + write FOnStaticDeleted; + property OnStaticElevated: TStaticChangedEvent read FOnStaticElevated + write FOnStaticElevated; + property OnStaticHued: TStaticChangedEvent read FOnStaticHued + write FOnStaticHued; { Methods } procedure FillDrawList(ADrawList: TScreenBuffer; AX, AY, AWidth, AHeight: Word; AMinZ, AMaxZ: ShortInt; AMap, AStatics: Boolean; @@ -478,6 +495,12 @@ begin FCellHeight := FHeight * 8; FBlockCache := TCacheManager.Create(256); FBlockCache.OnRemoveObject := @OnRemoveCachedObject; + + FOnChange := nil; + FOnStaticDeleted := nil; + FOnStaticElevated := nil; + FOnStaticHued := nil; + FOnStaticInserted := nil; SetLength(FOpenRequests, FWidth * FHeight); //TODO : TBits? for blockID := 0 to Length(FOpenRequests) - 1 do @@ -653,7 +676,8 @@ begin targetStaticList.Sort(@CompareWorldItems); staticItem.Owner := block; staticItem.CanBeEdited := dmNetwork.CanWrite(x, y); - if Assigned(FOnChange) then FOnChange; + + if Assigned(FOnStaticInserted) then FOnStaticInserted(staticItem); end; end; @@ -677,9 +701,10 @@ begin (staticItem.TileID = staticInfo.TileID) and (staticItem.Hue = staticInfo.Hue) then begin + if Assigned(FOnStaticDeleted) then FOnStaticDeleted(staticItem); statics.Delete(i); staticItem.Delete; - if Assigned(FOnChange) then FOnChange; + Break; end; end; @@ -712,7 +737,9 @@ begin ResMan.Tiledata.StaticTiles[TStaticItem(statics.Items[j]).TileID], j); statics.Sort(@CompareWorldItems); - if Assigned(FOnChange) then FOnChange; + + if Assigned(FOnStaticElevated) then FOnStaticElevated(staticItem); + Break; end; end; @@ -753,6 +780,7 @@ begin if staticItem <> nil then begin + if Assigned(FOnStaticDeleted) then FOnStaticDeleted(staticItem); statics.Remove(staticItem); staticItem.Delete; end; @@ -774,9 +802,10 @@ begin i); statics.Sort(@CompareWorldItems); staticItem.Owner := targetBlock; - end; + staticItem.CanBeEdited := dmNetwork.CanWrite(newX, newY); - if Assigned(FOnChange) then FOnChange; + if Assigned(FOnStaticInserted) then FOnStaticInserted(staticItem); + end; end; procedure TLandscape.OnHueStaticPacket(ABuffer: TEnhancedMemoryStream); @@ -800,7 +829,7 @@ begin (staticItem.Hue = staticInfo.Hue) then begin staticItem.Hue := ABuffer.ReadWord; - if Assigned(FOnChange) then FOnChange; + if Assigned(FOnStaticHued) then FOnStaticHued(staticItem); Break; end; end; @@ -1224,7 +1253,7 @@ begin Result^.State := ssNormal; Result^.Highlighted := False; - if (FShortCuts[0] = nil) or (CompareWorldItems(AItem, FShortCuts[0]) > 0) then + if (FShortCuts[0] = nil) or (CompareWorldItems(AItem, FShortCuts[0]) < 0) then begin //TODO : update last element if necessary Result^.Next := FShortCuts[0]; @@ -1234,7 +1263,7 @@ begin //find best entry point shortcut := 0; while (shortcut <= 10) and (FShortCuts[shortcut] <> nil) and - (CompareWorldItems(AItem, FShortCuts[shortcut]) <= 0) do + (CompareWorldItems(AItem, FShortCuts[shortcut]) >= 0) do begin current := FShortCuts[shortcut]; Inc(shortcut); diff --git a/Client/UfrmMain.lfm b/Client/UfrmMain.lfm index a634d80..81bc621 100644 --- a/Client/UfrmMain.lfm +++ b/Client/UfrmMain.lfm @@ -549,14 +549,14 @@ object frmMain: TfrmMain AnchorSideRight.Side = asrBottom AnchorSideBottom.Control = vdtTiles AnchorSideBottom.Side = asrBottom - Left = 114 + Left = 110 Height = 19 Hint = 'Append S or T to restrict the search to Statics or Terrain.' - Top = 283 + Top = 279 Width = 96 Anchors = [akRight, akBottom] - BorderSpacing.Right = 4 - BorderSpacing.Bottom = 4 + BorderSpacing.Right = 8 + BorderSpacing.Bottom = 8 CharCase = ecUppercase OnExit = edSearchIDExit OnKeyPress = edSearchIDKeyPress diff --git a/Client/UfrmMain.pas b/Client/UfrmMain.pas index e33ff23..0aad479 100644 --- a/Client/UfrmMain.pas +++ b/Client/UfrmMain.pas @@ -275,6 +275,7 @@ type FTextureManager: TLandTextureManager; FScreenBuffer: TScreenBuffer; FScreenBufferValid: Boolean; + FScreenBufferSorted: Boolean; FCurrentTile: TWorldItem; FSelectedTile: TWorldItem; FGhostTile: TWorldItem; @@ -296,6 +297,7 @@ type procedure InitRender; procedure InitSize; procedure InvalidateScreenBuffer; + procedure PrepareScreenBlock(ABlockInfo: PBlockInfo); procedure PrepareVirtualLayer(AWidth, AHeight: Word); procedure ProcessToolState; procedure ProcessAccessLevel; @@ -314,6 +316,9 @@ type { Events } procedure OnClientHandlingPacket(ABuffer: TEnhancedMemoryStream); procedure OnLandscapeChanged; + procedure OnStaticDeleted(AStaticItem: TStaticItem); + procedure OnStaticElevated(AStaticItem: TStaticItem); + procedure OnStaticInserted(AStaticItem: TStaticItem); procedure OnTileRemoved(ATile: TMulBlock); public { Fields } @@ -717,6 +722,10 @@ var begin FLandscape := ResMan.Landscape; FLandscape.OnChange := @OnLandscapeChanged; + FLandscape.OnStaticDeleted := @OnStaticDeleted; + FLandscape.OnStaticElevated := @OnStaticElevated; + FLandscape.OnStaticInserted := @OnStaticInserted; + FTextureManager := TLandTextureManager.Create; FScreenBuffer := TScreenBuffer.Create; FScreenBufferValid := False; @@ -1650,6 +1659,97 @@ begin FScreenBufferValid := False; end; +procedure TfrmMain.PrepareScreenBlock(ABlockInfo: PBlockInfo); +var + item: TWorldItem; + drawX, drawY: Single; + west, south, east: Single; + z: SmallInt; + staticItem: TStaticItem; + hue: THue; + staticTiledata: TStaticTiledata; +begin + //add normals to map tiles and materials where possible + + item := ABlockInfo^.Item; + + GetDrawOffset(item.X - FX, item.Y - FY, drawX, drawY); + + if acFlat.Checked then + z := 0 + else + z := item.Z; + + if item is TMapCell then + begin + if not acFlat.Checked then + begin + west := FLandscape.GetLandAlt(item.X, item.Y + 1, z); + south := FLandscape.GetLandAlt(item.X + 1, item.Y + 1, z); + east := FLandscape.GetLandAlt(item.X + 1, item.Y, z); + + if (west <> z) or (south <> z) or (east <> z) then + begin + ABlockInfo^.HighRes := FTextureManager.GetTexMaterial(item.TileID); + end; + end; + + ABlockInfo^.LowRes := FTextureManager.GetArtMaterial(item.TileID); + ABlockInfo^.ScreenRect := Bounds(Trunc(drawX - 22), Trunc(drawY - z * 4), 44, 44); + + if ABlockInfo^.HighRes <> nil then + begin + New(ABlockInfo^.Normals); + FLandscape.GetNormals(item.X, item.Y, ABlockInfo^.Normals^); + ABlockInfo^.DrawQuad[0][0] := drawX; + ABlockInfo^.DrawQuad[0][1] := drawY - z * 4; + ABlockInfo^.DrawQuad[1][0] := drawX + 22; + ABlockInfo^.DrawQuad[1][1] := drawY + 22 - east * 4; + ABlockInfo^.DrawQuad[2][0] := drawX; + ABlockInfo^.DrawQuad[2][1] := drawY + 44 - south * 4; + ABlockInfo^.DrawQuad[3][0] := drawX - 22; + ABlockInfo^.DrawQuad[3][1] := drawY + 22 - west * 4; + end else + begin + ABlockInfo^.DrawQuad[0][0] := drawX - 22; + ABlockInfo^.DrawQuad[0][1] := drawY - z * 4; + ABlockInfo^.DrawQuad[1][0] := drawX - 22 + ABlockInfo^.LowRes.Width; + ABlockInfo^.DrawQuad[1][1] := drawY - z * 4; + ABlockInfo^.DrawQuad[2][0] := drawX - 22 + ABlockInfo^.LowRes.Width; + ABlockInfo^.DrawQuad[2][1] := drawY + ABlockInfo^.LowRes.Height - z * 4; + ABlockInfo^.DrawQuad[3][0] := drawX - 22; + ABlockInfo^.DrawQuad[3][1] := drawY + ABlockInfo^.LowRes.Height - z * 4; + end; + end else + begin + staticItem := TStaticItem(item); + + staticTiledata := ResMan.Tiledata.StaticTiles[staticItem.TileID]; + if staticItem.Hue > 0 then + hue := ResMan.Hue.Hues[staticItem.Hue - 1] + else + hue := nil; + + ABlockInfo^.LowRes := FTextureManager.GetArtMaterial($4000 + staticItem.TileID, hue, (staticTileData.Flags and tdfPartialHue) = tdfPartialHue); + ABlockInfo^.ScreenRect := Bounds(Trunc(drawX - ABlockInfo^.LowRes.RealWidth / 2), + Trunc(drawY + 44 - ABlockInfo^.LowRes.RealHeight - z * 4), + ABlockInfo^.LowRes.RealWidth, + ABlockInfo^.LowRes.RealHeight); + + south := ABlockInfo^.LowRes.RealHeight; + east := ABlockInfo^.LowRes.RealWidth div 2; + + ABlockInfo^.DrawQuad[0][0] := drawX - east; + ABlockInfo^.DrawQuad[0][1] := drawY + 44 - south - z * 4; + ABlockInfo^.DrawQuad[1][0] := drawX - east + ABlockInfo^.LowRes.Width; + ABlockInfo^.DrawQuad[1][1] := drawY + 44 - south - z * 4; + ABlockInfo^.DrawQuad[2][0] := drawX - east + ABlockInfo^.LowRes.Width; + ABlockInfo^.DrawQuad[2][1] := drawY + 44 - south + ABlockInfo^.LowRes.Height - z * 4; + ABlockInfo^.DrawQuad[3][0] := drawX - east; + ABlockInfo^.DrawQuad[3][1] := drawY + 44 - south + ABlockInfo^.LowRes.Height - z * 4; + end; +end; + procedure TfrmMain.Render; var z: ShortInt; @@ -1670,6 +1770,12 @@ begin if not FScreenBufferValid then RebuildScreenBuffer; + + if not FScreenBufferSorted then + begin + FScreenBuffer.Sort; + FScreenBufferSorted := True; + end; {if acFilter.Checked then staticsFilter := @frmFilter.Filter @@ -1919,6 +2025,26 @@ begin UpdateCurrentTile; end; +procedure TfrmMain.OnStaticDeleted(AStaticItem: TStaticItem); +begin + FScreenBuffer.Delete(AStaticItem); +end; + +procedure TfrmMain.OnStaticElevated(AStaticItem: TStaticItem); +begin + FScreenBufferSorted := False; +end; + +procedure TfrmMain.OnStaticInserted(AStaticItem: TStaticItem); +begin + if (AStaticItem.X >= FX + FLowOffsetX) and (AStaticItem.X <= FX + FHighOffsetX) and + (AStaticItem.Y >= FY + FLowOffsetY) and (AStaticItem.Y <= FY + FHighOffsetY) then + begin + AStaticItem.PrioritySolver := FScreenBuffer.GetSerial; + PrepareScreenBlock(FScreenBuffer.Insert(AStaticItem)); + end; +end; + procedure TfrmMain.BuildTileList; var minID, maxID, i, lastID: Integer; @@ -2035,13 +2161,6 @@ end; procedure TfrmMain.RebuildScreenBuffer; var blockInfo: PBlockInfo; - item: TWorldItem; - drawX, drawY: Single; - west, south, east: Single; - z: SmallInt; - staticItem: TStaticItem; - hue: THue; - staticTiledata: TStaticTiledata; begin FDrawDistance := Trunc(Sqrt(oglGameWindow.Width * oglGameWindow.Width + oglGamewindow.Height * oglGamewindow.Height) / 44); @@ -2066,91 +2185,14 @@ begin acNoDraw.Checked, nil); //TODO : statics filter //TODO : ghost tile - //Pre-process the buffer - add normals to map tiles and materials where possible + //Pre-process the buffer blockInfo := nil; while FScreenBuffer.Iterate(blockInfo) do - begin - item := blockInfo^.Item; - - GetDrawOffset(item.X - FX, item.Y - FY, drawX, drawY); - - if acFlat.Checked then - z := 0 - else - z := item.Z; - - if item is TMapCell then - begin - if not acFlat.Checked then - begin - west := FLandscape.GetLandAlt(item.X, item.Y + 1, z); - south := FLandscape.GetLandAlt(item.X + 1, item.Y + 1, z); - east := FLandscape.GetLandAlt(item.X + 1, item.Y, z); - - if (west <> z) or (south <> z) or (east <> z) then - begin - blockInfo^.HighRes := FTextureManager.GetTexMaterial(item.TileID); - end; - end; - - blockInfo^.LowRes := FTextureManager.GetArtMaterial(item.TileID); - blockInfo^.ScreenRect := Bounds(Trunc(drawX - 22), Trunc(drawY - z * 4), 44, 44); - - if blockInfo^.HighRes <> nil then - begin - New(blockInfo^.Normals); - FLandscape.GetNormals(item.X, item.Y, blockInfo^.Normals^); - blockInfo^.DrawQuad[0][0] := drawX; - blockInfo^.DrawQuad[0][1] := drawY - z * 4; - blockInfo^.DrawQuad[1][0] := drawX + 22; - blockInfo^.DrawQuad[1][1] := drawY + 22 - east * 4; - blockInfo^.DrawQuad[2][0] := drawX; - blockInfo^.DrawQuad[2][1] := drawY + 44 - south * 4; - blockInfo^.DrawQuad[3][0] := drawX - 22; - blockInfo^.DrawQuad[3][1] := drawY + 22 - west * 4; - end else - begin - blockInfo^.DrawQuad[0][0] := drawX - 22; - blockInfo^.DrawQuad[0][1] := drawY - z * 4; - blockInfo^.DrawQuad[1][0] := drawX - 22 + blockInfo^.LowRes.Width; - blockInfo^.DrawQuad[1][1] := drawY - z * 4; - blockInfo^.DrawQuad[2][0] := drawX - 22 + blockInfo^.LowRes.Width; - blockInfo^.DrawQuad[2][1] := drawY + blockInfo^.LowRes.Height - z * 4; - blockInfo^.DrawQuad[3][0] := drawX - 22; - blockInfo^.DrawQuad[3][1] := drawY + blockInfo^.LowRes.Height - z * 4; - end; - end else - begin - staticItem := TStaticItem(item); - - staticTiledata := ResMan.Tiledata.StaticTiles[staticItem.TileID]; - if staticItem.Hue > 0 then - hue := ResMan.Hue.Hues[staticItem.Hue - 1] - else - hue := nil; - - blockInfo^.LowRes := FTextureManager.GetArtMaterial($4000 + staticItem.TileID, hue, (staticTileData.Flags and tdfPartialHue) = tdfPartialHue); - blockInfo^.ScreenRect := Bounds(Trunc(drawX - blockInfo^.LowRes.RealWidth / 2), - Trunc(drawY + 44 - blockInfo^.LowRes.RealHeight - z * 4), - blockInfo^.LowRes.RealWidth, - blockInfo^.LowRes.RealHeight); - - south := blockInfo^.LowRes.RealHeight; - east := blockInfo^.LowRes.RealWidth div 2; - - blockInfo^.DrawQuad[0][0] := drawX - east; - blockInfo^.DrawQuad[0][1] := drawY + 44 - south - z * 4; - blockInfo^.DrawQuad[1][0] := drawX - east + blockInfo^.LowRes.Width; - blockInfo^.DrawQuad[1][1] := drawY + 44 - south - z * 4; - blockInfo^.DrawQuad[2][0] := drawX - east + blockInfo^.LowRes.Width; - blockInfo^.DrawQuad[2][1] := drawY + 44 - south + blockInfo^.LowRes.Height - z * 4; - blockInfo^.DrawQuad[3][0] := drawX - east; - blockInfo^.DrawQuad[3][1] := drawY + 44 - south + blockInfo^.LowRes.Height - z * 4; - end; - end; + PrepareScreenBlock(blockInfo); FScreenBuffer.UpdateShortcuts; FScreenBufferValid := True; + FScreenBufferSorted := True; end; procedure TfrmMain.UpdateCurrentTile;