private static bool Matched(ProfileLog log, string s)
        {
            if (s == string.Empty)
            {
                Panel_TopRow.MatchType = string.Empty;
                return(true);
            }

            if (log.meth != null && log.meth.Name.ContainsCaseless(s))
            {
                Panel_TopRow.MatchType = "Assembly";
                return(true);
            }

            if (log.type != null && log.type.Assembly.FullName.ContainsCaseless(s))
            {
                Panel_TopRow.MatchType = "Assembly";
                return(true);
            }

            if (log.label.ContainsCaseless(s))
            {
                Panel_TopRow.MatchType = "Label";
                return(true);
            }

            return(false);
        }
        public string Value(ProfileLog log)
        {
            switch (sortBy)
            {
            case SortBy.Average: return($" {log.average:0.000}ms ");

            case SortBy.Max: return($" {log.max:0.000}ms ");

            case SortBy.Calls: return($" {log.calls.ToString("N0", CultureInfo.InvariantCulture)} ");

            case SortBy.AvPc: return($" {log.total/log.calls:0.000}ms ");

            case SortBy.Percent: return($" {log.percent * 100:0.0}% ");

            case SortBy.Name: return("    " + log.label);

            case SortBy.Total: return($" {log.total:0.000}ms ");

            case SortBy.CallsPu:
                var num = log.calls / log.entries;
                return(num < 1 ? $" {num:F3}" : $" {(int)Math.Round(num)}");
            }

            return("");
        }
        public static void Checkbox(ref Rect rect, ProfileLog log, Profiler profile, ref bool active)
        {
            var checkboxRect = new Rect(rect.x, rect.y, 25f, rect.height);

            rect.x += 25f;
            if (DubGUI.Checkbox(checkboxRect, "", ref active))
            {
                GUIController.CurrentEntry.checkBox.Invoke(null, new object[] { log });
                Modbase.Settings.Write();
            }
        }
