summaryrefslogtreecommitdiff
path: root/MapEd/MapControl.cs
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2018-09-29 18:01:34 +0000
committerIan C <ianc@noddybox.co.uk>2018-09-29 18:01:34 +0000
commit8ed524392ae4b3b88ab5e9fafdce7620a0467623 (patch)
tree3e982bd04490063c3c98fb1c3cb8406030bab036 /MapEd/MapControl.cs
parentcd56676ac2b8757a31d01eb28b13691e350f9d8d (diff)
Initial version
Diffstat (limited to 'MapEd/MapControl.cs')
-rw-r--r--MapEd/MapControl.cs837
1 files changed, 837 insertions, 0 deletions
diff --git a/MapEd/MapControl.cs b/MapEd/MapControl.cs
new file mode 100644
index 0000000..2acb8cb
--- /dev/null
+++ b/MapEd/MapControl.cs
@@ -0,0 +1,837 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace MapEd
+{
+ public partial class MapControl : UserControl
+ {
+ public enum DrawMode
+ {
+ Plot,
+ Line,
+ Fill,
+ Rect,
+ FillRect,
+ Circle,
+ FillCircle
+ };
+
+ private const int SCALE = 2;
+
+ private bool mapSet;
+ private int width;
+ private int height;
+ private int tileSize;
+ private int[,] map;
+ private int[,] data;
+ private TileStrip tiles;
+ private bool dataMode;
+ private int tileNumber;
+ private int dataNumber;
+
+ private int lastX;
+ private int lastY;
+
+ private int firstX;
+ private int firstY;
+
+ private DrawMode drawMode;
+
+ private Timer timer;
+ private bool timerDraw;
+ private bool timerColour;
+ private int timerX;
+ private int timerY;
+
+ public MapControl()
+ {
+ InitializeComponent();
+
+ mapSet = false;
+
+ timer = new Timer();
+ timer.Interval = 200;
+ timer.Tick += OnTimerTick;
+ timer.Enabled = true;
+ }
+
+ private void OnTimerTick(object sender, EventArgs e)
+ {
+ if (firstX != -1 && firstX != -1)
+ {
+ timerX = firstX;
+ timerY = firstY;
+
+ timerDraw = true;
+ timerColour = !timerColour;
+
+ if (timerColour)
+ {
+ DrawBlock(timerX, timerY, Brushes.White);
+ }
+ else
+ {
+ DrawBlock(timerX, timerY, Brushes.Black);
+ }
+ }
+
+ if (firstX == -1 && firstY == -1 && timerDraw)
+ {
+ if (dataMode)
+ {
+ DrawData(timerX, timerY, data[timerY,timerX]);
+ }
+ else
+ {
+ DrawCell(timerX, timerY, map[timerY,timerX]);
+ }
+
+ timerDraw = false;
+ }
+ }
+
+ public DrawMode MapDrawMode
+ {
+ get
+ {
+ return drawMode;
+ }
+
+ set
+ {
+ drawMode = value;
+ firstX = -1;
+ firstY = -1;
+ }
+ }
+
+ public void SetMap(int width, int height, TileStrip tiles, int tileSize)
+ {
+ this.width = width;
+ this.height = height;
+ this.tiles = tiles;
+ this.tileSize = tileSize;
+
+ map = new int[height, width];
+ data = new int[height, width];
+
+ Width = width * tileSize * SCALE;
+ Height = height * tileSize * SCALE;
+
+ lastX = -1;
+ lastY = -1;
+ firstX = -1;
+ firstY = -1;
+
+ mapSet = true;
+ RedrawMap();
+ }
+
+ public int MapWidth
+ {
+ get
+ {
+ return width;
+ }
+ }
+
+ public int MapHeight
+ {
+ get
+ {
+ return height;
+ }
+ }
+
+ public int TileSize
+ {
+ get
+ {
+ return tileSize;
+ }
+ }
+
+ public int[,] MapTiles
+ {
+ get
+ {
+ return map;
+ }
+ }
+
+ public int[,] MapData
+ {
+ get
+ {
+ return data;
+ }
+ }
+
+ public void SetTileNumber(int tile)
+ {
+ tileNumber = tile;
+ }
+
+ public void SetDataNumber(int data)
+ {
+ dataNumber = data;
+ }
+
+ public void SetDataMode(bool on)
+ {
+ dataMode = on;
+ RedrawMap();
+ }
+
+ public void SetMap(int[,] map)
+ {
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ this.map[y,x] = map[y,x];
+ }
+ }
+
+ RedrawMap();
+ }
+
+ public void SetData(int[,] data)
+ {
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ this.data[y,x] = data[y,x];
+ }
+ }
+
+ RedrawMap();
+ }
+
+ private void OnMouseMove(object sender, MouseEventArgs e)
+ {
+ if (!mapSet)
+ {
+ return;
+ }
+
+ int x = ScreenToMap(e.X);
+ int y = ScreenToMap(e.Y);
+
+ if (x < width && y < height && (x != lastX || y != lastY))
+ {
+ if (dataMode)
+ {
+ if (e.Button == MouseButtons.Left && drawMode == DrawMode.Plot)
+ {
+ data[y,x] = dataNumber;
+ }
+
+ if (lastX != -1 && lastY != -1)
+ {
+ DrawData(lastX, lastY, data[lastY,lastX]);
+ }
+
+ DrawData(x, y, dataNumber);
+ }
+ else
+ {
+ if (e.Button == MouseButtons.Left && drawMode == DrawMode.Plot)
+ {
+ map[y,x] = tileNumber;
+ }
+
+ if (lastX != -1 && lastY != -1)
+ {
+ DrawCell(lastX, lastY, map[lastY,lastX]);
+ }
+
+ DrawCell(x, y, tileNumber);
+ }
+
+ DrawSelection(x, y);
+
+ lastX = x;
+ lastY = y;
+
+ if (dataMode)
+ {
+ toolTip.Show(data[y,x].ToString(), this, 500);
+ }
+ }
+ }
+
+ private void OnMouseLeave(object sender, EventArgs e)
+ {
+ if (!mapSet)
+ {
+ return;
+ }
+
+ if (lastX != -1 && lastY != -1)
+ {
+ if (dataMode)
+ {
+ DrawData(lastX, lastY, data[lastY,lastX]);
+ }
+ else
+ {
+ DrawCell(lastX, lastY, map[lastY,lastX]);
+ }
+ }
+
+ }
+
+ private void OnMouseDown(object sender, MouseEventArgs e)
+ {
+ if (!mapSet)
+ {
+ return;
+ }
+
+ int x = ScreenToMap(e.X);
+ int y = ScreenToMap(e.Y);
+
+ if (x >= width || y >= height)
+ {
+ return;
+ }
+
+ switch(drawMode)
+ {
+ case DrawMode.Plot:
+ if (dataMode)
+ {
+ if (data[y,x] != dataNumber)
+ {
+ data[y,x] = dataNumber;
+ }
+ }
+ else
+ {
+ if (map[y,x] != tileNumber)
+ {
+ map[y,x] = tileNumber;
+ }
+ }
+ break;
+
+ case DrawMode.Line:
+ if (firstX == -1)
+ {
+ firstX = x;
+ firstY = y;
+ }
+ else
+ {
+ Line(x, y, firstX, firstY);
+ firstX = -1;
+ firstY = -1;
+ }
+ break;
+
+ case DrawMode.Fill:
+ Fill(x, y);
+ break;
+
+ case DrawMode.Rect:
+ if (firstX == -1)
+ {
+ firstX = x;
+ firstY = y;
+ }
+ else
+ {
+ DrawRect(x, y, firstX, firstY, false);
+ firstX = -1;
+ firstY = -1;
+ }
+ break;
+
+ case DrawMode.FillRect:
+ if (firstX == -1)
+ {
+ firstX = x;
+ firstY = y;
+ }
+ else
+ {
+ DrawRect(x, y, firstX, firstY, true);
+ firstX = -1;
+ firstY = -1;
+ }
+ break;
+
+ case DrawMode.Circle:
+ if (firstX == -1)
+ {
+ firstX = x;
+ firstY = y;
+ }
+ else
+ {
+ DrawCircle(firstX, firstY, x, y, false);
+ firstX = -1;
+ firstY = -1;
+ }
+ break;
+
+ case DrawMode.FillCircle:
+ if (firstX == -1)
+ {
+ firstX = x;
+ firstY = y;
+ }
+ else
+ {
+ DrawCircle(firstX, firstY, x, y, true);
+ firstX = -1;
+ firstY = -1;
+ }
+ break;
+ }
+ }
+
+ private void OnMouseUp(object sender, MouseEventArgs e)
+ {
+ if (!mapSet)
+ {
+ return;
+ }
+ }
+
+ private int ScreenToMap(int x)
+ {
+ return x / (tileSize * SCALE);
+ }
+
+ private bool XInRange(int x)
+ {
+ return x >=0 && x < width;
+ }
+
+ private bool YInRange(int y)
+ {
+ return y >=0 && y < height;
+ }
+
+ private void DrawCell(int x, int y, int tile)
+ {
+ using(Graphics g = CreateGraphics())
+ {
+ int tx = x * tileSize * SCALE;
+ int ty = y * tileSize * SCALE;
+
+ g.DrawImage(tiles.GetImage(tile), tx, ty, tileSize * SCALE, tileSize * SCALE);
+ }
+ }
+
+ private void DrawData(int x, int y, int data)
+ {
+ using(Graphics g = CreateGraphics())
+ {
+ int tx = x * tileSize * SCALE;
+ int ty = y * tileSize * SCALE;
+
+ g.DrawImage(tiles.GetImage(map[y,x]), tx, ty, tileSize * SCALE, tileSize * SCALE);
+ g.DrawString(data.ToString(), Font, Brushes.Magenta, tx, ty);
+ }
+ }
+
+ private void DrawRect(int x1, int y1, int x2, int y2, bool fill)
+ {
+ if (x1 > x2)
+ {
+ var t = x2;
+ x2 = x1;
+ x1 = t;
+ }
+
+ if (y1 > y2)
+ {
+ var t = y2;
+ y2 = y1;
+ y1 = t;
+ }
+
+ int x,y;
+
+ for(y = y1; y <= y2; y++)
+ {
+ for(x = x1; x <= x2; x++)
+ {
+ if (y == y1 || y == y2 || x == x1 | x == x2 | fill)
+ {
+ if (dataMode)
+ {
+ data[y,x] = dataNumber;
+ DrawData(x, y, dataNumber);
+ }
+ else
+ {
+ map[y,x] = tileNumber;
+ DrawCell(x, y, tileNumber);
+ }
+ }
+ }
+ }
+ }
+
+ private void DrawCircle(int x1, int y1, int x2, int y2, bool fill)
+ {
+ double radius;
+ double dx,dy;
+
+ dx = x2 - x1;
+ dy = y2 - y1;
+
+ radius = Math.Sqrt((dx * dx) + (dy * dy));
+
+ for(double a = 0; a < Math.PI ; a += Math.PI / 180.0)
+ {
+ double x,y;
+
+ x = Math.Sin(a) * radius;
+ y = Math.Cos(a) * radius;
+
+ int px1, px2, py;
+
+ px1 = (int)(x1 - x);
+ px2 = (int)(x1 + x);
+ py = (int)(y1 + y);
+
+ if (fill)
+ {
+ for( ; px1 <= px2; px1++)
+ {
+ if (XInRange(px1) && YInRange(py))
+ {
+ if (dataMode)
+ {
+ data[py, px1] = dataNumber;
+ DrawData(px1, py, dataNumber);
+ }
+ else
+ {
+ map[py, px1] = tileNumber;
+ DrawCell(px1, py, tileNumber);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (XInRange(px1) && YInRange(py))
+ {
+ if (dataMode)
+ {
+ data[py, px1] = dataNumber;
+ DrawData(px1, py, dataNumber);
+ }
+ else
+ {
+ map[py, px1] = tileNumber;
+ DrawCell(px1, py, tileNumber);
+ }
+ }
+
+ if (XInRange(px2) && YInRange(py))
+ {
+ if (dataMode)
+ {
+ data[py, px2] = dataNumber;
+ DrawData(px2, py, dataNumber);
+ }
+ else
+ {
+ map[py, px2] = tileNumber;
+ DrawCell(px2, py, tileNumber);
+ }
+ }
+ }
+ }
+
+ }
+
+ private void Fill(int x, int y)
+ {
+ int back;
+
+ if (dataMode)
+ {
+ back = data[y,x];
+
+ if (back == dataNumber)
+ {
+ return;
+ }
+ }
+ else
+ {
+ back = map[y,x];
+
+ if (back == tileNumber)
+ {
+ return;
+ }
+ }
+
+ FloodFill(x, y, back);
+ }
+
+ private void FloodFill(int x, int y, int back)
+ {
+ if (x < 0 || x >= width || y < 0 || y >= height)
+ {
+ return;
+ }
+
+ if (dataMode)
+ {
+ if (data[y,x] != back)
+ {
+ return;
+ }
+
+ data[y, x] = dataNumber;
+ DrawData(x, y, dataNumber);
+ }
+ else
+ {
+ if (map[y,x] != back)
+ {
+ return;
+ }
+
+ map[y,x] = tileNumber;
+ DrawCell(x, y, tileNumber);
+ }
+
+ FloodFill(x + 1, y, back);
+ FloodFill(x - 1, y, back);
+ FloodFill(x, y + 1, back);
+ FloodFill(x, y - 1, back);
+ }
+
+ private void Line(int x1, int y1, int x2, int y2)
+ {
+ int dx = x2 - x1;
+ int dy = y2 - y1;
+
+ int ix = Math.Sign(dx);
+ int iy = Math.Sign(dy);
+
+ dx = Math.Abs(dx);
+ dy = Math.Abs(dy);
+
+ int incrE;
+ int incrNE;
+ int d;
+ bool ymode;
+
+ if (dy>dx)
+ {
+ ymode = true;
+ d = dx * 2 - dy;
+ incrE = dx * 2;
+ incrNE = (dx - dy) * 2;
+ }
+ else
+ {
+ ymode = false;
+ d = dy * 2 - dx;
+ incrE = dy * 2;
+ incrNE = (dy - dx) * 2;
+ }
+
+ int x = x1;
+ int y = y1;
+
+ if (dataMode)
+ {
+ data[y,x] = dataNumber;
+ DrawData(x, y, dataNumber);
+ }
+ else
+ {
+ map[y,x] = tileNumber;
+ DrawCell(x, y, tileNumber);
+ }
+
+ if (ymode)
+ {
+ while(y!=y2)
+ {
+ if (d<=0)
+ {
+ d+=incrE;
+ y+=iy;
+ }
+ else
+ {
+ d+=incrNE;
+ y+=iy;
+ x+=ix;
+ }
+
+ if (dataMode)
+ {
+ data[y,x] = dataNumber;
+ DrawData(x, y, dataNumber);
+ }
+ else
+ {
+ map[y,x] = tileNumber;
+ DrawCell(x, y, tileNumber);
+ }
+ }
+ }
+ else
+ {
+ while(x!=x2)
+ {
+ if (d<=0)
+ {
+ d+=incrE;
+ x+=ix;
+ }
+ else
+ {
+ d+=incrNE;
+ y+=iy;
+ x+=ix;
+ }
+
+ if (dataMode)
+ {
+ data[y,x] = dataNumber;
+ DrawData(x, y, dataNumber);
+ }
+ else
+ {
+ map[y,x] = tileNumber;
+ DrawCell(x, y, tileNumber);
+ }
+ }
+ }
+ }
+
+ private void RedrawMap()
+ {
+ using(Graphics g = CreateGraphics())
+ {
+ if (dataMode)
+ {
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ int tx = x * tileSize * SCALE;
+ int ty = y * tileSize * SCALE;
+
+ g.DrawImage(tiles.GetImage(map[y,x]), tx, ty, tileSize * SCALE, tileSize * SCALE);
+ g.DrawString(data[y,x].ToString(), Font, Brushes.Magenta, tx, ty);
+ }
+ }
+ }
+ else
+ {
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ int tx = x * tileSize * SCALE;
+ int ty = y * tileSize * SCALE;
+
+ g.DrawImage(tiles.GetImage(map[y,x]), tx, ty, tileSize * SCALE, tileSize * SCALE);
+ }
+ }
+ }
+ }
+ }
+
+ private void RedrawMap(int x1, int y1, int x2, int y2, Graphics g)
+ {
+ if (dataMode)
+ {
+ for(int y = y1; y <= y2; y++)
+ {
+ for(int x = x1; x <= x2; x++)
+ {
+ int tx = x * tileSize * SCALE;
+ int ty = y * tileSize * SCALE;
+
+ g.DrawImage(tiles.GetImage(map[y,x]), tx, ty, tileSize * SCALE, tileSize * SCALE);
+ g.DrawString(data[y,x].ToString(), Font, Brushes.Magenta, tx, ty);
+ }
+ }
+ }
+ else
+ {
+ for(int y = y1; y <= y2; y++)
+ {
+ for(int x = x1; x <= x2; x++)
+ {
+ int tx = x * tileSize * SCALE;
+ int ty = y * tileSize * SCALE;
+
+ g.DrawImage(tiles.GetImage(map[y,x]), tx, ty, tileSize * SCALE, tileSize * SCALE);
+ }
+ }
+ }
+ }
+
+ private void DrawSelection(int x, int y)
+ {
+ using(Graphics g = CreateGraphics())
+ {
+ int tx1 = x * tileSize * SCALE;
+ int ty1 = y * tileSize * SCALE;
+ int tx2 = tx1 + tileSize * SCALE - 1;
+ int ty2 = ty1 + tileSize * SCALE - 1;
+
+ g.DrawLine(Pens.White, tx1, ty1, tx2, ty1);
+ g.DrawLine(Pens.White, tx2, ty1, tx2, ty2);
+ g.DrawLine(Pens.White, tx2, ty2, tx1, ty2);
+ g.DrawLine(Pens.White, tx1, ty2, tx1, ty1);
+ }
+ }
+
+ private void DrawBlock(int x, int y, Brush b)
+ {
+ using(Graphics g = CreateGraphics())
+ {
+ int tx = x * tileSize * SCALE;
+ int ty = y * tileSize * SCALE;
+
+ g.FillRectangle(b, tx, ty, tileSize * SCALE, tileSize * SCALE);
+ }
+ }
+
+ private void OnPaint(object sender, PaintEventArgs e)
+ {
+ if (!mapSet)
+ {
+ return;
+ }
+
+ int x1,y1,x2,y2;
+
+ x1 = Math.Max(0, ScreenToMap(e.ClipRectangle.X));
+ y1 = Math.Max(0, ScreenToMap(e.ClipRectangle.Y));
+
+ x2 = Math.Min(width - 1, ScreenToMap(e.ClipRectangle.Right));
+ y2 = Math.Min(height -1, ScreenToMap(e.ClipRectangle.Bottom));
+
+ RedrawMap(x1,y1,x2,y2,e.Graphics);
+ }
+ }
+}