diff --git a/ChivalryServerLauncher.dpr b/ChivalryServerLauncher.dpr
index a1d972e..1e9d139 100644
--- a/ChivalryServerLauncher.dpr
+++ b/ChivalryServerLauncher.dpr
@@ -13,7 +13,8 @@ uses
Bindings.Converters in 'source\bindings\Bindings.Converters.pas',
Game.List in 'source\model\Game.List.pas',
Persist.GameList in 'source\persist\Persist.GameList.pas',
- Forms.Map in 'source\view\Forms.Map.pas' {MapForm};
+ Forms.Map in 'source\view\Forms.Map.pas' {MapForm},
+ Frame.MapPreview in 'source\view\Frame.MapPreview.pas' {MapPreviewFrame: TFrame};
{$R *.res}
diff --git a/ChivalryServerLauncher.dproj b/ChivalryServerLauncher.dproj
index 949299a..b0045fc 100644
--- a/ChivalryServerLauncher.dproj
+++ b/ChivalryServerLauncher.dproj
@@ -6,7 +6,7 @@
ChivalryServerLauncher.dpr
True
Build
- Win32
+ Win64
3
Application
@@ -99,6 +99,11 @@
+
+
+ dfm
+ TFrame
+
Base
diff --git a/assets/maps/AOCCTF-Frigid_p.jpg b/assets/maps/AOCCTF-Frigid_p.jpg
new file mode 100644
index 0000000..6188420
Binary files /dev/null and b/assets/maps/AOCCTF-Frigid_p.jpg differ
diff --git a/assets/maps/AOCCTF-Moor_p.jpg b/assets/maps/AOCCTF-Moor_p.jpg
new file mode 100644
index 0000000..86b8d13
Binary files /dev/null and b/assets/maps/AOCCTF-Moor_p.jpg differ
diff --git a/assets/maps/AOCCTF-Ruins_Large_P.jpg b/assets/maps/AOCCTF-Ruins_Large_P.jpg
new file mode 100644
index 0000000..39865ab
Binary files /dev/null and b/assets/maps/AOCCTF-Ruins_Large_P.jpg differ
diff --git a/assets/maps/AOCCTF-Ruins_P.jpg b/assets/maps/AOCCTF-Ruins_P.jpg
new file mode 100644
index 0000000..39865ab
Binary files /dev/null and b/assets/maps/AOCCTF-Ruins_P.jpg differ
diff --git a/assets/maps/AOCDuel-Arena_Flat_p.jpg b/assets/maps/AOCDuel-Arena_Flat_p.jpg
new file mode 100644
index 0000000..2981a0c
Binary files /dev/null and b/assets/maps/AOCDuel-Arena_Flat_p.jpg differ
diff --git a/assets/maps/AOCDuel-Arena_p.jpg b/assets/maps/AOCDuel-Arena_p.jpg
new file mode 100644
index 0000000..2981a0c
Binary files /dev/null and b/assets/maps/AOCDuel-Arena_p.jpg differ
diff --git a/assets/maps/AOCDuel-Bridge_p.jpg b/assets/maps/AOCDuel-Bridge_p.jpg
new file mode 100644
index 0000000..9183e19
Binary files /dev/null and b/assets/maps/AOCDuel-Bridge_p.jpg differ
diff --git a/assets/maps/AOCDuel-Cistern_p.jpg b/assets/maps/AOCDuel-Cistern_p.jpg
new file mode 100644
index 0000000..f33fd9a
Binary files /dev/null and b/assets/maps/AOCDuel-Cistern_p.jpg differ
diff --git a/assets/maps/AOCDuel-Courtyard_p.jpg b/assets/maps/AOCDuel-Courtyard_p.jpg
new file mode 100644
index 0000000..6fc606b
Binary files /dev/null and b/assets/maps/AOCDuel-Courtyard_p.jpg differ
diff --git a/assets/maps/AOCDuel-Dininghall_p.jpg b/assets/maps/AOCDuel-Dininghall_p.jpg
new file mode 100644
index 0000000..08ff463
Binary files /dev/null and b/assets/maps/AOCDuel-Dininghall_p.jpg differ
diff --git a/assets/maps/AOCDuel-FrostPeak_p.jpg b/assets/maps/AOCDuel-FrostPeak_p.jpg
new file mode 100644
index 0000000..3e3c4e6
Binary files /dev/null and b/assets/maps/AOCDuel-FrostPeak_p.jpg differ
diff --git a/assets/maps/AOCDuel-Mines_p.jpg b/assets/maps/AOCDuel-Mines_p.jpg
new file mode 100644
index 0000000..6cacc86
Binary files /dev/null and b/assets/maps/AOCDuel-Mines_p.jpg differ
diff --git a/assets/maps/AOCDuel-Shaft_p.jpg b/assets/maps/AOCDuel-Shaft_p.jpg
new file mode 100644
index 0000000..ab9765c
Binary files /dev/null and b/assets/maps/AOCDuel-Shaft_p.jpg differ
diff --git a/assets/maps/AOCDuel-Shipyard_p.jpg b/assets/maps/AOCDuel-Shipyard_p.jpg
new file mode 100644
index 0000000..c0693e8
Binary files /dev/null and b/assets/maps/AOCDuel-Shipyard_p.jpg differ
diff --git a/assets/maps/AOCDuel-ThroneRoom_p.jpg b/assets/maps/AOCDuel-ThroneRoom_p.jpg
new file mode 100644
index 0000000..7778712
Binary files /dev/null and b/assets/maps/AOCDuel-ThroneRoom_p.jpg differ
diff --git a/assets/maps/AOCDuel-Tower_p.jpg b/assets/maps/AOCDuel-Tower_p.jpg
new file mode 100644
index 0000000..c9d4a04
Binary files /dev/null and b/assets/maps/AOCDuel-Tower_p.jpg differ
diff --git a/assets/maps/AOCFFA-Arena3_p.jpg b/assets/maps/AOCFFA-Arena3_p.jpg
new file mode 100644
index 0000000..2981a0c
Binary files /dev/null and b/assets/maps/AOCFFA-Arena3_p.jpg differ
diff --git a/assets/maps/AOCFFA-Darkforest_Cistern_p.jpg b/assets/maps/AOCFFA-Darkforest_Cistern_p.jpg
new file mode 100644
index 0000000..b315959
Binary files /dev/null and b/assets/maps/AOCFFA-Darkforest_Cistern_p.jpg differ
diff --git a/assets/maps/AOCFFA-Darkforest_Valley_p.jpg b/assets/maps/AOCFFA-Darkforest_Valley_p.jpg
new file mode 100644
index 0000000..495e9ff
Binary files /dev/null and b/assets/maps/AOCFFA-Darkforest_Valley_p.jpg differ
diff --git a/assets/maps/AOCFFA-HillsidePyre_P.jpg b/assets/maps/AOCFFA-HillsidePyre_P.jpg
new file mode 100644
index 0000000..7f5f557
Binary files /dev/null and b/assets/maps/AOCFFA-HillsidePyre_P.jpg differ
diff --git a/assets/maps/AOCFFA-Hillside_P.jpg b/assets/maps/AOCFFA-Hillside_P.jpg
new file mode 100644
index 0000000..36b1fcd
Binary files /dev/null and b/assets/maps/AOCFFA-Hillside_P.jpg differ
diff --git a/assets/maps/AOCFFA-Moor_p.jpg b/assets/maps/AOCFFA-Moor_p.jpg
new file mode 100644
index 0000000..86b8d13
Binary files /dev/null and b/assets/maps/AOCFFA-Moor_p.jpg differ
diff --git a/assets/maps/AOCFFA-Ruins_P.jpg b/assets/maps/AOCFFA-Ruins_P.jpg
new file mode 100644
index 0000000..39865ab
Binary files /dev/null and b/assets/maps/AOCFFA-Ruins_P.jpg differ
diff --git a/assets/maps/AOCFFA-StoneshillVillage_P.jpg b/assets/maps/AOCFFA-StoneshillVillage_P.jpg
new file mode 100644
index 0000000..66c9af3
Binary files /dev/null and b/assets/maps/AOCFFA-StoneshillVillage_P.jpg differ
diff --git a/assets/maps/AOCFFA-ThroneRoomXL_P.jpg b/assets/maps/AOCFFA-ThroneRoomXL_P.jpg
new file mode 100644
index 0000000..7778712
Binary files /dev/null and b/assets/maps/AOCFFA-ThroneRoomXL_P.jpg differ
diff --git a/assets/maps/AOCKOTH-Arena3_p.jpg b/assets/maps/AOCKOTH-Arena3_p.jpg
new file mode 100644
index 0000000..2981a0c
Binary files /dev/null and b/assets/maps/AOCKOTH-Arena3_p.jpg differ
diff --git a/assets/maps/AOCKOTH-Darkforest_Valley_p.jpg b/assets/maps/AOCKOTH-Darkforest_Valley_p.jpg
new file mode 100644
index 0000000..495e9ff
Binary files /dev/null and b/assets/maps/AOCKOTH-Darkforest_Valley_p.jpg differ
diff --git a/assets/maps/AOCKOTH-Hillside_P.jpg b/assets/maps/AOCKOTH-Hillside_P.jpg
new file mode 100644
index 0000000..7f5f557
Binary files /dev/null and b/assets/maps/AOCKOTH-Hillside_P.jpg differ
diff --git a/assets/maps/AOCKOTH-Moor_p.jpg b/assets/maps/AOCKOTH-Moor_p.jpg
new file mode 100644
index 0000000..86b8d13
Binary files /dev/null and b/assets/maps/AOCKOTH-Moor_p.jpg differ
diff --git a/assets/maps/AOCLTS-Arena3_p.jpg b/assets/maps/AOCLTS-Arena3_p.jpg
new file mode 100644
index 0000000..2981a0c
Binary files /dev/null and b/assets/maps/AOCLTS-Arena3_p.jpg differ
diff --git a/assets/maps/AOCLTS-ArgonsWall_p.jpg b/assets/maps/AOCLTS-ArgonsWall_p.jpg
new file mode 100644
index 0000000..e419ed1
Binary files /dev/null and b/assets/maps/AOCLTS-ArgonsWall_p.jpg differ
diff --git a/assets/maps/AOCLTS-Battlegrounds_Farm_p.jpg b/assets/maps/AOCLTS-Battlegrounds_Farm_p.jpg
new file mode 100644
index 0000000..06534ec
Binary files /dev/null and b/assets/maps/AOCLTS-Battlegrounds_Farm_p.jpg differ
diff --git a/assets/maps/AOCLTS-Battlegrounds_p.jpg b/assets/maps/AOCLTS-Battlegrounds_p.jpg
new file mode 100644
index 0000000..7231226
Binary files /dev/null and b/assets/maps/AOCLTS-Battlegrounds_p.jpg differ
diff --git a/assets/maps/AOCLTS-Darkforest_Valley_p.jpg b/assets/maps/AOCLTS-Darkforest_Valley_p.jpg
new file mode 100644
index 0000000..495e9ff
Binary files /dev/null and b/assets/maps/AOCLTS-Darkforest_Valley_p.jpg differ
diff --git a/assets/maps/AOCLTS-Darkforest_XL_p.jpg b/assets/maps/AOCLTS-Darkforest_XL_p.jpg
new file mode 100644
index 0000000..e155320
Binary files /dev/null and b/assets/maps/AOCLTS-Darkforest_XL_p.jpg differ
diff --git a/assets/maps/AOCLTS-Frigid_p.jpg b/assets/maps/AOCLTS-Frigid_p.jpg
new file mode 100644
index 0000000..6188420
Binary files /dev/null and b/assets/maps/AOCLTS-Frigid_p.jpg differ
diff --git a/assets/maps/AOCLTS-HillsidePyre_P.jpg b/assets/maps/AOCLTS-HillsidePyre_P.jpg
new file mode 100644
index 0000000..7f5f557
Binary files /dev/null and b/assets/maps/AOCLTS-HillsidePyre_P.jpg differ
diff --git a/assets/maps/AOCLTS-Hillside_P.jpg b/assets/maps/AOCLTS-Hillside_P.jpg
new file mode 100644
index 0000000..36b1fcd
Binary files /dev/null and b/assets/maps/AOCLTS-Hillside_P.jpg differ
diff --git a/assets/maps/AOCLTS-Moor_Large_p.jpg b/assets/maps/AOCLTS-Moor_Large_p.jpg
new file mode 100644
index 0000000..86b8d13
Binary files /dev/null and b/assets/maps/AOCLTS-Moor_Large_p.jpg differ
diff --git a/assets/maps/AOCLTS-Moor_p.jpg b/assets/maps/AOCLTS-Moor_p.jpg
new file mode 100644
index 0000000..86b8d13
Binary files /dev/null and b/assets/maps/AOCLTS-Moor_p.jpg differ
diff --git a/assets/maps/AOCLTS-Ruins_Large_P.jpg b/assets/maps/AOCLTS-Ruins_Large_P.jpg
new file mode 100644
index 0000000..39865ab
Binary files /dev/null and b/assets/maps/AOCLTS-Ruins_Large_P.jpg differ
diff --git a/assets/maps/AOCLTS-Ruins_P.jpg b/assets/maps/AOCLTS-Ruins_P.jpg
new file mode 100644
index 0000000..39865ab
Binary files /dev/null and b/assets/maps/AOCLTS-Ruins_P.jpg differ
diff --git a/assets/maps/AOCLTS-StoneshillVillage_P.jpg b/assets/maps/AOCLTS-StoneshillVillage_P.jpg
new file mode 100644
index 0000000..66c9af3
Binary files /dev/null and b/assets/maps/AOCLTS-StoneshillVillage_P.jpg differ
diff --git a/assets/maps/AOCLTS-ThroneRoom_P.jpg b/assets/maps/AOCLTS-ThroneRoom_P.jpg
new file mode 100644
index 0000000..7778712
Binary files /dev/null and b/assets/maps/AOCLTS-ThroneRoom_P.jpg differ
diff --git a/assets/maps/AOCTD-ArgonsWall_p.jpg b/assets/maps/AOCTD-ArgonsWall_p.jpg
new file mode 100644
index 0000000..e419ed1
Binary files /dev/null and b/assets/maps/AOCTD-ArgonsWall_p.jpg differ
diff --git a/assets/maps/AOCTD-Battlegrounds_Farm_p.jpg b/assets/maps/AOCTD-Battlegrounds_Farm_p.jpg
new file mode 100644
index 0000000..06534ec
Binary files /dev/null and b/assets/maps/AOCTD-Battlegrounds_Farm_p.jpg differ
diff --git a/assets/maps/AOCTD-Battlegrounds_p.jpg b/assets/maps/AOCTD-Battlegrounds_p.jpg
new file mode 100644
index 0000000..7231226
Binary files /dev/null and b/assets/maps/AOCTD-Battlegrounds_p.jpg differ
diff --git a/assets/maps/AOCTD-Darkforest_Valley_p.jpg b/assets/maps/AOCTD-Darkforest_Valley_p.jpg
new file mode 100644
index 0000000..495e9ff
Binary files /dev/null and b/assets/maps/AOCTD-Darkforest_Valley_p.jpg differ
diff --git a/assets/maps/AOCTD-Darkforest_XL_p.jpg b/assets/maps/AOCTD-Darkforest_XL_p.jpg
new file mode 100644
index 0000000..e155320
Binary files /dev/null and b/assets/maps/AOCTD-Darkforest_XL_p.jpg differ
diff --git a/assets/maps/AOCTD-Frigid_p.jpg b/assets/maps/AOCTD-Frigid_p.jpg
new file mode 100644
index 0000000..6188420
Binary files /dev/null and b/assets/maps/AOCTD-Frigid_p.jpg differ
diff --git a/assets/maps/AOCTD-HillsidePyre_P.jpg b/assets/maps/AOCTD-HillsidePyre_P.jpg
new file mode 100644
index 0000000..7f5f557
Binary files /dev/null and b/assets/maps/AOCTD-HillsidePyre_P.jpg differ
diff --git a/assets/maps/AOCTD-Hillside_P.jpg b/assets/maps/AOCTD-Hillside_P.jpg
new file mode 100644
index 0000000..36b1fcd
Binary files /dev/null and b/assets/maps/AOCTD-Hillside_P.jpg differ
diff --git a/assets/maps/AOCTD-Moor_Large_p.jpg b/assets/maps/AOCTD-Moor_Large_p.jpg
new file mode 100644
index 0000000..86b8d13
Binary files /dev/null and b/assets/maps/AOCTD-Moor_Large_p.jpg differ
diff --git a/assets/maps/AOCTD-Moor_p.jpg b/assets/maps/AOCTD-Moor_p.jpg
new file mode 100644
index 0000000..86b8d13
Binary files /dev/null and b/assets/maps/AOCTD-Moor_p.jpg differ
diff --git a/assets/maps/AOCTD-Ruins_Large_P.jpg b/assets/maps/AOCTD-Ruins_Large_P.jpg
new file mode 100644
index 0000000..86b8d13
Binary files /dev/null and b/assets/maps/AOCTD-Ruins_Large_P.jpg differ
diff --git a/assets/maps/AOCTD-Ruins_P.jpg b/assets/maps/AOCTD-Ruins_P.jpg
new file mode 100644
index 0000000..39865ab
Binary files /dev/null and b/assets/maps/AOCTD-Ruins_P.jpg differ
diff --git a/assets/maps/AOCTD-StoneshillVillage_P.jpg b/assets/maps/AOCTD-StoneshillVillage_P.jpg
new file mode 100644
index 0000000..66c9af3
Binary files /dev/null and b/assets/maps/AOCTD-StoneshillVillage_P.jpg differ
diff --git a/assets/maps/AOCTD-ThroneRoom_P.jpg b/assets/maps/AOCTD-ThroneRoom_P.jpg
new file mode 100644
index 0000000..7778712
Binary files /dev/null and b/assets/maps/AOCTD-ThroneRoom_P.jpg differ
diff --git a/assets/maps/AOCTO-Battlegrounds_v3_P.jpg b/assets/maps/AOCTO-Battlegrounds_v3_P.jpg
new file mode 100644
index 0000000..06534ec
Binary files /dev/null and b/assets/maps/AOCTO-Battlegrounds_v3_P.jpg differ
diff --git a/assets/maps/AOCTO-Citadel_p.jpg b/assets/maps/AOCTO-Citadel_p.jpg
new file mode 100644
index 0000000..2e18959
Binary files /dev/null and b/assets/maps/AOCTO-Citadel_p.jpg differ
diff --git a/assets/maps/AOCTO-Darkforest_p.jpg b/assets/maps/AOCTO-Darkforest_p.jpg
new file mode 100644
index 0000000..4f2b9e8
Binary files /dev/null and b/assets/maps/AOCTO-Darkforest_p.jpg differ
diff --git a/assets/maps/AOCTO-Hillside_P.jpg b/assets/maps/AOCTO-Hillside_P.jpg
new file mode 100644
index 0000000..7f5f557
Binary files /dev/null and b/assets/maps/AOCTO-Hillside_P.jpg differ
diff --git a/assets/maps/AOCTO-Stoneshill_P.jpg b/assets/maps/AOCTO-Stoneshill_P.jpg
new file mode 100644
index 0000000..66c9af3
Binary files /dev/null and b/assets/maps/AOCTO-Stoneshill_P.jpg differ
diff --git a/resources/images/UnknownMap.jpg b/resources/images/UnknownMap.jpg
new file mode 100644
index 0000000..11b3934
Binary files /dev/null and b/resources/images/UnknownMap.jpg differ
diff --git a/resources/images/toolbar/active.png b/resources/images/toolbar/active.png
new file mode 100644
index 0000000..7da7a71
Binary files /dev/null and b/resources/images/toolbar/active.png differ
diff --git a/source/Resources.pas b/source/Resources.pas
index 7c67ffe..b861966 100644
--- a/source/Resources.pas
+++ b/source/Resources.pas
@@ -4,6 +4,8 @@ interface
const
AssetsPath = 'assets\';
AssetChivalryMedievalWarfareMapListFileName = 'Chivalry.MedievalWarfare.MapList.ini';
+ AssetMapPreviewPath = 'maps\';
+ AssetMapPreviewExtension = '.jpg';
UserDataPath = 'Chivalry Server Launcher\';
diff --git a/source/view/Forms.Main.dfm b/source/view/Forms.Main.dfm
index 1d257f3..24e0778 100644
--- a/source/view/Forms.Main.dfm
+++ b/source/view/Forms.Main.dfm
@@ -76,7 +76,7 @@ object MainForm: TMainForm
AlignWithMargins = True
Left = 8
Top = 30
- Width = 541
+ Width = 403
Height = 359
Margins.Left = 8
Margins.Top = 0
@@ -99,11 +99,12 @@ object MainForm: TMainForm
OnChange = vstMapListChange
OnDragOver = vstMapListDragOver
OnDragDrop = vstMapListDragDrop
+ OnFocusChanged = vstMapListFocusChanged
OnGetText = vstMapListGetText
Columns = <
item
Position = 0
- Width = 337
+ Width = 199
WideText = 'Map name'
end
item
@@ -161,6 +162,64 @@ object MainForm: TMainForm
AutoSize = True
end
end
+ object pnlMapListSidebar: TPanel
+ AlignWithMargins = True
+ Left = 419
+ Top = 30
+ Width = 130
+ Height = 359
+ Margins.Left = 0
+ Margins.Top = 0
+ Margins.Right = 8
+ Margins.Bottom = 8
+ Align = alRight
+ BevelOuter = bvNone
+ TabOrder = 2
+ ExplicitLeft = 415
+ inline frmMapPreview: TMapPreviewFrame
+ Left = 0
+ Top = 0
+ Width = 130
+ Height = 130
+ Align = alTop
+ TabOrder = 0
+ ExplicitTop = 216
+ end
+ object btnMapListSave: TButton
+ AlignWithMargins = True
+ Left = 0
+ Top = 171
+ Width = 130
+ Height = 25
+ Margins.Left = 0
+ Margins.Top = 8
+ Margins.Right = 0
+ Margins.Bottom = 0
+ Action = actMapListSave
+ Align = alTop
+ TabOrder = 2
+ ExplicitLeft = 28
+ ExplicitTop = 168
+ ExplicitWidth = 75
+ end
+ object btnMapListLoad: TButton
+ AlignWithMargins = True
+ Left = 0
+ Top = 138
+ Width = 130
+ Height = 25
+ Margins.Left = 0
+ Margins.Top = 8
+ Margins.Right = 0
+ Margins.Bottom = 0
+ Action = actMapListLoad
+ Align = alTop
+ TabOrder = 1
+ ExplicitLeft = 28
+ ExplicitTop = 168
+ ExplicitWidth = 75
+ end
+ end
end
object tsConfiguration: TTabSheet
Caption = 'Server - Configuration'
@@ -309,8 +368,10 @@ object MainForm: TMainForm
TabOrder = 1
TreeOptions.PaintOptions = [toHideFocusRect, toShowDropmark, toShowTreeLines, toThemeAware, toUseBlendedImages]
TreeOptions.SelectionOptions = [toFullRowSelect, toMiddleClickSelect, toRightClickSelect]
+ OnDblClick = vstGamesDblClick
OnFocusChanged = vstGamesFocusChanged
OnGetText = vstGamesGetText
+ OnPaintText = vstGamesPaintText
Columns = <
item
Position = 0
@@ -518,6 +579,20 @@ object MainForm: TMainForm
Action = actGameRemove
AutoSize = True
end
+ object tbGamesSep1: TToolButton
+ Left = 178
+ Top = 0
+ Width = 8
+ Caption = 'tbGamesSep1'
+ ImageIndex = 2
+ Style = tbsSeparator
+ end
+ object tbGameActive: TToolButton
+ Left = 186
+ Top = 0
+ Action = actGameActive
+ AutoSize = True
+ end
end
end
object tsAbout: TTabSheet
@@ -2260,6 +2335,121 @@ object MainForm: TMainForm
FDCBD5FEC029EF257802B99873F02768CFEC0000000049454E44AE426082}
PictureName = 'down'
end
+ object gcToolbaractive: TX2GraphicContainerItem
+ Picture.Data = {
+ 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000
+ 001008060000001FF3FF6100000B2769545874584D4C3A636F6D2E61646F6265
+ 2E786D7000000000003C3F787061636B657420626567696E3D22EFBBBF222069
+ 643D2257354D304D7043656869487A7265537A4E54637A6B633964223F3E0A3C
+ 783A786D706D65746120786D6C6E733A783D2261646F62653A6E733A6D657461
+ 2F2220783A786D70746B3D2241646F626520584D5020436F726520352E302D63
+ 3036302036312E3133343737372C20323031302F30322F31322D31373A33323A
+ 30302020202020202020223E0A203C7264663A52444620786D6C6E733A726466
+ 3D22687474703A2F2F7777772E77332E6F72672F313939392F30322F32322D72
+ 64662D73796E7461782D6E7323223E0A20203C7264663A446573637269707469
+ 6F6E207264663A61626F75743D22220A20202020786D6C6E733A70686F746F73
+ 686F703D22687474703A2F2F6E732E61646F62652E636F6D2F70686F746F7368
+ 6F702F312E302F220A20202020786D6C6E733A786D705269676874733D226874
+ 74703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F726967687473
+ 2F220A20202020786D6C6E733A786D703D22687474703A2F2F6E732E61646F62
+ 652E636F6D2F7861702F312E302F220A20202020786D6C6E733A786D704D4D3D
+ 22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E302F6D6D2F
+ 220A20202020786D6C6E733A73744576743D22687474703A2F2F6E732E61646F
+ 62652E636F6D2F7861702F312E302F73547970652F5265736F75726365457665
+ 6E7423220A20202020786D6C6E733A64633D22687474703A2F2F7075726C2E6F
+ 72672F64632F656C656D656E74732F312E312F220A20202020786D6C6E733A49
+ 70746334786D70436F72653D22687474703A2F2F697074632E6F72672F737464
+ 2F4970746334786D70436F72652F312E302F786D6C6E732F220A20202020786D
+ 6C6E733A706C75735F315F3D22687474703A2F2F6E732E757365706C75732E6F
+ 72672F6C64662F786D702F312E302F220A20202070686F746F73686F703A4865
+ 61646C696E653D225573657220696E74657266616365206D616B65207570220A
+ 202020786D705269676874733A4D61726B65643D2254727565220A202020786D
+ 703A4D65746164617461446174653D22323031312D30312D32355431333A3535
+ 3A31352B30313A3030220A202020786D704D4D3A496E7374616E636549443D22
+ 786D702E6969643A363135353933354138323238453031313938394343304131
+ 4144303242354332220A202020786D704D4D3A446F63756D656E7449443D2278
+ 6D702E6469643A30434645453044344530323745303131393839434330413141
+ 44303242354332220A202020786D704D4D3A4F726967696E616C446F63756D65
+ 6E7449443D22786D702E6469643A304346454530443445303237453031313938
+ 3943433041314144303242354332223E0A2020203C786D705269676874733A55
+ 736167655465726D733E0A202020203C7264663A416C743E0A20202020203C72
+ 64663A6C6920786D6C3A6C616E673D22782D64656661756C74223E4372656174
+ 69766520436F6D6D6F6E73204174747269627574696F6E2D4E6F6E436F6D6D65
+ 726369616C206C6963656E73653C2F7264663A6C693E0A202020203C2F726466
+ 3A416C743E0A2020203C2F786D705269676874733A55736167655465726D733E
+ 0A2020203C786D704D4D3A486973746F72793E0A202020203C7264663A536571
+ 3E0A20202020203C7264663A6C690A20202020202073744576743A616374696F
+ 6E3D227361766564220A20202020202073744576743A696E7374616E63654944
+ 3D22786D702E6969643A30434645453044344530323745303131393839434330
+ 41314144303242354332220A20202020202073744576743A7768656E3D223230
+ 31312D30312D32345431383A33393A30312B30313A3030220A20202020202073
+ 744576743A6368616E6765643D222F6D65746164617461222F3E0A2020202020
+ 3C7264663A6C690A20202020202073744576743A616374696F6E3D2273617665
+ 64220A20202020202073744576743A696E7374616E636549443D22786D702E69
+ 69643A3631353539333541383232384530313139383943433041314144303242
+ 354332220A20202020202073744576743A7768656E3D22323031312D30312D32
+ 355431333A35353A31352B30313A3030220A20202020202073744576743A6368
+ 616E6765643D222F6D65746164617461222F3E0A202020203C2F7264663A5365
+ 713E0A2020203C2F786D704D4D3A486973746F72793E0A2020203C64633A6372
+ 6561746F723E0A202020203C7264663A5365713E0A20202020203C7264663A6C
+ 693E47656E746C656661636520637573746F6D20746F6F6C6261722069636F6E
+ 732064657369676E3C2F7264663A6C693E0A202020203C2F7264663A5365713E
+ 0A2020203C2F64633A63726561746F723E0A2020203C64633A64657363726970
+ 74696F6E3E0A202020203C7264663A416C743E0A20202020203C7264663A6C69
+ 20786D6C3A6C616E673D22782D64656661756C74223E576972656672616D6520
+ 6D6F6E6F20746F6F6C6261722069636F6E733C2F7264663A6C693E0A20202020
+ 3C2F7264663A416C743E0A2020203C2F64633A6465736372697074696F6E3E0A
+ 2020203C64633A7375626A6563743E0A202020203C7264663A4261673E0A2020
+ 2020203C7264663A6C693E637573746F6D2069636F6E2064657369676E3C2F72
+ 64663A6C693E0A20202020203C7264663A6C693E746F6F6C6261722069636F6E
+ 733C2F7264663A6C693E0A20202020203C7264663A6C693E637573746F6D2069
+ 636F6E733C2F7264663A6C693E0A20202020203C7264663A6C693E696E746572
+ 666163652064657369676E3C2F7264663A6C693E0A20202020203C7264663A6C
+ 693E75692064657369676E3C2F7264663A6C693E0A20202020203C7264663A6C
+ 693E6775692064657369676E3C2F7264663A6C693E0A20202020203C7264663A
+ 6C693E7461736B6261722069636F6E733C2F7264663A6C693E0A202020203C2F
+ 7264663A4261673E0A2020203C2F64633A7375626A6563743E0A2020203C6463
+ 3A7269676874733E0A202020203C7264663A416C743E0A20202020203C726466
+ 3A6C6920786D6C3A6C616E673D22782D64656661756C74223E43726561746976
+ 6520436F6D6D6F6E73204174747269627574696F6E2D4E6F6E436F6D6D657263
+ 69616C206C6963656E73653C2F7264663A6C693E0A202020203C2F7264663A41
+ 6C743E0A2020203C2F64633A7269676874733E0A2020203C4970746334786D70
+ 436F72653A43726561746F72436F6E74616374496E666F0A2020202049707463
+ 34786D70436F72653A436955726C576F726B3D22687474703A2F2F7777772E67
+ 656E746C65666163652E636F6D222F3E0A2020203C706C75735F315F3A496D61
+ 676543726561746F723E0A202020203C7264663A5365713E0A20202020203C72
+ 64663A6C690A202020202020706C75735F315F3A496D61676543726561746F72
+ 4E616D653D2267656E746C65666163652E636F6D222F3E0A202020203C2F7264
+ 663A5365713E0A2020203C2F706C75735F315F3A496D61676543726561746F72
+ 3E0A2020203C706C75735F315F3A436F707972696768744F776E65723E0A2020
+ 20203C7264663A5365713E0A20202020203C7264663A6C690A20202020202070
+ 6C75735F315F3A436F707972696768744F776E65724E616D653D2267656E746C
+ 65666163652E636F6D222F3E0A202020203C2F7264663A5365713E0A2020203C
+ 2F706C75735F315F3A436F707972696768744F776E65723E0A20203C2F726466
+ 3A4465736372697074696F6E3E0A203C2F7264663A5244463E0A3C2F783A786D
+ 706D6574613E0A3C3F787061636B657420656E643D2272223F3E47D4B9E10000
+ 001974455874536F6674776172650041646F626520496D616765526561647971
+ C9653C0000003C74455874414C54546167005468697320697320746865206963
+ 6F6E2066726F6D2047656E746C65666163652E636F6D20667265652069636F6E
+ 73207365742E20D86BE8C40000004474455874436F7079726967687400437265
+ 617469766520436F6D6D6F6E73204174747269627574696F6E204E6F6E2D436F
+ 6D6D65726369616C204E6F2044657269766174697665737BDDB0A00000004569
+ 5458744465736372697074696F6E000000000054686973206973207468652069
+ 636F6E2066726F6D2047656E746C65666163652E636F6D20667265652069636F
+ 6E73207365742E20BC11F81A0000004869545874436F70797269676874000000
+ 0000437265617469766520436F6D6D6F6E73204174747269627574696F6E204E
+ 6F6E2D436F6D6D65726369616C204E6F2044657269766174697665735882CB05
+ 000001044944415478DA6364A0103092A3C9C0C040809191713F907981640374
+ 7575619A0D80F8034906686A6A823503B101C95E505555C5D00C048D28062829
+ 2981241DEEDDBB37014D1CD9D93070E0EEDDBB8E7003E4E4E40CA03608FCFFFF
+ 7FC2C3870F0BA1E2D86CFE00E42BDEBF7F1F120652525270CD30154043128178
+ 0316CD20E0F8E4C99303F030909090788FAC19C9900740710534E1C6E7CF9F37
+ A004A2A8A8E87C20954044581E78FDFAB523B2003C0C040505091902F6F7BB77
+ EF3E60350004F8F8F8F019E2F8E9D3A703E88218E9808B8B0B9B218DDFBE7D6B
+ C0662AD684C4C6C6866CC8815FBF7E3932E000385322333333C8900090BFFFFC
+ F9F3816403880500C19F5431B559EAF70000000049454E44AE426082}
+ PictureName = 'active'
+ end
end
object glToolbar: TX2GraphicList
Container = gcToolbar
@@ -2323,6 +2513,14 @@ object MainForm: TMainForm
ShortCut = 16424
OnExecute = actMapDownExecute
end
+ object actMapListLoad: TAction
+ Caption = '&Load map list'
+ Visible = False
+ end
+ object actMapListSave: TAction
+ Caption = 'Sa&ve map list'
+ Visible = False
+ end
end
object alGames: TActionList
Images = glToolbar
@@ -2341,5 +2539,11 @@ object MainForm: TMainForm
ShortCut = 16430
OnExecute = actGameRemoveExecute
end
+ object actGameActive: TAction
+ Caption = '&Set as active'
+ Enabled = False
+ ImageIndex = 4
+ OnExecute = actGameActiveExecute
+ end
end
end
diff --git a/source/view/Forms.Main.pas b/source/view/Forms.Main.pas
index 8184152..22f87f5 100644
--- a/source/view/Forms.Main.pas
+++ b/source/view/Forms.Main.pas
@@ -11,6 +11,8 @@ uses
Vcl.Controls,
Vcl.ExtCtrls,
Vcl.Forms,
+ Vcl.Graphics,
+ Vcl.Imaging.jpeg,
Vcl.Imaging.pngimage,
Vcl.ImgList,
Vcl.Mask,
@@ -29,6 +31,7 @@ uses
X2CLMenuBar,
X2CLmusikCubeMenuBarPainter,
+ Frame.MapPreview,
Game.Base,
Game.Intf;
@@ -121,6 +124,16 @@ type
alGames: TActionList;
actGameAdd: TAction;
actGameRemove: TAction;
+ pnlMapListSidebar: TPanel;
+ frmMapPreview: TMapPreviewFrame;
+ tbGamesSep1: TToolButton;
+ tbGameActive: TToolButton;
+ actGameActive: TAction;
+ gcToolbaractive: TX2GraphicContainerItem;
+ btnMapListSave: TButton;
+ btnMapListLoad: TButton;
+ actMapListLoad: TAction;
+ actMapListSave: TAction;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
@@ -132,22 +145,26 @@ type
procedure actCloseExecute(Sender: TObject);
procedure actGameAddExecute(Sender: TObject);
procedure actGameRemoveExecute(Sender: TObject);
+ procedure actGameActiveExecute(Sender: TObject);
procedure vstGamesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
+ procedure vstGamesPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType);
procedure vstGamesFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
+ procedure vstGamesDblClick(Sender: TObject);
procedure vstMapListGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
procedure vstMapListChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
procedure vstMapListDragOver(Sender: TBaseVirtualTree; Source: TObject; Shift: TShiftState; State: TDragState; Pt: TPoint; Mode: TDropMode; var Effect: Integer; var Accept: Boolean);
procedure vstMapListDragDrop(Sender: TBaseVirtualTree; Source: TObject; DataObject: IDataObject; Formats: TFormatArray; Shift: TShiftState; Pt: TPoint; var Effect: Integer; Mode: TDropMode);
+ procedure vstMapListFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
procedure actMapAddExecute(Sender: TObject);
procedure actMapRemoveExecute(Sender: TObject);
procedure actMapUpExecute(Sender: TObject);
procedure actMapDownExecute(Sender: TObject);
private type
TBindingExpressionList = TList;
- TPageMenuMap = TDictionary;
+ TPageMenuDictionary = TDictionary;
private
FActiveGame: TCustomGame;
- FPageMenuMap: TPageMenuMap;
+ FPageMenuMap: TPageMenuDictionary;
FUIBindings: TBindingExpressionList;
procedure SetActiveGame(const Value: TCustomGame);
@@ -171,7 +188,7 @@ type
procedure CopyMapSelection(ANodes: TNodeArray; ATargetIndex: Integer);
property ActiveGame: TCustomGame read FActiveGame write SetActiveGame;
- property PageMenuMap: TPageMenuMap read FPageMenuMap;
+ property PageMenuMap: TPageMenuDictionary read FPageMenuMap;
property UIBindings: TBindingExpressionList read FUIBindings;
end;
@@ -182,7 +199,6 @@ uses
System.Math,
System.StrUtils,
System.SysUtils,
- Vcl.Graphics,
Vcl.GraphUtil,
Vcl.Themes,
Winapi.ShellAPI,
@@ -236,7 +252,7 @@ var
begin
FUIBindings := TBindingExpressionList.Create;
- FPageMenuMap := TPageMenuMap.Create(pcMain.PageCount);
+ FPageMenuMap := TPageMenuDictionary.Create(pcMain.PageCount);
vstGames.NodeDataSize := SizeOf(TCustomGame);
@@ -441,12 +457,11 @@ var
sourceShift: Integer;
sourceIndex: Integer;
newIndex: Integer;
- newNode: PVirtualNode;
selectedMaps: TList;
map: TGameMap;
begin
- if (ATargetIndex < 0) or (ATargetIndex > vstMapList.RootNodeCount) then
+ if (ATargetIndex < 0) or (Cardinal(ATargetIndex) > vstMapList.RootNodeCount) then
exit;
if not Supports(ActiveGame, IGameMapList, gameMapList) then
@@ -629,6 +644,21 @@ begin
end;
+procedure TMainForm.actGameActiveExecute(Sender: TObject);
+begin
+ if Assigned(vstGames.FocusedNode) then
+ begin
+ vstGames.BeginUpdate;
+ try
+ ActiveGame := TGameList.Instance[vstGames.FocusedNode^.Index];
+ vstGames.InvalidateNode(vstGames.FocusedNode);
+ finally
+ vstGames.EndUpdate;
+ end;
+ end;
+end;
+
+
procedure TMainForm.vstGamesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
game: TCustomGame;
@@ -649,6 +679,13 @@ end;
procedure TMainForm.vstGamesFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
begin
actGameRemove.Enabled := Assigned(Sender.FocusedNode);
+ actGameActive.Enabled := Assigned(Sender.FocusedNode) and (ActiveGame <> TGameList.Instance[Sender.FocusedNode^.Index]);
+end;
+
+
+procedure TMainForm.vstGamesDblClick(Sender: TObject);
+begin
+ actGameActive.Execute;
end;
@@ -673,6 +710,13 @@ begin
end;
+procedure TMainForm.vstGamesPaintText(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType);
+begin
+ if (Column = GameColumnName) and (TGameList.Instance[Node^.Index] = ActiveGame) then
+ TargetCanvas.Font.Style := [fsBold];
+end;
+
+
procedure TMainForm.vstMapListChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
hasSelection: Boolean;
@@ -730,6 +774,18 @@ begin
end;
+procedure TMainForm.vstMapListFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
+var
+ gameMapList: IGameMapList;
+
+begin
+ if not Supports(ActiveGame, IGameMapList, gameMapList) then
+ exit;
+
+ frmMapPreview.Load(gameMapList.GetMapList[Node^.Index].Name);
+end;
+
+
procedure TMainForm.actMapAddExecute(Sender: TObject);
var
gameMapList: IGameMapList;
diff --git a/source/view/Forms.Map.dfm b/source/view/Forms.Map.dfm
index 12a6e85..df24f7f 100644
--- a/source/view/Forms.Map.dfm
+++ b/source/view/Forms.Map.dfm
@@ -32,8 +32,6 @@ object MapForm: TMapForm
AutoSize = True
BevelOuter = bvNone
TabOrder = 3
- ExplicitTop = 91
- ExplicitWidth = 503
object btnCancel: TButton
Left = 486
Top = 0
@@ -44,7 +42,6 @@ object MapForm: TMapForm
Caption = 'Cancel'
ModalResult = 2
TabOrder = 1
- ExplicitLeft = 428
end
object btnOK: TButton
AlignWithMargins = True
@@ -61,14 +58,13 @@ object MapForm: TMapForm
Default = True
TabOrder = 0
OnClick = btnOKClick
- ExplicitLeft = 345
end
end
object vstMap: TVirtualStringTree
AlignWithMargins = True
- Left = 8
+ Left = 154
Top = 37
- Width = 561
+ Width = 415
Height = 433
Margins.Left = 8
Margins.Top = 8
@@ -91,8 +87,8 @@ object MapForm: TMapForm
OnFocusChanging = vstMapFocusChanging
OnGetText = vstMapGetText
OnPaintText = vstMapPaintText
- ExplicitTop = 13
- ExplicitHeight = 457
+ ExplicitLeft = 8
+ ExplicitWidth = 561
Columns = <>
end
object pnlMapName: TPanel
@@ -109,27 +105,25 @@ object MapForm: TMapForm
AutoSize = True
BevelOuter = bvNone
TabOrder = 2
- ExplicitTop = 468
- ExplicitWidth = 689
+ ExplicitTop = 475
DesignSize = (
561
21)
object lblMapName: TLabel
- Left = 0
+ Left = 146
Top = 3
Width = 53
Height = 13
Caption = 'Map name:'
end
object edtMapName: TEdit
- Left = 76
+ Left = 216
Top = 0
- Width = 485
+ Width = 341
Height = 21
Anchors = [akLeft, akTop, akRight]
TabOrder = 0
OnChange = edtMapNameChange
- ExplicitWidth = 613
end
end
object pnlFilter: TPanel
@@ -146,26 +140,54 @@ object MapForm: TMapForm
AutoSize = True
BevelOuter = bvNone
TabOrder = 0
- ExplicitLeft = 12
- ExplicitTop = 482
DesignSize = (
561
21)
object lblFilter: TLabel
- Left = 0
+ Left = 146
Top = 3
Width = 28
Height = 13
Caption = 'Filter:'
end
object edtFilter: TEdit
- Left = 76
+ Left = 216
Top = 0
- Width = 485
+ Width = 345
Height = 21
Anchors = [akLeft, akTop, akRight]
TabOrder = 0
OnChange = edtFilterChange
end
end
+ object pnlMapPreview: TPanel
+ AlignWithMargins = True
+ Left = 8
+ Top = 29
+ Width = 130
+ Height = 449
+ Margins.Left = 8
+ Margins.Top = 0
+ Margins.Right = 8
+ Margins.Bottom = 0
+ Align = alLeft
+ BevelOuter = bvNone
+ TabOrder = 4
+ ExplicitLeft = 0
+ ExplicitHeight = 342
+ inline frmMapPreview: TMapPreviewFrame
+ AlignWithMargins = True
+ Left = 0
+ Top = 8
+ Width = 130
+ Height = 130
+ Margins.Left = 0
+ Margins.Top = 8
+ Margins.Right = 0
+ Margins.Bottom = 0
+ Align = alTop
+ TabOrder = 0
+ ExplicitWidth = 342
+ end
+ end
end
diff --git a/source/view/Forms.Map.pas b/source/view/Forms.Map.pas
index c8492cb..f5f5d68 100644
--- a/source/view/Forms.Map.pas
+++ b/source/view/Forms.Map.pas
@@ -11,6 +11,7 @@ uses
VirtualTrees,
+ Frame.MapPreview,
Game.Base,
Game.Intf;
@@ -27,6 +28,8 @@ type
pnlFilter: TPanel;
lblFilter: TLabel;
edtFilter: TEdit;
+ frmMapPreview: TMapPreviewFrame;
+ pnlMapPreview: TPanel;
procedure btnOKClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
@@ -177,7 +180,7 @@ begin
begin
nodeData := Sender.GetNodeData(Node);
- Abort := SameText(nodeData^.Name, AMapName);
+ Abort := (Sender.GetNodeLevel(Node) > 0) and SameText(nodeData^.Name, AMapName);
end,
nil);
end;
@@ -259,9 +262,13 @@ var
nodeData: PGameMap;
begin
+ if FLockMapChange then
+ exit;
+
if Assigned(Node) then
begin
nodeData := Sender.GetNodeData(Node);
+ frmMapPreview.Load(nodeData^.Name);
FLockMapChange := True;
try
@@ -269,7 +276,8 @@ begin
finally
FLockMapChange := False;
end;
- end;
+ end else
+ frmMapPreview.Clear;
end;
@@ -298,8 +306,6 @@ end;
procedure TMapForm.edtFilterChange(Sender: TObject);
var
node: PVirtualNode;
- filtered: Boolean;
- childNode: PVirtualNode;
begin
vstMap.BeginUpdate;
@@ -347,12 +353,22 @@ begin
exit;
node := FindMapNode(MapName);
- vstMap.FocusedNode := node;
+ FLockMapChange := True;
+ try
+ vstMap.FocusedNode := node;
+ finally
+ FLockMapChange := False;
+ end;
if Assigned(node) then
- vstMap.Selected[node] := True
- else
+ begin
+ vstMap.Selected[node] := True;
+ frmMapPreview.Load(MapName);
+ end else
+ begin
vstMap.ClearSelection;
+ frmMapPreview.Clear;
+ end;
end;
end.
diff --git a/source/view/Frame.MapPreview.dfm b/source/view/Frame.MapPreview.dfm
new file mode 100644
index 0000000..b476c4d
--- /dev/null
+++ b/source/view/Frame.MapPreview.dfm
@@ -0,0 +1,226 @@
+object MapPreviewFrame: TMapPreviewFrame
+ Left = 0
+ Top = 0
+ Width = 130
+ Height = 130
+ TabOrder = 0
+ object shpBorder: TShape
+ Left = 0
+ Top = 0
+ Width = 41
+ Height = 45
+ Brush.Style = bsClear
+ end
+ object imgMapPreview: TImage
+ AlignWithMargins = True
+ Left = 0
+ Top = 2
+ Width = 29
+ Height = 35
+ Margins.Left = 1
+ Margins.Top = 1
+ Margins.Right = 1
+ Margins.Bottom = 1
+ end
+ object gcMapPreview: TX2GraphicContainer
+ Left = 36
+ Top = 28
+ object gcMapPreviewUnknownMap: TX2GraphicContainerItem
+ Picture.Data = {
+ 0A544A504547496D616765FE170000FFD8FFE000104A46494600010200006400
+ 640000FFEC00114475636B79000100040000003C0000FFEE000E41646F626500
+ 64C000000001FFDB0084000604040405040605050609060506090B080606080B
+ 0C0A0A0B0A0A0C100C0C0C0C0C0C100C0E0F100F0E0C1313141413131C1B1B1B
+ 1C1F1F1F1F1F1F1F1F1F1F010707070D0C0D181010181A1511151A1F1F1F1F1F
+ 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F
+ 1F1F1F1F1F1F1F1F1F1F1F1FFFC00011080080008003011100021101031101FF
+ C400960000020301010101000000000000000000040502030607010008010003
+ 0101010000000000000000000000000102030405100002010204050203060404
+ 060300000001020311040021120531415113066122713214819142522307A162
+ 7215B1D1A233F0E1825324164393251100020202020201020603010000000000
+ 000111022103311241045161227181A1D14213C1F13214FFDA000C0301000211
+ 0311003F00ED897018568472CF2C60681313D79E002CEE807001EF72B960033B
+ E5F20B9BAD8B65198BEBE59AE17AC1663BCE0FC5828C26557CB346D73CF04927
+ 82E873C0079F5280E670C0F4DD57860020ECAEA4380C0F1073C0054B31321570
+ D2460575AFBA45A7A71907FAFF00AB00145C37E9A4A8EB25BCC3543321AA38F4
+ 3FE238E1318B669C8273C4B1823CC49C0050F70A1B4161AF8E9AE74F860012DF
+ F926DF0CE606726456D2C029A03EA7040CDB09472C5121313903D70488917A71
+ C21C14BDD3D72C861819AB7B8379E717770C6B16D36696A9E935CB77643F622A
+ 8C22BC1A15BB078E024935C823A530001CBBE6D504ED0DC5CAA3C67F522AD1F8
+ 034A1A71AE28200B77F37B7B6899ED2D7BBA464B9F01CEA0E2BF208FA8B7C7BF
+ 74B64DEEEFE80ABD96E2455209482B275ED38A6AF852B84D0441A0FEE1A4D41C
+ F911880299B75963EE5CC64998E72C24068671CFBA991D6393A10DD6B84CA4A7
+ 00936E3B5DEBB47B6BB7F7055D726D52652E9FCD139A0753CB81C1286E965966
+ 466F23DD1277D4153492A6165A53E35F757008452DC3872EB2307E0581209078
+ E78000DEEA38DBB8E9DE63511C6491A9E99027A0E2DE98A480ECD1DC2E9D6400
+ 0E6286B97F0C2242A3BA4640C0E4786003D370A700C1E4B8450598D154558F40
+ 38E09032FE1CEF36D32EE726526ED7335E67F919B4443FFAD0610EC3BEF95C04
+ 9E8B9D4CA09C8915C319CDBCB37B81BC867908D5292CAAD41AB56428BC864B9E
+ 1D6D2CD2D5846577ABF79AC97DC174E71E93EDA00A084E7A7E39E34821331725
+ FDC437B1CB6EE639223DE5753F294CF50E94C508FD07E31E4716F9B159EE4A40
+ 9278FF005D0705957DB201E9AB318C6CA010C8CC3AE2462BBEDCE1B6BA579A24
+ B9B67A06A10B346CBC1A3907BD48F8D30872E206EF6165E43145169FAC120290
+ 6E71E94B84D20B69B91906A01C4FFA789B488E0CB6EFE3DB0ED96324B79BF44D
+ 76A5CC56F6F0C926A08330CC40D27565D3D7A5FF005895CCC1CDFBA191D48A44
+ A86BA52BCEB9EA6E2C7EEC8622D82D1AD7DCE5625A39DF429A85D5450390A570
+ 84151F90DF22690D52465ED5C8D78E0005B9DDAEEE40EEBB871500AFB72FB298
+ 005FBE7906E56DB0DCDBC52306997E9E339125E73A06673FC584341516E77905
+ 9C5648C45AC312C2880014545D233030C4531DD5CC527761670FC0126BE87080
+ 23FBC6E0DF2C8F519F2FF2C0339DF9D3EE515D4D242FFA2CC090A2AE35D09666
+ 232CD820C6AAB0A415A5C099361DF2F6E36EB72422DF422E5535977589AA03CA
+ 175151974C45B6249B3A69A1B697C8AF79B09F6FBDEDC647B498A474AD482396
+ A15E58BD56EC8CF7D3A3835BFB71B8DFA7D4D9C3A1638C891C2B149351142420
+ CA869EE23D306C506299B57DC2F5AB491C7FD4719140524C5DBDC0173C4D73AF
+ 1AE0081AEDBB95D78FECDB86F4B04D3349118A04B70ACE8AAEA5EE1A37203C62
+ 9A39E67962E9F526C739DE7F750CD0B496E23BA765096AECA62ED95C8892225A
+ B4EA2953D78E36215449E3F16E70EF506E3B8DD04B670657FD45479514E97489
+ 4F2AE55A6919F4C2BA2D283A5770E922B91CC8E47190065A4EAD1E80DEF5AF1A
+ D6989605C4B5695A9A65C700186FDC2B8DD967B78E1940B48D45CB0506AA626F
+ 9DBEDA05C125246C2D6E52EACE1B946AA4E8197222B97BA80D381C1022F0A436
+ 469E984324132143E87AE10408BC966DAB6D4B896E57BD737B069168481A97F3
+ B7E5E1C79D31D7AB43B2978A89B484B26F7BB6FF00696CDB5DDC5B742BA61DDE
+ 58C0371098FF00183505D5940A0E472C716CD54D567E53E3F63D4D5B2FBAA926
+ AB1CFCFE2663CB277EFDB8794BCD45323380A5F4823569CBAE35F5961FC1C9EE
+ 3FB9006DF3DD43325E5BCC62B8473A241E9CBD6BCC63A4E33F477835EF85DD78
+ DD8EE0DB73DFEFB7A5A35B520CAA93A00194443222A75660E58E7D50DB4F94FF
+ 00D1774F0D703F9FFB5C3215BE82DEF7730A08DBE1822ECC6D4A524655F730AF
+ C8A7EDC5DACB84895530FF00B89FB85B6EDBB7CD6770EB717C47B582A0EC05F9
+ 6381402A8BC9D6946191CB109365A38B78C596D3BCEEB7326E10089A5025B785
+ 18A067D5EEA0AD68472C696C2279635BFB8DB368DFDA0BCB60DB5B592430A1AD
+ 5523058AA356AA5E4515233E3D7129F6592B8CA35C182398C9F683442321F0FF
+ 002C41321566F4B85E86A08C024342D55A624A02B09D22BBDD6EDA40972EB0D9
+ D93269D4A151A4929A87E661C317526D2F839F4FBFDDA6F306E8F7125E5D2369
+ 91E5919F50AE961A8F0071AB52A0CD383A4DA9B9BAB05BC36D25BAB00C5641C2
+ BC0D7983C8E30B55A374E4AF77DE2DB68DA9EF6450F293DBB583FEE4C46429D1
+ 466D8E8F574F772F840DC2167EDBFEDD9F3DDCAFB7ADFEF5ADFC6ACE5297B78D
+ 20592E660A0BC11BF0545AFBD87F48C746DDCDE0CA4EF7796DFB59FB77E2ADBA
+ C3B6D9596DB047AE378A247964A81401DAB23B364055B1C5B76250B96F82A8AC
+ DCF107E72F2AF30F38F30B99B708DE1D836E9AA6DEC6DA18FEA3B35A069A6214
+ FBBE3C780C4D742E6D97FA1A777E04167E1BE5B721A54432C318265BCB955458
+ CE927F526A22AFA6ACF1BAAFC19B66D7C73CA67B48E5D8B646B7DA377B901847
+ 11FD1DCE254F7ADB4F255E3B939FB75057E191A0C677AE64AAD97923E4FF00B8
+ 76365B505DB1B4BB2D0CA6A26561F3AB039A904612A8D1CB6C2DFF00F60DCCCF
+ 7F70B05BB12503B2AD7A91A881974E672C6B104B723EDF6CB61B3065B79D6D6D
+ 56047B1B47AC97371213473A57D88A0FE266E55184A405FE77B84286CF65497E
+ A05A5B24B3DDB68677BA94565456503F4E1A76C2826A6AD9E54210D3375133CD
+ 3767B2E5E4A05A0E7D6A787DB8C59290E61DA6DD5EDE2BC9985CAC940915349A
+ 91EE2DF8A9D073C64B726F069D20023BDB749AF6F267D11290B56340401C33E6
+ 71A3252236304D75B4C093A069AE58DC48BFCCC4D474F90D3ECC55536E113669
+ 297C1969B6B822BD91EE9219222E585AABB301FD6E85450F456C7A7ABD36D7DD
+ 8382FECAFE26B22F2E85A35BDB701248008E4B634A14A50C7C335651C71E7EED
+ 2F5DA19DDAB62B2931FE77BE8BBDCC5BDAFF00B4891259961987B865F77C403F
+ C31D557D3514F2CDC6F092ED9B75A6D16EC536ADB2358D554FB10FCCF23D0FCC
+ CC6AC71C5DFED4CD69AE6D00BFB97B84177BA788ED0F72D7BB44A62B99955AA1
+ D54572AF2049C61A6DDF6DADF185FE4AD95E9555FA8C2E6EB63315BDC42EB1A9
+ 4866B80E3585FAA790811915CE0B740003CEA698EB325C4B2CB38B70DFAFEF21
+ BE67B4D8E1731436CBA8C5028CE3A2FE32C0D589CCE2E3E0C6D7C2C193F3ADAF
+ 69DAECE4B59144B0D6A91A3668C335B8B793967CB125239ADDDD497772B35FB1
+ 9D541EF4CA4AB4FA05416AD4770E41A9F1C34A0AE40E4DD25770248C30A69444
+ 14007200618B80799A682E2B28789B22A1C153A788C9A996043B391BDEEE36B7
+ D16A9214ABB771580A1576A6B4A8E03F2FA614049DB6430EDD03A40C1EFA4D22
+ 590E6AA9C5D1473AF0AE381DD5B9E0D556047B96E42CEC9AECD5A504456B12D6
+ BA883EE006748CD3EDC3D549616643C37C5EEBC86C778B437B1DAA5BF6E6B8B9
+ 948114606AD45DC9D2B97F1C6BB2B94D934BC2690BBCBF7ED967BB6DBFC7A792
+ 6DB2CD16292FC9A2CB30AD5A15C8E80294EB8BAA6B2438664EE3739F456A42B5
+ 54BF2AD3865C33C7A74F6257D4E1B698651B7EE724770BA891A805901AE32DCB
+ B2FA9A6B7D596F94CEC6E24746E0D0C8AC3AE83983E86985B14D57E47549ACB1
+ F35BBDE76A92CE0922FACB8005DDA3A80ED5203988F30C33EA31E6DAAEAA3C1D
+ DA7655D93FE480B78DE66B6DA7C7B768CF7A6D86E64B29108A512BAD55B9E618
+ E1685176BE507B89E19E5C79578FDCD8CD00D7190804601E26363A7A71B790AF
+ F50F5C75C338938348BFB89B74FB0D9CB6737FFAB656E963770643BF1C22914D
+ 97E2D3C6BCEBD70CCFAE4C1EF5BBDC6EEAC1EAC03160D50029E3424D07D98703
+ 33B757D3CF1456CCFF00F8F6E4F6A3000153C5B21EE27A9C0CBAA41DE313CF6F
+ 7CD736E81E6B7469550D3DCABF3AE7D56B9E161E194745867DB775B68EED523B
+ 889B34322AB15EAA6A0D08E78E7B55D5C153251B9EDD65B847DBBA855C7E1651
+ A597A6923055B42793413C9042CCF348B2B7E18D0EA04FF330E0B8CABABE46EC
+ 6637CD9E7BEBB4BE865D13434D31162B180331A78E9A7F1C7456119D9499BBE6
+ DC2DECEE6C3B9DFB59D83CF142E4C5A92B42C0501209C5369B252842DB69DE3B
+ A86794095A2D234BA8D1EDE45464700076E096D797373F4E163EEB1784466888
+ 4FE0653CBD460AB879075958141B3BF8641DE8FB47504899B3D6B4E2295AD3A8
+ C7552D2F0616AC7214D21B98FE8A5986B8D4D6A6829C88FE938D1A4D43E4BD76
+ 94266592294A31D2EBC194F03C98118E5B5630CDAAF21ADE41B95E5BFD2DFDD3
+ C912B0660E6AC4A0A0AB7CC69CAB885AAA9CA592AD7B3505316D9AE3EF16D05D
+ AA8AD9D13AE077CC1BD7D67D3B371FB0FE0F0BDF62B18EFF00E8DFB6C3B8B22B
+ A8744A5753AEAD4829D463AE8F5F0DE4F3EF5BF2B8135CA770025CE9E22BC2A7
+ 9E34B694B833AEC6F92A86DD58BD7DE545550102A4E55CF90C617AC1B55C85EC
+ 327D2EEF01724062503A30E2C34D6B9F5C569D74B5A2C16BD92C05EC9BC4BB2E
+ E52DBCB536C5B45C47CC53838F5A7F0C46DD732BCA2EB637A1D248D64460D1B0
+ 0C8C0F1073046389A8340A2187E1FB30E44299B679E59E48AE2F266B59486088
+ 400B4FC26B5CBA5300CF6D364B3FA7B8EC23160E52135258E9C8FDED5C26C685
+ 3BD6C315B48238DD5DCD05141F99B9660660E58BAF67E09B42F278FE256EB704
+ CDB942AB9552206490310091F8538E5C71D5AFD4B3E5A4725FDB4B84D8D6CDB6
+ C8626B4B9B75BDB6D2000F93AF1A90D90E7E98DD7AD0B0CC9FB12F28164F12DB
+ EE6368BC7675B3BB946705FA90CC3A248726F41538E478B7393A6B6C0877AF1A
+ B9B08DA2BEB59639D4829352894E74E35CF9571BAFBD7D4A56467D60114C0CB1
+ 8627E56E469CF1CF7AB474EAB29C87C12BB48920A12A43134A83A4D40A1E23AE
+ 34F5B44BC8BDBF67ED8513E4EA3B56ECF716A2669FB9752B19C4674831AB50E8
+ C801A54D6831CEE2610DD2CB2C4973B5ED5B5B5FEED71A4AC8ECF1A950562591
+ B2445E6C6BC7A6367B2D64AA62AAAB2C41BFDC779076A18E609FEE23282DA48A
+ 82ACB9E5E871351D8CFDBA8B9BC862B642819C00356B6A923870FB31B56CAAE5
+ B23ABB2C20BF2082F26BB8B714B578D6F0307A0F6168CD2BAB87C856A7EDC2D9
+ B55EEECBC82A3AAC8D7C5B7CED536CB8208D47E95EB9024E695E84FCBEB88D94
+ 9528B4CD74B3CA57E7231CC515C4659251ADD80E25893C067C05700065DDEDBE
+ DD6EA9B7B16908ACD7272219B36544FC39F3E78D35D97E66774CCA5E6E0EC68F
+ 21A961427AD78E359220A2293719AE9A288FCB5008190CF9B540181FB2D13FF9
+ D0EAC36786202EAEE532C8BEE50C498C1072A0CABFE18E7BEEB5BC9B57556A7D
+ 7F7B2DECDD9894BC60FB47520F1385550361C9B9EF7B66DCBDD912EE163A65B2
+ B8A4A9A07A1A95AFA1C6B5B4325D4CD5F45617DAFF00B65A88269583FD23FEA0
+ 565AE7139F7019F06FE38E95B13E494FC00EED65042F1CD6209866501E0D2C1E
+ 298002442385351AAD0F0C6DB3656BE605AF4DACFF00E5DBF00DD9B76DC20416
+ F2DBBB4714652D108D059F59246B6229F363877EDD5329E4ECD1EAEF756BAFDA
+ 886E335C6E96EED732C51450316FA712333160429AD000280F138CE9BD6624D3
+ 6FA56ABAD6ED2EC67CA42CB495CBB2D5638D6A7DBF1E43155D9662DBA7553CF6
+ 642CEE13EB232B1232A9F6A3E51E5CDF864302A322FEC2784A17D061B9DE2DFB
+ 06D2CF3B4548C70AC701D1A634F957D895514E54C5A5073D9C8ADD9CC71B23AB
+ C6C7D8CAAA8E08FCC00AFDB8BAB11D42589C674200CEBE98E5342FBF961AC734
+ 602EB51901D000460013EE4804CAF1966130A54E4A70AAC76A8A67DB58A991DC
+ 328398420B53A915C6BDCCFA109BBC205785DE349541201E9D71112506DB4777
+ 785565B83DA5A51304407269ECB6FB44D28A8BA40CE435D4C70041ECDB7BCCCC
+ 2422385797518A101C496DB73B7D3C40B36465A7BB0810CADFC7B66BBB7EF6F6
+ D208A6632C691921CE8CAA0A826AE7DB5E58E9D15D6D7DF9F833D9B7755AFEB7
+ 1F26377CD9B6A82213DABC9148C4F72D64677D22B97BC85271AEBD3ADD67ED4F
+ E0D2FEC6CED136B2F991118622AD414047004E78E95AA9E2A8E377B666CC1661
+ 2339A926BC470AFDD8CEDAAA82B76CA9ACE53908CFDD8869169845B595EBDCC0
+ 429530D3B6FC34D093CFD4E31BA46B56C732ED090C7AF40D4FEF60A28BC73A63
+ 328E81BA4448EE22D0380C0FC78FFAAB8E646A2093BD2445548FD36D555CFDAD
+ 91E3EA06181F4D692B595B99413A5DB8E555E35EBCF12B91BE0B06CD0BC46A34
+ 92A4A83EB8A102DC6D8E9046AA0D14675E3CF218689637DAB68096E24A740C48
+ CB031A1A2C49150FE203DA0600069DD9D73CC13EEC007D67B7FD4DE450A2336A
+ 6150295A7127A6430E4502ADEB72BA6DC24B5BB7580C474C49ED7D207CA63202
+ 8A7F49C5D5A6B038EAF280771113ABA349A52404AA00C40195391652748A9634
+ 15A629DA055A37C09E5DADFEA342839B67D00A654E071D7A7D88C5B839B6699C
+ A26F650C6725A11954F3C696B499AAC124B676CE807318E7B5D266CA85D6B118
+ CEA26B21F9428AD3E38CAD692EB580AB58DAE64313305241D3239E0FF841A753
+ 9626419B178068ACC866543511D74E4DFF003C61E4D00A18AE04F218610BAD29
+ A5BDF9A9D438FC303433E8ACEEA79EB39153D797DF81206C6325BA12230C2A07
+ B9CE1C08AE68632B41EE0052A39E1814C3298D0A6607155198AE0802B3216933
+ 6F5CB2C012418716AE75CC939E0035BE1FE37F55B56E5E437F2B5B6DBB7C6CB1
+ 846ED99E623FDBD441AA8A8A8E6683AE2E954F9E08BDDAE393984BBDF665B887
+ 72B21716F348599C7B250782D1865ED1C294C66F5F958365B3E720DB7FD5EE92
+ CC96B3C5226605BCEFA6720B56ACECB4734F5C5BBC724AACF032B2B2BF86E0C0
+ E8CB712921548550753534EAA8AEAA0C8138A4D325A28695096D542A1B4B7407
+ 9AF2197A61881A76662597E4047B72140295AE5CF0002B4EC5989CCF251C3EE1
+ 8045667951F5834AFCC38570B919AFB1DEE7B862EDDF8A1CE8C238D55B97CD21
+ 27EE182B45E57EA4BB075A5C2B5D2D6E649119823950958DC9A2F11EE15F9B86
+ 587B2A9295C0AB67C17C7796FAA44635742470E5D798C2BD7AB2EAE51169A06A
+ 9D401F5E189191377181426A47003860022D7259288748E9800188766000A9AF
+ 1E784036F1ED91770BCED4EE63B6895A7B97500B08D3885FE63C061A426E02F7
+ FF00269B71B2FF00D6F6F31EDD6B0256CA2622550C4D4195E9ED766E75A75C52
+ 6B8074B25D8E793C61BBA9B9C220BF8AB1491D280953C704647DB102431A4555
+ 8720714405C1BD5FDAC5DBEEF720FF00B12FBD7EE3C3ECC4BAA652B344937AB5
+ 932689E1A1A858C8295E15A30C10C3B22335DA4B42935686A15D0104F5391A9C
+ 0A41C114914255AACDCF2FF8182184A0AB5D96496237338283FF008D1B8D3AD3
+ 0C4378AE15D241313AC37CDE98724C14DBEE6B6979ADDEA1482A78D40CC540C2
+ B6502E4B9EFDADE1495894797F535AB7B82E6B4A0FBF11B5F665D705716FA65D
+ 21E31293C5ABA5ABF6647EEC4650E46D1BC6D10700807911420E1D6D2104B557
+ E38A024AE56B415AE001C307DB36492F4B9B892FD15161B270F2470337EAB4AA
+ 3DCA4659606B025C9F5EEE3E316BB32A58BC72A32E954419B659892B43F1AE2E
+ 17825DACDCB394F926E0935C17EF1330F6A393C053253D74F2C34025DAEF374B
+ ABA10449DE7A3108054FB454F0C0C0314DC4CF49A178645F991C11F75700406D
+ BEDF7327FB30B37F3532FBF8614840C6DFC767908371208D3F2266C7EDE030BB
+ 0E03A5B74B19E37887FE31A2B026BA4F0AFF00D58246696DADE19EDE311A879A
+ 5A88A3390A8E2CDE830107FFD9}
+ PictureName = 'UnknownMap'
+ end
+ end
+end
diff --git a/source/view/Frame.MapPreview.pas b/source/view/Frame.MapPreview.pas
new file mode 100644
index 0000000..c890e4a
--- /dev/null
+++ b/source/view/Frame.MapPreview.pas
@@ -0,0 +1,96 @@
+unit Frame.MapPreview;
+
+interface
+uses
+ System.Classes,
+ Vcl.Controls,
+ Vcl.Dialogs,
+ Vcl.ExtCtrls,
+ Vcl.Forms,
+ Vcl.Imaging.jpeg,
+
+ X2CLGraphicList;
+
+
+type
+ TMapPreviewFrame = class(TFrame)
+ shpBorder: TShape;
+ imgMapPreview: TImage;
+ gcMapPreview: TX2GraphicContainer;
+ gcMapPreviewUnknownMap: TX2GraphicContainerItem;
+ public
+ constructor Create(AOwner: TComponent); override;
+
+ procedure Clear;
+ procedure Load(const AMapName: string);
+ end;
+
+
+implementation
+uses
+ System.SysUtils,
+ Vcl.Graphics,
+
+ Resources;
+
+
+{$R *.dfm}
+
+
+{ TMapPreviewFrame }
+constructor TMapPreviewFrame.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+
+ { Having the components not aligned at design-time makes it easier to drag the frame around }
+ shpBorder.Align := alClient;
+ imgMapPreview.Align := alClient;
+
+ Clear;
+end;
+
+
+procedure TMapPreviewFrame.Clear;
+begin
+ imgMapPreview.Picture.Assign(gcMapPreviewUnknownMap.Picture);
+end;
+
+
+procedure TMapPreviewFrame.Load(const AMapName: string);
+var
+ preview: TPicture;
+ fileName: string;
+ previewItem: TX2GraphicContainerItem;
+
+begin
+ preview := nil;
+
+ if Length(AMapName) > 0 then
+ begin
+ preview := gcMapPreview.PictureByName(AMapName);
+ if not Assigned(preview) then
+ begin
+ previewItem := TX2GraphicContainerItem.Create(Self);
+ previewItem.Container := gcMapPreview;
+ previewItem.PictureName := AMapName;
+ preview := previewItem.Picture;
+
+ fileName := GetAssetPath(AssetMapPreviewPath + AMapName + AssetMapPreviewExtension);
+ if FileExists(fileName) then
+ begin
+ try
+ preview.LoadFromFile(fileName);
+ except
+ preview.Assign(nil);
+ end;
+ end;
+ end;
+ end;
+
+ if Assigned(preview) and Assigned(preview.Graphic) then
+ imgMapPreview.Picture.Assign(preview)
+ else
+ Clear;
+end;
+
+end.