using CommonAI.RTS; using CommonLang.Vector; using CommonAI.RTS.Manhattan; using CommonAI.Zone; using CommonAI.Zone.ZoneEditor; using CommonLang; using GameEditorPlugin.Win32; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; using CommonAI.Zone.Helper; using CommonLang.Property; namespace GameEditorPlugin.Tools { public partial class FormAstar : Form { private AStarTerrain display; private Vector2 mPathBegin; public static Vector2 pic_lastMouesPos = new Vector2(0, 0); private string mScenePath; public FormAstar(string scene_path = null, TerrainDefinitionMap define = null, SceneData zone = null) { InitializeComponent(); this.mScenePath = scene_path; this.display = new AStarTerrain(define); try { display.RandomSeed = DateTime.Now.Millisecond; display.Reset(zone); } catch (Exception err) { MessageBox.Show(err.Message); } } private void FormAstar_Load(object sender, EventArgs e) { this.displayTerrainPanel1.Display = display; this.display.PathFinder.SpaceDivEnableDistance = (int)num_EnableSpaceDivDistance.Value; this.display.PathFinder.SpaceOptimizePathLimitDistance = (int)num_OptimizePathLimit.Value; this.display.SetSpaceDiv((int)num_SpaceDivDistance.Value); this.display.GenShowItems(toolStripDropDownButton3); } private void resetToolStripMenuItem_Click(object sender, EventArgs e) { display.Reset(); } private void btn_LoadScene_Click(object sender, EventArgs e) { OpenFileDialog fd = new OpenFileDialog(); if (mScenePath != null) { fd.InitialDirectory = mScenePath; } if (fd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { try { string text = File.ReadAllText(fd.FileName); SceneData sd = EditorTemplates.DataFromXML(text); display.Reset(sd); } catch (Exception err) { MessageBox.Show(err.Message); } } } private void btn_FillTerrain_Click(object sender, EventArgs e) { btn_CleanTerrain.Checked = false; } private void btn_CleanTerrain_Click(object sender, EventArgs e) { btn_FillTerrain.Checked = false; } private void num_SpaceDivDistance_ValueChanged(object sender, EventArgs e) { this.display.SetSpaceDiv((int)num_SpaceDivDistance.Value); } private void num_EnableSpaceDivDistance_ValueChanged(object sender, EventArgs e) { this.display.PathFinder.SpaceDivEnableDistance = (int)num_EnableSpaceDivDistance.Value; } private void num_OptimizePathLimit_ValueChanged(object sender, EventArgs e) { this.display.PathFinder.SpaceOptimizePathLimitDistance = (int)num_OptimizePathLimit.Value; } private void displayTerrainPanel1_PictureBoxMouseDown(object sender, MouseEventArgs e) { float wx = display.screenToWorldX(e.X); float wy = display.screenToWorldY(e.Y); pic_lastMouesPos.SetX(wx); pic_lastMouesPos.SetY(wy); if (btn_FillTerrain.Checked || btn_CleanTerrain.Checked) { display.ShowPoint = true; int size = int.Parse(com_FillTerrainSize.Text); display.SetPointer(wx, wy, size); if (e.Button == System.Windows.Forms.MouseButtons.Left) { display.FillTerrain(btn_FillTerrain.Checked); } } else if (mPathBegin == null) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { mPathBegin = new Vector2(e.X, e.Y); display.BeginFindPath(wx, wy); } } else if (!btn_FreeMove.Checked) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { mPathBegin = null; display.EndFindPath(wx, wy, btn_Optimize.Checked); } } } private void displayTerrainPanel1_PictureBoxMouseMove(object sender, MouseEventArgs e) { float wx = display.screenToWorldX(e.X); float wy = display.screenToWorldY(e.Y); pic_lastMouesPos.SetX(wx); pic_lastMouesPos.SetY(wy); display.ShowPoint = false; if (btn_FillTerrain.Checked || btn_CleanTerrain.Checked) { display.ShowPoint = true; int size = int.Parse(com_FillTerrainSize.Text); display.SetPointer(wx, wy, size); if (e.Button == System.Windows.Forms.MouseButtons.Left) { display.FillTerrain(btn_FillTerrain.Checked); } } else if (btn_FreeMove.Checked) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { if (mPathBegin != null) { display.EndFindPath(wx, wy, btn_Optimize.Checked); } } } } private void displayTerrainPanel1_PictureBoxMouseUp(object sender, MouseEventArgs e) { float wx = display.screenToWorldX(e.X); float wy = display.screenToWorldY(e.Y); if (btn_FillTerrain.Checked) { } else if (btn_FreeMove.Checked) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { if (mPathBegin != null) { mPathBegin = null; display.EndFindPath(wx, wy, btn_Optimize.Checked); } } } } class AStarTerrain : DisplayManhattanTerrain { [Desc("显示点", "show")] public bool ShowPoint = true; private const int BLOCK_VALUE = (int)0x7F00FF00; private int random_seed_index = 1; private ZoneInfo zone_data; private TerrainDefinitionMap define; private AstarManhattan path_finder; private AstarManhattan.MWayPoint current_path; private Vector2 path_begin; private Vector2 path_end; private long last_pathfind_tick = 0; private long last_touchmap_tick = 0; private Vector2 point_pos = new Vector2(); private int point_size = 1; public override AstarManhattan PathFinder { get { return path_finder; } } public override int SpaceDivSize { get { return path_finder.SpaceDivSize; } } public int RandomSeed { get { return random_seed_index; } set { random_seed_index = value; } } public AStarTerrain(TerrainDefinitionMap define) { this.define = define; this.ShowSpaceDiv = true; this.ShowTerrainMesh = true; } public void SetSpaceDiv(int value) { if (zone_data != null) { if (path_finder == null || path_finder.SpaceDivSize != value) { this.path_finder = new AstarManhattan(this.zone_data.TemplateID, new EditorZoneManhattanMap(zone_data, define), true, value); } } } public void Reset(SceneData sd = null) { if (sd == null) { Random random = new Random(random_seed_index); random_seed_index++; this.zone_data = new ZoneInfo(random.Next(50, 200), random.Next(50, 200), 32, 32); for (int x = 0; x < zone_data.XCount; x++) { for (int y = 0; y < zone_data.YCount; y++) { zone_data.TerrainMatrix[x, y] = CUtils.RandomPercent(random, 85) ? 0 : BLOCK_VALUE; } } this.InitTerrain(zone_data); } else { zone_data = (ZoneInfo)sd.ZoneData.Clone(); // zone_data.mGridCellW = sd.; // zone_data.mGridCellH = 32; this.InitTerrain(zone_data); } } public override void Dispose() { } //-------------------------------------------------------------------------------------- protected override void InitTerrain(ZoneInfo zone) { base.InitTerrain(zone); if (path_finder != null) { path_finder.Dispose(); } this.path_finder = new AstarManhattan(zone.TemplateID, new EditorZoneManhattanMap(zone, define), true, 8); } internal void SetPointer(float sx, float sy, int r) { point_pos.SetX(sx); point_pos.SetY(sy); point_size = r; } internal void BeginFindPath(float sx, float sy) { path_begin = new Vector2(sx, sy); path_end = null; current_path = null; } internal void EndFindPath(float dx, float dy, bool optimize) { path_end = new Vector2(dx, dy); { var sw = Stopwatch.StartNew(); path_finder.findPath(path_begin.X, path_begin.Y, dx, dy, out current_path, optimize); sw.Stop(); last_pathfind_tick = sw.ElapsedTicks; } } internal void FillTerrain(bool block) { int bx, by; path_finder.PosToBlock(point_pos.X, point_pos.Y, out bx, out by); path_finder.FillTerrainByBlock( (bx - point_size / 2), (by - point_size / 2), (point_size), (point_size), block ? BLOCK_VALUE : 0); } //-------------------------------------------------------------------------------------- #region Render private Pen path_pen = new Pen(Color.Red); private SolidBrush path_brush = new SolidBrush(Color.FromArgb(0x80, Color.Gray)); private Pen pen_point = new Pen(Color.FromArgb(0xA0, 0xff, 0xff, 0xff)); private Pen pen_begin = new Pen(Color.FromArgb(0xFF, 0, 0xff, 0)); private Pen pen_space_div = new Pen(Color.FromArgb(0x20, 0xff, 0xff, 0xff)); private Pen pen_space_div_next = new Pen(Color.FromArgb(0x20, 0xff, 0xff, 0xff)); //private Brush brush_mesh = new SolidBrush(Color.FromArgb(0x80, 0xff, 0xff, 0xff)); private Pen pen_path_begin = new Pen(Color.FromArgb(0x10, 0xFF, 0xFF, 0xFF)); private Pen pen_ray = new Pen(Color.Yellow); public override void render(Graphics g) { pen_point.Width = pen_space_div_next.Width = pen_space_div.Width = pen_begin.Width = path_pen.Width = pen_path_begin.Width = pen_ray.Width = 1 / getCameraScale(); base.render(g); } protected override void renderTerrain(Graphics g, RectangleF rect) { base.renderTerrain(g, rect); if (ShowPoint) { int bx, by; path_finder.PosToBlock(point_pos.X, point_pos.Y, out bx, out by); g.DrawRectangle(pen_point, (bx - point_size / 2) * base.CellW, (by - point_size / 2) * base.CellH, (point_size) * base.CellW, (point_size) * base.CellH); } } protected override void renderCell(Graphics g, int bx, int by, int flag) { base.renderCell(g, bx, by, flag); if (ShowSpaceDiv && path_finder != null && path_finder.SpaceDivSize > 0) { if (bx % path_finder.SpaceDivSize == 0 && by % path_finder.SpaceDivSize == 0) { int cx = bx / path_finder.SpaceDivSize; int cy = by / path_finder.SpaceDivSize; var sn = path_finder.GetSpaceMapNode(cx, cy); if (sn != null && sn.AnchorNode != null) { g.DrawRectangle(pen_space_div, sn.AnchorNode.BX * CellW, sn.AnchorNode.BY * CellH, CellW, CellH); foreach (var next in sn.NextsSpaceNode) { var link = sn.GetNextLink(next); if (link != null) { renderPath(g, new Vector2(sn.AnchorNode.PosX, sn.AnchorNode.PosY), link, pen_space_div_next, pen_space_div_next); } } } } } } protected override void renderMeshCell(Graphics g, AstarManhattan.MMapNode tn) { //if (tn.Mesh != null) { //g.FillRectangle(brush_mesh, tn.BX * CellW, tn.BY * CellH, CellW, CellH); base.renderMeshCell(g, tn); } } protected void renderPath(Graphics g, Vector2 path_begin, AstarManhattan.MWayPoint path, Pen pen_line, Pen pen_begin = null, Brush pen_brush = null) { if (path_begin != null && pen_begin != null) { g.DrawLine(pen_begin, path_begin.X, path_begin.Y, path.PosX, path.PosY); } if (path != null) { foreach (AstarManhattan.MWayPoint wp in path) { if (pen_brush != null) { g.FillRectangle(pen_brush, wp.BX * CellW, wp.BY * CellH, CellW, CellH); } if (wp.Next != null) { g.DrawLine(pen_line, wp.PosX, wp.PosY, wp.Next.PosX, wp.Next.PosY); } } } } protected override void renderObjects(Graphics g, RectangleF worldBounds) { if (path_begin != null) { g.DrawArc(path_pen, path_begin.X - 1, path_begin.Y - 1, 2, 2, 0, 360); } if (path_end != null) { g.DrawArc(path_pen, path_end.X - 1, path_end.Y - 1, 2, 2, 0, 360); } if (path_begin != null && path_end != null) { g.DrawLine(pen_path_begin, path_begin.X, path_begin.Y, path_end.X, path_end.Y); float tx, ty, td; Stopwatch watch = new Stopwatch(); watch.Start(); bool ret = (path_finder.GetLineTouchPoint(path_begin.X, path_begin.Y, path_end.X, path_end.Y, out tx, out ty, out td)); watch.Stop(); last_touchmap_tick = watch.ElapsedTicks; if (ret) { g.DrawLine(pen_ray, path_begin.X, path_begin.Y, tx, ty); g.DrawArc(pen_ray, tx - 1, ty - 1, 2, 2, 0, 360); } else { g.DrawLine(pen_ray, path_begin.X, path_begin.Y, path_end.X, path_end.Y); g.DrawArc(pen_ray, path_end.X - 1, path_end.Y - 1, 2, 2, 0, 360); } } if (current_path != null) { renderPath(g, path_begin, current_path, path_pen, pen_begin, path_brush); } } protected override void renderSpaceDiv(Graphics g, RectangleF rect) { base.renderSpaceDiv(g, rect); } protected override void renderScreen(Graphics g, RectangleF worldBounds) { g.DrawString( string.Format(" mnodes={0}/{1} mesh={2} wps={3} pathfind={4}(t) touchmap={5}(t), Mouse=({6},{7})", AstarManhattan.MMapNode.ActiveObjectCount, (PathFinder != null ? (PathFinder.MMap.XCount * PathFinder.MMap.YCount) : 0), AstarManhattan.MMapNode.BlockMesh.ActiveObjectCount, AstarManhattan.MWayPoint.ActiveObjectCount, last_pathfind_tick, last_touchmap_tick, pic_lastMouesPos.X, pic_lastMouesPos.Y ), Control.DefaultFont, new SolidBrush(Color.White), 10, 10); } #endregion } private void gCToolStripMenuItem_Click(object sender, EventArgs e) { GC.Collect(); } } }