mainformunit.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. unit mainformunit;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Menus, ExtCtrls,
  6. ComCtrls, StdCtrls, fpjson, gameproject, globals, databaseformunit,
  7. tilepaletteunit, mapviewframeunit, maplistframeunit, tileselectionunit,
  8. LCLTranslator, languagehelper, testhelper;
  9. type
  10. { TMainForm }
  11. TMainForm = class(TForm)
  12. MainImageList: TImageList;
  13. MainFormMenu: TMainMenu;
  14. FileMenuItem: TMenuItem;
  15. CloseProjectMenuItem: TMenuItem;
  16. ExportMenuItem: TMenuItem;
  17. FileSeparator2MenuItem: TMenuItem;
  18. GameMapListFrame: TMapListFrame;
  19. MapModeMenuItem: TMenuItem;
  20. EventModeMenuItem: TMenuItem;
  21. DrawMenuItem: TMenuItem;
  22. DatabaseMenuItem: TMenuItem;
  23. MapLayer1MenuItem: TMenuItem;
  24. MapLayer2MenuItem: TMenuItem;
  25. MapLayer3MenuItem: TMenuItem;
  26. MapLayer4MenuItem: TMenuItem;
  27. EllipseMenuItem: TMenuItem;
  28. FloodFillMenuItem: TMenuItem;
  29. DefaultZoomMenuItem: TMenuItem;
  30. EventSearchMenuItem: TMenuItem;
  31. CharacterGeneratorMenuItem: TMenuItem;
  32. HelpMenuItem: TMenuItem;
  33. AboutMenuItem: TMenuItem;
  34. EditSeparatorMenuItem: TMenuItem;
  35. CutMenuItem: TMenuItem;
  36. CopyMenuItem: TMenuItem;
  37. DeleteMenuItem: TMenuItem;
  38. MainMapViewFrame: TMapViewFrame;
  39. LanguageMenuItem: TMenuItem;
  40. GameMenuItem: TMenuItem;
  41. GameSeparatorMenuItem: TMenuItem;
  42. OpenFolderMenuItem: TMenuItem;
  43. PlaytestMenuItem: TMenuItem;
  44. OptionsMenuItem: TMenuItem;
  45. ToolsSeparatorMenuItem: TMenuItem;
  46. PasteMenuItem: TMenuItem;
  47. RedoMenuItem: TMenuItem;
  48. CutToolButton: TToolButton;
  49. CopyToolButton: TToolButton;
  50. PasteToolButton: TToolButton;
  51. Separator2ToolButton: TToolButton;
  52. Separator3ToolButton: TToolButton;
  53. MapModeToolButton: TToolButton;
  54. MapLayer1ToolButton: TToolButton;
  55. MapLayer2ToolButton: TToolButton;
  56. MapLayer3ToolButton: TToolButton;
  57. MapLayer4ToolButton: TToolButton;
  58. EventModeToolButton: TToolButton;
  59. Separator4ToolButton: TToolButton;
  60. UndoToolButton: TToolButton;
  61. UndoMenuItem: TMenuItem;
  62. ResourceManagerMenuItem: TMenuItem;
  63. SoundTestMenuItem: TMenuItem;
  64. MainToolBar: TToolBar;
  65. NewProjectToolButton: TToolButton;
  66. OpenProjectToolButton: TToolButton;
  67. SaveProjectToolButton: TToolButton;
  68. Separator1ToolButton: TToolButton;
  69. ZoomOutMenuItem: TMenuItem;
  70. ZoomInMenuItem: TMenuItem;
  71. ShadowPenMenuItem: TMenuItem;
  72. RectangleMenuItem: TMenuItem;
  73. PencilMenuItem: TMenuItem;
  74. SingleMapLayerMenuItem: TMenuItem;
  75. PluginManagerMenuItem: TMenuItem;
  76. MainTilePaletteFrame: TTilePaletteFrame;
  77. TilePalettePanel: TPanel;
  78. ToolsMenuItem: TMenuItem;
  79. ScaleMenuItem: TMenuItem;
  80. ModeMenuItem: TMenuItem;
  81. FileSeparator1MenuItem: TMenuItem;
  82. CloseEditorMenuItem: TMenuItem;
  83. LeftPanel: TPanel;
  84. EditMenuItem: TMenuItem;
  85. OpenProjectOpenDialog: TOpenDialog;
  86. SaveProjectMenuItem: TMenuItem;
  87. OpenProjectMenuItem: TMenuItem;
  88. NewProjectMenuItem: TMenuItem;
  89. MainSplitter: TSplitter;
  90. PaletteMapSplitter: TSplitter;
  91. MainStatusBar: TStatusBar;
  92. procedure AboutMenuItemClick(Sender: TObject);
  93. procedure CloseEditorMenuItemClick(Sender: TObject);
  94. procedure CloseProjectMenuItemClick(Sender: TObject);
  95. procedure DatabaseMenuItemClick(Sender: TObject);
  96. procedure DefaultZoomMenuItemClick(Sender: TObject);
  97. procedure FormCreate(Sender: TObject);
  98. procedure LanguageMenuItemClick(Sender: TObject);
  99. procedure MapModeToolButtonClick(Sender: TObject);
  100. procedure OpenFolderMenuItemClick(Sender: TObject);
  101. procedure OpenProjectMenuItemClick(Sender: TObject);
  102. procedure PlaytestMenuItemClick(Sender: TObject);
  103. procedure SaveProjectMenuItemClick(Sender: TObject);
  104. procedure OpenMap(MapId: Integer);
  105. procedure NewPaletteSelectionChosen(ASelection: TTileSelection);
  106. procedure ZoomInMenuItemClick(Sender: TObject);
  107. procedure ZoomOutMenuItemClick(Sender: TObject);
  108. private
  109. SelectedLayer: Integer;
  110. Selection: TTileSelection;
  111. CurrentZoom: Integer;
  112. procedure UpdateAvailability;
  113. procedure SelectMapLayer(LayerId: Integer);
  114. procedure UpdateZoomAvailability;
  115. procedure CloseProject;
  116. public
  117. procedure UpdateLanguage(Code: String);
  118. procedure MapSelectionChanged(MapId: Integer);
  119. end;
  120. var
  121. MainForm: TMainForm;
  122. implementation
  123. uses
  124. {$IF Defined(UNIX)}
  125. BaseUnix, Strings,
  126. {$ELSEIF Defined(MSWINDOWS)}
  127. ShellApi,
  128. {$ENDIF}
  129. aboutformunit, constants, LCLClasses;
  130. {$R *.lfm}
  131. { TMainForm }
  132. procedure TMainForm.NewPaletteSelectionChosen(ASelection: TTileSelection);
  133. begin
  134. MainMapViewFrame.SetSelection(nil);
  135. if Selection <> nil then begin
  136. Selection.Free;
  137. Selection := nil;
  138. end;
  139. Selection := ASelection;
  140. MainMapViewFrame.SetSelection(Selection);
  141. end;
  142. procedure TMainForm.ZoomInMenuItemClick(Sender: TObject);
  143. begin
  144. Inc(CurrentZoom);
  145. if CurrentZoom > High(Zooms) then
  146. CurrentZoom := High(Zooms);
  147. MainMapViewFrame.SetZoom(CurrentZoom);
  148. UpdateZoomAvailability
  149. end;
  150. procedure TMainForm.ZoomOutMenuItemClick(Sender: TObject);
  151. begin
  152. Dec(CurrentZoom);
  153. if CurrentZoom < Low(Zooms) then
  154. CurrentZoom := Low(Zooms);
  155. MainMapViewFrame.SetZoom(CurrentZoom);
  156. UpdateZoomAvailability
  157. end;
  158. procedure TMainForm.CloseEditorMenuItemClick(Sender: TObject);
  159. begin
  160. Close;
  161. end;
  162. procedure TMainForm.AboutMenuItemClick(Sender: TObject);
  163. begin
  164. AboutForm.ShowModal;
  165. end;
  166. procedure TMainForm.CloseProjectMenuItemClick(Sender: TObject);
  167. begin
  168. CloseProject;
  169. end;
  170. procedure TMainForm.DatabaseMenuItemClick(Sender: TObject);
  171. begin
  172. DatabaseForm.ShowModal;
  173. end;
  174. procedure TMainForm.DefaultZoomMenuItemClick(Sender: TObject);
  175. begin
  176. CurrentZoom := 5;
  177. MainMapViewFrame.SetZoom(CurrentZoom);
  178. UpdateZoomAvailability
  179. end;
  180. procedure TMainForm.FormCreate(Sender: TObject);
  181. begin
  182. CurrentZoom := 5;
  183. UpdateAvailability;
  184. SelectMapLayer(LAYER_ALL);
  185. MainTilePaletteFrame.SetType(tptDrawing);
  186. MainTilePaletteFrame.UpdateCallback := @NewPaletteSelectionChosen;
  187. GameMapListFrame.SelectionChangedCallback := @MapSelectionChanged;
  188. MainMapViewFrame.Mode := mvfmEdit;
  189. end;
  190. procedure TMainForm.LanguageMenuItemClick(Sender: TObject);
  191. begin
  192. if LCLTranslator.GetDefaultLang <> 'uk' then
  193. SetGlobalLanguage('uk')
  194. else
  195. SetGlobalLanguage('en');
  196. end;
  197. procedure TMainForm.MapModeToolButtonClick(Sender: TObject);
  198. begin
  199. SelectMapLayer((Sender as TLCLComponent).Tag);
  200. end;
  201. procedure TMainForm.OpenFolderMenuItemClick(Sender: TObject);
  202. {$IF Defined(UNIX)}
  203. procedure OpenDirectory(Dir: String);
  204. var
  205. Argv: PPChar;
  206. begin
  207. GetMem(Argv, 3 * SizeOf(PChar));
  208. Argv[0] := PChar(Dir);
  209. Argv[1] := nil;
  210. FpExecve('xdg-open', Argv, nil);
  211. FreeMem(Argv);
  212. end;
  213. {$ELSEIF Defined(MSWINDOWS)}
  214. procedure OpenDirectory(Dir: String);
  215. begin
  216. ShellExecute(0, 'open', PWideChar(UTF8Decode(Dir)), '', '', 10 {SW_SHOWDEFAULT});
  217. end;
  218. {$ELSE}
  219. procedure OpenDirectory(Dir: String);
  220. begin
  221. MessageDlg('Unsupported OS!');
  222. {TODO: just hide this menu item if OS is not supported, don't display anything}
  223. end;
  224. {$ENDIF}
  225. begin
  226. if (Game <> nil) and (Game.Db <> nil) then begin
  227. OpenDirectory(Game.Dir);
  228. end;
  229. end;
  230. procedure TMainForm.OpenProjectMenuItemClick(Sender: TObject);
  231. begin
  232. if OpenProjectOpenDialog.Execute then begin
  233. if Game <> nil then
  234. CloseProject;
  235. Game := TGameProject.Create();
  236. Game.Open(OpenProjectOpenDialog.FileName);
  237. GameMapListFrame.FillMapInfoList;
  238. UpdateAvailability;
  239. end;
  240. end;
  241. procedure TMainForm.PlaytestMenuItemClick(Sender: TObject);
  242. begin
  243. if (Game <> nil) and (Game.Db <> nil) then
  244. StartTestPlay(Game.Dir);
  245. end;
  246. procedure TMainForm.SaveProjectMenuItemClick(Sender: TObject);
  247. begin
  248. Game.Save;
  249. end;
  250. procedure TMainForm.UpdateAvailability;
  251. var
  252. PrjExists: Boolean;
  253. begin
  254. PrjExists := (Game <> nil) and (Game.Db <> nil);
  255. CloseProjectMenuItem.Enabled := PrjExists;
  256. ExportMenuItem.Enabled := PrjExists;
  257. SaveProjectMenuItem.Enabled := PrjExists;
  258. SaveProjectToolButton.Enabled := PrjExists;
  259. DatabaseMenuItem.Enabled := PrjExists;
  260. PluginManagerMenuItem.Enabled := PrjExists;
  261. end;
  262. procedure TMainForm.OpenMap(MapId: Integer);
  263. var
  264. TilesetIdJson: TJSONNumber;
  265. TilesetId: Integer = 0;
  266. Tileset: TJSONObject = nil;
  267. begin
  268. Game.OpenMap(MapId);
  269. if (Game.Map <> nil) and Game.Map.Find('tilesetId', TilesetIdJson) then begin
  270. TilesetId := TilesetIdJson.AsInteger;
  271. if (TilesetId > 0) and (TilesetId < Game.Db.Tilesets.Count) then
  272. Tileset := Game.Db.Tilesets.Objects[TilesetId];
  273. MainTilePaletteFrame.UpdateFromTileset(Game.TilesetGraphics, Tileset);
  274. MainMapViewFrame.SetMap(Game.Map, Game.TilesetGraphics, Game.Db);
  275. end;
  276. end;
  277. procedure TMainForm.SelectMapLayer(LayerId: Integer);
  278. procedure SelectOrDeselectMenuItem(MenuItem: TMenuItem);
  279. begin
  280. MenuItem.Checked := MenuItem.Tag = LayerId;
  281. end;
  282. procedure SelectToolButton(AToolButton: TToolButton);
  283. begin
  284. AToolButton.Down := (AToolButton.Tag = LayerId);
  285. end;
  286. begin
  287. SelectOrDeselectMenuItem(MapModeMenuItem);
  288. SelectOrDeselectMenuItem(MapLayer1MenuItem);
  289. SelectOrDeselectMenuItem(MapLayer2MenuItem);
  290. SelectOrDeselectMenuItem(MapLayer3MenuItem);
  291. SelectOrDeselectMenuItem(MapLayer4MenuItem);
  292. SelectOrDeselectMenuItem(EventModeMenuItem);
  293. SingleMapLayerMenuItem.Checked := LayerId >= 0;
  294. SelectToolButton(MapModeToolButton);
  295. SelectToolButton(MapLayer1ToolButton);
  296. SelectToolButton(MapLayer2ToolButton);
  297. SelectToolButton(MapLayer3ToolButton);
  298. SelectToolButton(MapLayer4ToolButton);
  299. SelectToolButton(EventModeToolButton);
  300. SelectedLayer := LayerId;
  301. if (LayerId >= -1) then //if it's not an event layer
  302. MainTilePaletteFrame.SelectMapLayer(LayerId)
  303. else
  304. MainTilePaletteFrame.SelectMapLayer(LAYER_ALL);
  305. MainMapViewFrame.SelectMapLayer(LayerId);
  306. end;
  307. procedure TMainForm.UpdateZoomAvailability;
  308. var
  309. HasZoomIn, HasZoomOut: Boolean;
  310. begin
  311. HasZoomIn := CurrentZoom < High(Zooms);
  312. HasZoomOut := CurrentZoom > Low(Zooms);
  313. ZoomInMenuItem.Enabled := HasZoomIn;
  314. ZoomOutMenuItem.Enabled := HasZoomOut;
  315. end;
  316. procedure TMainForm.CloseProject;
  317. begin
  318. GameMapListFrame.ClearList;
  319. if Game <> nil then begin
  320. Game.Free;
  321. Game := nil;
  322. end;
  323. UpdateAvailability;
  324. end;
  325. procedure TMainForm.UpdateLanguage(Code: String);
  326. procedure RepositionToolbarButtons;
  327. var
  328. I: Integer;
  329. ItemWidth: Integer;
  330. begin
  331. ItemWidth := NewProjectToolButton.Width;
  332. MainToolBar.BeginUpdate;
  333. { TODO: this is hacky; test that it works on all platforms }
  334. for I := 0 to MainToolBar.ButtonCount - 1 do
  335. with MainToolBar do begin
  336. { I don't think LCL actually cares about this value, it re-calculates
  337. the position itself. But without this line, it doesn't. }
  338. MainToolBar.Buttons[I].Left := ItemWidth * (I + 1);
  339. end;
  340. MainToolBar.EndUpdate;
  341. end;
  342. begin
  343. if IsLanguageRtl(Code) then begin
  344. UndoToolButton.ImageIndex := 7;
  345. UndoMenuItem.ImageIndex := 7;
  346. RedoMenuItem.ImageIndex := 6;
  347. PlaytestMenuItem.ImageIndex := 32;
  348. if MainToolBar.Tag = 0 then
  349. RepositionToolbarButtons;
  350. MainToolBar.Tag := 1;
  351. end else begin
  352. UndoToolButton.ImageIndex := 6;
  353. UndoMenuItem.ImageIndex := 6;
  354. RedoMenuItem.ImageIndex := 7;
  355. PlaytestMenuItem.ImageIndex := 30;
  356. if MainToolBar.Tag = 1 then
  357. RepositionToolbarButtons;
  358. MainToolBar.Tag := 0;
  359. end;
  360. if MainMapViewFrame <> nil then
  361. MainMapViewFrame.UpdateLanguage(Code);
  362. end;
  363. procedure TMainForm.MapSelectionChanged(MapId: Integer);
  364. begin
  365. if (MapId > 0) and (MapId < Game.MapInfos.Data.Count) then begin
  366. OpenMap(MapId);
  367. end
  368. else begin
  369. MainMapViewFrame.SetSelection(nil);
  370. if Selection <> nil then begin
  371. Selection.Free;
  372. Selection := nil;
  373. end;
  374. //MainTilePaletteFrame.UpdateFromTileset(nil); (* TODO: fix sigsegv *)
  375. MainMapViewFrame.SetMap(nil, nil, nil);
  376. end;
  377. end;
  378. end.