浏览代码
Factorized Various Input Events (Direct, InputAction, InputAssetAction)
/feature-new-input-system
Factorized Various Input Events (Direct, InputAction, InputAssetAction)
/feature-new-input-system
Thomas ICHÉ
4 年前
当前提交
7e60b3ec
共有 12 个文件被更改,包括 257 次插入 和 129 次删除
-
4Runtime/LevelScripting/Events/OnInputActionEvent.cs
-
73Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs
-
6Runtime/Attributes/InputAssetActionAttribute.cs
-
74Runtime/Input/InputActionManager.cs
-
11Runtime/Input/InputActionManager.cs.meta
-
91Runtime/LevelScripting/Events/OnInputAssetActionEvent.cs
-
73Editor/PropertyDrawers/PlayerInputActionPropertyDrawer.cs
-
14Runtime/Attributes/PlayerInputActionAttribute.cs
-
40Runtime/LevelScripting/Events/OnPlayerInputActionEvent.cs
-
0/Editor/PropertyDrawers/InputActionReferencePropertyDrawer.cs.meta
-
0/Runtime/Attributes/InputAssetActionAttribute.cs.meta
-
0/Runtime/LevelScripting/Events/OnInputAssetActionEvent.cs.meta
|
|||
#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
|
|
|||
using UnityEngine; |
|||
|
|||
namespace GameplayIngredients |
|||
{ |
|||
public class InputAssetActionAttribute : PropertyAttribute { } |
|||
} |
|
|||
#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
|
|
|||
fileFormatVersion: 2 |
|||
guid: e15a6e8bcae6a00428ea0f885dd28d15 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
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
|
|||
} |
|||
} |
|||
|
|||
|
|
|||
#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
|
|
|||
using UnityEngine; |
|||
|
|||
namespace GameplayIngredients |
|||
{ |
|||
public class PlayerInputActionAttribute : PropertyAttribute |
|||
{ |
|||
public readonly string name; |
|||
|
|||
public PlayerInputActionAttribute(string propertyName) |
|||
{ |
|||
this.name = propertyName; |
|||
} |
|||
} |
|||
} |
|
|||
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
|
|||
} |
|||
} |
|||
|
|||
|
撰写
预览
正在加载...
取消
保存
Reference in new issue