浏览代码

Factorized Various Input Events (Direct, InputAction, InputAssetAction)

/feature-new-input-system
Thomas ICHÉ 3 年前
当前提交
7e60b3ec
共有 12 个文件被更改,包括 257 次插入129 次删除
  1. 4
      Runtime/LevelScripting/Events/OnInputActionEvent.cs
  2. 73
      Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs
  3. 6
      Runtime/Attributes/InputAssetActionAttribute.cs
  4. 74
      Runtime/Input/InputActionManager.cs
  5. 11
      Runtime/Input/InputActionManager.cs.meta
  6. 91
      Runtime/LevelScripting/Events/OnInputAssetActionEvent.cs
  7. 73
      Editor/PropertyDrawers/PlayerInputActionPropertyDrawer.cs
  8. 14
      Runtime/Attributes/PlayerInputActionAttribute.cs
  9. 40
      Runtime/LevelScripting/Events/OnPlayerInputActionEvent.cs
  10. 0
      /Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta
  11. 0
      /Runtime/Attributes/InputAssetActionAttribute.cs.meta
  12. 0
      /Runtime/LevelScripting/Events/OnInputAssetActionEvent.cs.meta

4
Runtime/LevelScripting/Events/OnInputActionEvent.cs


private void OnEnable()
{
inputAction.performed += InputAction_performed;
InputActionManager.Request(inputAction, InputAction_performed);
inputAction.performed -= InputAction_performed;
InputActionManager.Release(inputAction, InputAction_performed);
}
private void InputAction_performed(InputAction.CallbackContext obj)

73
Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs


#if ENABLE_INPUT_SYSTEM
using UnityEngine;
using UnityEditor;
using UnityEngine.InputSystem;
using System.Linq;
using System.Collections.Generic;
using GameplayIngredients.Events;
namespace GameplayIngredients.Editor
{
[CustomPropertyDrawer(typeof(InputAssetActionAttribute))]
public class InputActionReferencePropertyDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUIUtility.singleLineHeight * 2 + 8;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var asset = property.FindPropertyRelative("asset");
var path = property.FindPropertyRelative("path");
position.height = EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(position, asset, new GUIContent("Input Action Asset"));
EditorGUI.indentLevel++;
position.y += EditorGUIUtility.singleLineHeight + 2;
//EditorGUI.PropertyField(position, path);
var paths = GetPaths(asset.objectReferenceValue as InputActionAsset);
int selected = paths.IndexOf(path.stringValue);
selected = EditorGUI.Popup(position, "Action", selected, paths);
if(GUI.changed)
{
path.stringValue = paths[selected];
}
EditorGUI.indentLevel--;
}
string[] GetPaths(InputActionAsset asset)
{
if (asset == null)
return new string[0];
List<string> paths = new List<string>();
foreach(var map in asset.actionMaps)
{
if (map == null) continue;
foreach(var action in map.actions)
{
if (action == null) continue;
paths.Add($"{map.name}{InputAssetAction.pathSeparator}{action.name}");
}
}
return paths.ToArray();
}
}
public static class Extensions
{
public static int IndexOf(this string[] array, string value)
{
for (int i = 0; i < array.Length; i++)
{
if (array[i] == value)
return i;
}
return -1;
}
}
}
#endif

6
Runtime/Attributes/InputAssetActionAttribute.cs


using UnityEngine;
namespace GameplayIngredients
{
public class InputAssetActionAttribute : PropertyAttribute { }
}

74
Runtime/Input/InputActionManager.cs


#if ENABLE_INPUT_SYSTEM
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
namespace GameplayIngredients
{
public static class InputActionManager
{
static Dictionary<InputAction, List<Action<InputAction.CallbackContext>>> m_Mappings = new Dictionary<InputAction, List<Action<InputAction.CallbackContext>>>();
public static void Request(InputAction action, Action<InputAction.CallbackContext> onPerformed)
{
if(action == null || onPerformed == null)
{
Debug.LogWarning($"Cannot request InputAction, either action or callback is null");
return;
}
if(!m_Mappings.ContainsKey(action))
{
m_Mappings.Add(action, new List<Action<InputAction.CallbackContext>>());
}
if (m_Mappings[action].Contains(onPerformed))
{
Debug.LogWarning($"InputAction already Registered : {action.name} : {onPerformed}");
return;
}
else
{
m_Mappings[action].Add(onPerformed);
if(!action.enabled)
action.Enable();
action.performed += onPerformed;
}
}
public static void Release(InputAction action, Action<InputAction.CallbackContext> onPerformed)
{
if (action == null || onPerformed == null)
{
Debug.LogWarning($"Cannot release InputAction, either action or callback is null");
return;
}
if (!m_Mappings.ContainsKey(action))
{
Debug.LogWarning($"Tried to release action {action.name} that was not already registered");
}
else
{
// Remove entry if present
if(m_Mappings[action].Contains(onPerformed))
{
action.performed -= onPerformed;
m_Mappings[action].Remove(onPerformed);
}
// If no more callbacks registered, remove entry and disable action.
if(m_Mappings[action].Count == 0)
{
action.Disable();
m_Mappings.Remove(action);
}
}
}
}
}
#endif

11
Runtime/Input/InputActionManager.cs.meta


fileFormatVersion: 2
guid: e15a6e8bcae6a00428ea0f885dd28d15
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

91
Runtime/LevelScripting/Events/OnInputAssetActionEvent.cs


