- Added Undo operation

This commit is contained in:
Andreas Schneider 2009-12-04 20:24:36 +01:00
parent 14ab47bdf8
commit 2fedab62cc
3 changed files with 504 additions and 364 deletions

View File

@ -21,7 +21,7 @@
* CDDL HEADER END
*
*
* Portions Copyright 2007 Andreas Schneider
* Portions Copyright 2009 Andreas Schneider
*)
unit UPackets;
@ -73,6 +73,13 @@ type
constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word);
end;
{ TStaticPacket }
TStaticPacket = class(TPacket)
protected
procedure WriteStaticItem(AStaticItem: TStaticItem);
end;
{ TInsertStaticPacket }
TInsertStaticPacket = class(TPacket)
@ -81,26 +88,32 @@ type
{ TDeleteStaticPacket }
TDeleteStaticPacket = class(TPacket)
TDeleteStaticPacket = class(TStaticPacket)
constructor Create(AStaticItem: TStaticItem);
end;
{ TElevateStaticPacket }
TElevateStaticPacket = class(TPacket)
TElevateStaticPacket = class(TStaticPacket)
constructor Create(AStaticItem: TStaticItem; ANewZ: ShortInt);
constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word; AHue: Word;
ANewZ: Word);
end;
{ TMoveStaticPacket }
TMoveStaticPacket = class(TPacket)
TMoveStaticPacket = class(TStaticPacket)
constructor Create(AStaticItem: TStaticItem; ANewX, ANewY: Word);
constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word; AHue: Word;
ANewX, ANewY: Word);
end;
{ THueStaticPacket }
THueStaticPacket = class(TPacket)
THueStaticPacket = class(TStaticPacket)
constructor Create(AStaticItem: TStaticItem; ANewHue: Word);
constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word; AHue: Word;
ANewHue: Word);
end;
{ TUpdateClientPosPacket }
@ -209,6 +222,17 @@ begin
FStream.WriteWord(ATileID);
end;
{ TStaticPacket }
procedure TStaticPacket.WriteStaticItem(AStaticItem: TStaticItem);
begin
FStream.WriteWord(AStaticItem.X);
FStream.WriteWord(AStaticItem.Y);
FStream.WriteShortInt(AStaticItem.Z);
FStream.WriteWord(AStaticItem.TileID);
FStream.WriteWord(AStaticItem.Hue);
end;
{ TInsertStaticPacket }
constructor TInsertStaticPacket.Create(AX, AY: Word; AZ: ShortInt;
@ -227,11 +251,7 @@ end;
constructor TDeleteStaticPacket.Create(AStaticItem: TStaticItem);
begin
inherited Create($08, 10);
FStream.WriteWord(AStaticItem.X);
FStream.WriteWord(AStaticItem.Y);
FStream.WriteShortInt(AStaticItem.Z);
FStream.WriteWord(AStaticItem.TileID);
FStream.WriteWord(AStaticItem.Hue);
WriteStaticItem(AStaticItem);
end;
{ TElevateStaticPacket }
@ -239,11 +259,19 @@ end;
constructor TElevateStaticPacket.Create(AStaticItem: TStaticItem; ANewZ: ShortInt);
begin
inherited Create($09, 11);
FStream.WriteWord(AStaticItem.X);
FStream.WriteWord(AStaticItem.Y);
FStream.WriteShortInt(AStaticItem.Z);
FStream.WriteWord(AStaticItem.TileID);
FStream.WriteWord(AStaticItem.Hue);
WriteStaticItem(AStaticItem);
FStream.WriteShortInt(ANewZ);
end;
constructor TElevateStaticPacket.Create(AX, AY: Word; AZ: ShortInt;
ATileID: Word; AHue: Word; ANewZ: Word);
begin
inherited Create($09, 11);
FStream.WriteWord(AX);
FStream.WriteWord(AY);
FStream.WriteShortInt(AZ);
FStream.WriteWord(ATileID);
FStream.WriteWord(AHue);
FStream.WriteShortInt(ANewZ);
end;
@ -253,11 +281,20 @@ constructor TMoveStaticPacket.Create(AStaticItem: TStaticItem; ANewX,
ANewY: Word);
begin
inherited Create($0A, 14);
FStream.WriteWord(AStaticItem.X);
FStream.WriteWord(AStaticItem.Y);
FStream.WriteShortInt(AStaticItem.Z);
FStream.WriteWord(AStaticItem.TileID);
FStream.WriteWord(AStaticItem.Hue);
WriteStaticItem(AStaticItem);
FStream.WriteWord(ANewX);
FStream.WriteWord(ANewY);
end;
constructor TMoveStaticPacket.Create(AX, AY: Word; AZ: ShortInt; ATileID: Word;
AHue: Word; ANewX, ANewY: Word);
begin
inherited Create($0A, 14);
FStream.WriteWord(AX);
FStream.WriteWord(AY);
FStream.WriteShortInt(AZ);
FStream.WriteWord(ATileID);
FStream.WriteWord(AHue);
FStream.WriteWord(ANewX);
FStream.WriteWord(ANewY);
end;
@ -267,11 +304,19 @@ end;
constructor THueStaticPacket.Create(AStaticItem: TStaticItem; ANewHue: Word);
begin
inherited Create($0B, 12);
FStream.WriteWord(AStaticItem.X);
FStream.WriteWord(AStaticItem.Y);
FStream.WriteShortInt(AStaticItem.Z);
FStream.WriteWord(AStaticItem.TileID);
FStream.WriteWord(AStaticItem.Hue);
WriteStaticItem(AStaticItem);
FStream.WriteWord(ANewHue);
end;
constructor THueStaticPacket.Create(AX, AY: Word; AZ: ShortInt; ATileID: Word;
AHue: Word; ANewHue: Word);
begin
inherited Create($0B, 12);
FStream.WriteWord(AX);
FStream.WriteWord(AY);
FStream.WriteShortInt(AZ);
FStream.WriteWord(ATileID);
FStream.WriteWord(AHue);
FStream.WriteWord(ANewHue);
end;

View File

@ -915,29 +915,29 @@ object frmMain: TfrmMain
ShowHint = True
Style = tbsCheck
end
object tbSeparator2: TToolButton
Left = 178
object tbSeparator3: TToolButton
Left = 209
Top = 2
Width = 15
Caption = 'tbSeparator2'
Width = 16
Caption = 'tbSeparator3'
Style = tbsDivider
end
object tbBoundaries: TToolButton
Left = 193
Left = 225
Top = 2
Action = acBoundaries
ParentShowHint = False
ShowHint = True
end
object tbSeparator3: TToolButton
Left = 262
object tbSeparator4: TToolButton
Left = 294
Top = 2
Width = 15
Caption = 'tbSeparator3'
Width = 17
Caption = 'tbSeparator4'
Style = tbsDivider
end
object tbTerrain: TToolButton
Left = 277
Left = 311
Hint = 'Show Terrain'
Top = 2
Caption = 'Terrain'
@ -949,7 +949,7 @@ object frmMain: TfrmMain
OnClick = tbTerrainClick
end
object tbStatics: TToolButton
Left = 300
Left = 334
Hint = 'Show Statics'
Top = 2
Caption = 'Statics'
@ -960,15 +960,15 @@ object frmMain: TfrmMain
Style = tbsCheck
OnClick = tbStaticsClick
end
object tbSeparator4: TToolButton
Left = 369
object tbSeparator5: TToolButton
Left = 403
Top = 2
Width = 15
Caption = 'tbSeparator4'
Width = 17
Caption = 'tbSeparator5'
Style = tbsDivider
end
object tbRadarMap: TToolButton
Left = 384
Left = 420
Hint = 'Radar Map'
Top = 2
Caption = 'Radar Map'
@ -978,29 +978,41 @@ object frmMain: TfrmMain
OnClick = tbRadarMapClick
end
object tbVirtualLayer: TToolButton
Left = 216
Left = 248
Top = 2
Action = acVirtualLayer
end
object tbFilter: TToolButton
Left = 239
Left = 271
Top = 2
Action = acFilter
Style = tbsCheck
OnMouseMove = tbFilterMouseMove
end
object tbFlat: TToolButton
Left = 346
Left = 380
Top = 2
Action = acFlat
Style = tbsCheck
end
object tbNoDraw: TToolButton
Left = 323
Left = 357
Top = 2
Action = acNoDraw
Style = tbsCheck
end
object tbSeparator2: TToolButton
Left = 178
Top = 2
Width = 8
Caption = 'tbSeparator2'
Style = tbsDivider
end
object tbUndo: TToolButton
Left = 186
Top = 2
Action = acUndo
end
end
object pnlChatHeader: TPanel
AnchorSideLeft.Control = pnlChat
@ -1419,7 +1431,7 @@ object frmMain: TfrmMain
left = 264
top = 32
Bitmap = {
4C69140000001000000010000000000000000000000000000000000000000000
4C69150000001000000010000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000D9A781FFD39E76FF00000000000000000000000000000000000000000000
0000000000000000000000000000ECBEA1FFE7BB9DFFE4B697FFE0B292FFDAAE
@ -2059,7 +2071,39 @@ object frmMain: TfrmMain
84FF94C7F9FF91C9F9FF4185C9FF256BACFFB7D9D4FFD4E2ECFFCFE5D6FFD5ED
D9FFD8EFDCFFD5EDD9FF616C63FF454D47FF5F6A61FF636F64FF646F64FF143F
56FF295F86FF4988BCFF4A86A7FF5D7070FF646F66FF646F66FF646F67FF646F
67FF647067FF616C63FF474E48FF
67FF647067FF616C63FF474E48FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0066C472FF64C270FF62BF
6EFF60BC6BFF5DB868FF5BB565FF58B162FD55AC5FEA52A85BB74FA358704B9F
541DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0064C170FFA6DBB0FFA6DA
AFFFA3D9ADFFA2D8ABFF9FD7A8FF9CD5A5FF94D09DFF83C58CFF6CB474FF4799
50B044944C39FFFFFF00FFFFFF00FFFFFF00FFFFFF0062BE6DFFA5DAAEFFA2D8
ACFFA1D8AAFF9ED6A7FF9CD5A5FF99D4A2FF97D29FFF8CCD95FF91CF99FF73B8
7BFF408F47B03C8A431DFFFFFF00FFFFFF00FFFFFF005FBA6AFF5CB667FF59B3
64FF56AE60FF53AA5DFF50A659FF4DA156FF68B170FF88C890FF8DCC95FF8BCB
92FF5DA564FF38853F70FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0046974E8F42924AE281C388FF7DC4
85FF6EB375FF357F3BB7FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003E8D458F64AB6BFF7FC4
86FF79BE81FF317A36EAFFFFFF00FFFFFF00FFFFFF00FFFFFF0052A85B034FA3
587BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003A87418F61A867FF7BC2
82FF76BC7CFF2D7532EAFFFFFF00FFFFFF00FFFFFF00FFFFFF004EA3579F4B9E
53D2FFFFFF00FFFFFF00FFFFFF00FFFFFF003A86408F36813CE275BB7BFF70BD
77FF63AB69FF2A702EB7FFFFFF00FFFFFF00FFFFFF004DA2569367B16FFF64AD
6BFF43944BFF408F47FF3C8A43FF398540FF549D5AFF74BA7AFF79C17FFF77BF
7DFF4A914FFF266B2B70FFFFFF00FFFFFF004DA1568A66B06EFF8ACA92FF89CA
90FF86C88DFF83C68AFF80C587FF7EC384FF7BC281FF6DBB74FF76BE7CFF59A0
5DFF266B2AB02367271DFFFFFF00FFFFFF00499C518462AC6AFF85C88DFF85C7
8BFF82C688FF7FC486FF7CC282FF79C180FF71B978FF5FA865FF49914EFF256A
2AB023662739FFFFFF00FFFFFF00FFFFFF00FFFFFF00429149905AA462FF58A1
5EFF37833EFF347E3AFF317A36FF2E7533FF2B712FEA286D2CB7256929702266
261DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003A87419C3782
3DD2FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0036813C03337D
3978FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00
}
end
object pmTileList: TPopupMenu
@ -2530,6 +2574,15 @@ object frmMain: TfrmMain
ImageIndex = 18
OnExecute = acNoDrawExecute
end
object acUndo: TAction
Category = 'Tools'
Caption = 'Undo'
Enabled = False
Hint = 'Undo last set of changes'
ImageIndex = 20
OnExecute = acUndoExecute
ShortCut = 16474
end
end
object tmGrabTileInfo: TTimer
Enabled = False

View File

@ -33,8 +33,8 @@ uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, Menus,
ComCtrls, OpenGLContext, GL, GLU, UGameResources, ULandscape, ExtCtrls,
StdCtrls, Spin, UEnums, VirtualTrees, Buttons, UMulBlock, UWorldItem, math,
LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList,
ImagingClasses, dateutils, UPlatformTypes, UMap;
LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList, fgl,
ImagingClasses, dateutils, UPlatformTypes, UMap, UPacket;
type
TAccessChangedListener = procedure(AAccessLevel: TAccessLevel) of object;
@ -42,6 +42,7 @@ type
TScreenBufferStates = set of TScreenBufferState;
TGhostTile = class(TStaticItem);
TPacketList = specialize TFPGObjectList<TPacket>;
{ TfrmMain }
@ -56,6 +57,7 @@ type
acFilter: TAction;
acFlat: TAction;
acNoDraw: TAction;
acUndo: TAction;
acVirtualLayer: TAction;
ActionList1: TActionList;
ApplicationProperties1: TApplicationProperties;
@ -128,11 +130,13 @@ type
tbFlat: TToolButton;
tbNoDraw: TToolButton;
tmTileHint: TTimer;
tbSeparator2: TToolButton;
tbUndo: TToolButton;
tsLocations: TTabSheet;
tbSetHue: TToolButton;
tmGrabTileInfo: TTimer;
tmMovement: TTimer;
tbSeparator4: TToolButton;
tbSeparator5: TToolButton;
tbRadarMap: TToolButton;
tbVirtualLayer: TToolButton;
tsClients: TTabSheet;
@ -144,9 +148,9 @@ type
tbMoveTile: TToolButton;
tbElevateTile: TToolButton;
tbDeleteTile: TToolButton;
tbSeparator2: TToolButton;
tbBoundaries: TToolButton;
tbSeparator3: TToolButton;
tbBoundaries: TToolButton;
tbSeparator4: TToolButton;
tbTerrain: TToolButton;
tbStatics: TToolButton;
tsTiles: TTabSheet;
@ -164,6 +168,7 @@ type
procedure acMoveExecute(Sender: TObject);
procedure acNoDrawExecute(Sender: TObject);
procedure acSelectExecute(Sender: TObject);
procedure acUndoExecute(Sender: TObject);
procedure acVirtualLayerExecute(Sender: TObject);
procedure ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
procedure btnAddLocationClick(Sender: TObject);
@ -288,6 +293,7 @@ type
FAccessChangedListeners: array of TAccessChangedListener;
FRepaintNeeded: Boolean;
FSelection: TRect;
FUndoList: TPacketList;
{ Methods }
procedure BuildTileList;
function ConfirmAction: Boolean;
@ -543,7 +549,7 @@ var
targetRect: TRect;
offsetX, offsetY: Integer;
tile: TWorldItem;
tileX, tileY: Word;
tileX, tileY, newX, newY: Word;
targetTiles: TWorldItemList;
targetTile: TWorldItem;
begin
@ -569,6 +575,7 @@ begin
if (not acSelect.Checked) and (targetTile <> nil) and (SelectedTile <> nil) then
begin
targetRect := GetSelectedRect;
FUndoList.Clear;
if (SelectedTile = targetTile) or ConfirmAction then
begin
@ -579,16 +586,23 @@ begin
begin
map := FLandscape.MapCell[tileX, tileY];
if map.IsGhost then
begin
FUndoList.Add(TDrawMapPacket.Create(tileX, tileY, map.RawZ,
map.RawTileID));
dmNetwork.Send(TDrawMapPacket.Create(tileX, tileY, map.Z,
map.TileID));
end;
end;
for i := 0 to FVirtualTiles.Count - 1 do
begin
tile := FVirtualTiles[i];
if tile is TGhostTile then
begin
dmNetwork.Send(TInsertStaticPacket.Create(tile.X, tile.Y, tile.Z,
tile.TileID, TGhostTile(tile).Hue));
FUndoList.Add(TDeleteStaticPacket.Create(TGhostTile(tile)));
end;
end;
end else if (SelectedTile <> targetTile) or targetTile.CanBeEdited then
begin
@ -623,9 +637,12 @@ begin
if tile is TStaticItem then
begin
newX := EnsureRange(tile.X + offsetX, 0, FLandscape.CellWidth - 1);
newY := EnsureRange(tile.Y + offsetY, 0, FLandscape.CellHeight - 1);
FUndoList.Add(TMoveStaticPacket.Create(newX, newY, tile.Z,
tile.TileID, TStaticItem(tile).Hue, tile.X, tile.Y));
dmNetwork.Send(TMoveStaticPacket.Create(TStaticItem(tile),
EnsureRange(tile.X + offsetX, 0, FLandscape.CellWidth - 1),
EnsureRange(tile.Y + offsetY, 0, FLandscape.CellHeight - 1)));
newX, newY));
end;
end;
end else if acElevate.Checked then //***** Elevate tile *****//
@ -644,10 +661,14 @@ begin
begin
if frmElevateSettings.cbRandomHeight.Checked then
Inc(z, Random(frmElevateSettings.seRandomHeight.Value));
dmNetwork.Send(TDrawMapPacket.Create(tile.X, tile.Y,
z, tile.TileID));
FUndoList.Add(TDrawMapPacket.Create(tile.X, tile.Y, tile.Z,
tile.TileID));
dmNetwork.Send(TDrawMapPacket.Create(tile.X, tile.Y, z,
tile.TileID));
end else
begin
FUndoList.Add(TElevateStaticPacket.Create(tile.X, tile.Y,
z, tile.TileID, TStaticItem(tile).Hue, tile.Z));
dmNetwork.Send(TElevateStaticPacket.Create(TStaticItem(tile), z));
end;
end;
@ -658,8 +679,12 @@ begin
tile := targetTiles.Items[i];
if tile is TStaticItem then
begin
FUndoList.Add(TInsertStaticPacket.Create(tile.X, tile.Y,
tile.Z, tile.TileID, TStaticItem(tile).Hue));
dmNetwork.Send(TDeleteStaticPacket.Create(TStaticItem(tile)));
end;
end;
end else if acHue.Checked then //***** Hue tile *****//
begin
for i := 0 to targetTiles.Count - 1 do
@ -669,6 +694,9 @@ begin
if (tile is TStaticItem) and
(TStaticItem(tile).Hue <> frmHueSettings.lbHue.ItemIndex) then
begin
FUndoList.Add(THueStaticPacket.Create(tile.X, tile.Y, tile.Z,
tile.TileID, frmHueSettings.lbHue.ItemIndex,
TStaticItem(tile).Hue));
dmNetwork.Send(THueStaticPacket.Create(TStaticItem(tile),
frmHueSettings.lbHue.ItemIndex));
end;
@ -680,6 +708,7 @@ begin
end;
end;
end;
acUndo.Enabled := FUndoList.Count > 0;
SelectedTile := nil;
FRepaintNeeded := True;
end;
@ -771,6 +800,7 @@ begin
virtualLayerGraphic.Free;
FVirtualTiles := TWorldItemList.Create(True);
FUndoList := TPacketList.Create(True);
FRandomPresetLocation := IncludeTrailingPathDelimiter(ExtractFilePath(
Application.ExeName)) + 'RandomPresets' + PathDelim;
@ -893,6 +923,19 @@ begin
ProcessToolState;
end;
procedure TfrmMain.acUndoExecute(Sender: TObject);
var
i: Integer;
begin
for i := FUndoList.Count - 1 downto 0 do
begin
dmNetwork.Send(FUndoList[i]);
FUndoList[i] := nil;
end;
FUndoList.Clear;
acUndo.Enabled := False;
end;
procedure TfrmMain.acVirtualLayerExecute(Sender: TObject);
begin
frmVirtualLayer.Show;
@ -1044,6 +1087,7 @@ begin
FreeAndNil(FOverlayUI);
FreeAndNil(FVLayerMaterial);
FreeAndNil(FVirtualTiles);
FreeAndNil(FUndoList);
RegisterPacketHandler($0C, nil);
end;
@ -2211,7 +2255,6 @@ begin
FLandscape.FillDrawList(FScreenBuffer, FX + FLowOffsetX, FY + FLowOffsetY,
FRangeX, FRangeY, tbTerrain.Down, tbStatics.Down, acNoDraw.Checked,
FVirtualTiles);
//TODO : ghost tile
//Pre-process the buffer
blockInfo := nil;
@ -2327,7 +2370,6 @@ procedure TfrmMain.UpdateSelection;
if tileInfo <> nil then
begin
//TODO Update Ghost Tile
if tileInfo^.ID < $4000 then
begin
cell := FLandscape.MapCell[AX, AY];