private void DrawOther(Listing_Extended lister, Settings settings) { if (lister.ButtonText($"Results", Text.LineHeight)) { Find.WindowStack.Add(new FloatMenu(new List <FloatMenuOption> { new FloatMenuOption("Dump to SLK", () => { List <StopwatchRecord> result = PatchHandler.GetProfileRecordsSorted(); FS.WriteAllText($"Profiler_{DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")}.slk", result.DumpToSlk()); }), new FloatMenuOption("Dump to CSV", () => { List <StopwatchRecord> result = PatchHandler.GetProfileRecordsSorted(); FS.WriteAllText($"Profiler_{DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")}.csv", result.DumpToCsv()); }), new FloatMenuOption("Reset results", () => { PatchHandler.Reset(); }), })); } if (lister.ButtonText($"Tools / Other", Text.LineHeight)) { IEnumerable <FloatMenuOption> getOptions() { yield return(new FloatMenuOption($"Enable disabled methods: {PatchDisabler.DisabledCount}", () => { PatchDisabler.EnableAllDisabled(); })); yield return(new FloatMenuOption("Dump all harmony patches", () => { FS.WriteAllText("HarmonyPatches.txt", HarmonyMain.AllHarmonyPatchesDump()); FS.WriteAllText("HarmonyPatches-Conflicts.txt", HarmonyMain.CanConflictHarmonyPatchesDump()); })); // if (DubsProfilerReset.CanUnpatch()) // { // yield return new FloatMenuOption("Reset DubsPerfomanceAnalyzer patches", DubsProfilerReset.ResetProfiler); // } } Find.WindowStack.Add(new FloatMenu(new List <FloatMenuOption>(getOptions()))); } // Method resolver. Handle string >= 3 chars. Results show after 2 sec. when str not changed. Has filter AND, example: 'pawn tick' => Verse.Pawn:Tick { var prevStr = _methodResolver; Rect labelRect = lister.GetRect(Text.LineHeight), textEntyRect = labelRect; float width = labelRect.width; labelRect.width = width / 3; textEntyRect.width = 2 * width / 3; textEntyRect.x = labelRect.xMax; Widgets.Label(labelRect, $"Method resolver"); _methodResolver = Widgets.TextArea(textEntyRect, _methodResolver); if (!String.IsNullOrWhiteSpace(_methodResolver) && _methodResolver.Length >= 4) { if (!prevStr.Equals(_methodResolver)) { _methodResolverInputTimer = Stopwatch.StartNew(); } } else { _methodResolverInputTimer = null; } if (_methodResolverInputTimer != null && _methodResolverInputTimer.ElapsedMilliseconds > 1500) { var strLower = _methodResolver.ToLower(); var arrFilters = strLower.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); var allMethods = Utils.GetAllMethods(); IEnumerable <string> filterMethods() { if (_methodResolverCache == null) { _methodResolverCache = allMethods .OrderBy(x => x) .Select(x => (x, x.ToLower())) .ToList(); } foreach (var m in (from tuple in _methodResolverCache where arrFilters.All(x => tuple.nameLower.Contains(x)) select tuple)) { yield return(m.name); } } IEnumerable <FloatMenuOption> makeVariants(int maxResult) { foreach (var m in filterMethods().OrderBy(x => x)) { if (maxResult-- < 0) { break; } yield return(new FloatMenuOption(m, () => _methodResolver = m)); } } Find.WindowStack.Add(new FloatMenu(new List <FloatMenuOption>(makeVariants(20)))); _methodResolverInputTimer = null; } } lister.CheckboxLabeled("CRASH DEBUG", ref settings.debug); lister.Gap(20f); }
private void DrawProfilerTop15(Listing_Extended lister, Settings settings) { lister.LabelColored($"Top 15 (Triggered:{PatchHandler.ProfiledRecordsCount()} Methods:{Patcher.PatchedMethodsCount()})", TitleLabelColor); int maxRecordCount = 15; // update cache every 1 sec and skip update if mouse on buttons if (cached == null || !stopUpdate && cacheUpdateTimer.ElapsedMilliseconds > 1000L) { cached = PatchHandler.GetProfileRecordsSorted() .Where(x => !hided.Any(x.MethodName.Equals)) //.OrderByDescending(x => x.TimeSpent) .Take(maxRecordCount) .ToList(); cacheUpdateTimer = Stopwatch.StartNew(); } // draw cached info stopUpdate = false; var backFont = Text.Font; foreach (var r in cached) { string tooltip = r.Tooltip; Rect buttonRect1 = lister.GetRect(Text.LineHeight), buttonRect2 = buttonRect1, buttonRect3 = buttonRect1, buttonRect4 = buttonRect1, buttonRect5 = buttonRect1; buttonRect1.width = buttonRect2.width = buttonRect3.width = buttonRect4.width = 40; buttonRect2.x = buttonRect1.xMax; buttonRect3.x = buttonRect2.xMax; buttonRect4.x = buttonRect3.xMax; buttonRect5.width -= 40 * 4; buttonRect5.x = buttonRect4.xMax; if (ButtonText(buttonRect1, "Copy", tooltip + "\nPress for copy this method name", out bool button1IsMouseOver)) { if (!settings.profileCustom.Contains(r.MethodName)) { bool addLine = !settings.profileCustom.IsNullOrEmptyOrEqual(Settings.CustomExampleStr); if (addLine) { settings.profileCustom += $"\n{r.MethodName}"; } else { settings.profileCustom = $"{r.MethodName}"; } } } bool logActive = PatchHandler.logMethod != null && r.Method == PatchHandler.logMethod; if (ButtonText(buttonRect2, logActive ? "X" : "Log", tooltip + "\nPress for copy this method name", out bool button2IsMouseOver)) { // disable log this method if (logActive) { PatchHandler.logMethod = null; } // enable log this method else { PatchHandler.logMethod = r.Method; } } bool isDisabled = PatchDisabler.IsDisabled(r.Method); if (ButtonText(buttonRect3, isDisabled ? "On" : "Off", tooltip + (isDisabled ? "\nPress for ENABLE this method" : "\nPress for DISABLE this method"), out bool button3IsMouseOver)) { if (isDisabled) { PatchDisabler.EnableMethod(r.Method); } else { PatchDisabler.DisableMethod(r.Method); } } if (ButtonText(buttonRect4, "Undo", tooltip + ("\nPress for REMOVE PROFILER for this method"), out bool button4IsMouseOver)) { Patcher.UnpatchMethod(r.Method); cached = null; break; // and redraw } if (ButtonText(buttonRect5, r.MethodName, tooltip + "\nPress for hide this line", out bool button5IsMouseOver)) { hided.Add(r.MethodName); cached = null; break; // and redraw } if (button1IsMouseOver || button2IsMouseOver || button3IsMouseOver || button4IsMouseOver || button5IsMouseOver) { stopUpdate = true; } lister.Label($" TimeSpent:{r.TimeSpent}ms AvgTick:{r.AvgTime:0.00000}ms Ticks:{r.TicksNum}"); } Text.Font = backFont; if (hided.Count > 0 && lister.ButtonText($"Reset Hided", Text.LineHeight)) { hided.Clear(); cached = null; } }
private void DrawSettings(Listing_Extended lister, Settings settings) { lister.LabelColored("Settings", TitleLabelColor); lister.CheckboxLabeled("Check main thread", ref settings.checkMainThread); lister.CheckboxLabeled("Transpiler Mode(SLOW PATCHING/BETTER TPS)", ref settings.profilerTranspileMode); if (settings.profilerTranspileMode) { lister.CheckboxLabeled(" Get original from dictionary", ref settings.getOriginalFromDict); } // memory options { bool prevColMemUs = settings.collectMemAlloc; lister.CheckboxLabeled("Collect memory allocations", ref settings.collectMemAlloc); if (prevColMemUs != settings.collectMemAlloc) { if (!settings.collectMemAlloc) { settings.sortByMemAlloc = false; } PatchHandler.Reset(); } if (settings.collectMemAlloc) { lister.CheckboxLabeled(" Sort by memory allocations", ref settings.sortByMemAlloc); } } // perfomance mode Rect checkboxRect = lister.GetRect(Text.LineHeight), buttonRect = checkboxRect; if (settings.perfomanceMode) { buttonRect.width = checkboxRect.width /= 2; buttonRect.x = checkboxRect.xMax; if (Widgets.ButtonText(buttonRect, "Force optimize")) { Patcher.UnpatchByRule(settings.ruleTiming, settings.ruleTicks); } } Widgets.CheckboxLabeled(checkboxRect, "Perfomance mode", ref settings.perfomanceMode); { if (settings.perfomanceMode) { Rect rect = lister.GetRect(Text.LineHeight), timeRect = rect, ticksRect = rect; timeRect.width = rect.width / 2 + 35; Widgets.TextFieldNumericLabeled(timeRect, "clean AvgTime < ", ref settings.ruleTiming, ref settings.ruleTimingBuf); ticksRect.x = timeRect.xMax; ticksRect.width -= timeRect.width; Widgets.TextFieldNumericLabeled(ticksRect, "and Ticks > ", ref settings.ruleTicks, ref settings.ruleTicksBuf); } } if (lister.ButtonText($"Stop profiling", Text.LineHeight)) { Profiler.Logger.LogOperation("ResetProfiling", Patcher.UnpatchAll); PatchHandler.ClearGetMethodByKey(); } }