Skip to content

Commit

Permalink
Add ConfigurationManagerAttributes.CustomHotkeyDrawer
Browse files Browse the repository at this point in the history
Closes #56
  • Loading branch information
ManlyMarco committed Mar 7, 2023
1 parent 093fee8 commit 9fff578
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 4 deletions.
26 changes: 23 additions & 3 deletions ConfigurationManager/SettingEntryBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,24 @@ public abstract class SettingEntryBase
public bool? ShowRangeAsPercent { get; protected set; }

/// <summary>
/// Custom setting draw action
/// Custom setting draw action.
/// Use either CustomDrawer or CustomHotkeyDrawer, using both at the same time leads to undefined behaviour.
/// </summary>
public Action<BepInEx.Configuration.ConfigEntryBase> CustomDrawer { get; private set; }

/// <summary>
/// Custom setting draw action that allows polling keyboard input with the Input class.
/// Use either CustomDrawer or CustomHotkeyDrawer, using both at the same time leads to undefined behaviour.
/// </summary>
public CustomHotkeyDrawerFunc CustomHotkeyDrawer { get; private set; }

/// <summary>
/// Custom setting draw action that allows polling keyboard input with the Input class.
/// </summary>
/// <param name="setting">Setting currently being set, is available</param>
/// <param name="isCurrentlyAcceptingInput">Set this ref parameter to true when you want the current setting drawer to receive Input events. Remember to set it to false after you are done!</param>
public delegate void CustomHotkeyDrawerFunc(BepInEx.Configuration.ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

/// <summary>
/// Show this setting in the settings screen at all? If false, don't show.
/// </summary>
Expand Down Expand Up @@ -144,7 +158,7 @@ internal void SetFromAttributes(object[] attribs, BaseUnityPlugin pluginInstance
switch (attrib)
{
case null: break;

case DisplayNameAttribute da:
DispName = da.DisplayName;
break;
Expand All @@ -163,7 +177,7 @@ internal void SetFromAttributes(object[] attribs, BaseUnityPlugin pluginInstance
case BrowsableAttribute bro:
Browsable = bro.Browsable;
break;

case Action<SettingEntryBase> newCustomDraw:
CustomDrawer = _ => newCustomDraw(this);
break;
Expand All @@ -189,7 +203,13 @@ internal void SetFromAttributes(object[] attribs, BaseUnityPlugin pluginInstance
{
var val = propertyPair.other.GetValue(attrib);
if (val != null)
{
// Handle delegate covariance not working when using reflection by manually converting the delegate
if (propertyPair.my.PropertyType != propertyPair.other.FieldType && typeof(Delegate).IsAssignableFrom(propertyPair.my.PropertyType))
val = Delegate.CreateDelegate(propertyPair.my.PropertyType, ((Delegate)val).Target, ((Delegate)val).Method);

propertyPair.my.SetValue(this, val, null);
}
}
catch (Exception ex)
{
Expand Down
12 changes: 11 additions & 1 deletion ConfigurationManager/SettingFieldDrawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ public void DrawSettingValue(SettingEntryBase setting)
{
if (setting.CustomDrawer != null)
setting.CustomDrawer(setting is ConfigSettingEntry newSetting ? newSetting.Entry : null);
else if (setting.CustomHotkeyDrawer != null)
{
var isBeingSet = _currentKeyboardShortcutToSet == setting;
var isBeingSetOriginal = isBeingSet;

setting.CustomHotkeyDrawer(setting is ConfigSettingEntry newSetting ? newSetting.Entry : null, ref isBeingSet);

if (isBeingSet != isBeingSetOriginal)
_currentKeyboardShortcutToSet = isBeingSet ? setting : null;
}
else if (setting.ShowRangeAsPercent != null && setting.AcceptableValueRange.Key != null)
DrawRangeField(setting);
else if (setting.AcceptableValues != null)
Expand Down Expand Up @@ -380,7 +390,7 @@ private static void DrawKeyboardShortcut(SettingEntryBase setting)
{
GUILayout.Label("Press any key combination", GUILayout.ExpandWidth(true));
GUIUtility.keyboardControl = -1;

var input = UnityInput.Current;
if (_keysToCheck == null) _keysToCheck = input.SupportedKeyCodes.Except(new[] { KeyCode.Mouse0, KeyCode.None }).ToArray();
foreach (var key in _keysToCheck)
Expand Down
46 changes: 46 additions & 0 deletions ConfigurationManagerAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,52 @@ internal sealed class ConfigurationManagerAttributes
/// </summary>
public System.Action<BepInEx.Configuration.ConfigEntryBase> CustomDrawer;

/// <summary>
/// Custom setting editor that allows polling keyboard input with the Input (or UnityInput) class.
/// Use either CustomDrawer or CustomHotkeyDrawer, using both at the same time leads to undefined behaviour.
/// </summary>
public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

/// <summary>
/// Custom setting draw action that allows polling keyboard input with the Input class.
/// Note: Make sure to focus on your UI control when you are accepting input so user doesn't type in the search box or in another setting (best to do this on every frame).
/// If you don't draw any selectable UI controls You can use `GUIUtility.keyboardControl = -1;` on every frame to make sure that nothing is selected.
/// </summary>
/// <example>
/// CustomHotkeyDrawer = (ConfigEntryBase setting, ref bool isEditing) =>
/// {
/// if (isEditing)
/// {
/// // Make sure nothing else is selected since we aren't focusing on a text box with GUI.FocusControl.
/// GUIUtility.keyboardControl = -1;
///
/// // Use Input.GetKeyDown and others here, remember to set isEditing to false after you're done!
/// // It's best to check Input.anyKeyDown and set isEditing to false immediately if it's true,
/// // so that the input doesn't have a chance to propagate to the game itself.
///
/// if (GUILayout.Button("Stop"))
/// isEditing = false;
/// }
/// else
/// {
/// if (GUILayout.Button("Start"))
/// isEditing = true;
/// }
///
/// // This will only be true when isEditing is true and you hold any key
/// GUILayout.Label("Any key pressed: " + Input.anyKey);
/// }
/// </example>
/// <param name="setting">
/// Setting currently being set (if available).
/// </param>
/// <param name="isCurrentlyAcceptingInput">
/// Set this ref parameter to true when you want the current setting drawer to receive Input events.
/// The value will persist after being set, use it to see if the current instance is being edited.
/// Remember to set it to false after you are done!
/// </param>
public delegate void CustomHotkeyDrawerFunc(BepInEx.Configuration.ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

/// <summary>
/// Show this setting in the settings screen at all? If false, don't show.
/// </summary>
Expand Down

0 comments on commit 9fff578

Please sign in to comment.
  翻译: