MapEditor.Mod 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. MODULE MapEditor;
  2. IMPORT G := Graph, S := SimpleGui, Out, Int, Strings, E := GameEngine;
  3. CONST window = FALSE;
  4. TYPE
  5. MapWidget = POINTER TO MapWidgetDesc;
  6. MapWidgetDesc = RECORD(S.WidgetDesc)
  7. curX, curY: INTEGER
  8. END;
  9. TilesetWidget = POINTER TO TilesetWidgetDesc;
  10. TilesetWidgetDesc = RECORD(S.ScrollBox)
  11. curTile: INTEGER
  12. END;
  13. VAR
  14. frmMain: S.Form;
  15. pnlTop: S.Panel;
  16. lblMapName: S.Label;
  17. edtMapName: S.Edit;
  18. btnOpen: S.Button;
  19. btnSave: S.Button;
  20. btnExit: S.Button;
  21. pnlSide: S.Panel;
  22. sbxMap: S.ScrollBox;
  23. wgtMap: MapWidget;
  24. wgtTileset: TilesetWidget;
  25. game: E.Game;
  26. PROCEDURE Limit(x, min, max: INTEGER): INTEGER;
  27. BEGIN
  28. IF x < min THEN x := min ELSIF x > max THEN x := max END
  29. RETURN x END Limit;
  30. (** Map Widget **)
  31. PROCEDURE MapWidgetHandleDraw(c: S.Widget; VAR msg: S.DrawMsg);
  32. VAR x: INTEGER;
  33. X, Y, i, j: INTEGER;
  34. cx, cy, cw, ch: INTEGER;
  35. x0, y0, x1, y1: INTEGER;
  36. col: G.Color;
  37. m: MapWidget;
  38. BEGIN
  39. m := c(MapWidget);
  40. G.GetClip(cx, cy, cw, ch);
  41. (*INC(cx, E.cellW * 2);
  42. INC(cy, E.cellW * 2);
  43. DEC(cw, E.cellW * 4);
  44. DEC(ch, E.cellW * 4);*)
  45. x0 := (cx - msg.x) DIV E.cellW;
  46. IF x0 < 0 THEN x0 := 0 END;
  47. y0 := (cy - msg.y) DIV E.cellH;
  48. IF y0 < 0 THEN y0 := 0 END;
  49. x1 := (cx - msg.x + cw - 1) DIV E.cellW;
  50. IF x1 >= game.map.w THEN x1 := game.map.w - 1 END;
  51. y1 := (cy - msg.y + ch - 1) DIV E.cellH;
  52. IF y1 >= game.map.h THEN y1 := game.map.h - 1 END;
  53. G.MakeCol(col, 255, 0, 128);
  54. G.FillRect(0, 0, 2000, 2000, col);
  55. x := msg.x + x0 * E.cellW;
  56. Y := msg.y + y0 * E.cellH;
  57. FOR i := y0 TO y1 DO
  58. X := x;
  59. FOR j := x0 TO x1 DO
  60. E.DrawCell(game.map.cells[i, j], i, j, X, Y);
  61. INC(X, E.cellW)
  62. END;
  63. INC(Y, E.cellH)
  64. END;
  65. IF m.curX >= 0 THEN
  66. G.MakeCol(col, 240, 0, 0);
  67. X := msg.x + m.curX * E.cellW;
  68. Y := msg.y + m.curY * E.cellH;
  69. G.Rect(X - 1, Y - 1, X + E.cellW, Y + E.cellH, col);
  70. END
  71. END MapWidgetHandleDraw;
  72. (** (x; y) in cells *)
  73. PROCEDURE OnMapMouseDown(x, y: INTEGER);
  74. BEGIN
  75. E.SetCell(game.map, x, y, wgtTileset.curTile);
  76. S.Redraw(wgtMap)
  77. END OnMapMouseDown;
  78. PROCEDURE MapWidgetHandleMouseDown(c: S.Widget; VAR msg: S.MouseDownMsg);
  79. VAR m: MapWidget;
  80. x, y: INTEGER;
  81. BEGIN
  82. m := c(MapWidget);
  83. x := Limit(msg.x DIV E.cellW, 0, game.map.w - 1);
  84. y := Limit(msg.y DIV E.cellH, 0, game.map.h - 1);
  85. IF msg.btn = 1 THEN
  86. OnMapMouseDown(x, y)
  87. END
  88. END MapWidgetHandleMouseDown;
  89. PROCEDURE MapWidgetHandleMouseMove(c: S.Widget; VAR msg: S.MouseMoveMsg);
  90. VAR m: MapWidget;
  91. x, y: INTEGER;
  92. BEGIN
  93. m := c(MapWidget);
  94. x := Limit(msg.x DIV E.cellW, 0, game.map.w - 1);
  95. y := Limit(msg.y DIV E.cellH, 0, game.map.h - 1);
  96. IF (x # m.curX) OR (y # m.curY) THEN
  97. m.curX := x; m.curY := y;
  98. IF 1 IN msg.btns THEN
  99. OnMapMouseDown(x, y)
  100. END;
  101. S.Redraw(c)
  102. END
  103. END MapWidgetHandleMouseMove;
  104. PROCEDURE MapWidgetHandler(c: S.Widget; VAR msg: S.Message);
  105. BEGIN
  106. IF msg IS S.MouseMoveMsg THEN
  107. MapWidgetHandleMouseMove(c, msg(S.MouseMoveMsg))
  108. ELSIF msg IS S.MouseLeaveMsg THEN
  109. c(MapWidget).curX := -1; S.Redraw(c)
  110. ELSIF msg IS S.MouseDownMsg THEN
  111. MapWidgetHandleMouseDown(c, msg(S.MouseDownMsg))
  112. ELSIF msg IS S.DrawMsg THEN
  113. MapWidgetHandleDraw(c, msg(S.DrawMsg))
  114. ELSE
  115. S.WidgetHandler(c, msg)
  116. END
  117. END MapWidgetHandler;
  118. PROCEDURE NewMapWidget(where: S.Widget; x, y, w, h: INTEGER): MapWidget;
  119. VAR c: MapWidget;
  120. BEGIN
  121. NEW(c); S.InitWidget(c, w, h);
  122. c.curX := -1; c.curY := 0;
  123. c.handle := MapWidgetHandler;
  124. S.Put(c, where, x, y)
  125. RETURN c END NewMapWidget;
  126. (** Tileset Widget **)
  127. PROCEDURE TilesetWidgetOnInnerPaint(c: S.Widget; x, y, w, h: INTEGER);
  128. VAR col: G.Color;
  129. n, X, Y: INTEGER;
  130. t: TilesetWidget;
  131. BEGIN
  132. t := c.parent.parent(TilesetWidget);
  133. G.Draw(E.tiles, x, y);
  134. G.MakeCol(col, 0, 110, 240);
  135. X := x + t.curTile MOD E.tilesInRow * E.cellW;
  136. Y := y + t.curTile DIV E.tilesInRow * E.cellH;
  137. G.Rect(X, Y, X + E.cellW - 1, Y + E.cellH - 1, col)
  138. END TilesetWidgetOnInnerPaint;
  139. PROCEDURE TilesetWidgetOnMouseDown(c: S.Widget; x, y, btn: INTEGER);
  140. VAR t: TilesetWidget;
  141. n: INTEGER;
  142. BEGIN t := c.parent.parent(TilesetWidget);
  143. IF btn = 1 THEN
  144. IF x < 0 THEN x := 0 ELSIF x >= c.w THEN x := c.w - 1 END;
  145. IF y < 0 THEN y := 0 ELSIF y >= c.h THEN y := c.h - 1 END;
  146. n := y DIV E.cellH * E.tilesInRow + x DIV E.cellW;
  147. IF t.curTile # n THEN
  148. t.curTile := n;
  149. S.Redraw(c)
  150. END
  151. END
  152. END TilesetWidgetOnMouseDown;
  153. PROCEDURE TilesetWidgetOnMouseMove(c: S.Widget; x, y: INTEGER; btns: SET);
  154. BEGIN IF 1 IN btns THEN TilesetWidgetOnMouseDown(c, x, y, 1) END
  155. END TilesetWidgetOnMouseMove;
  156. PROCEDURE NewTilesetWidget(where: S.Widget; x, y, w, h: INTEGER): TilesetWidget;
  157. VAR c: TilesetWidget;
  158. BEGIN
  159. NEW(c); S.InitScrollBox(c, where, x, y, w, h);
  160. S.ScrollBoxSetInnerSize(c, E.tiles.w, E.tiles.h);
  161. S.SetOnPaint(c.inner, TilesetWidgetOnInnerPaint);
  162. S.SetOnMouseMove(c.inner, TilesetWidgetOnMouseMove);
  163. S.SetOnMouseDown(c.inner, TilesetWidgetOnMouseDown);
  164. c.curTile := 0
  165. RETURN c END NewTilesetWidget;
  166. (** - **)
  167. PROCEDURE BtnOpenOnClick(c: S.Widget);
  168. VAR s: ARRAY 256 OF CHAR;
  169. BEGIN
  170. S.EditGetText(edtMapName, s);
  171. IF s[0] # 0X THEN
  172. Strings.Append('.gam', s);
  173. IF E.LoadGame(game, s) THEN END;
  174. S.Redraw(wgtMap)
  175. END
  176. END BtnOpenOnClick;
  177. PROCEDURE BtnSaveOnClick(c: S.Widget);
  178. VAR s: ARRAY 256 OF CHAR;
  179. BEGIN
  180. S.EditGetText(edtMapName, s);
  181. IF s[0] # 0X THEN
  182. Strings.Append('.gam', s);
  183. E.SaveGame(game, s)
  184. END
  185. END BtnSaveOnClick;
  186. PROCEDURE BtnExitOnClick(c: S.Widget);
  187. BEGIN
  188. S.Quit
  189. END BtnExitOnClick;
  190. PROCEDURE InitInterface(): BOOLEAN;
  191. VAR W, H, w, h: INTEGER;
  192. color: G.Color;
  193. BEGIN
  194. G.GetScreenSize(W, H);
  195. frmMain := S.NewForm(0, 0, W, H);
  196. pnlTop := S.NewPanel(frmMain, 0, 0, W, 40);
  197. lblMapName := S.NewLabel(pnlTop, 8, 9, 88, 22, 'Имя файла:');
  198. S.LabelSetAlign(lblMapName, S.alRight);
  199. edtMapName := S.NewEdit(pnlTop, lblMapName.x + lblMapName.w + 8,
  200. 9, 40, 22);
  201. btnOpen := S.NewButton(pnlTop, edtMapName.x + edtMapName.w + 8,
  202. 8, 70, 24, 'Открыть');
  203. S.SetOnClick(btnOpen, BtnOpenOnClick);
  204. btnSave := S.NewButton(pnlTop, btnOpen.x + btnOpen.w + 8,
  205. 8, 80, 24, 'Сохранить');
  206. S.SetOnClick(btnSave, BtnSaveOnClick);
  207. btnExit := S.NewButton(pnlTop, W - 68, 8, 52, 24, 'Выход');
  208. S.SetOnClick(btnExit, BtnExitOnClick);
  209. pnlSide := S.NewPanel(frmMain, 0, pnlTop.h, 144, H - pnlTop.h);
  210. G.MakeCol(color, 40, 150, 40);
  211. S.SetBgColor(pnlSide, color);
  212. wgtTileset := NewTilesetWidget(pnlSide, 0, 0, pnlSide.w, pnlSide.h);
  213. sbxMap := S.NewScrollBox(frmMain, pnlSide.w, pnlTop.h,
  214. W - pnlSide.w, H - pnlTop.h);
  215. w := game.map.w * E.cellW;
  216. h := game.map.h * E.cellH;
  217. S.ScrollBoxSetInnerSize(sbxMap, w, h);
  218. (*S.ScrollBoxSetNoBg(sbxMap, TRUE);*)
  219. wgtMap := NewMapWidget(sbxMap, 0, 0, w, h)
  220. RETURN TRUE END InitInterface;
  221. PROCEDURE Init(): BOOLEAN;
  222. VAR ok: BOOLEAN;
  223. BEGIN ok := TRUE;
  224. G.Settings(320, 200, {});
  225. IF window THEN G.Settings(1240, 780, {G.window(*, G.maximized*)}) END;
  226. G.Init;
  227. IF ~G.Done THEN ok := FALSE END;
  228. IF ok THEN
  229. S.Init;
  230. IF ~S.Done THEN ok := FALSE END
  231. END;
  232. IF ok & ~E.Init() THEN ok := FALSE END;
  233. IF ok THEN E.InitGame(game) END;
  234. IF ok & ~InitInterface() THEN ok := FALSE END
  235. RETURN ok END Init;
  236. PROCEDURE Close;
  237. BEGIN
  238. G.Close
  239. END Close;
  240. BEGIN
  241. IF Init() THEN S.Run ELSE Out.String('Error loading.'); Out.Ln END;
  242. Close
  243. END MapEditor.