/// <summary> /// Unknown type, read only /// </summary> public void DrawUnknownField(PropSettingEntry setting) { // Try to use user-supplied converters if (setting.ObjToStr != null && setting.StrToObj != null) { var text = setting.ObjToStr(setting.Get()); var result = GUILayout.TextField(text); if (result != text) { setting.Set(setting.StrToObj(result)); } return; } // Fall back to slow/less reliable method var value = setting.Get()?.ToString() ?? "NULL"; if (CanCovert(value, setting.SettingType)) { var result = GUILayout.TextField(value); if (result != value) { setting.Set(Convert.ChangeType(result, setting.SettingType)); } } else { GUILayout.TextArea(value); } }
public void DrawRangeField(PropSettingEntry setting, AcceptableValueRangeAttribute range) { var value = setting.Get(); var converted = (float)Convert.ToDouble(value); var leftValue = (float)Convert.ToDouble(range.MinValue); var rightValue = (float)Convert.ToDouble(range.MaxValue); var result = GUILayout.HorizontalSlider(converted, leftValue, rightValue, GUILayout.ExpandWidth(true)); if (Math.Abs(result - converted) > Mathf.Abs(rightValue - leftValue) / 1000) { var newValue = Convert.ChangeType(result, value.GetType()); setting.Set(newValue); } if (range.ShowAsPercentage) { DrawCenteredLabel( Mathf.Round(100 * Mathf.Abs(result - leftValue) / Mathf.Abs(rightValue - leftValue)) + "%", GUILayout.Width(50)); } else { DrawCenteredLabel(value.ToString(), GUILayout.Width(50)); } }
public void DrawBoolField(PropSettingEntry setting) { var boolVal = (bool)setting.Get(); var result = GUILayout.Toggle(boolVal, boolVal ? "Enabled" : "Disabled", GUILayout.ExpandWidth(true)); if (result != boolVal) { setting.Set(result); } }
public void DrawKeyboardShortcut(PropSettingEntry setting) { var shortcut = (KeyboardShortcut)setting.Get(); GUILayout.BeginHorizontal(); { if (CurrentKeyboardShortcutToSet == setting) { GUILayout.Label("Press any key combination", GUILayout.ExpandWidth(true)); GUIUtility.keyboardControl = -1; foreach (var key in KeysToCheck) { if (Input.GetKeyUp(key)) { shortcut.MainKey = key; shortcut.Modifiers = KeysToCheck.Where(Input.GetKey).OrderBy(x => x.ToString()).ToArray(); CurrentKeyboardShortcutToSet = null; break; } } if (GUILayout.Button("Cancel", GUILayout.ExpandWidth(false))) { CurrentKeyboardShortcutToSet = null; } } else { if (GUILayout.Button(shortcut.ToString(), GUILayout.ExpandWidth(true))) { CurrentKeyboardShortcutToSet = setting; } if (GUILayout.Button("Clear", GUILayout.ExpandWidth(false))) { setting.Set(KeyboardShortcut.Empty); CurrentKeyboardShortcutToSet = null; } } } GUILayout.EndHorizontal(); }
public void DrawComboboxField(PropSettingEntry setting, IList list) { var buttonText = new GUIContent(setting.Get().ToString()); var dispRect = GUILayoutUtility.GetRect(buttonText, GUI.skin.button, GUILayout.ExpandWidth(true)); if (!_comboBoxCache.TryGetValue(setting, out var box)) { box = new ComboBox(dispRect, buttonText, list.Cast <object>().Select(x => new GUIContent(x.ToString())).ToArray(), GUI.skin.button); _comboBoxCache[setting] = box; } else { box.Rect = dispRect; box.ButtonContent = buttonText; } var id = box.Show(); if (id >= 0 && id < list.Count) { setting.Set(list[id]); } }
/// <summary> /// Unknown type, read only /// </summary> public void DrawUnknownField(PropSettingEntry setting) { GUILayout.TextArea(setting.Get()?.ToString() ?? "NULL"); }
public static void CollectSettings(out IEnumerable <PropSettingEntry> results, out List <string> modsWithoutSettings, bool showDebug) { var baseSettingType = typeof(ConfigWrapper <>); results = Enumerable.Empty <PropSettingEntry>(); modsWithoutSettings = new List <string>(); foreach (var plugin in Utils.FindPlugins()) { var type = plugin.GetType(); var pluginInfo = MetadataHelper.GetMetadata(type); if (pluginInfo == null) { ConfigurationManager.Logger.Log(LogLevel.Error, $"Plugin {type.FullName} is missing the BepInPlugin attribute!"); modsWithoutSettings.Add(type.FullName); continue; } if (type.GetCustomAttributes(typeof(BrowsableAttribute), false).Cast <BrowsableAttribute>() .Any(x => !x.Browsable)) { modsWithoutSettings.Add(pluginInfo.Name); continue; } var detected = new List <PropSettingEntry>(); // Config wrappers ------ var settingProps = type .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .FilterBrowsable(true, true); var settingFields = type.GetFields(BindingFlags.Instance | BindingFlags.Public) .Where(f => !f.IsSpecialName) .FilterBrowsable(true, true) .Select(f => new FieldToPropertyInfoWrapper(f)); var settingEntries = settingProps.Concat(settingFields.Cast <PropertyInfo>()) .Where(x => x.PropertyType.IsSubclassOfRawGeneric(baseSettingType)); detected.AddRange(settingEntries.Select(x => PropSettingEntry.FromConfigWrapper(plugin, x, pluginInfo, plugin)).Where(x => x != null)); // Config wrappers static ------ var settingStaticProps = type .GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) .FilterBrowsable(true, true); var settingStaticFields = type.GetFields(BindingFlags.Static | BindingFlags.Public) .Where(f => !f.IsSpecialName) .FilterBrowsable(true, true) .Select(f => new FieldToPropertyInfoWrapper(f)); var settingStaticEntries = settingStaticProps.Concat(settingStaticFields.Cast <PropertyInfo>()) .Where(x => x.PropertyType.IsSubclassOfRawGeneric(baseSettingType)); detected.AddRange(settingStaticEntries.Select(x => PropSettingEntry.FromConfigWrapper(null, x, pluginInfo, plugin)).Where(x => x != null)); // Normal properties ------ bool IsPropSafeToShow(PropertyInfo p) => p.GetSetMethod()?.IsPublic == true && (p.PropertyType.IsValueType || p.PropertyType == typeof(string)); var normalPropsSafeToShow = type .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly) .Where(IsPropSafeToShow) .FilterBrowsable(true, true) .Where(x => !x.PropertyType.IsSubclassOfRawGeneric(baseSettingType)); var normalPropsWithBrowsable = type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) .FilterBrowsable(true, false) .Where(x => !x.PropertyType.IsSubclassOfRawGeneric(baseSettingType)); var normalProps = normalPropsSafeToShow.Concat(normalPropsWithBrowsable).Distinct(); detected.AddRange(normalProps.Select(x => PropSettingEntry.FromNormalProperty(plugin, x, pluginInfo, plugin)).Where(x => x != null)); // Normal static properties ------ var normalStaticPropsSafeToShow = type .GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly) .Where(IsPropSafeToShow) .FilterBrowsable(true, true) .Where(x => !x.PropertyType.IsSubclassOfRawGeneric(baseSettingType)); var normalStaticPropsWithBrowsable = type.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) .FilterBrowsable(true, false) .Where(x => !x.PropertyType.IsSubclassOfRawGeneric(baseSettingType)); var normalStaticProps = normalStaticPropsSafeToShow.Concat(normalStaticPropsWithBrowsable).Distinct(); detected.AddRange(normalStaticProps.Select(x => PropSettingEntry.FromNormalProperty(null, x, pluginInfo, plugin)).Where(x => x != null)); detected.RemoveAll(x => x.Browsable == false); if (!detected.Any()) { modsWithoutSettings.Add(pluginInfo.Name); } // Allow to enable/disable plugin if it uses any update methods ------ if (showDebug && type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any(x => _updateMethodNames.Contains(x.Name))) { var enabledSetting = PropSettingEntry.FromNormalProperty(plugin, type.GetProperty("enabled"), pluginInfo, plugin); enabledSetting.DispName = "!Allow plugin to run on every frame"; enabledSetting.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."; enabledSetting.IsAdvanced = true; detected.Add(enabledSetting); } if (detected.Any()) { var isAdvancedPlugin = type.GetCustomAttributes(typeof(AdvancedAttribute), false).Cast <AdvancedAttribute>() .Any(x => x.IsAdvanced); if (isAdvancedPlugin) { detected.ForEach(entry => entry.IsAdvanced = true); } results = results.Concat(detected); } } }