using System;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace GameplayIngredients.Events
{
#if ENABLE_INPUT_SYSTEM
[Serializable]
public struct InputAssetAction
{
public InputActionAsset asset;
public string path;
public InputAction action
{
get
{
if (asset == null)
return null;
else
{
if(m_CachedPath != path || m_CachedInputAction == null)
{
string[] split = path.Split(pathSeparator);
if(split.Length != 2)
{
Debug.LogWarning($"Invalid Path '{path}'", asset);
return null;
}
int mapIdx = asset.actionMaps.IndexOf(o => o.name == split[0]);
if(mapIdx == -1) // not found
{
Debug.LogWarning($"Could not find action map '{split[0]}' in asset {asset.name}", asset);
return null;
}
var map = asset.actionMaps[mapIdx];
int actionIdx = map.actions.IndexOf(o => o.name == split[1]);
if(actionIdx == -1) // not found
{
Debug.LogWarning($"Could not find action '{split[1]}' of map '{map.name}' in asset {asset.name}", asset);
return null;
}
m_CachedInputAction = map.actions[actionIdx];
m_CachedPath = path;
}
return m_CachedInputAction;
}
}
}
public const char pathSeparator = '/';
string m_CachedPath;
InputAction m_CachedInputAction;
}
#endif
#if !ENABLE_INPUT_SYSTEM
[WarnDisabledModule("New Input System")]
#endif
[AddComponentMenu(ComponentMenu.eventsPath + "On Input Asset Action Event (New Input System)")]
public class OnInputAssetActionEvent : EventBase
{
#if ENABLE_INPUT_SYSTEM
[SerializeField, InputAssetAction]
InputAssetAction inputAction;
[Header("Action")]
public Callable[] onButtonDown;
private void OnEnable()
{
InputActionManager.Request(inputAction.action, InputAction_performed);
}
private void OnDisable()
{
InputActionManager.Release(inputAction.action, InputAction_performed);
}
private void InputAction_performed(InputAction.CallbackContext obj)
{
Callable.Call(onButtonDown, gameObject);
}
#endif
}
}

73
Editor/PropertyDrawers/PlayerInputActionPropertyDrawer.cs


#if ENABLE_INPUT_SYSTEM
using UnityEngine;
using UnityEditor;
using UnityEngine.InputSystem;
using System;
using System.Reflection;
namespace GameplayIngredients.Editor
{
[CustomPropertyDrawer(typeof(PlayerInputActionAttribute))]
public class PlayerInputActionPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
PlayerInputActionAttribute pia = attribute as PlayerInputActionAttribute;
var obj = property.serializedObject.targetObject;
var fi = obj.GetType().GetField(pia.name, BindingFlags.NonPublic
| BindingFlags.Public
| BindingFlags.Instance);
if(fi != null)
{
var playerInput = fi.GetValue(obj) as PlayerInput;
if(playerInput != null)
{
if (playerInput.actions != null)
{
var field = obj.GetType().GetField(property.name, BindingFlags.NonPublic
| BindingFlags.Public
| BindingFlags.Instance);
var fieldValue = field.GetValue(property.serializedObject.targetObject);
var actionMap = playerInput.actions.FindActionMap(playerInput.defaultActionMap);
int selected = -1;
string[] names = new string[actionMap.actions.Count];
for(int i = 0; i < actionMap.actions.Count; i ++)
{
if (fieldValue == actionMap.actions[i])
selected = i;
names[i] = actionMap.actions[i].name;
}
selected = EditorGUI.Popup(position, ObjectNames.NicifyVariableName(property.name), selected, names);
if(GUI.changed)
{
Undo.RecordObject(property.serializedObject.targetObject, "Set Action Map");
property.serializedObject.Update();
field.SetValue(property.serializedObject.targetObject, actionMap.actions[selected]);
EditorUtility.SetDirty(property.serializedObject.targetObject);
property.serializedObject.ApplyModifiedProperties();
}
}
else
EditorGUI.HelpBox(position, $"Target Player Input had no actions configured", MessageType.Warning);
}
else
EditorGUI.HelpBox(position, $"Property {pia.name} is null or not of PlayerInput type", MessageType.Error);
}
else
EditorGUI.HelpBox(position, $"Could not find field {pia.name}", MessageType.Error);
}
}
}
#endif

14
Runtime/Attributes/PlayerInputActionAttribute.cs


using UnityEngine;
namespace GameplayIngredients
{
public class PlayerInputActionAttribute : PropertyAttribute
{
public readonly string name;
public PlayerInputActionAttribute(string propertyName)
{
this.name = propertyName;
}
}
}

40
Runtime/LevelScripting/Events/OnPlayerInputActionEvent.cs


using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace GameplayIngredients.Events
{
#if !ENABLE_INPUT_SYSTEM
[WarnDisabledModule("New Input System")]
#endif
[AddComponentMenu(ComponentMenu.eventsPath + "On Player Input Action Event (New Input System)")]
public class OnPlayerInputActionEvent : EventBase
{
#if ENABLE_INPUT_SYSTEM
[SerializeField]
public PlayerInput playerInput;
[SerializeField, PlayerInputAction("playerInput")]
InputAction inputAction;
public Callable[] onButtonDown;
private void OnEnable()
{
inputAction.performed += InputAction_performed;
}
private void OnDisable()
{
inputAction.performed -= InputAction_performed;
}
private void InputAction_performed(InputAction.CallbackContext obj)
{
Callable.Call(onButtonDown, gameObject);
}
#endif
}
}

/Editor/PropertyDrawers/PlayerInputActionPropertyDrawer.cs.meta → /Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta

/Runtime/Attributes/PlayerInputActionAttribute.cs.meta → /Runtime/Attributes/InputAssetActionAttribute.cs.meta

/Runtime/LevelScripting/Events/OnPlayerInputActionEvent.cs.meta → /Runtime/LevelScripting/Events/OnInputAssetActionEvent.cs.meta

正在加载...
取消
保存