Example #4
0
        public static void DrawHover(ProfileLog log, Rect visible)
        {
            if (log.meth != null)
            {
                if (log.label != tipLabelCache) // If we have a new label, re-create the string, else use our cached version.
                {
                    tipLabelCache = log.label;
                    StringBuilder builder = new StringBuilder();
                    Patches       patches = Harmony.GetPatchInfo(log.meth);
                    if (patches != null)
                    {
                        foreach (Patch patch in patches.Prefixes)
                        {
                            GetString("Prefix", patch);
                        }
                        foreach (Patch patch in patches.Postfixes)
                        {
                            GetString("Postfix", patch);
                        }
                        foreach (Patch patch in patches.Transpilers)
                        {
                            GetString("Transpiler", patch);
                        }
                        foreach (Patch patch in patches.Finalizers)
                        {
                            GetString("Finalizer", patch);
                        }

                        void GetString(string type, Patch patch)
                        {
                            if (Utility.IsNotAnalyzerPatch(patch.owner))
                            {
                                string ass     = patch.PatchMethod.DeclaringType.Assembly.FullName;
                                string modName = ModInfoCache.AssemblyToModname[ass];

                                builder.AppendLine($"{type} from {modName} with the index {patch.index} and the priority {patch.priority}\n");
                            }
                        }

                        tipCache = builder.ToString();
                    }
                }
                TooltipHandler.TipRegion(visible, tipCache);
            }
        }
        private static IEnumerable <FloatMenuOption> RightClickDropDown(ProfileLog log, Profiler profiler)
        {
            var meth = log.meth as MethodInfo;

            if (Input.GetKey(KeyCode.LeftShift))
            {
                if (GUIController.CurrentEntry.name.Contains("Harmony")) // we can return an 'unpatch' for methods in a harmony tab
                {
                    yield return(new FloatMenuOption("Unpatch Method (Destructive)", () => Utility.UnpatchMethod(meth)));
                }

                yield return(new FloatMenuOption("Unpatch methods that patch (Destructive)", () => Utility.UnpatchMethodsOnMethod(meth)));
            }

            var message = profiler.pinned ? "Unpin profile from entry" : "Pin profile to the top of the entry";

            yield return(new FloatMenuOption(message, () => profiler.pinned = !profiler.pinned));

            if (GUIController.CurrentEntry.type != typeof(H_HarmonyTranspilersInternalMethods))
            {
                yield return(new FloatMenuOption("Profile the internal methods of", () => Utility.PatchInternalMethod(meth, GUIController.CurrentCategory)));
            }

            // This part is WIP - it would require the ability to change the tab a method is active in on the fly
            // which is possible (with a transpiler to the current transpiler) but it would likely end up being
            // quite ugly, and I'd rather give a little more thought to the problem
            //yield return new FloatMenuOption("Profile in Custom Tab", () =>
            //{
            //    if (GUIController.CurrentCategory == Category.Tick)
            //    {
            //        MethodTransplanting.UpdateMethod(typeof(CustomProfilersTick), meth);
            //        GUIController.SwapToEntry("Custom Tick");
            //    }
            //    else
            //    {
            //        MethodTransplanting.UpdateMethod(typeof(CustomProfilersUpdate), meth);
            //        GUIController.SwapToEntry("Custom Update");
            //    }
            //});
        }
        public static void ClickWork(ProfileLog log, Profiler profile)
        {
            if (Event.current.button == 0) // left click
            {
                if (Input.GetKey(KeyCode.LeftControl))
                {
                    GUIController.CurrentEntry.onClick?.Invoke(null, new object[] { profile, log });
                    Modbase.Settings.Write();
                }
                else
                {
                    if (GUIController.CurrentProfiler == profile)
                    {
                        GUIController.CurrentProfiler = null;
                    }
                    else // This is now the 'active' profile
                    {
                        GUIController.CurrentProfiler = profile;
                    }
                }
            }
            else if (Event.current.button == 1) // right click
            {
                if (log.meth == null)
                {
                    return;
                }

                var options = RightClickDropDown(log, profile).ToList();

                if (options.Count != 0)
                {
                    Find.WindowStack.Add(new FloatMenu(options));
                }
            }
        }
 public static void OnSelect(ProfileLog log, Profiler profile, out bool active)
 {
     active = (bool)GUIController.CurrentEntry.onSelect.Invoke(null, new object[] { profile, log });
 }
        private static void DrawLog(ProfileLog log, ref float currentListHeight)
        {
            if (log.pinned is false && Matched(log, Panel_TopRow.TimesFilter) is false)
            {
                return;
            }

            columns[(int)SortBy.Average].total += log.average;

            var visible = listing.GetRect(BOX_HEIGHT);

            if (!visible.Overlaps(viewFrustum)) // if we don't overlap, continue, but continue to adjust for further logs.
            {
                listing.GapLine(0f);
                currentListHeight += (BOX_HEIGHT + 4);

                return;
            }

            var profile = ProfileController.Profiles[log.key];

            // Is this entry currently 'active'?
            if (GUIController.CurrentEntry.onSelect != null)
            {
                OnSelect(log, profile, out var active);

                // Show a button to toggle whether an entry is 'active'
                if (GUIController.CurrentEntry.checkBox != null)
                {
                    Checkbox(ref visible, log, profile, ref active);
                }
            }

            Widgets.DrawHighlightIfMouseover(visible);

            if (GUIController.CurrentProfiler?.key == profile.key)
            {
                Widgets.DrawHighlightSelected(visible);
            }

            // onclick work, left click view stats, right click internal patch, ctrl + left click unpatch
            if (Widgets.ButtonInvisible(visible))
            {
                ClickWork(log, profile);
            }

            // Colour a fillable bar below the log depending on the % fill of a log
            var colour = Textures.grey;

            if (log.percent <= .25f)
            {
                colour = Textures.grey;                      // <= 25%
            }
            else if (log.percent <= .75f)
            {
                colour = Textures.blue;                           //  25% < x <=75%
            }
            else if (log.percent <= .999)
            {
                colour = Textures.red;                           // 75% < x <= 99.99% (we want 100% to be grey)
            }
            Widgets.FillableBar(visible.BottomPartPixels(8f), log.percent, colour, Textures.clear, false);

            Text.Anchor = TextAnchor.MiddleCenter;

            foreach (var column in columns.Where(c => c.Active(GUIController.CurrentEntry.type)).OrderBy(c => c.order))
            {
                DrawColumnContents(ref visible, column, column.Value(log), profile);
            }

            GUI.color = Color.white;

            listing.GapLine(0f);
            currentListHeight += (BOX_HEIGHT + 4);
        }
