From b82c18064f9bcf19a8f51408a6883faee91a5d75 Mon Sep 17 00:00:00 2001 From: codeimp Date: Thu, 23 Oct 2008 13:33:59 +0000 Subject: [PATCH] more work on error checking --- Source/BuilderModes/BuilderModes.csproj | 1 + .../ErrorChecks/CheckStuckedThings.cs | 66 ++++++++++++- .../BuilderModes/ErrorChecks/ErrorChecker.cs | 16 ++-- .../ErrorChecks/ResultStuckedThing.cs | 74 ++++++++++++++ .../BuilderModes/Interface/ErrorCheckForm.cs | 96 ++++++++++++++++--- 5 files changed, 226 insertions(+), 27 deletions(-) create mode 100644 Source/BuilderModes/ErrorChecks/ResultStuckedThing.cs diff --git a/Source/BuilderModes/BuilderModes.csproj b/Source/BuilderModes/BuilderModes.csproj index 4179218a..2f6db9a2 100644 --- a/Source/BuilderModes/BuilderModes.csproj +++ b/Source/BuilderModes/BuilderModes.csproj @@ -45,6 +45,7 @@ + diff --git a/Source/BuilderModes/ErrorChecks/CheckStuckedThings.cs b/Source/BuilderModes/ErrorChecks/CheckStuckedThings.cs index 8046323c..c1e26449 100644 --- a/Source/BuilderModes/ErrorChecks/CheckStuckedThings.cs +++ b/Source/BuilderModes/ErrorChecks/CheckStuckedThings.cs @@ -61,21 +61,81 @@ namespace CodeImp.DoomBuilder.BuilderModes // Go for all the things foreach(Thing t in General.Map.Map.Things) { - // Make square from thing + // Make square coordinates from thing + Vector2D lt = new Vector2D(t.Position.x - t.Size, t.Position.y - t.Size); + Vector2D rb = new Vector2D(t.Position.x + t.Size, t.Position.y + t.Size); - // Go for all the lines + // Go for all the lines to see if this thing is stucked + bool stucked = false; foreach(Linedef l in General.Map.Map.Linedefs) { - // Test if the line intersects the square + // Test only single-sided lines + if(l.Back == null) + { + // Test if line ends are inside the thing + if(PointInRect(lt, rb, l.Start.Position) || + PointInRect(lt, rb, l.End.Position)) + { + // Thing stucked in line! + stucked = true; + } + // Test if the line intersects the square + else if(Line2D.GetIntersection(l.Start.Position, l.End.Position, lt.x, lt.y, rb.x, lt.y) || + Line2D.GetIntersection(l.Start.Position, l.End.Position, rb.x, lt.y, rb.x, rb.y) || + Line2D.GetIntersection(l.Start.Position, l.End.Position, rb.x, rb.y, lt.x, rb.y) || + Line2D.GetIntersection(l.Start.Position, l.End.Position, lt.x, rb.y, lt.x, lt.y)) + { + // Thing stucked in line! + stucked = true; + } + } + } + + // Stucked? + if(stucked) + { + // Make result + ResultStuckedThing r = new ResultStuckedThing(t); + SubmitResult(r); + } + else + { + // Get the nearest line to see if the thing is outside the map + bool outside = false; + Linedef l = General.Map.Map.NearestLinedef(t.Position); + if(l.SideOfLine(t.Position) <= 0) + { + outside = (l.Front == null); + } + else + { + outside = (l.Back == null); + } + // Outside the map? + if(outside) + { + // Make result + ResultStuckedThing r = new ResultStuckedThing(t); + SubmitResult(r); + } } // Handle thread interruption try { Thread.Sleep(0); } catch(ThreadInterruptedException) { return; } + + // We are making progress! + AddProgress(1); } } + // Point in rect? + private bool PointInRect(Vector2D lt, Vector2D rb, Vector2D p) + { + return (p.x >= lt.x) && (p.x <= rb.x) && (p.y >= lt.y) && (p.y <= rb.y); + } + #endregion } } diff --git a/Source/BuilderModes/ErrorChecks/ErrorChecker.cs b/Source/BuilderModes/ErrorChecks/ErrorChecker.cs index 13370654..6d4908e6 100644 --- a/Source/BuilderModes/ErrorChecks/ErrorChecker.cs +++ b/Source/BuilderModes/ErrorChecks/ErrorChecker.cs @@ -76,19 +76,17 @@ namespace CodeImp.DoomBuilder.BuilderModes // This submits a result to show in the results list protected void SubmitResult(ErrorResult result) { - + BuilderPlug.Me.ErrorCheckForm.SubmitResult(result); } // This reports a change in progress - protected void ShowProgress(int percent) + protected void AddProgress(int amount) { - // Any change? - if(percent > lastprogress) - { - if(percent < 0) percent = 0; - if(percent > totalprogress) percent = totalprogress; - lastprogress = percent; - } + // Make changes + if(amount < 0) amount = 0; + if((lastprogress + amount) > totalprogress) throw new InvalidOperationException("Cannot exceed total progress amount!"); + lastprogress += amount; + BuilderPlug.Me.ErrorCheckForm.AddProgressValue(amount); } // This sets the total progress diff --git a/Source/BuilderModes/ErrorChecks/ResultStuckedThing.cs b/Source/BuilderModes/ErrorChecks/ResultStuckedThing.cs new file mode 100644 index 00000000..f2847e05 --- /dev/null +++ b/Source/BuilderModes/ErrorChecks/ResultStuckedThing.cs @@ -0,0 +1,74 @@ + +#region ================== Copyright (c) 2007 Pascal vd Heiden + +/* + * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com + * This program is released under GNU General Public License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#endregion + +#region ================== Namespaces + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Windows.Forms; +using System.IO; +using System.Reflection; +using CodeImp.DoomBuilder.Windows; +using CodeImp.DoomBuilder.IO; +using CodeImp.DoomBuilder.Map; +using CodeImp.DoomBuilder.Rendering; +using CodeImp.DoomBuilder.Geometry; +using CodeImp.DoomBuilder.Editing; +using CodeImp.DoomBuilder.Actions; +using CodeImp.DoomBuilder.Types; +using CodeImp.DoomBuilder.Config; + +#endregion + +namespace CodeImp.DoomBuilder.BuilderModes +{ + public class ResultStuckedThing : ErrorResult + { + #region ================== Variables + + private Thing thing; + + #endregion + + #region ================== Properties + + #endregion + + #region ================== Constructor / Destructor + + // Constructor + public ResultStuckedThing(Thing t) + { + // Initialize + this.thing = t; + } + + #endregion + + #region ================== Methods + + // This must return the string that is displayed in the listbox + public override string ToString() + { + return "Stucked thing '" + General.Map.Config.GetThingInfo(thing.Type).Title + "' at " + thing.Position.x + ", " + thing.Position.y; + } + + #endregion + } +} diff --git a/Source/BuilderModes/Interface/ErrorCheckForm.cs b/Source/BuilderModes/Interface/ErrorCheckForm.cs index a8f58ad1..99e1712f 100644 --- a/Source/BuilderModes/Interface/ErrorCheckForm.cs +++ b/Source/BuilderModes/Interface/ErrorCheckForm.cs @@ -39,6 +39,14 @@ namespace CodeImp.DoomBuilder.BuilderModes { public partial class ErrorCheckForm : DelayedForm { + #region ================== Delegates + + private delegate void CallVoidMethodDeletage(); + private delegate void CallIntMethodDelegate(int i); + private delegate void CallResultMethodDelegate(ErrorResult r); + + #endregion + #region ================== Constants // Constants @@ -96,13 +104,75 @@ namespace CodeImp.DoomBuilder.BuilderModes } #endregion + + #region ================== Cross-Thread Calls + + public void SubmitResult(ErrorResult result) + { + if(results.InvokeRequired) + { + CallResultMethodDelegate d = new CallResultMethodDelegate(SubmitResult); + try { progress.Invoke(d, result); } catch(ThreadInterruptedException) { } + } + else + { + results.Items.Add(result); + } + } + private void SetProgressMaximum(int maximum) + { + if(progress.InvokeRequired) + { + CallIntMethodDelegate d = new CallIntMethodDelegate(SetProgressMaximum); + try { progress.Invoke(d, maximum); } catch(ThreadInterruptedException) { } + } + else + { + progress.Maximum = maximum; + } + } + + public void AddProgressValue(int value) + { + if(progress.InvokeRequired) + { + CallIntMethodDelegate d = new CallIntMethodDelegate(AddProgressValue); + try { progress.Invoke(d, value); } catch(ThreadInterruptedException) { } + } + else + { + progress.Value += value; + } + } + + private void StopChecking() + { + if(this.InvokeRequired) + { + CallVoidMethodDeletage d = new CallVoidMethodDeletage(StopChecking); + this.Invoke(d); + } + else + { + checksthread = null; + running = false; + progress.Value = 0; + buttoncheck.Text = "Start Analysis"; + Cursor.Current = Cursors.Default; + } + } + + #endregion + #region ================== Methods - + // This runs in a seperate thread to manage the checking threads private void RunChecks() { List checkers = new List(); + List threads = new List(); + int maxthreads = Environment.ProcessorCount; int totalprogress = 0; int nextchecker = 0; @@ -145,16 +215,14 @@ namespace CodeImp.DoomBuilder.BuilderModes } // Setup - progress.Maximum = totalprogress; - const int maxthreads = Environment.ProcessorCount; - List threads = new List(maxthreads); + SetProgressMaximum(totalprogress); // Continue while threads are running or checks are to be done while((nextchecker < checkers.Count) || (threads.Count > 0)) { // Start new thread when less than maximum number of // threads running and there is more work to be done - while((threads.Count < maxthreads) && (checkers.Count > 0)) + while((threads.Count < maxthreads) && (nextchecker < checkers.Count)) { ErrorChecker c = checkers[nextchecker++]; Thread t = new Thread(new ThreadStart(c.Run)); @@ -165,7 +233,7 @@ namespace CodeImp.DoomBuilder.BuilderModes } // Remove threads that are done - for(int i = threads.Count; i >= 0; i--) + for(int i = threads.Count - 1; i >= 0; i--) if(!threads[i].IsAlive) threads.RemoveAt(i); // Handle thread interruption @@ -184,7 +252,7 @@ namespace CodeImp.DoomBuilder.BuilderModes checkers = null; // Done - progress.Value = 0; + StopChecking(); } #endregion @@ -205,24 +273,22 @@ namespace CodeImp.DoomBuilder.BuilderModes // Start/stop private void buttoncheck_Click(object sender, EventArgs e) { - Cursor.Current = Cursors.WaitCursor; - // Currently running? if(running) { - // Stop checking + Cursor.Current = Cursors.WaitCursor; checksthread.Interrupt(); - checksthread.Join(); - checksthread = null; - running = false; } else { + Cursor.Current = Cursors.WaitCursor; + // Open the results panel this.Size = new Size(this.Width, this.Height - this.ClientSize.Height + resultspanel.Top + resultspanel.Height); progress.Value = 0; results.Items.Clear(); resultspanel.Visible = true; + buttoncheck.Text = "Abort Analysis"; // Start checking running = true; @@ -230,9 +296,9 @@ namespace CodeImp.DoomBuilder.BuilderModes checksthread.Name = "Checking Management"; checksthread.Priority = ThreadPriority.Normal; checksthread.Start(); + + Cursor.Current = Cursors.Default; } - - Cursor.Current = Cursors.Default; } #endregion