using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; using CommonAI.Zone.ZoneEditor.Plugin.EditorToScene; using CommonAI.Zone.ZoneEditor.Plugin.SceneToEditor; using CommonAI.Zone; using CommonAI.Zone.ZoneEditor; using CommonAI.RTS; using CommonLang.Vector; using System.Collections; using CommonAI.Zone.Instance; using CommonLang; using GameEditorPlugin.Win32; using CommonFroms.Drawing; using CommonAI.RTS.Manhattan; using GameEditorPlugin.Tools; using CommonAI.Zone.Helper; namespace GameEditorPlugin.Win32.Editor { public abstract class EditorObject : DisplayObject { readonly private SceneObjectData Data; readonly public EditorWorld world; readonly public Pen pen; readonly public Pen pen_hight; readonly public SolidBrush brush; public bool Selected = false; public abstract bool Pickable { get; } public abstract float Direction { get; set; } public abstract bool IsDirectionality { get; } public EditorObject(EditorWorld wd, SceneObjectData data) { this.world = wd; this.Data = data; this.pen = new Pen(Color.FromArgb(data.Color)); this.pen_hight = new Pen(Color.White); this.brush = new SolidBrush(Color.FromArgb(data.Color)); } public virtual bool touch(float x, float y) { return CMath.includeRectPoint2( this.X + this.LocalBounds.X, this.Y + this.LocalBounds.Y, this.LocalBounds.Width, this.LocalBounds.Height, x, y); } public string Name { get { return Data.Name; } set { Data.Name = value; } } public override float X { get { return Data.X; } } public override float Y { get { return Data.Y; } } public override float Z { get { return 0; } } public void SetPos(float x, float y) { this.Data.X = x; this.Data.Y = y; } public override void render_begin(Graphics g) { float penscale = 1f / world.getCameraScale(); pen.Width = pen_hight.Width = penscale; } public override void render_end(Graphics g) { base.render_end(g); if (Selected) this.render_selected(g); } protected virtual void render_selected(Graphics g) { g.DrawEllipse(pen_hight, LocalBounds); if (IsDirectionality) { float r = Math.Max(LocalBounds.Width, LocalBounds.Height) * 1.25f * 0.5f; g.DrawLine(pen_hight, 0, 0, (float)Math.Cos(Direction) * r, (float)Math.Sin(Direction) * r); } } public virtual void render_in_terrain(Graphics g) { } } public class EditorUnit : EditorObject { readonly public UnitData Data; readonly public UnitInfo Info; private RectangleF mLocalBounds; private static Pen pen_hitbody = new Pen(Color.Green); private static Pen pen_guardrange = new Pen(Color.Yellow); public override RectangleF LocalBounds { get { return mLocalBounds; } } public override bool Pickable { get { return EditorDisplayPanel.ShowUnit; } } public override bool Visible { get { return EditorDisplayPanel.ShowAll || Pickable; } } public override float Direction { get { return Data.Direction; } set { this.Data.Direction = value; } } public override bool IsDirectionality { get { return true; } } public EditorUnit(EditorWorld wd, MsgPutUnit unit) : base(wd, unit.Data) { this.Data = unit.Data; this.Info = unit.UnitData; if (Info != null) { this.mLocalBounds = new RectangleF( -Info.BodySize, -Info.BodySize, Info.BodySize * 2, Info.BodySize * 2); } else { this.mLocalBounds = new RectangleF(-1, -1, 2, 2); } } public override bool touch(float x, float y) { if (Info != null) { return CMath.includeRoundPoint(this.X, this.Y, this.Info.BodySize, x, y); } return base.touch(x, y); } public override void render(Graphics g) { float penscale = 1f / world.getCameraScale(); pen.Width = pen_hight.Width = pen_hitbody.Width = pen_guardrange.Width = penscale; g.DrawEllipse(pen, mLocalBounds); if (Selected) { g.FillEllipse(brush, mLocalBounds); if(Info != null) { g.DrawArc(pen_hitbody, -Info.BodyHitSize, -Info.BodyHitSize, Info.BodyHitSize * 2, Info.BodyHitSize * 2, 0, 360); g.DrawArc(pen_guardrange, -Info.GuardRange, -Info.GuardRange, Info.GuardRange * 2, Info.GuardRange * 2, 0, 360); } g.DrawLine(pen_hight, 0, 0, (float)Math.Cos(Data.Direction) * mLocalBounds.Width, (float)Math.Sin(Data.Direction) * mLocalBounds.Width); } else { g.DrawLine(pen, 0, 0, (float)Math.Cos(Data.Direction) * mLocalBounds.Width, (float)Math.Sin(Data.Direction) * mLocalBounds.Width); } } } public class EditorItem : EditorObject { readonly public ItemData Data; readonly public ItemTemplate Info; private RectangleF mLocalBounds; public override RectangleF LocalBounds { get { return mLocalBounds; } } public override bool Pickable { get { return EditorDisplayPanel.ShowItem; } } public override bool Visible { get { return EditorDisplayPanel.ShowAll || Pickable; } } public override float Direction { get { return Data.Direction; } set { this.Data.Direction = value; } } public override bool IsDirectionality { get { return true; } } public EditorItem(EditorWorld wd, MsgPutItem item) : base(wd, item.Data) { this.Data = item.Data; this.Info = item.Item; if (Info != null) { this.mLocalBounds = new RectangleF( -Info.BodySize, -Info.BodySize, Info.BodySize * 2, Info.BodySize * 2); } else { this.mLocalBounds = new RectangleF(-1, -1, 2, 2); } } public override bool touch(float x, float y) { if (Info != null) { return CMath.includeRoundPoint(this.X, this.Y, this.Info.BodySize, x, y); } return base.touch(x, y); } public override void render(Graphics g) { float penscale = 1f / world.getCameraScale(); pen.Width = pen_hight.Width = penscale; g.DrawEllipse(pen, mLocalBounds); if (Selected) { g.FillEllipse(brush, mLocalBounds); g.DrawLine(pen_hight, 0, 0, (float)Math.Cos(Data.Direction) * mLocalBounds.Width, (float)Math.Sin(Data.Direction) * mLocalBounds.Width); } else { g.DrawLine(pen, 0, 0, (float)Math.Cos(Data.Direction) * mLocalBounds.Width, (float)Math.Sin(Data.Direction) * mLocalBounds.Width); } } } public class EditorRegion : EditorObject { readonly public RegionData Data; public override bool Pickable { get { return EditorDisplayPanel.ShowRegion; } } public override bool Visible { get { return EditorDisplayPanel.ShowAll || Pickable; } } public override float Direction { get { return 0; } set { } } public override bool IsDirectionality { get { return false; } } public override RectangleF LocalBounds { get { if (Data.RegionType == RegionData.Shape.RECTANGLE) { return new RectangleF(-Data.W / 2, -Data.H / 2, Data.W, Data.H); } else if (Data.RegionType == RegionData.Shape.ROUND) { return new RectangleF(-Data.W / 2, -Data.W / 2, Data.W, Data.W); } else { return new RectangleF(-Data.W / 2, -Data.W / 2, Data.W, Data.W); } } } public EditorRegion(EditorWorld wd, MsgPutRegion data) : base(wd, data.Data) { this.Data = data.Data; } public override bool touch(float x, float y) { if (Data.RegionType == RegionData.Shape.RECTANGLE) { return base.touch(x, y); } else if(Data.RegionType == RegionData.Shape.ROUND) { return CMath.includeRoundPoint(X, Y, Data.W / 2, x, y); } else if (Data.RegionType == RegionData.Shape.STRIP) { float line_r = Data.W / 2; Vector2 p = new Vector2(X, Y); Vector2 q = new Vector2(X, Y); MathVector.movePolar(p, Data.StripDirection, -Data.H / 2); MathVector.movePolar(q, Data.StripDirection, +Data.H / 2); return CMath.includeStripWidthPoint(p.X, p.Y, q.X, q.Y, line_r, x, y); } return base.touch(x, y); } public override void render(Graphics g) { float penscale = 1f / world.getCameraScale(); pen.Width = pen_hight.Width = penscale; if (Data.RegionType == RegionData.Shape.RECTANGLE) { g.DrawRectangle(pen, -Data.W / 2, -Data.H / 2, Data.W, Data.H); if (Selected) { g.FillRectangle(brush, -Data.W / 2, -Data.H / 2, Data.W, Data.H); } } else if (Data.RegionType == RegionData.Shape.ROUND) { g.DrawEllipse(pen, -Data.W / 2, -Data.W / 2, Data.W, Data.W); if (Selected) { g.FillEllipse(brush, -Data.W / 2, -Data.W / 2, Data.W, Data.W); } } else if (Data.RegionType == RegionData.Shape.STRIP) { float line_r = Data.W / 2; Line2 line = new Line2(0, 0, 0, 0); MathVector.movePolar(line.p, Data.StripDirection, -Data.H / 2); MathVector.movePolar(line.q, Data.StripDirection, +Data.H / 2); DrawingUtils.FillLineRect(g, brush, line.p.X, line.p.Y, line.q.X, line.q.Y, line_r); } } } public class EditorDecoration : EditorObject { private static SolidBrush deco_block_brush = new SolidBrush(Color.FromArgb(0x80, 0xFF, 0xFF, 0xFF)); readonly public DecorationData Data; public override bool Pickable { get { return EditorDisplayPanel.ShowDecoration; } } public override bool Visible { get { return EditorDisplayPanel.ShowAll || Pickable; } } public override bool IsDirectionality { get { return true; } } public override float Direction { get { return Data.Direction; } set { if (Data.RegionType == DecorationData.Shape.STRIP) { this.Data.StripDirection = value; } this.Data.Direction = value; } } public override RectangleF LocalBounds { get { if (Data.RegionType == DecorationData.Shape.STRIP) { return new RectangleF(-Data.W / 2, -Data.W / 2, Data.W, Data.W); } else { return new RectangleF(-Data.W / 2, -Data.H / 2, Data.W, Data.H); } } } public EditorDecoration(EditorWorld wd, MsgPutDecoration data) : base(wd, data.Data) { this.Data = data.Data; } public override bool touch(float x, float y) { if (Data.RegionType == DecorationData.Shape.RECTANGLE) { return base.touch(x, y); } else if (Data.RegionType == DecorationData.Shape.ROUND) { return CMath.includeEllipsePoint(X, Y, Data.W / 2, Data.H / 2, x, y); } else if (Data.RegionType == DecorationData.Shape.STRIP) { float line_r = Data.W / 2; Vector2 p = new Vector2(X, Y); Vector2 q = new Vector2(X, Y); MathVector.movePolar(p, Data.StripDirection, -Data.H / 2); MathVector.movePolar(q, Data.StripDirection, +Data.H / 2); return CMath.includeStripWidthPoint(p.X, p.Y, q.X, q.Y, line_r, x, y); } return base.touch(x, y); } public override void render(Graphics g) { float penscale = 1f / world.getCameraScale(); pen.Width = pen_hight.Width = penscale; if (Data.RegionType == DecorationData.Shape.RECTANGLE) { if (Selected) { g.FillRectangle(brush, -Data.W / 2, -Data.H / 2, Data.W, Data.H); } g.DrawRectangle(pen, -Data.W / 2, -Data.H / 2, Data.W, Data.H); } else if (Data.RegionType == DecorationData.Shape.ROUND) { if (Selected) { g.FillEllipse(brush, -Data.W / 2, -Data.H / 2, Data.W, Data.H); } g.DrawEllipse(pen, -Data.W / 2, -Data.H / 2, Data.W, Data.H); } else if (Data.RegionType == DecorationData.Shape.STRIP) { float line_r = Data.W / 2; Line2 line = new Line2(0, 0, 0, 0); MathVector.movePolar(line.p, Data.StripDirection, -Data.H / 2); MathVector.movePolar(line.q, Data.StripDirection, +Data.H / 2); if (Selected) { DrawingUtils.FillLineRect(g, brush, line.p.X, line.p.Y, line.q.X, line.q.Y, line_r); } g.DrawEllipse(pen, -Data.W / 2, -Data.W / 2, Data.W, Data.W); DrawingUtils.DrawLineRect(g, pen, line.p.X, line.p.Y, line.q.X, line.q.Y, line_r); } if (this.Selected) { using (var pts = ListObjectPool.AllocAutoRelease()) { var pen_res = new Pen(Color.Yellow); pen_res.Width = penscale; Data.GetResourcePoints(pts); var st = g.Save(); try { if (Data.ShapDirectionality) { g.RotateTransform(CMath.RadiansToDegrees(Data.StripDirection)); } foreach (var pt in pts) { DrawingUtils.DrawCross(g, pen_res, pt.X, pt.Y, 2 * penscale); } } finally { g.Restore(st); } } } } public override void render_begin(Graphics g) { base.render_begin(g); } public override void render_in_terrain(Graphics g) { if (this.Data.Blockable) { if (this.Selected || this.Pickable) { var ed = this; var bounds = ed.LocalBounds; AstarManhattan.ForEachTerrainAction action = (bx, by) => { g.FillRectangle(deco_block_brush, bx * world.CellW, by * world.CellH, world.CellW, world.CellH); }; var mmap = world.ManhattanMap; switch (ed.Data.RegionType) { case DecorationData.Shape.RECTANGLE: AstarManhattan.ForEachTerrainRect(mmap, ed.X + bounds.X, ed.Y + bounds.Y, bounds.Width, bounds.Height, action); break; case DecorationData.Shape.ROUND: AstarManhattan.ForEachTerrainEllipse(mmap, ed.X + bounds.X, ed.Y + bounds.Y, bounds.Width, bounds.Height, action); break; case DecorationData.Shape.STRIP: Line2 line = new Line2(Data.X, Data.Y, Data.X, Data.Y); MathVector.movePolar(line.p, Data.StripDirection, -Data.H / 2); MathVector.movePolar(line.q, Data.StripDirection, +Data.H / 2); AstarManhattan.ForEachTerrainStripWidth(mmap, line.p.X, line.p.Y, line.q.X, line.q.Y, Data.W / 2, action); break; } } } } } public class EditorPoint : EditorObject { readonly public PointData Data; private static Pen pen_link = new Pen(Color.FromArgb(0x80, 0x80, 0x80, 0xFF)); private static Brush brush_link = new SolidBrush(Color.FromArgb(0x80, 0x80, 0x80, 0xFF)); public override RectangleF LocalBounds { get { float penscale = 1f / world.getCameraScale(); float ds = -4 * penscale; float dw = 8 * penscale; return new RectangleF(ds, ds, dw, dw); } } public override bool Pickable { get { return EditorDisplayPanel.ShowPoint; } } public override bool Visible { get { return EditorDisplayPanel.ShowAll || Pickable; } } public override float Direction { get { return 0; } set { } } public override bool IsDirectionality { get { return false; } } public EditorPoint(EditorWorld wd, MsgPutPoint data) : base(wd, data.Data) { this.Data = data.Data; } public override bool touch(float x, float y) { float penscale = 1f / world.getCameraScale(); return CMath.includeRoundPoint(this.X, this.Y, 4 * penscale, x, y); } public override void render(Graphics g) { float penscale = 1f / world.getCameraScale(); pen_link.Width = pen.Width = pen_hight.Width = penscale; if (Data.NextNames != null) { float dw = 4 * penscale; float cw = 12 * penscale; float ch = 16 * penscale; foreach (string next in Data.NextNames) { EditorObject nextobb = world.GetObject(next); if (nextobb != null) { float ox = nextobb.X - X; float oy = nextobb.Y - Y; if (Selected) { DrawingUtils.FillCursor(g, brush_link, 0, 0, ox, oy, dw, cw, ch); } DrawingUtils.DrawCursor(g, pen_link, 0, 0, ox, oy, dw, cw, ch); } } } { float ds = -4 * penscale; float dw = 8 * penscale; g.DrawEllipse(pen, ds, ds, dw, dw); if (Selected) { g.FillEllipse(brush, ds, ds, dw, dw); } } } } public class EditorArea : EditorObject { readonly public AreaData Data; private Pen pen_link; private Pen pen_border; private Vector2 old_pos = new Vector2(); private Vector2 old_size = new Vector2(); private bool area_dirty = true; private ManhattanMapAreaGenerator.ContinuousMapNode area_blocks; public override RectangleF LocalBounds { get { float penscale = 1f / world.getCameraScale(); float ds = -4 * penscale; float dw = 8 * penscale; return new RectangleF(ds, ds, dw, dw); } } public override bool Pickable { get { return EditorDisplayPanel.ShowArea; } } public override bool Visible { get { return EditorDisplayPanel.ShowAll || Pickable; } } public override float Direction { get { return 0; } set { } } public override bool IsDirectionality { get { return false; } } public EditorArea(EditorWorld wd, MsgPutArea data) : base(wd, data.Data) { this.Data = data.Data; var bc = Color.FromArgb((0xFFFFFF & data.Data.Color)); this.pen_link = new Pen(Color.FromArgb(0x40, bc)); this.pen_border = new Pen(Color.FromArgb(0xFF, bc)); } public override bool touch(float x, float y) { float penscale = 1f / world.getCameraScale(); return CMath.includeRoundPoint(this.X, this.Y, 4 * penscale, x, y); } public override void render(Graphics g) { float penscale = 1f / world.getCameraScale(); pen_border.Width = pen_link.Width = pen.Width = pen_hight.Width = penscale; { float ds = -4 * penscale; float dw = 8 * penscale; g.DrawEllipse(pen, ds, ds, dw, dw); if (Selected) { g.FillEllipse(brush, ds, ds, dw, dw); } } if (Selected) { g.DrawRectangle(pen_hight, -Data.W / 2, -Data.H / 2, Data.W, Data.H); } if (world.IsAreaDirty || old_pos.X != X || old_pos.Y != Y || old_size.X != Data.W || old_size.Y != Data.H) { this.area_dirty = true; } this.old_pos.SetX(X); this.old_pos.SetY(Y); this.old_size.SetX(Data.W); this.old_size.SetY(Data.H); } public override void render_in_terrain(Graphics g) { if (this.Selected || this.Pickable) { if (area_dirty) { area_dirty = false; area_blocks = world.MapAreaGenerator.GetContinuousMapNode(X, Y, Data.W / 2, Data.H / 2); } if (area_blocks != null) { int current_value; if (world.MapAreaGenerator.TryGetValue(X, Y, out current_value)) { int sx, sy; int sw = world.CellW; int sh = world.CellH; foreach (var index in area_blocks) { sx = index.BX * sw; sy = index.BY * sh; g.DrawRectangle(pen_link, sx, sy, sw, sh); if (area_blocks.GetIndex(index.BX, index.BY - 1) == null) g.DrawLine(pen_border, sx, sy, sx + sw, sy); if (area_blocks.GetIndex(index.BX, index.BY + 1) == null) g.DrawLine(pen_border, sx, sy + sh, sx + sw, sy + sh); if (area_blocks.GetIndex(index.BX - 1, index.BY) == null) g.DrawLine(pen_border, sx, sy, sx, sy + sh); if (area_blocks.GetIndex(index.BX + 1, index.BY) == null) g.DrawLine(pen_border, sx + sw, sy, sx + sw, sy + sh); } } } } } } }