Example #9
0
        private static void DrawLog(ProfileLog log, ref float currentListHeight)
        {
            if (Panel_TopRow.TimesFilter != "")
            {
                if (!log.label.ToLower().Contains(Panel_TopRow.TimesFilter.ToLower()))
                {
                    return;
                }
            }


            Rect visible = listing.GetRect(BOX_HEIGHT);

            if (!visible.Overlaps(viewFrustum)) // if we don't overlap, continue, but continue to adjust for further logs.
            {
                listing.GapLine(0f);
                currentListHeight += (BOX_HEIGHT + 4);

                return;
            }

            Profiler profile = ProfileController.Profiles[log.key];


            // Is this entry currently 'active'?
            if (GUIController.CurrentEntry.onSelect != null)
            {
                OnSelect(log, profile, out var active);

                // Show a button to toggle whether an entry is 'active'
                if (GUIController.CurrentEntry.checkBox != null)
                {
                    Checkbox(ref visible, log, profile, ref active);
                }
            }

            Widgets.DrawHighlightIfMouseover(visible);

            if (GUIController.CurrentProfiler?.key == profile.key)
            {
                Widgets.DrawHighlightSelected(visible);
            }

            // onhover tooltip
            if (Mouse.IsOver(visible))
            {
                DrawHover(log, visible);
            }

            // onclick work, left click view stats, right click internal patch, ctrl + left click unpatch
            if (Widgets.ButtonInvisible(visible))
            {
                ClickWork(log, profile);
            }

            // Colour a fillable bar below the log depending on the % fill of a log
            var colour = ResourceCache.GUI.grey;

            if (log.percent <= .25f)
            {
                colour = ResourceCache.GUI.grey;                      // <= 25%
            }
            else if (log.percent <= .75f)
            {
                colour = ResourceCache.GUI.blue;                           //  25% < x <=75%
            }
            else if (log.percent <= .999)
            {
                colour = ResourceCache.GUI.red;                           // 75% < x <= 99.99% (we want 100% to be grey)
            }
            Widgets.FillableBar(visible.BottomPartPixels(8f), log.percent, colour, ResourceCache.GUI.clear, false);

            Text.Anchor = TextAnchor.MiddleCenter;

            DrawColumnContents(ref visible, $" {log.max:0.000}ms ", SortBy.Max);
            DrawColumnContents(ref visible, $" {log.average:0.000}ms ", SortBy.Average);
            DrawColumnContents(ref visible, $" {log.percent * 100:0.0}% ", SortBy.Percent);
            DrawColumnContents(ref visible, $" {log.total:0.000}ms ", SortBy.Total);

            if (GUIController.CurrentEntry.type != typeof(H_HarmonyTranspilers))
            {
                DrawColumnContents(ref visible, $" {log.calls.ToString("N0", CultureInfo.InvariantCulture)} ", SortBy.Calls);
            }


            Text.Anchor   = TextAnchor.MiddleLeft;
            visible.width = 10000;
            DrawColumnContents(ref visible, "    " + log.label, SortBy.Name);

            GUI.color = Color.white;

            listing.GapLine(0f);
            currentListHeight += (BOX_HEIGHT + 4);
        }