using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Numerics; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using ImGuiNET; using skyscraper5.Skyscraper.Scraper; namespace SDL2Demo.Forms { internal class LogWindow : IRenderable, ISkyscraperEventLogger { public LogWindow() { logEntries = new LinkedList(); clipperMemory = Marshal.AllocHGlobal(1024); flags = Int32.MaxValue; } private string GetFullLogAsString() { StringWriter sw = new StringWriter(); LinkedListNode logEntriesFirst = logEntries.First; while (true) { if (logEntriesFirst.Next == null) break; sw.WriteLine(logEntriesFirst.Value); logEntriesFirst = logEntriesFirst.Next; } return sw.ToString(); } private IntPtr clipperMemory; private Vector2 zero; private LinkedList logEntries; private int flags; private Vector2 windowSize; private bool isOpen; public bool IsOpen { get => isOpen; set { logEntries = new LinkedList(); isOpen = value; } } public void Render() { if (!IsOpen) return; if (windowSize == Vector2.Zero) windowSize = new Vector2(0.0f, ImGui.GetFontSize() * 12.0f); ImGui.SetNextWindowSize(windowSize, ImGuiCond.FirstUseEver); if (!ImGui.Begin("skyscraper5 Debug Log", ref isOpen)) { ImGui.End(); return; } ImGui.AlignTextToFramePadding(); ImGui.Text("Log events:"); ImGui.SameLine(); ImGui.CheckboxFlags("All", ref flags, Int32.MaxValue); ImGui.SameLine(); ImGui.CheckboxFlags("UI", ref flags, 1); ImGui.SameLine(); ImGui.CheckboxFlags("Scraper", ref flags, 2); ImGui.SameLine(); ImGui.CheckboxFlags("Seconds", ref flags, 4); ImGui.SameLine(); ImGui.CheckboxFlags("Job", ref flags, 8); //ImGui.SameLine(); ImGui.CheckboxFlags("???16", ref flags, 16); //ImGui.SameLine(); ImGui.CheckboxFlags("???32", ref flags, 32); //ImGui.SameLine(); ImGui.CheckboxFlags("???32", ref flags, 64); //ImGui.SameLine(); ImGui.CheckboxFlags("???32", ref flags, 128); //ImGui.SameLine(); ImGui.CheckboxFlags("???32", ref flags, 256); if (ImGui.SmallButton("Clear")) { logEntries = new LinkedList(); } ImGui.SameLine(); if (ImGui.SmallButton("Copy")) ImGui.SetClipboardText(GetFullLogAsString()); ImGui.BeginChild("##log", zero, true, ImGuiWindowFlags.AlwaysVerticalScrollbar | ImGuiWindowFlags.AlwaysHorizontalScrollbar); ImGuiListClipperPtr clipper = new ImGuiListClipperPtr(clipperMemory); clipper.Begin(logEntries.Count); while (clipper.Step()) for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++) { string line = GetLine(line_no); ImGui.TextUnformatted(line); } if (ImGui.GetScrollY() >= ImGui.GetScrollMaxY()) ImGui.SetScrollHereY(1.0f); ImGui.EndChild(); ImGui.End(); } private string GetLine(int lineNo) { LinkedListNode logEntriesFirst = logEntries.First; if (lineNo == 0) return logEntriesFirst.Value; try { for (int i = 1; i < lineNo; i++) { if (logEntriesFirst == null) return ""; if (logEntriesFirst.Next == null) return ""; logEntriesFirst = logEntriesFirst.Next; } } catch (NullReferenceException e) { return ""; } return logEntriesFirst.Value; } private const bool LOG_TO_CONSOLE = true; private const bool LOG_TO_DEBUG = false; private const bool LOG_TO_TRACE = false; public void Log(string toString, int flags = 1) { lock (logEntries) { while (logEntries.Count > 9000) { logEntries.RemoveFirst(); } if (isOpen) { if (((this.flags) & (flags)) != 0) { logEntries.AddLast(toString); if (LOG_TO_CONSOLE) Console.WriteLine(toString); if (LOG_TO_DEBUG) Debug.WriteLine(toString); if (LOG_TO_TRACE) Trace.WriteLine(toString); } } } } public void Log(TimeSpan duration, DateTime eventTimestamp, SkyscraperContextEvent eventType, string name = null) { StringBuilder sb = new StringBuilder(); sb.AppendFormat("[{0} {1}] ", eventTimestamp.ToShortDateString(), eventTimestamp.ToShortTimeString()); sb.AppendFormat("{0}", eventType.ToString()); if (!string.IsNullOrEmpty(name) && !string.IsNullOrWhiteSpace(name)) { sb.AppendFormat(" ({0}) ", name); } if (eventType != SkyscraperContextEvent.StartPacketProcessing && eventType != SkyscraperContextEvent.TdtTime && eventType != SkyscraperContextEvent.TotTime) { sb.AppendFormat(" ({0} ms)", duration.TotalMilliseconds); } Log(sb.ToString(),2); } public ulong NumEvents => (uint)logEntries.Count; } }