MapEditor.Mod 7.1 KB

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