2
0

MapEditor.Mod 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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.tile MOD E.tilesInRow * E.cellW;
  35. ky := cell.tile 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. BEGIN
  82. E.SetCell(game.map, x, y, wgtTileset.curTile);
  83. S.Redraw(wgtMap)
  84. END OnMapMouseDown;
  85. PROCEDURE MapWidgetHandleMouseDown(c: S.Widget; VAR msg: S.MouseDownMsg);
  86. VAR m: MapWidget;
  87. x, y: INTEGER;
  88. BEGIN
  89. m := c(MapWidget);
  90. x := Limit(msg.x DIV E.cellW, 0, game.map.w - 1);
  91. y := Limit(msg.y DIV E.cellH, 0, game.map.h - 1);
  92. IF msg.btn = 1 THEN
  93. OnMapMouseDown(x, y)
  94. END
  95. END MapWidgetHandleMouseDown;
  96. PROCEDURE MapWidgetHandleMouseMove(c: S.Widget; VAR msg: S.MouseMoveMsg);
  97. VAR m: MapWidget;
  98. x, y: INTEGER;
  99. BEGIN
  100. m := c(MapWidget);
  101. x := Limit(msg.x DIV E.cellW, 0, game.map.w - 1);
  102. y := Limit(msg.y DIV E.cellH, 0, game.map.h - 1);
  103. IF (x # m.curX) OR (y # m.curY) THEN
  104. m.curX := x; m.curY := y;
  105. IF 1 IN msg.btns THEN
  106. OnMapMouseDown(x, y)
  107. END;
  108. S.Redraw(c)
  109. END
  110. END MapWidgetHandleMouseMove;
  111. PROCEDURE MapWidgetHandler(c: S.Widget; VAR msg: S.Message);
  112. BEGIN
  113. IF msg IS S.MouseMoveMsg THEN
  114. MapWidgetHandleMouseMove(c, msg(S.MouseMoveMsg))
  115. ELSIF msg IS S.MouseLeaveMsg THEN
  116. c(MapWidget).curX := -1; S.Redraw(c)
  117. ELSIF msg IS S.MouseDownMsg THEN
  118. MapWidgetHandleMouseDown(c, msg(S.MouseDownMsg))
  119. ELSIF msg IS S.DrawMsg THEN
  120. MapWidgetHandleDraw(c, msg(S.DrawMsg))
  121. ELSE
  122. S.WidgetHandler(c, msg)
  123. END
  124. END MapWidgetHandler;
  125. PROCEDURE NewMapWidget(where: S.Widget; x, y, w, h: INTEGER): MapWidget;
  126. VAR c: MapWidget;
  127. BEGIN
  128. NEW(c); S.InitWidget(c, w, h);
  129. c.curX := -1; c.curY := 0;
  130. c.handle := MapWidgetHandler;
  131. S.Put(c, where, x, y)
  132. RETURN c END NewMapWidget;
  133. (** Tileset Widget **)
  134. PROCEDURE TilesetWidgetOnInnerPaint(c: S.Widget; x, y, w, h: INTEGER);
  135. VAR col: G.Color;
  136. n, X, Y: INTEGER;
  137. t: TilesetWidget;
  138. BEGIN
  139. t := c.parent.parent(TilesetWidget);
  140. G.Draw(E.tiles, x, y);
  141. G.MakeCol(col, 0, 110, 240);
  142. X := x + t.curTile MOD E.tilesInRow * E.cellW;
  143. Y := y + t.curTile DIV E.tilesInRow * E.cellH;
  144. G.Rect(X, Y, X + E.cellW - 1, Y + E.cellH - 1, col)
  145. END TilesetWidgetOnInnerPaint;
  146. PROCEDURE TilesetWidgetOnMouseDown(c: S.Widget; x, y, btn: INTEGER);
  147. VAR t: TilesetWidget;
  148. n: INTEGER;
  149. BEGIN t := c.parent.parent(TilesetWidget);
  150. IF btn = 1 THEN
  151. IF x < 0 THEN x := 0 ELSIF x >= c.w THEN x := c.w - 1 END;
  152. IF y < 0 THEN y := 0 ELSIF y >= c.h THEN y := c.h - 1 END;
  153. n := y DIV E.cellH * E.tilesInRow + x DIV E.cellW;
  154. IF t.curTile # n THEN
  155. t.curTile := n;
  156. S.Redraw(c)
  157. END
  158. END
  159. END TilesetWidgetOnMouseDown;
  160. PROCEDURE TilesetWidgetOnMouseMove(c: S.Widget; x, y: INTEGER; btns: SET);
  161. BEGIN IF 1 IN btns THEN TilesetWidgetOnMouseDown(c, x, y, 1) END
  162. END TilesetWidgetOnMouseMove;
  163. PROCEDURE NewTilesetWidget(where: S.Widget; x, y, w, h: INTEGER): TilesetWidget;
  164. VAR c: TilesetWidget;
  165. BEGIN
  166. NEW(c); S.InitScrollBox(c, where, x, y, w, h);
  167. S.ScrollBoxSetInnerSize(c, E.tiles.w, E.tiles.h);
  168. S.SetOnPaint(c.inner, TilesetWidgetOnInnerPaint);
  169. S.SetOnMouseMove(c.inner, TilesetWidgetOnMouseMove);
  170. S.SetOnMouseDown(c.inner, TilesetWidgetOnMouseDown);
  171. c.curTile := 0
  172. RETURN c END NewTilesetWidget;
  173. (** - **)
  174. PROCEDURE BtnExitOnClick(c: S.Widget);
  175. BEGIN
  176. S.Quit
  177. END BtnExitOnClick;
  178. PROCEDURE InitInterface(): BOOLEAN;
  179. VAR W, H, w, h: INTEGER;
  180. color: G.Color;
  181. BEGIN
  182. G.GetScreenSize(W, H);
  183. frmMain := S.NewForm(0, 0, W, H);
  184. pnlTop := S.NewPanel(frmMain, 0, 0, W, 40);
  185. lblMapName := S.NewLabel(pnlTop, 8, 9, 88, 22, 'Имя файла:');
  186. S.LabelSetAlign(lblMapName, S.alRight);
  187. edtMapName := S.NewEdit(pnlTop, lblMapName.x + lblMapName.w + 8,
  188. 9, 40, 22);
  189. btnOpen := S.NewButton(pnlTop, edtMapName.x + edtMapName.w + 8,
  190. 8, 70, 24, 'Открыть');
  191. btnSave := S.NewButton(pnlTop, btnOpen.x + btnOpen.w + 8,
  192. 8, 80, 24, 'Сохранить');
  193. btnExit := S.NewButton(pnlTop, W - 68, 8, 52, 24, 'Выход');
  194. S.SetOnClick(btnExit, BtnExitOnClick);
  195. pnlSide := S.NewPanel(frmMain, 0, pnlTop.h, 144, H - pnlTop.h);
  196. G.MakeCol(color, 40, 150, 40);
  197. S.SetBgColor(pnlSide, color);
  198. wgtTileset := NewTilesetWidget(pnlSide, 0, 0, pnlSide.w, pnlSide.h);
  199. sbxMap := S.NewScrollBox(frmMain, pnlSide.w, pnlTop.h,
  200. W - pnlSide.w, H - pnlTop.h);
  201. w := game.map.w * E.cellW;
  202. h := game.map.h * E.cellH;
  203. S.ScrollBoxSetInnerSize(sbxMap, w, h);
  204. (*S.ScrollBoxSetNoBg(sbxMap, TRUE);*)
  205. wgtMap := NewMapWidget(sbxMap, 0, 0, w, h)
  206. RETURN TRUE END InitInterface;
  207. PROCEDURE Init(): BOOLEAN;
  208. VAR ok: BOOLEAN;
  209. BEGIN ok := TRUE;
  210. G.Settings(320, 200, {});
  211. IF window THEN G.Settings(1240, 780, {G.window(*, G.maximized*)}) END;
  212. G.Init;
  213. IF ~G.Done THEN ok := FALSE END;
  214. IF ok THEN
  215. S.Init;
  216. IF ~S.Done THEN ok := FALSE END
  217. END;
  218. IF ok & ~E.Init() THEN ok := FALSE END;
  219. IF ok THEN E.InitGame(game) END;
  220. IF ok & ~InitInterface() THEN ok := FALSE END
  221. RETURN ok END Init;
  222. PROCEDURE Close;
  223. BEGIN
  224. G.Close
  225. END Close;
  226. BEGIN
  227. IF Init() THEN S.Run ELSE Out.String('Error loading.'); Out.Ln END;
  228. Close
  229. END MapEditor.