// Consolidated decompiled source — Azumatt-BepInEx_ConfigurationManager v18.0.1 // Generated by Hexium's decompiled-source browser. Best-effort concatenation of every type in this // version's manifest — decompiler output isn't guaranteed to compile as-is. using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using BepInEx; using BepInEx.Configuration; using System.ComponentModel; using BepInEx.Bootstrap; using ConfigurationManager.Utilities; using System.IO; using BepInEx.Logging; using UnityEngine; using System.Globalization; using System.Diagnostics; // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.ConfigSettingEntry ---- namespace ConfigurationManager { internal sealed class ConfigSettingEntry : SettingEntryBase { public ConfigEntryBase Entry { get; } public override Type SettingType => Entry.SettingType; public ConfigSettingEntry(ConfigEntryBase entry, BaseUnityPlugin owner) { Entry = entry; DispName = entry.Definition.Key; base.Category = entry.Definition.Section; base.Description = entry.Description?.Description; TypeConverter converter = TomlTypeConverter.GetConverter(entry.SettingType); if (converter != null) { base.ObjToStr = (object o) => converter.ConvertToString(o, entry.SettingType); base.StrToObj = (string s) => converter.ConvertToObject(s, entry.SettingType); } AcceptableValueBase acceptableValueBase = entry.Description?.AcceptableValues; if (acceptableValueBase != null) { GetAcceptableValues(acceptableValueBase); } base.DefaultValue = entry.DefaultValue; SetFromAttributes(entry.Description?.Tags, owner); } private void GetAcceptableValues(AcceptableValueBase values) { Type type = values.GetType(); PropertyInfo property = type.GetProperty("AcceptableValues", BindingFlags.Instance | BindingFlags.Public); if ((object)property != null) { base.AcceptableValues = ((IEnumerable)property.GetValue(values, null)).Cast().ToArray(); return; } PropertyInfo property2 = type.GetProperty("MinValue", BindingFlags.Instance | BindingFlags.Public); if ((object)property2 != null) { PropertyInfo property3 = type.GetProperty("MaxValue", BindingFlags.Instance | BindingFlags.Public); if ((object)property3 == null) { throw new ArgumentNullException("maxProp"); } base.AcceptableValueRange = new KeyValuePair(property2.GetValue(values, null), property3.GetValue(values, null)); base.ShowRangeAsPercent = ((base.AcceptableValueRange.Key.Equals(0) || base.AcceptableValueRange.Key.Equals(1)) && base.AcceptableValueRange.Value.Equals(100)) || (base.AcceptableValueRange.Key.Equals(0f) && base.AcceptableValueRange.Value.Equals(1f)); } } public override object Get() { return Entry.BoxedValue; } protected override void SetValue(object newVal) { Entry.BoxedValue = newVal; } } } // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.PropertySettingEntry ---- namespace ConfigurationManager { internal class PropertySettingEntry : SettingEntryBase { private Type _settingType; public object Instance { get; internal set; } public PropertyInfo Property { get; internal set; } public override string DispName { get { return string.IsNullOrEmpty(base.DispName) ? Property.Name : base.DispName; } protected internal set { base.DispName = value; } } public override Type SettingType => _settingType ?? (_settingType = Property.PropertyType); public PropertySettingEntry(object instance, PropertyInfo settingProp, BaseUnityPlugin pluginInstance) { SetFromAttributes(settingProp.GetCustomAttributes(inherit: false), pluginInstance); if (!base.Browsable.HasValue) { base.Browsable = settingProp.CanRead && settingProp.CanWrite; } base.ReadOnly = settingProp.CanWrite; Property = settingProp; Instance = instance; } public override object Get() { return Property.GetValue(Instance, null); } protected override void SetValue(object newVal) { Property.SetValue(Instance, newVal, null); } } } // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.SettingSearcher ---- namespace ConfigurationManager { internal static class SettingSearcher { private static readonly ICollection _updateMethodNames = new string[4] { "Update", "FixedUpdate", "LateUpdate", "OnGUI" }; public static void CollectSettings(out IEnumerable results, out List modsWithoutSettings, bool showDebug) { modsWithoutSettings = new List(); try { results = GetBepInExCoreConfig(); } catch (Exception data) { results = Enumerable.Empty(); ConfigurationManager.Logger.LogError(data); } BaseUnityPlugin[] array = Utils.FindPlugins(); foreach (BaseUnityPlugin baseUnityPlugin in array) { Type type = baseUnityPlugin.GetType(); BepInPlugin metadata = baseUnityPlugin.Info.Metadata; if (type.GetCustomAttributes(typeof(BrowsableAttribute), inherit: false).Cast().Any((BrowsableAttribute x) => !x.Browsable)) { modsWithoutSettings.Add(metadata.Name); continue; } List list = new List(); list.AddRange(GetPluginConfig(baseUnityPlugin).Cast()); list.RemoveAll((SettingEntryBase x) => x.Browsable == false); if (list.Count == 0) { modsWithoutSettings.Add(metadata.Name); } if (showDebug && type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any((MethodInfo x) => _updateMethodNames.Contains(x.Name))) { PropertySettingEntry propertySettingEntry = new PropertySettingEntry(baseUnityPlugin, type.GetProperty("enabled"), baseUnityPlugin); propertySettingEntry.DispName = "!Allow plugin to run on every frame"; propertySettingEntry.Description = "Disabling this will disable some or all of the plugin's functionality.\nHooks and event-based functionality will not be disabled.\nThis setting will be lost after game restart."; propertySettingEntry.IsAdvanced = true; list.Add(propertySettingEntry); } if (list.Count > 0) { results = results.Concat(list); } } } private static IEnumerable GetBepInExCoreConfig() { PropertyInfo property = typeof(ConfigFile).GetProperty("CoreConfig", BindingFlags.Static | BindingFlags.NonPublic); if ((object)property == null) { throw new ArgumentNullException("coreConfigProp"); } ConfigFile source = (ConfigFile)property.GetValue(null, null); BepInPlugin bepinMeta = new BepInPlugin("BepInEx", "BepInEx", typeof(Chainloader).Assembly.GetName().Version.ToString()); return ((IEnumerable>)source).Select((Func, SettingEntryBase>)((KeyValuePair kvp) => new ConfigSettingEntry(kvp.Value, null) { IsAdvanced = true, PluginInfo = bepinMeta })); } private static IEnumerable GetPluginConfig(BaseUnityPlugin plugin) { return plugin.Config.Select((KeyValuePair kvp) => new ConfigSettingEntry(kvp.Value, plugin)); } } } // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.ConfigurationManager ---- namespace ConfigurationManager { [BepInPlugin("com.bepis.bepinex.configurationmanager", "Configuration Manager", "18.0.1")] public class ConfigurationManager : BaseUnityPlugin { private sealed class PluginSettingsData { public sealed class PluginSettingsGroupData { public string Name; public List Settings; } public BepInPlugin Info; public List Categories; public int Height; public string Website; private bool _collapsed; public bool Collapsed { get { return _collapsed; } set { _collapsed = value; Height = 0; } } } public const string GUID = "com.bepis.bepinex.configurationmanager"; public const string Version = "18.0.1"; internal new static ManualLogSource Logger; private static SettingFieldDrawer _fieldDrawer; private static readonly Color _advancedSettingColor = new Color(1f, 0.95f, 0.67f, 1f); private const int WindowId = -68; private const string SearchBoxName = "searchBox"; private bool _focusSearchBox; private string _searchString = string.Empty; public bool OverrideHotkey; private bool _displayingWindow; private bool _obsoleteCursor; private string _modsWithoutSettings; private List _allSettings; private List _filteredSetings = new List(); private bool _windowWasMoved; private bool _tipsPluginHeaderWasClicked; private bool _tipsWindowWasMoved; private Rect currentWindowRect; private Rect _screenRect; private Vector2 _settingWindowScrollPos; private int _tipsHeight; private PropertyInfo _curLockState; private PropertyInfo _curVisible; private int _previousCursorLockState; private bool _previousCursorVisible; private readonly ConfigEntry _showAdvanced; private readonly ConfigEntry _showKeybinds; private readonly ConfigEntry _showSettings; private readonly ConfigEntry _keybind; private readonly ConfigEntry _hideSingleSection; private readonly ConfigEntry _pluginConfigCollapsedDefault; private bool _showDebug; public static ConfigEntry _windowPosition; public static ConfigEntry _windowSize; public static ConfigEntry _textSize; public static ConfigEntry _windowBackgroundColor; public static ConfigEntry _entryBackgroundColor; public static ConfigEntry _fontColor; public static ConfigEntry _widgetBackgroundColor; public static GUIStyle windowStyle; public static GUIStyle headerStyle; public static GUIStyle entryStyle; public static GUIStyle labelStyle; public static GUIStyle textStyle; public static GUIStyle toggleStyle; public static GUIStyle buttonStyle; public static GUIStyle boxStyle; public static GUIStyle sliderStyle; public static GUIStyle thumbStyle; public static GUIStyle categoryHeaderSkin; public static GUIStyle pluginHeaderSkin; public static int fontSize = 14; internal Rect SettingWindowRect { get; private set; } internal Rect DefaultWindowRect { get; private set; } internal static Texture2D TooltipBg { get; private set; } internal static Texture2D WindowBackground { get; private set; } internal static Texture2D EntryBackground { get; private set; } internal static Texture2D WidgetBackground { get; private set; } internal int LeftColumnWidth { get; private set; } internal int RightColumnWidth { get; private set; } public bool DisplayingWindow { get { return _displayingWindow; } set { if (_displayingWindow == value) { return; } _displayingWindow = value; SettingFieldDrawer.ClearCache(); if (_displayingWindow) { CalculateWindowRect(); BuildSettingList(); _focusSearchBox = true; if ((object)_curLockState != null) { _previousCursorLockState = (_obsoleteCursor ? Convert.ToInt32((bool)_curLockState.GetValue(null, null)) : ((int)_curLockState.GetValue(null, null))); _previousCursorVisible = (bool)_curVisible.GetValue(null, null); } } else if (!_previousCursorVisible || _previousCursorLockState != 0) { SetUnlockCursor(_previousCursorLockState, _previousCursorVisible); } this.DisplayingWindowChanged?.Invoke(this, new ValueChangedEventArgs(value)); } } public string SearchString { get { return _searchString; } private set { if (value == null) { value = string.Empty; } if (!(_searchString == value)) { _searchString = value; BuildFilteredSettingList(); } } } public event EventHandler> DisplayingWindowChanged; public ConfigurationManager() { Logger = base.Logger; _fieldDrawer = new SettingFieldDrawer(this); _showAdvanced = base.Config.Bind("Filtering", "Show advanced", defaultValue: false); _showKeybinds = base.Config.Bind("Filtering", "Show keybinds", defaultValue: true); _showSettings = base.Config.Bind("Filtering", "Show settings", defaultValue: true); _keybind = base.Config.Bind("General", "Show config manager", new KeyboardShortcut(KeyCode.F1), new ConfigDescription("The shortcut used to toggle the config manager window on and off.\nThe key can be overridden by a game-specific plugin if necessary, in that case this setting is ignored.", null)); _hideSingleSection = base.Config.Bind("General", "Hide single sections", defaultValue: false, new ConfigDescription("Show section title for plugins with only one section", null)); _pluginConfigCollapsedDefault = base.Config.Bind("General", "Plugin collapsed default", defaultValue: true, new ConfigDescription("If set to true plugins will be collapsed when opening the configuration manager window", null)); _windowPosition = base.Config.Bind("General", "WindowPosition", new Vector2(55f, 35f), "Window position"); _windowSize = base.Config.Bind("General", "WindowSize", DefaultWindowRect.size, "Window size"); _textSize = base.Config.Bind("General", "FontSize", 14, "Font Size"); _windowBackgroundColor = base.Config.Bind("Colors", "WindowBackgroundColor", new Color(0.27f, 0.26f, 0.26f, 1f), "Window background color"); _entryBackgroundColor = base.Config.Bind("Colors", "EntryBackgroundColor", new Color(0.435f, 0.415f, 0.396f, 1f), "Entry background color"); _fontColor = base.Config.Bind("Colors", "FontColor", new Color(1f, 1f, 1f, 1f), "Font color"); _widgetBackgroundColor = base.Config.Bind("Colors", "WidgetColor", new Color(0.2f, 0.44f, 0.314f, 1f), "Widget color"); currentWindowRect = new Rect(_windowPosition.Value, _windowSize.Value); } public static void RegisterCustomSettingDrawer(Type settingType, Action onGuiDrawer) { if ((object)settingType == null) { throw new ArgumentNullException("settingType"); } if (onGuiDrawer == null) { throw new ArgumentNullException("onGuiDrawer"); } if (SettingFieldDrawer.SettingDrawHandlers.ContainsKey(settingType)) { Logger.LogWarning("Tried to add a setting drawer for type " + settingType.FullName + " while one already exists."); } else { SettingFieldDrawer.SettingDrawHandlers[settingType] = onGuiDrawer; } } public void BuildSettingList() { SettingSearcher.CollectSettings(out var results, out var modsWithoutSettings, _showDebug); _modsWithoutSettings = string.Join(", ", (from x in modsWithoutSettings select x.TrimStart(new char[1] { '!' }) into x orderby x select x).ToArray()); _allSettings = results.ToList(); BuildFilteredSettingList(); } private void BuildFilteredSettingList() { IEnumerable source = _allSettings; string[] searchStrings = SearchString.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (searchStrings.Length != 0) { source = source.Where((SettingEntryBase x) => ContainsSearchString(x, searchStrings)); } else { if (!_showAdvanced.Value) { source = source.Where((SettingEntryBase x) => x.IsAdvanced != true); } if (!_showKeybinds.Value) { source = source.Where((SettingEntryBase x) => !IsKeyboardShortcut(x)); } if (!_showSettings.Value) { source = source.Where((SettingEntryBase x) => x.IsAdvanced == true || IsKeyboardShortcut(x)); } } bool settingsAreCollapsed = _pluginConfigCollapsedDefault.Value; HashSet nonDefaultCollpasingStateByPluginName = new HashSet(); foreach (PluginSettingsData filteredSeting in _filteredSetings) { if (filteredSeting.Collapsed != settingsAreCollapsed) { nonDefaultCollpasingStateByPluginName.Add(filteredSeting.Info.Name); } } _filteredSetings = (from x in (from x in source group x by x.PluginInfo).Select(delegate(IGrouping pluginSettings) { IEnumerable source2 = from eb in pluginSettings group eb by eb.Category into x orderby string.Equals(x.Key, "Keyboard shortcuts", StringComparison.Ordinal), x.Key select new PluginSettingsData.PluginSettingsGroupData { Name = x.Key, Settings = (from set in x orderby set.Order descending, set.DispName select set).ToList() }; string website = Utils.GetWebsite(pluginSettings.First().PluginInstance); return new PluginSettingsData { Info = pluginSettings.Key, Categories = source2.ToList(), Collapsed = (nonDefaultCollpasingStateByPluginName.Contains(pluginSettings.Key.Name) ? (!settingsAreCollapsed) : settingsAreCollapsed), Website = website }; }) orderby x.Info.Name select x).ToList(); } private static bool IsKeyboardShortcut(SettingEntryBase x) { return (object)x.SettingType == typeof(KeyboardShortcut); } private static bool ContainsSearchString(SettingEntryBase setting, string[] searchStrings) { string combinedSearchTarget = setting.PluginInfo.Name + "\n" + setting.PluginInfo.GUID + "\n" + setting.DispName + "\n" + setting.Category + "\n" + setting.Description + "\n" + setting.DefaultValue?.ToString() + "\n" + setting.Get(); return searchStrings.All((string s) => combinedSearchTarget.IndexOf(s, StringComparison.InvariantCultureIgnoreCase) >= 0); } private void CalculateWindowRect() { int num = Mathf.Min(Screen.width, 650); int num2 = ((Screen.height < 560) ? Screen.height : (Screen.height - 100)); int num3 = Mathf.RoundToInt((float)(Screen.width - num) / 2f); int num4 = Mathf.RoundToInt((float)(Screen.height - num2) / 2f); SettingWindowRect = new Rect(num3, num4, num, num2); _screenRect = new Rect(0f, 0f, Screen.width, Screen.height); LeftColumnWidth = Mathf.RoundToInt(SettingWindowRect.width / 2.5f); RightColumnWidth = (int)SettingWindowRect.width - LeftColumnWidth - 115; _windowWasMoved = false; } private void OnGUI() { if (!DisplayingWindow) { return; } if (Event.current.type == EventType.KeyUp && Event.current.keyCode == _keybind.Value.MainKey) { DisplayingWindow = false; return; } if (_textSize.Value > 9 && _textSize.Value < 100) { fontSize = Mathf.Clamp(_textSize.Value, 10, 30); } CreateBackgrounds(); CreateStyles(); SetUnlockCursor(0, cursorVisible: true); GUI.Box(currentWindowRect, GUIContent.none, new GUIStyle { normal = new GUIStyleState { background = WindowBackground } }); GUI.backgroundColor = _windowBackgroundColor.Value; if (_windowSize.Value.x > 200f && _windowSize.Value.x < (float)Screen.width && _windowSize.Value.y > 200f && _windowSize.Value.y < (float)Screen.height) { currentWindowRect.size = _windowSize.Value; } RightColumnWidth = Mathf.RoundToInt(currentWindowRect.width / 2.5f * (float)fontSize / 12f); LeftColumnWidth = Mathf.RoundToInt(currentWindowRect.width - (float)RightColumnWidth - 115f); currentWindowRect = GUILayout.Window(-68, SettingWindowRect, SettingsWindow, "Plugin / mod settings"); if (currentWindowRect != SettingWindowRect) { _windowWasMoved = true; SettingWindowRect = currentWindowRect; _tipsWindowWasMoved = true; } if (!SettingFieldDrawer.SettingKeyboardShortcut && (!_windowWasMoved || SettingWindowRect.Contains(UnityInput.Current.mousePosition))) { UnityInput.Current.ResetInputAxes(); } if (!Input.GetKey(KeyCode.Mouse0) && (currentWindowRect.x != _windowPosition.Value.x || currentWindowRect.y != _windowPosition.Value.y)) { _windowPosition.Value = currentWindowRect.position; base.Config.Save(); } } private static void DrawTooltip(Rect area) { if (!string.IsNullOrEmpty(GUI.tooltip)) { Event current = Event.current; GUIStyle gUIStyle = new GUIStyle(boxStyle) { wordWrap = true, alignment = TextAnchor.MiddleCenter }; Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = _entryBackgroundColor.Value; float num = gUIStyle.CalcHeight(new GUIContent(GUI.tooltip), 400f) + 10f; float x = ((current.mousePosition.x + 400f > area.width) ? (area.width - 400f) : current.mousePosition.x); float y = ((current.mousePosition.y + 25f + num > area.height) ? (current.mousePosition.y - num) : (current.mousePosition.y + 25f)); GUI.Box(new Rect(x, y, 400f, num), GUI.tooltip, gUIStyle); GUI.backgroundColor = backgroundColor; } } private void SettingsWindow(int id) { GUI.DragWindow(new Rect(0f, 0f, currentWindowRect.width, 20f)); DrawWindowHeader(); _settingWindowScrollPos = GUILayout.BeginScrollView(_settingWindowScrollPos, false, true); float y = _settingWindowScrollPos.y; float height = SettingWindowRect.height; GUILayout.BeginVertical(); if (string.IsNullOrEmpty(SearchString)) { DrawTips(); if (_tipsHeight == 0 && Event.current.type == EventType.Repaint) { _tipsHeight = (int)GUILayoutUtility.GetLastRect().height; } } int num = _tipsHeight; foreach (PluginSettingsData filteredSeting in _filteredSetings) { if (filteredSeting.Height == 0 || ((float)(num + filteredSeting.Height) >= y && (float)num <= y + height)) { try { DrawSinglePlugin(filteredSeting); } catch (ArgumentException) { } if (filteredSeting.Height == 0 && Event.current.type == EventType.Repaint) { filteredSeting.Height = (int)GUILayoutUtility.GetLastRect().height; } } else { try { GUILayout.Space(filteredSeting.Height); } catch (ArgumentException) { } } num += filteredSeting.Height; } if (_showDebug) { GUILayout.Space(10f); GUILayout.Label("Plugins with no options available: " + _modsWithoutSettings); } else { GUILayout.Space(70f); } GUILayout.EndVertical(); GUILayout.EndScrollView(); if (!SettingFieldDrawer.DrawCurrentDropdown()) { DrawTooltip(SettingWindowRect); } } private void DrawTips() { string text = ((!_tipsPluginHeaderWasClicked) ? "Tip: Click plugin names to expand. Click setting and group names to see their descriptions." : ((!_tipsWindowWasMoved) ? "Tip: You can drag this window to move it. It will stay open while you interact with the game." : null)); if (text != null) { GUILayout.BeginHorizontal(); GUILayout.Label(text); GUILayout.EndHorizontal(); } } private void DrawWindowHeader() { GUI.backgroundColor = _entryBackgroundColor.Value; GUILayout.BeginHorizontal(GUI.skin.box); GUI.enabled = SearchString == string.Empty; bool flag = GUILayout.Toggle(_showSettings.Value, "Normal settings"); if (_showSettings.Value != flag) { _showSettings.Value = flag; BuildFilteredSettingList(); } flag = GUILayout.Toggle(_showKeybinds.Value, "Keyboard shortcuts"); if (_showKeybinds.Value != flag) { _showKeybinds.Value = flag; BuildFilteredSettingList(); } Color color = GUI.color; GUI.color = _advancedSettingColor; flag = GUILayout.Toggle(_showAdvanced.Value, "Advanced settings"); if (_showAdvanced.Value != flag) { _showAdvanced.Value = flag; BuildFilteredSettingList(); } GUI.color = color; GUI.enabled = true; GUILayout.Space(8f); flag = GUILayout.Toggle(_showDebug, "Debug info"); if (_showDebug != flag) { _showDebug = flag; BuildSettingList(); } if (GUILayout.Button("Open Log")) { try { Utils.OpenLog(); } catch (SystemException ex) { Logger.Log(LogLevel.Error | LogLevel.Message, ex.Message); } } GUILayout.Space(8f); if (GUILayout.Button("Close")) { DisplayingWindow = false; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(GUI.skin.box); GUILayout.Label("Search: ", GUILayout.ExpandWidth(expand: false)); GUI.SetNextControlName("searchBox"); SearchString = GUILayout.TextField(SearchString, GUILayout.ExpandWidth(expand: true)); if (_focusSearchBox) { GUI.FocusWindow(-68); GUI.FocusControl("searchBox"); _focusSearchBox = false; } Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = _widgetBackgroundColor.Value; if (GUILayout.Button("Clear", GUILayout.ExpandWidth(expand: false))) { SearchString = string.Empty; } GUI.backgroundColor = backgroundColor; GUILayout.Space(8f); if (GUILayout.Button(_pluginConfigCollapsedDefault.Value ? "Expand All" : "Collapse All", GUILayout.ExpandWidth(expand: false))) { bool flag2 = !_pluginConfigCollapsedDefault.Value; _pluginConfigCollapsedDefault.Value = flag2; foreach (PluginSettingsData filteredSeting in _filteredSetings) { filteredSeting.Collapsed = flag2; } _tipsPluginHeaderWasClicked = true; } GUILayout.EndHorizontal(); } private void DrawSinglePlugin(PluginSettingsData plugin) { GUIStyle gUIStyle = new GUIStyle(GUI.skin.box); gUIStyle.normal.textColor = _fontColor.Value; gUIStyle.normal.background = EntryBackground; gUIStyle.fontSize = fontSize; GUI.backgroundColor = _entryBackgroundColor.Value; GUILayout.BeginVertical(gUIStyle); GUIContent content = (_showDebug ? new GUIContent($"{plugin.Info.Name.TrimStart(new char[1] { '!' })} {plugin.Info.Version}", "GUID: " + plugin.Info.GUID) : new GUIContent($"{plugin.Info.Name.TrimStart(new char[1] { '!' })} {plugin.Info.Version}")); bool flag = !string.IsNullOrEmpty(SearchString); bool flag2 = plugin.Website != null; if (flag2) { GUILayout.BeginHorizontal(); GUILayout.Space(29f); } if (SettingFieldDrawer.DrawPluginHeader(content, plugin.Collapsed && !flag) && !flag) { _tipsPluginHeaderWasClicked = true; plugin.Collapsed = !plugin.Collapsed; } if (flag2) { Color color = GUI.color; GUI.color = Color.gray; if (GUILayout.Button(new GUIContent("URL", plugin.Website), GUI.skin.label, GUILayout.ExpandWidth(expand: false))) { Utils.OpenWebsite(plugin.Website); } GUI.color = color; GUILayout.EndHorizontal(); } if (flag || !plugin.Collapsed) { foreach (PluginSettingsData.PluginSettingsGroupData category in plugin.Categories) { if (!string.IsNullOrEmpty(category.Name) && (plugin.Categories.Count > 1 || !_hideSingleSection.Value)) { SettingFieldDrawer.DrawCategoryHeader(category.Name); } foreach (SettingEntryBase setting in category.Settings) { DrawSingleSetting(setting); GUILayout.Space(2f); } } GUILayout.BeginHorizontal(); Color backgroundColor = GUI.backgroundColor; GUI.backgroundColor = _widgetBackgroundColor.Value; if (GUILayout.Button("Reload", buttonStyle, GUILayout.ExpandWidth(expand: true))) { using (List.Enumerator enumerator3 = plugin.Categories.GetEnumerator()) { if (enumerator3.MoveNext()) { PluginSettingsData.PluginSettingsGroupData current3 = enumerator3.Current; using List.Enumerator enumerator4 = current3.Settings.GetEnumerator(); if (enumerator4.MoveNext()) { SettingEntryBase current4 = enumerator4.Current; current4.PluginInstance.Config.Reload(); } } } BuildFilteredSettingList(); } if (GUILayout.Button("Reset", buttonStyle, GUILayout.ExpandWidth(expand: true))) { foreach (PluginSettingsData.PluginSettingsGroupData category2 in plugin.Categories) { foreach (SettingEntryBase setting2 in category2.Settings) { setting2.Set(setting2.DefaultValue); } } BuildFilteredSettingList(); } GUI.backgroundColor = backgroundColor; GUILayout.EndHorizontal(); } GUILayout.EndVertical(); } private void DrawSingleSetting(SettingEntryBase setting) { GUILayout.BeginHorizontal(); try { DrawSettingName(setting); _fieldDrawer.DrawSettingValue(setting); DrawDefaultButton(setting); } catch (Exception arg) { Logger.Log(LogLevel.Error, $"Failed to draw setting {setting.DispName} - {arg}"); GUILayout.Label("Failed to draw this field, check log for details."); } GUILayout.EndHorizontal(); } private void DrawSettingName(SettingEntryBase setting) { if (!setting.HideSettingName) { Color color = GUI.color; if (setting.IsAdvanced == true) { GUI.color = _advancedSettingColor; } GUILayout.Label(new GUIContent(setting.DispName.TrimStart(new char[1] { '!' }), setting.Description), GUILayout.Width(LeftColumnWidth), GUILayout.MaxWidth(LeftColumnWidth)); GUI.color = color; } } private static void DrawDefaultButton(SettingEntryBase setting) { if (setting.HideDefaultButton) { return; } GUI.backgroundColor = _widgetBackgroundColor.Value; if (setting.DefaultValue != null) { if (DefaultButton()) { setting.Set(setting.DefaultValue); } } else if (setting.SettingType.IsClass && DefaultButton()) { setting.Set(null); } static bool DefaultButton() { GUILayout.Space(5f); return GUILayout.Button("Reset", GUILayout.ExpandWidth(expand: false)); } } private void Start() { Type typeFromHandle = typeof(Cursor); _curLockState = typeFromHandle.GetProperty("lockState", BindingFlags.Static | BindingFlags.Public); _curVisible = typeFromHandle.GetProperty("visible", BindingFlags.Static | BindingFlags.Public); if ((object)_curLockState == null && (object)_curVisible == null) { _obsoleteCursor = true; _curLockState = typeof(Screen).GetProperty("lockCursor", BindingFlags.Static | BindingFlags.Public); _curVisible = typeof(Screen).GetProperty("showCursor", BindingFlags.Static | BindingFlags.Public); } try { base.Config.Save(); } catch (IOException ex) { Logger.Log(LogLevel.Warning | LogLevel.Message, "WARNING: Failed to write to config directory, expect issues!\nError message:" + ex.Message); } catch (UnauthorizedAccessException ex2) { Logger.Log(LogLevel.Warning | LogLevel.Message, "WARNING: Permission denied to write to config directory, expect issues!\nError message:" + ex2.Message); } } private void Update() { if (DisplayingWindow) { SetUnlockCursor(0, cursorVisible: true); } if (!OverrideHotkey && !DisplayingWindow && _keybind.Value.IsUp()) { CreateBackgrounds(); DisplayingWindow = true; } } private void LateUpdate() { if (DisplayingWindow) { SetUnlockCursor(0, cursorVisible: true); } } private void SetUnlockCursor(int lockState, bool cursorVisible) { if ((object)_curLockState != null) { if (_obsoleteCursor) { _curLockState.SetValue(null, Convert.ToBoolean(lockState), null); } else { _curLockState.SetValue(null, lockState, null); } _curVisible.SetValue(null, cursorVisible, null); } } private void CreateBackgrounds() { Texture2D texture2D = new Texture2D(1, 1, TextureFormat.ARGB32, mipChain: false); texture2D.SetPixel(0, 0, _windowBackgroundColor.Value); texture2D.Apply(); WindowBackground = texture2D; Texture2D texture2D2 = new Texture2D(1, 1, TextureFormat.ARGB32, mipChain: false); texture2D2.SetPixel(0, 0, _entryBackgroundColor.Value); texture2D2.Apply(); EntryBackground = texture2D2; } private void CreateStyles() { windowStyle = new GUIStyle(GUI.skin.window); windowStyle.normal.textColor = _fontColor.Value; windowStyle.active.textColor = _fontColor.Value; labelStyle = new GUIStyle(GUI.skin.label); labelStyle.normal.textColor = _fontColor.Value; labelStyle.fontSize = fontSize; textStyle = new GUIStyle(GUI.skin.textArea); textStyle.normal.textColor = _fontColor.Value; textStyle.fontSize = fontSize; buttonStyle = new GUIStyle(GUI.skin.button); buttonStyle.normal.textColor = _fontColor.Value; buttonStyle.fontSize = fontSize; categoryHeaderSkin = new GUIStyle(labelStyle) { alignment = TextAnchor.UpperCenter, wordWrap = true, stretchWidth = true }; pluginHeaderSkin = new GUIStyle(categoryHeaderSkin); toggleStyle = new GUIStyle(GUI.skin.toggle); toggleStyle.normal.textColor = _fontColor.Value; toggleStyle.fontSize = fontSize; boxStyle = new GUIStyle(GUI.skin.box); boxStyle.normal.textColor = _fontColor.Value; boxStyle.fontSize = fontSize; sliderStyle = new GUIStyle(GUI.skin.horizontalSlider); thumbStyle = new GUIStyle(GUI.skin.horizontalSliderThumb); } } } // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.SettingEntryBase ---- namespace ConfigurationManager { public abstract class SettingEntryBase { public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput); private static readonly PropertyInfo[] _myProperties = typeof(SettingEntryBase).GetProperties(BindingFlags.Instance | BindingFlags.Public); public object[] AcceptableValues { get; protected set; } public KeyValuePair AcceptableValueRange { get; protected set; } public bool? ShowRangeAsPercent { get; protected set; } public Action CustomDrawer { get; private set; } public CustomHotkeyDrawerFunc CustomHotkeyDrawer { get; private set; } public bool? Browsable { get; protected set; } public string Category { get; protected set; } public object DefaultValue { get; protected set; } public bool HideDefaultButton { get; protected set; } public bool HideSettingName { get; protected set; } public string Description { get; protected internal set; } public virtual string DispName { get; protected internal set; } public BepInPlugin PluginInfo { get; protected internal set; } public bool? ReadOnly { get; protected set; } public abstract Type SettingType { get; } public BaseUnityPlugin PluginInstance { get; private set; } public bool? IsAdvanced { get; internal set; } public int Order { get; protected set; } public Func ObjToStr { get; internal set; } public Func StrToObj { get; internal set; } public abstract object Get(); public void Set(object newVal) { if (ReadOnly != true) { SetValue(newVal); } } protected abstract void SetValue(object newVal); internal void SetFromAttributes(object[] attribs, BaseUnityPlugin pluginInstance) { PluginInstance = pluginInstance; PluginInfo = pluginInstance?.Info.Metadata; if (attribs == null || attribs.Length == 0) { return; } foreach (object obj in attribs) { object obj2 = obj; object obj3 = obj2; if (obj3 == null) { continue; } if (!(obj3 is DisplayNameAttribute displayNameAttribute)) { if (!(obj3 is CategoryAttribute categoryAttribute)) { if (!(obj3 is DescriptionAttribute descriptionAttribute)) { if (!(obj3 is DefaultValueAttribute defaultValueAttribute)) { if (!(obj3 is ReadOnlyAttribute readOnlyAttribute)) { if (!(obj3 is BrowsableAttribute browsableAttribute)) { Action action = obj3 as Action; if (action == null) { if (obj3 is string text) { switch (text) { case "ReadOnly": ReadOnly = true; break; case "Browsable": Browsable = true; break; case "Unbrowsable": case "Hidden": Browsable = false; break; case "Advanced": IsAdvanced = true; break; } continue; } Type type = obj.GetType(); if (!(type.Name == "ConfigurationManagerAttributes")) { break; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public); foreach (var item in from my in _myProperties join other in fields on my.Name equals other.Name select new { my, other }) { try { object obj4 = item.other.GetValue(obj); if (obj4 != null) { if ((object)item.my.PropertyType != item.other.FieldType && typeof(Delegate).IsAssignableFrom(item.my.PropertyType)) { obj4 = Delegate.CreateDelegate(item.my.PropertyType, ((Delegate)obj4).Target, ((Delegate)obj4).Method); } item.my.SetValue(this, obj4, null); } } catch (Exception ex) { ConfigurationManager.Logger.LogWarning("Failed to copy value " + item.my.Name + " from provided tag object " + type.FullName + " - " + ex.Message); } } } else { CustomDrawer = delegate { action(this); }; } } else { Browsable = browsableAttribute.Browsable; } } else { ReadOnly = readOnlyAttribute.IsReadOnly; } } else { DefaultValue = defaultValueAttribute.Value; } } else { Description = descriptionAttribute.Description; } } else { Category = categoryAttribute.Category; } } else { DispName = displayNameAttribute.DisplayName; } } } } } // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.SettingFieldDrawer ---- namespace ConfigurationManager { internal class SettingFieldDrawer { private sealed class FloatConfigCacheEntry { public float Value = 0f; public string FieldText = string.Empty; public Color FieldColor = Color.clear; } private sealed class ColorCacheEntry { public Color Last; public Texture2D Tex; } private static IEnumerable _keysToCheck; private static readonly Dictionary _comboBoxCache; private static readonly Dictionary _colorCache; private static ConfigurationManager _instance; private static SettingEntryBase _currentKeyboardShortcutToSet; private static GUIStyle _categoryHeaderSkin; private static GUIStyle _pluginHeaderSkin; private static readonly Dictionary _floatConfigCache; private readonly Dictionary _canCovertCache = new Dictionary(); public static Dictionary> SettingDrawHandlers { get; } public static bool SettingKeyboardShortcut => _currentKeyboardShortcutToSet != null; static SettingFieldDrawer() { _comboBoxCache = new Dictionary(); _colorCache = new Dictionary(); _floatConfigCache = new Dictionary(); SettingDrawHandlers = new Dictionary> { { typeof(bool), DrawBoolField }, { typeof(float), DrawFloatField }, { typeof(KeyboardShortcut), DrawKeyboardShortcut }, { typeof(KeyCode), DrawKeyCode }, { typeof(Color), DrawColor }, { typeof(Vector2), DrawVector2 }, { typeof(Vector3), DrawVector3 }, { typeof(Vector4), DrawVector4 }, { typeof(Quaternion), DrawQuaternion } }; } public SettingFieldDrawer(ConfigurationManager instance) { _instance = instance; } public void DrawSettingValue(SettingEntryBase setting) { if (setting.CustomDrawer != null) { setting.CustomDrawer((setting is ConfigSettingEntry configSettingEntry) ? configSettingEntry.Entry : null); } else if (setting.CustomHotkeyDrawer != null) { bool isCurrentlyAcceptingInput = _currentKeyboardShortcutToSet == setting; bool flag = isCurrentlyAcceptingInput; setting.CustomHotkeyDrawer((setting is ConfigSettingEntry configSettingEntry2) ? configSettingEntry2.Entry : null, ref isCurrentlyAcceptingInput); if (isCurrentlyAcceptingInput != flag) { _currentKeyboardShortcutToSet = (isCurrentlyAcceptingInput ? setting : null); } } else if (setting.ShowRangeAsPercent.HasValue && setting.AcceptableValueRange.Key != null) { DrawRangeField(setting); } else if (setting.AcceptableValues != null) { DrawListField(setting); } else if (!DrawFieldBasedOnValueType(setting)) { if (setting.SettingType.IsEnum) { DrawEnumField(setting); } else { DrawUnknownField(setting, _instance.RightColumnWidth); } } } public static void ClearCache() { _comboBoxCache.Clear(); foreach (KeyValuePair item in _colorCache) { UnityEngine.Object.Destroy(item.Value.Tex); } _colorCache.Clear(); } public static void DrawCenteredLabel(string text, params GUILayoutOption[] options) { GUILayout.BeginHorizontal(options); GUILayout.FlexibleSpace(); GUILayout.Label(text); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); } public static void DrawCategoryHeader(string text) { if (_categoryHeaderSkin == null) { _categoryHeaderSkin = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.UpperCenter, wordWrap = true, stretchWidth = true, fontSize = 14 }; } GUILayout.Label(text, _categoryHeaderSkin); } public static bool DrawPluginHeader(GUIContent content, bool isCollapsed) { if (_pluginHeaderSkin == null) { _pluginHeaderSkin = new GUIStyle(GUI.skin.label) { alignment = TextAnchor.UpperCenter, wordWrap = true, stretchWidth = true, fontSize = 15 }; } if (isCollapsed) { content.text += "\n..."; } return GUILayout.Button(content, _pluginHeaderSkin, GUILayout.ExpandWidth(expand: true)); } public static bool DrawCurrentDropdown() { if (ComboBox.CurrentDropdownDrawer != null) { ComboBox.CurrentDropdownDrawer(); ComboBox.CurrentDropdownDrawer = null; return true; } return false; } private static void DrawListField(SettingEntryBase setting) { object[] acceptableValues = setting.AcceptableValues; if (acceptableValues.Length == 0) { throw new ArgumentException("AcceptableValueListAttribute returned an empty list of acceptable values. You need to supply at least 1 option."); } if (!setting.SettingType.IsInstanceOfType(acceptableValues.FirstOrDefault((object x) => x != null))) { throw new ArgumentException("AcceptableValueListAttribute returned a list with items of type other than the settng type itself."); } if ((object)setting.SettingType == typeof(KeyCode)) { DrawKeyCode(setting); } else { DrawComboboxField(setting, acceptableValues, _instance.SettingWindowRect.yMax); } } private static bool DrawFieldBasedOnValueType(SettingEntryBase setting) { if (SettingDrawHandlers.TryGetValue(setting.SettingType, out var value)) { value(setting); return true; } return false; } private static void DrawBoolField(SettingEntryBase setting) { bool flag = (bool)setting.Get(); bool flag2 = GUILayout.Toggle(flag, flag ? "Enabled" : "Disabled", GUILayout.ExpandWidth(expand: true)); if (flag2 != flag) { setting.Set(flag2); } } public static void DrawFloatField(SettingEntryBase configEntry) { float num = (float)configEntry.Get(); if (!_floatConfigCache.TryGetValue(configEntry, out var value)) { value = new FloatConfigCacheEntry { Value = num, FieldColor = GUI.color }; _floatConfigCache[configEntry] = value; } if (GUIFocus.HasChanged() || GUIHelper.IsEnterPressed() || value.Value != num) { value.Value = num; value.FieldText = num.ToString(NumberFormatInfo.InvariantInfo); value.FieldColor = GUI.color; } GUIHelper.BeginColor(value.FieldColor); string text = GUILayout.TextField(value.FieldText, GUILayout.ExpandWidth(expand: true)); GUIHelper.EndColor(); if (text == value.FieldText) { return; } value.FieldText = text; if (ShouldParse(text) && float.TryParse(text, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var result)) { configEntry.Set(result); value.Value = (float)configEntry.Get(); value.FieldText = value.Value.ToString(NumberFormatInfo.InvariantInfo); if (value.FieldText == text) { value.FieldColor = GUI.color; return; } value.FieldColor = Color.yellow; value.FieldText = text; } else { value.FieldColor = Color.red; } } private static bool ShouldParse(string text) { if (text == null || text.Length <= 0) { return false; } switch (text[text.Length - 1]) { case '+': case ',': case '-': case '.': case 'E': case 'e': return false; default: return true; } } private static void DrawEnumField(SettingEntryBase setting) { if (setting.SettingType.GetCustomAttributes(typeof(FlagsAttribute), inherit: false).Any()) { DrawFlagsField(setting, Enum.GetValues(setting.SettingType), _instance.RightColumnWidth); } else { DrawComboboxField(setting, Enum.GetValues(setting.SettingType), _instance.SettingWindowRect.yMax); } } private static void DrawFlagsField(SettingEntryBase setting, IList enumValues, int maxWidth) { long num = Convert.ToInt64(setting.Get()); var array = (from Enum x in enumValues select new { name = x.ToString(), val = Convert.ToInt64(x) }).ToArray(); GUILayout.BeginVertical(GUILayout.MaxWidth(maxWidth)); int num2 = 0; while (num2 < array.Length) { GUILayout.BeginHorizontal(); int num3 = 0; for (; num2 < array.Length; num2++) { var anon = array[num2]; if (anon.val != 0) { int num4 = (int)GUI.skin.toggle.CalcSize(new GUIContent(anon.name)).x; num3 += num4; if (num3 > maxWidth) { break; } GUI.changed = false; bool flag = GUILayout.Toggle((num & anon.val) == anon.val, anon.name, GUILayout.ExpandWidth(expand: false)); if (GUI.changed) { long value = (flag ? (num | anon.val) : (num & ~anon.val)); setting.Set(Enum.ToObject(setting.SettingType, value)); } } } GUILayout.EndHorizontal(); } GUI.changed = false; GUILayout.EndVertical(); GUILayout.FlexibleSpace(); } private static void DrawComboboxField(SettingEntryBase setting, IList list, float windowYmax) { GUIContent gUIContent = ObjectToGuiContent(setting.Get()); Rect rect = GUILayoutUtility.GetRect(gUIContent, GUI.skin.button, GUILayout.ExpandWidth(expand: true)); if (!_comboBoxCache.TryGetValue(setting, out var value)) { value = new ComboBox(rect, gUIContent, list.Cast().Select(ObjectToGuiContent).ToArray(), GUI.skin.button, windowYmax); _comboBoxCache[setting] = value; } else { value.Rect = rect; value.ButtonContent = gUIContent; } value.Show(delegate(int id) { if (id >= 0 && id < list.Count) { setting.Set(list[id]); } }); } private static GUIContent ObjectToGuiContent(object x) { if (x is Enum) { Type type = x.GetType(); DescriptionAttribute descriptionAttribute = type.GetMember(x.ToString()).FirstOrDefault()?.GetCustomAttributes(typeof(DescriptionAttribute), inherit: false).Cast().FirstOrDefault(); if (descriptionAttribute != null) { return new GUIContent(descriptionAttribute.Description); } return new GUIContent(x.ToString().ToProperCase()); } return new GUIContent(x.ToString()); } private static void DrawRangeField(SettingEntryBase setting) { object obj = setting.Get(); float num = (float)Convert.ToDouble(obj, CultureInfo.InvariantCulture); float num2 = (float)Convert.ToDouble(setting.AcceptableValueRange.Key, CultureInfo.InvariantCulture); float num3 = (float)Convert.ToDouble(setting.AcceptableValueRange.Value, CultureInfo.InvariantCulture); float num4 = GUILayout.HorizontalSlider(num, num2, num3, GUILayout.ExpandWidth(expand: true)); if (Math.Abs(num4 - num) > Mathf.Abs(num3 - num2) / 1000f) { object newVal = Convert.ChangeType(num4, setting.SettingType, CultureInfo.InvariantCulture); setting.Set(newVal); } if (setting.ShowRangeAsPercent == true) { DrawCenteredLabel(Mathf.Round(100f * Mathf.Abs(num4 - num2) / Mathf.Abs(num3 - num2)) + "%", GUILayout.Width(50f)); return; } string text = obj.ToString().AppendZeroIfFloat(setting.SettingType); string text2 = GUILayout.TextField(text, GUILayout.Width(50f)); if (!(text2 != text)) { return; } try { float value = (float)Convert.ToDouble(text2, CultureInfo.InvariantCulture); float num5 = Mathf.Clamp(value, num2, num3); setting.Set(Convert.ChangeType(num5, setting.SettingType, CultureInfo.InvariantCulture)); } catch (FormatException) { } } private void DrawUnknownField(SettingEntryBase setting, int rightColumnWidth) { if (setting.ObjToStr != null && setting.StrToObj != null) { string text = setting.ObjToStr(setting.Get()).AppendZeroIfFloat(setting.SettingType); string text2 = GUILayout.TextField(text, GUILayout.Width(rightColumnWidth), GUILayout.MaxWidth(rightColumnWidth)); if (text2 != text) { setting.Set(setting.StrToObj(text2)); } } else { object obj = setting.Get(); string text3 = ((obj == null) ? "NULL" : obj.ToString().AppendZeroIfFloat(setting.SettingType)); if (CanCovert(text3, setting.SettingType)) { string text4 = GUILayout.TextField(text3, GUILayout.Width(rightColumnWidth), GUILayout.MaxWidth(rightColumnWidth)); if (text4 != text3) { setting.Set(Convert.ChangeType(text4, setting.SettingType, CultureInfo.InvariantCulture)); } } else { GUILayout.TextArea(text3, GUILayout.MaxWidth(rightColumnWidth)); } } GUILayout.FlexibleSpace(); } private bool CanCovert(string value, Type type) { if (_canCovertCache.ContainsKey(type)) { return _canCovertCache[type]; } try { object obj = Convert.ChangeType(value, type); _canCovertCache[type] = true; return true; } catch { _canCovertCache[type] = false; return false; } } private static void DrawKeyCode(SettingEntryBase setting) { if (_currentKeyboardShortcutToSet == setting) { GUILayout.Label("Press any key", GUILayout.ExpandWidth(expand: true)); GUIUtility.keyboardControl = -1; IInputSystem current = UnityInput.Current; if (_keysToCheck == null) { _keysToCheck = current.SupportedKeyCodes.Except(new KeyCode[2] { KeyCode.Mouse0, KeyCode.None }).ToArray(); } foreach (KeyCode item in _keysToCheck) { if (current.GetKeyUp(item)) { setting.Set(item); _currentKeyboardShortcutToSet = null; break; } } if (GUILayout.Button("Cancel", GUILayout.ExpandWidth(expand: false))) { _currentKeyboardShortcutToSet = null; } } else { object[] acceptableValues = setting.AcceptableValues; Array list = ((acceptableValues != null && acceptableValues.Length > 1) ? setting.AcceptableValues : Enum.GetValues(setting.SettingType)); DrawComboboxField(setting, list, _instance.SettingWindowRect.yMax); if (GUILayout.Button(new GUIContent("Set...", "Set the key by pressing any key on your keyboard."), GUILayout.ExpandWidth(expand: false))) { _currentKeyboardShortcutToSet = setting; } } } private static void DrawKeyboardShortcut(SettingEntryBase setting) { if (_currentKeyboardShortcutToSet == setting) { GUILayout.Label("Press any key combination", GUILayout.ExpandWidth(expand: true)); GUIUtility.keyboardControl = -1; IInputSystem current = UnityInput.Current; if (_keysToCheck == null) { _keysToCheck = current.SupportedKeyCodes.Except(new KeyCode[2] { KeyCode.Mouse0, KeyCode.None }).ToArray(); } foreach (KeyCode item in _keysToCheck) { if (current.GetKeyUp(item)) { setting.Set(new KeyboardShortcut(item, _keysToCheck.Where(current.GetKey).ToArray())); _currentKeyboardShortcutToSet = null; break; } } if (GUILayout.Button("Cancel", GUILayout.ExpandWidth(expand: false))) { _currentKeyboardShortcutToSet = null; } } else { if (GUILayout.Button(setting.Get().ToString(), GUILayout.ExpandWidth(expand: true))) { _currentKeyboardShortcutToSet = setting; } if (GUILayout.Button("Clear", GUILayout.ExpandWidth(expand: false))) { setting.Set(KeyboardShortcut.Empty); _currentKeyboardShortcutToSet = null; } } } private static void DrawVector2(SettingEntryBase obj) { Vector2 vector = (Vector2)obj.Get(); Vector2 vector2 = vector; vector.x = DrawSingleVectorSlider(vector.x, "X"); vector.y = DrawSingleVectorSlider(vector.y, "Y"); if (vector != vector2) { obj.Set(vector); } } private static void DrawVector3(SettingEntryBase obj) { Vector3 vector = (Vector3)obj.Get(); Vector3 vector2 = vector; vector.x = DrawSingleVectorSlider(vector.x, "X"); vector.y = DrawSingleVectorSlider(vector.y, "Y"); vector.z = DrawSingleVectorSlider(vector.z, "Z"); if (vector != vector2) { obj.Set(vector); } } private static void DrawVector4(SettingEntryBase obj) { Vector4 vector = (Vector4)obj.Get(); Vector4 vector2 = vector; vector.x = DrawSingleVectorSlider(vector.x, "X"); vector.y = DrawSingleVectorSlider(vector.y, "Y"); vector.z = DrawSingleVectorSlider(vector.z, "Z"); vector.w = DrawSingleVectorSlider(vector.w, "W"); if (vector != vector2) { obj.Set(vector); } } private static void DrawQuaternion(SettingEntryBase obj) { Quaternion quaternion = (Quaternion)obj.Get(); Quaternion quaternion2 = quaternion; quaternion.x = DrawSingleVectorSlider(quaternion.x, "X"); quaternion.y = DrawSingleVectorSlider(quaternion.y, "Y"); quaternion.z = DrawSingleVectorSlider(quaternion.z, "Z"); quaternion.w = DrawSingleVectorSlider(quaternion.w, "W"); if (quaternion != quaternion2) { obj.Set(quaternion); } } private static float DrawSingleVectorSlider(float setting, string label) { GUILayout.Label(label, GUILayout.ExpandWidth(expand: false)); float.TryParse(GUILayout.TextField(setting.ToString("F", CultureInfo.InvariantCulture), GUILayout.ExpandWidth(expand: true)), NumberStyles.Any, CultureInfo.InvariantCulture, out var result); return result; } private static void DrawColor(SettingEntryBase obj) { Color value = (Color)obj.Get(); GUILayout.BeginVertical(GUI.skin.box); GUILayout.BeginHorizontal(); DrawHexField(ref value); GUILayout.Space(3f); GUIHelper.BeginColor(value); GUILayout.Label(string.Empty, GUILayout.ExpandWidth(expand: true)); if (!_colorCache.TryGetValue(obj, out var value2)) { value2 = new ColorCacheEntry { Tex = new Texture2D(40, 10, TextureFormat.ARGB32, mipChain: false), Last = value }; value2.Tex.FillTexture(value); _colorCache[obj] = value2; } if (Event.current.type == EventType.Repaint) { GUI.DrawTexture(GUILayoutUtility.GetLastRect(), value2.Tex); } GUIHelper.EndColor(); GUILayout.Space(3f); GUILayout.EndHorizontal(); GUILayout.Space(4f); GUILayout.BeginHorizontal(); DrawColorField("R", ref value, ref value.r); GUILayout.Space(3f); DrawColorField("G", ref value, ref value.g); GUILayout.Space(3f); DrawColorField("B", ref value, ref value.b); GUILayout.Space(3f); DrawColorField("A", ref value, ref value.a); if (value != value2.Last) { obj.Set(value); value2.Tex.FillTexture(value); value2.Last = value; } GUILayout.EndHorizontal(); GUILayout.EndVertical(); } private static void DrawColorField(string fieldLabel, ref Color settingColor, ref float settingValue) { GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); GUILayout.Label(fieldLabel, GUILayout.ExpandWidth(expand: true)); GUILayout.TextField(settingValue.ToString(CultureInfo.CurrentCulture), GUILayout.MaxWidth(45f), GUILayout.ExpandWidth(expand: true)); GUILayout.EndHorizontal(); GUILayout.Space(2f); switch (fieldLabel) { case "R": settingColor.r = GUILayout.HorizontalSlider(settingValue, 0f, 1f, GUILayout.ExpandWidth(expand: true)); break; case "G": settingColor.g = GUILayout.HorizontalSlider(settingValue, 0f, 1f, GUILayout.ExpandWidth(expand: true)); break; case "B": settingColor.b = GUILayout.HorizontalSlider(settingValue, 0f, 1f, GUILayout.ExpandWidth(expand: true)); break; case "A": settingColor.a = GUILayout.HorizontalSlider(settingValue, 0f, 1f, GUILayout.ExpandWidth(expand: true)); break; } GUILayout.EndVertical(); } private static void DrawHexField(ref Color value) { string text = "#" + ColorUtility.ToHtmlStringRGBA(value); string text2 = GUILayout.TextField(text, GUILayout.Width(90f), GUILayout.ExpandWidth(expand: false)); if (!(text2 == text) && ColorUtility.TryParseHtmlString(text2, out var color)) { value = color; } } } } // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.ValueChangedEventArgs`1 ---- namespace ConfigurationManager { public sealed class ValueChangedEventArgs : EventArgs { public TValue NewValue { get; } public ValueChangedEventArgs(TValue newValue) { NewValue = newValue; } } } // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.Utilities.ComboBox ---- namespace ConfigurationManager.Utilities { internal class ComboBox { private static bool forceToUnShow; private static int useControlID = -1; private readonly string buttonStyle; private bool isClickedComboButton; private readonly GUIContent[] listContent; private readonly GUIStyle listStyle; private readonly int _windowYmax; private Vector2 _scrollPosition = Vector2.zero; public Rect Rect { get; set; } public GUIContent ButtonContent { get; set; } public static Action CurrentDropdownDrawer { get; set; } public ComboBox(Rect rect, GUIContent buttonContent, GUIContent[] listContent, GUIStyle listStyle, float windowYmax) { Rect = rect; ButtonContent = buttonContent; this.listContent = listContent; buttonStyle = "button"; this.listStyle = listStyle; _windowYmax = (int)windowYmax; } public void Show(Action onItemSelected) { if (forceToUnShow) { forceToUnShow = false; isClickedComboButton = false; } bool flag = false; int controlID = GUIUtility.GetControlID(FocusType.Passive); Vector2 vector = Vector2.zero; if (Event.current.GetTypeForControl(controlID) == EventType.MouseUp && isClickedComboButton) { flag = true; vector = Event.current.mousePosition; } if (GUI.Button(Rect, ButtonContent, buttonStyle)) { if (useControlID == -1) { useControlID = controlID; isClickedComboButton = false; } if (useControlID != controlID) { forceToUnShow = true; useControlID = controlID; } isClickedComboButton = true; } if (isClickedComboButton) { GUI.enabled = false; GUI.color = new Color(1f, 1f, 1f, 2f); Vector2 location = GUIUtility.GUIToScreenPoint(new Vector2(Rect.x, Rect.y + listStyle.CalcHeight(listContent[0], 1f))); Vector2 vector2 = new Vector2(Rect.width, listStyle.CalcHeight(listContent[0], 1f) * (float)listContent.Length); Rect innerRect = new Rect(0f, 0f, vector2.x, vector2.y); Rect outerRectScreen = new Rect(location.x, location.y, vector2.x, vector2.y); if (outerRectScreen.yMax > (float)_windowYmax) { outerRectScreen.height = (float)_windowYmax - outerRectScreen.y; outerRectScreen.width += 20f; } if (vector != Vector2.zero && outerRectScreen.Contains(GUIUtility.GUIToScreenPoint(vector))) { flag = false; } CurrentDropdownDrawer = delegate { GUI.enabled = true; Vector2 vector3 = GUIUtility.ScreenToGUIPoint(location); Rect position = new Rect(vector3.x, vector3.y, outerRectScreen.width, outerRectScreen.height); GUI.Box(position, GUIContent.none, new GUIStyle { normal = new GUIStyleState { background = ConfigurationManager.WindowBackground } }); _scrollPosition = GUI.BeginScrollView(position, _scrollPosition, innerRect, alwaysShowHorizontal: false, alwaysShowVertical: false); int num = GUI.SelectionGrid(innerRect, -1, listContent, 1, listStyle); if (num != -1) { onItemSelected(num); isClickedComboButton = false; } GUI.EndScrollView(handleScrollWheel: true); }; } if (flag) { isClickedComboButton = false; } } } } // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.Utilities.GUIFocus ---- namespace ConfigurationManager.Utilities { public static class GUIFocus { private static int _lastFrameCount; private static int _lastHotControl; private static int _lastKeyboardControl; private static bool _hasChanged; public static bool HasChanged() { int frameCount = Time.frameCount; if (_lastFrameCount == frameCount) { return _hasChanged; } _lastFrameCount = frameCount; int hotControl = GUIUtility.hotControl; int keyboardControl = GUIUtility.keyboardControl; _hasChanged = hotControl != _lastHotControl || keyboardControl != _lastKeyboardControl; if (_hasChanged) { _lastHotControl = hotControl; _lastKeyboardControl = keyboardControl; } return _hasChanged; } } } // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.Utilities.GUIHelper ---- namespace ConfigurationManager.Utilities { public static class GUIHelper { private static readonly Stack _colorStack = new Stack(); public static void BeginColor(Color color) { _colorStack.Push(GUI.color); GUI.color = color; } public static void EndColor() { GUI.color = _colorStack.Pop(); } public static bool IsEnterPressed() { return Event.current.isKey && (Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.KeypadEnter); } } } // ---- BepInEx/plugins/ConfigurationManager.dll :: ConfigurationManager.Utilities.Utils ---- namespace ConfigurationManager.Utilities { internal static class Utils { public static string ToProperCase(this string str) { if (string.IsNullOrEmpty(str)) { return string.Empty; } if (str.Length < 2) { return str; } string text = str.Substring(0, 1).ToUpper(); for (int i = 1; i < str.Length; i++) { if (char.IsUpper(str[i])) { text += " "; } text += str[i]; } return text; } public static BaseUnityPlugin[] FindPlugins() { return Chainloader.PluginInfos.Values.Select((PluginInfo x) => x.Instance).Union(UnityEngine.Object.FindObjectsOfType(typeof(BaseUnityPlugin)).Cast()).ToArray(); } public static string AppendZero(this string s) { return (!s.Contains(".")) ? (s + ".0") : s; } public static string AppendZeroIfFloat(this string s, Type type) { return ((object)type == typeof(float) || (object)type == typeof(double) || (object)type == typeof(decimal)) ? s.AppendZero() : s; } public static void FillTexture(this Texture2D tex, Color color) { for (int i = 0; i < tex.width; i++) { for (int j = 0; j < tex.height; j++) { tex.SetPixel(i, j, color); } } tex.Apply(updateMipmaps: false); } public static void OpenLog() { List list = new List(); string text = Path.Combine(Application.dataPath, ".."); list.Add(Path.Combine(text, "output_log.txt")); list.Add(Path.Combine(Application.dataPath, "output_log.txt")); PropertyInfo property = typeof(Application).GetProperty("consoleLogPath", BindingFlags.Static | BindingFlags.Public); if ((object)property != null) { string item = property.GetValue(null, null) as string; list.Add(item); } if (Directory.Exists(Application.persistentDataPath)) { string item2 = Directory.GetFiles(Application.persistentDataPath, "output_log.txt", SearchOption.AllDirectories).FirstOrDefault(); list.Add(item2); } string path = list.Where(File.Exists).OrderByDescending(File.GetLastWriteTimeUtc).FirstOrDefault(); if (!TryOpen(path)) { list.Clear(); list.AddRange(Directory.GetFiles(text, "LogOutput.log*", SearchOption.AllDirectories)); list.AddRange(Directory.GetFiles(text, "output_log.txt", SearchOption.AllDirectories)); path = list.Where(File.Exists).OrderByDescending(File.GetLastWriteTimeUtc).FirstOrDefault(); if (!TryOpen(path)) { throw new FileNotFoundException("No log files were found"); } } static bool TryOpen(string text2) { if (text2 != null) { try { Process.Start(text2); return true; } catch { return false; } } return false; } } public static string GetWebsite(BaseUnityPlugin bepInPlugin) { if (bepInPlugin == null) { return null; } try { string location = bepInPlugin.GetType().Assembly.Location; if (!File.Exists(location)) { return null; } FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(location); return new string[5] { versionInfo.CompanyName, versionInfo.FileDescription, versionInfo.Comments, versionInfo.LegalCopyright, versionInfo.LegalTrademarks }.FirstOrDefault((string x) => Uri.IsWellFormedUriString(x, UriKind.Absolute)); } catch (Exception ex) { ConfigurationManager.Logger.LogWarning("Failed to get URI for " + bepInPlugin?.Info?.Metadata?.Name + " - " + ex.Message); return null; } } public static void OpenWebsite(string url) { try { if (string.IsNullOrEmpty(url)) { throw new Exception("Empty URL"); } Process.Start(url); } catch (Exception ex) { ConfigurationManager.Logger.Log(LogLevel.Warning | LogLevel.Message, "Failed to open URL " + url + "\nCause: " + ex.Message); } } } }