UltimateZoneBuilder/Source/Core/Controls/DebugConsole.cs

327 lines
8.7 KiB
C#
Raw Normal View History

2014-11-13 09:43:39 +00:00
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
2014-11-13 09:43:39 +00:00
using System.Windows.Forms;
Added, Texture Browser: added "Show textures in subdirectories" checkbox (enabled by default). When enabled, textures from current PK3/PK7/Directory resource directory and it's subdirectories will be shown. Otherwise, only textures from current directory will be shown. Removed, Texture Browser: removed "Show image sizes" checkbox. "Show texture and flat sizes in browsers" preferences setting is now used instead. Fixed, Things mode: event line between pre-last and the last PatrolPoint was not drawn. Fixed, Things mode: highlight range for sizeless things (things with "fixedsize" game configuration property) was calculated incorrectly. Fixed: fixed a crash when opening Script Editor after using "Open map in current wad" command to switch to UDMF map with SCRIPTS lump when current script configuration was not saved in the wad's .dbs file. Fixed: map closing events were not triggered when using "Open map in current wad" command, which could potentially result in plugin crashes/incorrect behavior. Fixed: Sector Drawing overrides panel could trigger an exception when closing the map during resource loading. Internal: added "Debug + Profiler" solution configuration, added 2 profiling methods to DebugConsole. Internal: rewrote MainForm.DisplayStatus() / StatusInfo to handle selection info in a more structured way. Fixed, internal: some destructors could potentially be executed more than once potentially leading to exceptions. Other destructors were not called at all. Updated ZDoom_DECORATE.cfg.
2015-09-16 12:10:43 +00:00
#if PROFILE
using JetBrains.Profiler.Core.Api;
#endif
2014-11-13 09:43:39 +00:00
#endregion
namespace CodeImp.DoomBuilder
{
#region ================== Enums
[Flags]
public enum DebugMessageType
{
LOG = 1,
INFO = 2,
WARNING = 4,
ERROR = 8,
SPECIAL = 16,
2014-11-13 09:43:39 +00:00
}
#endregion
public partial class DebugConsole : UserControl
{
#region ================== Variables
private const int MAX_MESSAGES = 1024;
private static readonly List<KeyValuePair<DebugMessageType, string>> messages = new List<KeyValuePair<DebugMessageType, string>>(MAX_MESSAGES);
2014-11-13 09:43:39 +00:00
//Colors
private readonly Dictionary<DebugMessageType, Color> textcolors;
private readonly Dictionary<DebugMessageType, string> textheaders;
private DebugMessageType filters;
2014-11-13 09:43:39 +00:00
private static long starttime = -1;
private static long storedtime;
private static int counter;
private static string storedtext = string.Empty;
2014-11-13 09:43:39 +00:00
private static DebugConsole me;
#endregion
#region ================== Properties
public bool AlwaysOnTop { get { return alwaysontop.Checked; } }
public static int Counter { get { return counter; } }
2014-11-13 09:43:39 +00:00
#endregion
#region ================== Constructor
public DebugConsole()
{
InitializeComponent();
me = this;
// Setup filters
foreach(ToolStripMenuItem item in filterselector.DropDownItems)
2014-11-13 09:43:39 +00:00
{
UpdateFilters(item);
}
// Setup colors
textcolors = new Dictionary<DebugMessageType, Color> {
{ DebugMessageType.LOG, SystemColors.WindowText },
{ DebugMessageType.INFO, Color.DarkGreen },
{ DebugMessageType.WARNING, Color.DarkOrange },
{ DebugMessageType.ERROR, Color.DarkRed },
{ DebugMessageType.SPECIAL, Color.DarkMagenta }
2014-11-13 09:43:39 +00:00
};
// Setup headers
textheaders = new Dictionary<DebugMessageType, string> {
{ DebugMessageType.LOG, string.Empty},
{ DebugMessageType.INFO, string.Empty},
{ DebugMessageType.WARNING, "Warning: "},
{ DebugMessageType.ERROR, "ERROR: "},
{ DebugMessageType.SPECIAL, string.Empty}
2014-11-13 09:43:39 +00:00
};
// Word wrap?
wordwrap.Checked = console.WordWrap;
// Pending messages?
if(messages.Count > 0) UpdateMessages();
2014-11-13 09:43:39 +00:00
}
#endregion
#region ================== Methods
public static void StoreText(string text) { storedtext += text + Environment.NewLine; }
public static void SetStoredText() { Write(DebugMessageType.INFO, storedtext, false); storedtext = string.Empty; }
public static void SetText(string text) { Write(DebugMessageType.INFO, text, false); } // Useful to display frequently updated text without flickering
public static void WriteLine(string text) { Write(DebugMessageType.INFO, text + Environment.NewLine, true); }
public static void WriteLine(DebugMessageType type, string text) { Write(type, text + Environment.NewLine, true); }
public static void Write(string text) { Write(DebugMessageType.INFO, text, true); }
public static void Write(DebugMessageType type, string text) { Write(type, text, true); }
public static void Write(DebugMessageType type, string text, bool append)
2014-11-13 09:43:39 +00:00
{
if(me != null && me.InvokeRequired)
{
me.Invoke(new Action<DebugMessageType, string, bool>(Write), new object[] { type, text, append });
2014-11-13 09:43:39 +00:00
}
else
{
if(messages.Count + 1 > MAX_MESSAGES) lock (messages) { messages.RemoveAt(0); }
2014-11-13 09:43:39 +00:00
messages.Add(new KeyValuePair<DebugMessageType, string>(type, text));
if(me != null && (me.filters & type) == type)
{
me.AddMessage(type, text, true, append);
2014-11-13 09:43:39 +00:00
}
}
}
public static void Clear()
{
if(me != null && me.InvokeRequired)
2014-11-13 09:43:39 +00:00
{
me.Invoke(new Action(Clear));
}
else
{
if(me != null) me.console.Clear();
2014-11-13 09:43:39 +00:00
messages.Clear();
}
}
public static void StartTimer()
{
2019-08-08 02:02:00 +00:00
starttime = Clock.Timer.ElapsedMilliseconds;
2014-11-13 09:43:39 +00:00
}
public static void PauseTimer()
{
if(starttime == -1) throw new InvalidOperationException("DebugConsole.StartTimer() must be called before DebugConsole.PauseTimer()!");
2019-08-08 02:02:00 +00:00
storedtime += Clock.Timer.ElapsedMilliseconds - starttime;
}
2014-11-13 09:43:39 +00:00
public static void StopTimer(string message)
{
if(starttime == -1) throw new InvalidOperationException("DebugConsole.StartTimer() must be called before DebugConsole.StopTimer()!");
2019-08-08 02:02:00 +00:00
long duration = Clock.Timer.ElapsedMilliseconds - starttime + storedtime;
if(message.Contains("%"))
message = message.Replace("%", duration.ToString(CultureInfo.InvariantCulture));
else
message = message.TrimEnd() + " " + duration + " ms.";
#if DEBUG
WriteLine(DebugMessageType.SPECIAL, message);
#else
General.ShowErrorMessage(message, MessageBoxButtons.OK, false);
#endif
2014-11-13 09:43:39 +00:00
starttime = -1;
storedtime = 0;
2014-11-13 09:43:39 +00:00
}
public static void IncrementCounter() { IncrementCounter(1); }
public static void IncrementCounter(int incrementby)
{
counter += incrementby;
}
public static void ResetCounter() { ResetCounter(string.Empty); }
public static void ResetCounter(string message)
{
if(!string.IsNullOrEmpty(message))
{
if(message.Contains("%"))
message = message.Replace("%", counter.ToString());
else
message = message.TrimEnd() + ": " + counter;
WriteLine(DebugMessageType.SPECIAL, message);
}
counter = 0;
}
Added, Texture Browser: added "Show textures in subdirectories" checkbox (enabled by default). When enabled, textures from current PK3/PK7/Directory resource directory and it's subdirectories will be shown. Otherwise, only textures from current directory will be shown. Removed, Texture Browser: removed "Show image sizes" checkbox. "Show texture and flat sizes in browsers" preferences setting is now used instead. Fixed, Things mode: event line between pre-last and the last PatrolPoint was not drawn. Fixed, Things mode: highlight range for sizeless things (things with "fixedsize" game configuration property) was calculated incorrectly. Fixed: fixed a crash when opening Script Editor after using "Open map in current wad" command to switch to UDMF map with SCRIPTS lump when current script configuration was not saved in the wad's .dbs file. Fixed: map closing events were not triggered when using "Open map in current wad" command, which could potentially result in plugin crashes/incorrect behavior. Fixed: Sector Drawing overrides panel could trigger an exception when closing the map during resource loading. Internal: added "Debug + Profiler" solution configuration, added 2 profiling methods to DebugConsole. Internal: rewrote MainForm.DisplayStatus() / StatusInfo to handle selection info in a more structured way. Fixed, internal: some destructors could potentially be executed more than once potentially leading to exceptions. Other destructors were not called at all. Updated ZDoom_DECORATE.cfg.
2015-09-16 12:10:43 +00:00
public static void StartProfiler()
{
#if PROFILE
if(PerformanceProfiler.IsActive)
{
WriteLine(DebugMessageType.SPECIAL, "Starting the Profiler...");
PerformanceProfiler.Begin();
PerformanceProfiler.Start();
}
else
{
WriteLine(DebugMessageType.SPECIAL, "Unable to start the Profiler...");
}
#else
WriteLine(DebugMessageType.SPECIAL, "Unable to start the Profiler: incorrect build configuration selected!");
#endif
}
public static void StopProfiler() { StopProfiler(true); }
public static void StopProfiler(bool savesnapshot)
{
#if PROFILE
if(PerformanceProfiler.IsActive)
{
PerformanceProfiler.Stop();
if(savesnapshot) PerformanceProfiler.EndSave();
else PerformanceProfiler.EndDrop();
WriteLine(DebugMessageType.SPECIAL, "Profiler Stopped...");
}
else
{
WriteLine(DebugMessageType.SPECIAL, "Unable to stop the Profiler...");
}
#else
WriteLine(DebugMessageType.SPECIAL, "Unable to stop the Profiler: incorrect build configuration selected!");
#endif
}
private void AddMessage(DebugMessageType type, string text, bool scroll, bool append)
2014-11-13 09:43:39 +00:00
{
text = textheaders[type] + text;
if(append)
{
console.SelectionStart = console.TextLength;
console.SelectionColor = textcolors[type];
console.AppendText(text);
}
else
{
console.SuspendLayout();
console.Text = text;
console.SelectAll();
console.SelectionColor = textcolors[type];
console.Select(0, 0);
console.ResumeLayout();
}
2014-11-13 09:43:39 +00:00
if(scroll && autoscroll.Checked) console.ScrollToCaret();
}
private void UpdateFilters(ToolStripMenuItem item)
{
DebugMessageType flag = (DebugMessageType)(int)item.Tag;
if(item.Checked)
{
filters |= flag;
}
else
{
filters &= ~flag;
}
}
private void UpdateMessages()
{
console.Clear();
console.SuspendLayout();
foreach(KeyValuePair<DebugMessageType, string> pair in messages)
2014-11-13 09:43:39 +00:00
{
if((filters & pair.Key) == pair.Key && CheckTextFilter(pair.Value, searchbox.Text))
{
AddMessage(pair.Key, pair.Value, false, true);
2014-11-13 09:43:39 +00:00
}
}
console.ResumeLayout();
console.ScrollToCaret();
}
// Should we display this message?
private static bool CheckTextFilter(string text, string filter)
2014-11-13 09:43:39 +00:00
{
if(string.IsNullOrEmpty(filter) || filter.Length < 3) return true;
2014-11-13 09:43:39 +00:00
return text.ToUpperInvariant().Contains(filter.ToUpperInvariant());
}
#endregion
#region ================== Events
private void clearall_Click(object sender, EventArgs e)
{
Clear();
}
private void filters_Click(object sender, EventArgs e)
{
UpdateFilters(sender as ToolStripMenuItem);
UpdateMessages();
}
private void wordwrap_Click(object sender, EventArgs e)
{
console.WordWrap = wordwrap.Checked;
}
#endregion
#region ================== Search events
private void searchclear_Click(object sender, EventArgs e)
{
searchbox.Clear();
}
private void searchbox_TextChanged(object sender, EventArgs e)
{
if(string.IsNullOrEmpty(searchbox.Text) || searchbox.Text.Length > 2) UpdateMessages();
}
#endregion
}
}