浏览代码

New InputSystem package support. (#50)

* Base Work

* Added RegiteredInputActions Selector

* Added Direct Input Event, Fixes in Screenshot Manger / UIEventManager Prefab

* Action Mapping from Input System Manager

* Removed InputSystemManager, reworked actions. Start working on base behavior of UIEventManager

* Added Warnings to UI Event Manager editor

* Added UIEventManager page in the wizard

* Added entry for startup wizard

* Fixes when New Input System is not present

* OnPlayerInputAction

* Factorized Various Input Events (Direct, InputAction, InputAssetAction)

* Factorized Player Input for both systems

* Removed InputActionReference PropertyAttribute / Added OnPlayerInputActionEvent

* Cleanup/Rename

* Updated Changelog

* Property Drawer for InputPlayerAction

* Fix Package.json

* Input Player Action property drawer
/main
GitHub 4 年前
当前提交
34ee154f
共有 47 个文件被更改,包括 1235 次插入38 次删除
  1. 14
      CHANGELOG.md
  2. 2
      Editor/CustomInspectors/PingableEditor.cs
  3. 3
      Editor/GameplayIngredients-Editor.asmdef
  4. 25
      Editor/WelcomeScreen/WelcomeScreen.Setup.cs
  5. 7
      Editor/WelcomeScreen/WelcomeScreen.cs
  6. 6
      Resources/Default_UIEventManager.prefab
  7. 4
      Runtime/Attributes/WarnDisabledModuleAttribute.cs
  8. 4
      Runtime/Controllers/KeyboardGamepadPlayerInput.cs
  9. 36
      Runtime/Controllers/PlayerInput.cs
  10. 98
      Runtime/Controllers/SimplePlayerInput.cs
  11. 3
      Runtime/GameplayIngredients.asmdef
  12. 1
      Runtime/GameplayIngredients.cs
  13. 1
      Runtime/LevelScripting/Actions/CinemachineCameraShakeAction.cs
  14. 2
      Runtime/LevelScripting/Actions/CinemachineSetCameraNoiseAction.cs
  15. 1
      Runtime/LevelScripting/Actions/CinemachineSetCustomBlendsAction.cs
  16. 8
      Runtime/LevelScripting/Actions/FocusUIAction.cs
  17. 7
      Runtime/LevelScripting/Events/OnButtonDownEvent.cs
  18. 8
      Runtime/LevelScripting/Events/OnKeyDownEvent.cs
  19. 17
      Runtime/Managers/Implementations/ScreenshotManager.cs
  20. 55
      Runtime/Managers/Implementations/UIEventManager.cs
  21. 19
      Runtime/Managers/Manager.cs
  22. 54
      Editor/CustomInspectors/UIEventManagerEditor.cs
  23. 11
      Editor/CustomInspectors/UIEventManagerEditor.cs.meta
  24. 76
      Editor/PropertyDrawers/InputAssetActionPropertyDrawer.cs
  25. 11
      Editor/PropertyDrawers/InputAssetActionPropertyDrawer.cs.meta
  26. 64
      Editor/PropertyDrawers/InputPlayerActionPropertyDrawer.cs
  27. 11
      Editor/PropertyDrawers/InputPlayerActionPropertyDrawer.cs.meta
  28. 2
      Runtime/AssemblyInfo.cs
  29. 11
      Runtime/AssemblyInfo.cs.meta
  30. 8
      Runtime/Input.meta
  31. 37
      Runtime/LevelScripting/Events/OnInputActionEvent.cs
  32. 11
      Runtime/LevelScripting/Events/OnInputActionEvent.cs.meta
  33. 91
      Runtime/LevelScripting/Events/OnInputAssetActionEvent.cs
  34. 11
      Runtime/LevelScripting/Events/OnInputAssetActionEvent.cs.meta
  35. 81
      Runtime/LevelScripting/Events/OnInputDirectEvent.cs
  36. 11
      Runtime/LevelScripting/Events/OnInputDirectEvent.cs.meta
  37. 91
      Runtime/LevelScripting/Events/OnPlayerInputActionEvent.cs
  38. 11
      Runtime/LevelScripting/Events/OnPlayerInputActionEvent.cs.meta
  39. 37
      Runtime/LevelScripting/Logic/InputSystemLogic.cs
  40. 11
      Runtime/LevelScripting/Logic/InputSystemLogic.cs.meta
  41. 7
      Runtime/Managers/DoNotCreateManagerAttribute.cs
  42. 11
      Runtime/Managers/DoNotCreateManagerAttribute.cs.meta
  43. 74
      Runtime/Input/InputActionManager.cs
  44. 11
      Runtime/Input/InputActionManager.cs.meta
  45. 198
      Runtime/Input/InputSystemUtility.cs
  46. 11
      Runtime/Input/InputSystemUtility.cs.meta

14
CHANGELOG.md


#### Added
* Added `WarnDisabledModuleAttribute` for GameplayIngredientsBehaviors that need to be disabled (encapsulate into #ifdefs )
* Added New Input System support:
* Handles presence/absence of both systems (legacy/new) in Screenshot Manager, UIEventManager
* Added a page in the Wizard to create a default UIEventManager based on wanted Input System
* Added static `InputActionManager` that enables/disables InputActions based on their use in Events
* Added static `InputSystemUtility to return Controls based on keys/buttons`
* Added `InputSystemLogic` for Input System that checks which system is enabled.
* Added Events for Input System
* `OnInputActionEvent` defines InputActions directly on component
* `OnInputAssetActionEvent` defines InputActions based on Assets
* `OnInputDirectEvent` polls state without InputActions
* `OnPlayerInputAction` gets input from a `PlayerInput`
* Reworked PlayerInput for FirstPersonController using both Input Systems
* Added Cinemachine Actions:
* `CinemachineSetCameraNoiseAction` : Defines or remove noise for a Virtual Camera
* `CinemachineSetCustomBlendsAction` : Defines custom blends for the Cinemachine Brain of the Virtual Camera Manager

2
Editor/CustomInspectors/PingableEditor.cs


{
if(m_RequiredModule != null)
{
EditorGUILayout.HelpBox($"This Script Requires the {m_RequiredModule.module} module : It will not execute until you enable the module in the Package Manager.", MessageType.Warning);
EditorGUILayout.HelpBox($"This Script Requires the {m_RequiredModule.module} module : It will not execute until you enable the module in the {m_RequiredModule.fixLocation}.", MessageType.Warning);
EditorGUILayout.Space();
}
EditorGUI.BeginDisabledGroup(m_RequiredModule != null);

3
Editor/GameplayIngredients-Editor.asmdef


"GameplayIngredients",
"Unity.ugui",
"Unity.Timeline",
"Cinemachine"
"Cinemachine",
"Unity.InputSystem"
],
"includePlatforms": [
"Editor"

25
Editor/WelcomeScreen/WelcomeScreen.Setup.cs


public Action[] pages = new Action[]
{
WelcomePage, SettingAssetPage, UnpackPackagePage
WelcomePage, SettingAssetPage,
#if ENABLE_INPUT_SYSTEM
InputSystemPage,
#endif
UnpackPackagePage
};
static void WelcomePage()

GUILayout.Label(@"This wizard will help you set up your project so you can use and customize scripts.", Styles.body);
}
static void InputSystemPage()
{
GUILayout.Label("Input System package detected", Styles.title);
GUILayout.Space(12);
GUILayout.Label(@"It seems that you have the Input System configured for your project. In order to make it work with the UI Event Manager, we can create a configured prefab for you.", Styles.body);
GUILayout.Space(12);
if (GUILayout.Button("Create/Replace", GUILayout.Width(180), GUILayout.Height(32)))
{
if(AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Resources/UIEventManager.prefab") == null
|| EditorUtility.DisplayDialog("Prefab already present", "UIEventManager already exists, overwrite?", "Yes", "No"))
{
var go = UIEventManager.CreateManagerObject();
var prefab = PrefabUtility.SaveAsPrefabAsset(go, "Assets/Resources/UIEventManager.prefab");
DestroyImmediate(go);
Selection.activeObject = prefab;
}
}
public const string kSettingsAssetPath = "Assets/Resources/GameplayIngredientsSettings.asset";

7
Editor/WelcomeScreen/WelcomeScreen.cs


GetWindow<WelcomeScreen>(true, "Gameplay Ingredients");
}
[MenuItem("Window/Gameplay Ingredients/Setup Wizard", priority = MenuItems.kWindowMenuPriority)]
static void ShowWizard()
{
var window = GetWindow<WelcomeScreen>(true, "Gameplay Ingredients");
window.wizardMode = WizardMode.FirstTimeSetup;
}
private void OnEnable()
{
this.position = new Rect((Screen.width / 2.0f) - WindowWidth / 2, (Screen.height / 2.0f) - WindowHeight / 2, WindowWidth, WindowHeight);

6
Resources/Default_UIEventManager.prefab


- component: {fileID: 6448262098318784318}
- component: {fileID: 6448262098318784319}
m_Layer: 0
m_Name: UIEventManager
m_Name: Default_UIEventManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0

m_GameObject: {fileID: 6448262098318784316}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}

m_GameObject: {fileID: 6448262098318784316}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalAxis: Horizontal

4
Runtime/Attributes/WarnDisabledModuleAttribute.cs


public class WarnDisabledModuleAttribute : Attribute
{
public string module;
public string fixLocation;
public WarnDisabledModuleAttribute(string module)
public WarnDisabledModuleAttribute(string module, string fixLocation = "Package Manager")
this.fixLocation = fixLocation;
}
}
}

4
Runtime/Controllers/KeyboardGamepadPlayerInput.cs


public override void UpdateInput()
{
#if ENABLE_LEGACY_INPUT_MANAGER
if(useGamepad || useKeyboardAndMouse)
{
m_Movement = new Vector2(Input.GetAxisRaw(MovementHorizontalAxis), Input.GetAxisRaw(MovementVerticalAxis));

m_Look += new Vector2(Input.GetAxisRaw(MouseHorizontalAxis), Input.GetAxisRaw(MouseVerticalAxis));
m_Jump = GetButtonState(JumpButton);
#else
Debug.LogWarning("KeyboardGamepadPlayerInput is only compatible with legacy input");
#endif
}
}
}

36
Runtime/Controllers/PlayerInput.cs


using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
#endif
public abstract class PlayerInput : MonoBehaviour
public abstract class PlayerInput : GameplayIngredientsBehaviour
{
public enum ButtonState
{

public abstract ButtonState Jump { get; }
public abstract void UpdateInput();
#if ENABLE_INPUT_SYSTEM
protected static ButtonState GetButtonControlState(ButtonControl bc)
{
if(bc == null)
{
return ButtonState.Released;
}
if (bc.isPressed)
{
if(bc.wasPressedThisFrame)
return ButtonState.JustPressed;
else
return ButtonState.Pressed;
}
else
{
if(bc.wasReleasedThisFrame)
return ButtonState.JustReleased;
else
return ButtonState.Released;
}
}
#endif
#if ENABLE_LEGACY_INPUT_MANAGER
{
{
if (Input.GetButton(Button))
{
if (Input.GetButtonDown(Button))

}
}
#endif
}
}

98
Runtime/Controllers/SimplePlayerInput.cs


using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
#endif
namespace GameplayIngredients.Controllers
{

[Header("Movement")]
#if ENABLE_INPUT_SYSTEM && ENABLE_LEGACY_INPUT_MANAGER
public bool preferLegacyInput;
#endif
#if ENABLE_INPUT_SYSTEM
[Header("Input System Package")]
public InputAction move;
public InputAction look;
public InputAction jump;
#endif
#if ENABLE_LEGACY_INPUT_MANAGER
[Header("Legacy Input")]
[Header("Look")]
[Header("Buttons")]
#endif
public override Vector2 Look => m_Look;
public override Vector2 Movement => m_Movement;

Vector2 m_Look;
ButtonState m_Jump;
ButtonState m_Jump;
private void Reset()
{
#if ENABLE_LEGACY_INPUT_MANAGER
InitializeValuesLegacy();
#endif
#if ENABLE_INPUT_SYSTEM
InitializeValuesNIS();
#endif
}
#if ENABLE_LEGACY_INPUT_MANAGER
[ContextMenu("Initialize Values (Legacy Input)")]
void InitializeValuesLegacy()
{
MovementHorizontalAxis = "Horizontal";
MovementVerticalAxis = "Vertical";
LookHorizontalAxis = "Mouse X";
LookVerticalAxis = "Mouse Y";
JumpButton = "Jump";
}
#endif
#if ENABLE_INPUT_SYSTEM
[ContextMenu("Initialize Values (Input System Package)")]
void InitializeValuesNIS()
{
move = new InputAction("Left Stick", InputActionType.Value, "<Gamepad>/Left Stick");
move.AddCompositeBinding("2DVector")
.With("Up", "<Keyboard>/w")
.With("Down", "<Keyboard>/s")
.With("Left", "<Keyboard>/a")
.With("Right", "<Keyboard>/d");
look = new InputAction("Right Stick", InputActionType.Value, "<Gamepad>/Right Stick");
look.AddBinding("<Pointer>/Delta")
.WithProcessor("ScaleVector2(x=0.1,y=0.1)");
jump = new InputAction("Jump", InputActionType.Button, "<Gamepad>/Button South");
jump.AddBinding("<Keyboard>/space");
}
#endif
m_Movement = new Vector2(Input.GetAxis(MovementHorizontalAxis), Input.GetAxis(MovementVerticalAxis));
m_Look = new Vector2(Input.GetAxis(LookHorizontalAxis), Input.GetAxis(LookVerticalAxis));
m_Jump = GetButtonState(JumpButton);
#if ENABLE_INPUT_SYSTEM && ENABLE_LEGACY_INPUT_MANAGER
if(preferLegacyInput)
#endif
#if ENABLE_LEGACY_INPUT_MANAGER
{
m_Movement = new Vector2(Input.GetAxis(MovementHorizontalAxis), Input.GetAxis(MovementVerticalAxis));
m_Look = new Vector2(Input.GetAxis(LookHorizontalAxis), Input.GetAxis(LookVerticalAxis));
m_Jump = GetButtonState(JumpButton);
}
#endif
#if ENABLE_INPUT_SYSTEM && ENABLE_LEGACY_INPUT_MANAGER
else
#endif
#if ENABLE_INPUT_SYSTEM
{
if (!move.enabled)
move.Enable();
if(!look.enabled)
look.Enable();
if(!jump.enabled)
jump.Enable();
m_Movement = move.ReadValue<Vector2>();
m_Look = look.ReadValue<Vector2>();
m_Jump = GetButtonControlState(jump.activeControl as ButtonControl);
}
#endif
}
}
}

3
Runtime/GameplayIngredients.asmdef


"NaughtyAttributes.Core",
"Cinemachine",
"Unity.Timeline",
"UnityEngine.UI"
"UnityEngine.UI",
"Unity.InputSystem"
],
"includePlatforms": [],
"excludePlatforms": [],

1
Runtime/GameplayIngredients.cs


{
public const string basePath = "Gameplay Ingredients/";
public const string actionsPath = basePath + "Actions/";
public const string cinemachinePath = basePath + "Cinemachine/";
public const string controllerPath = basePath + "Controllers/";
public const string counterPath = basePath + "Counters/";
public const string eventsPath = basePath + "Events/";

1
Runtime/LevelScripting/Actions/CinemachineCameraShakeAction.cs


namespace GameplayIngredients.Actions
{
[Callable("Cinemachine", "Misc/ic-cinemachine.png")]
[AddComponentMenu(ComponentMenu.cinemachinePath + "Cinemachine Camera Shake Action")]
public class CinemachineCameraShakeAction : ActionBase
{
public enum ImpulseLocation

2
Runtime/LevelScripting/Actions/CinemachineSetCameraNoiseAction.cs


namespace GameplayIngredients.Actions
{
[Callable("Cinemachine", "Misc/ic-cinemachine.png")]
[AddComponentMenu(ComponentMenu.cinemachinePath + "Cinemachine Set Camera Noise Action")]
public class CinemachineSetCameraNoiseAction : ActionBase
{
[SerializeField]

1
Runtime/LevelScripting/Actions/CinemachineSetCustomBlendsAction.cs


namespace GameplayIngredients.Actions
{
[Callable("Cinemachine", "Misc/ic-cinemachine.png")]
[AddComponentMenu(ComponentMenu.cinemachinePath + "Cinemachine Set Custom Blends Action")]
public class CinemachineSetCustomBlendsAction : ActionBase
{
public enum Action

8
Runtime/LevelScripting/Actions/FocusUIAction.cs


public override void Execute(GameObject instigator = null)
{
if (UIObjectToFocus != null)
{
// Workaround : Before selecting, we ensure that there's no selection in the EventSystem
Manager.Get<UIEventManager>().eventSystem.SetSelectedGameObject(null);
UIObjectToFocus.Select();
}
Manager.Get<UIEventManager>().FocusUI(UIObjectToFocus);
public override string GetDefaultName()
{
return $"Focus UI : '{UIObjectToFocus?.name}'";

7
Runtime/LevelScripting/Events/OnButtonDownEvent.cs


namespace GameplayIngredients.Events
{
[AddComponentMenu(ComponentMenu.eventsPath + "On Button Down Event")]
#if !ENABLE_LEGACY_INPUT_MANAGER
[WarnDisabledModule("Legacy Input Manager","Player Settings")]
#endif
[AddComponentMenu(ComponentMenu.eventsPath + "On Button Down Event (Legacy Input)")]
public class OnButtonDownEvent : EventBase
{
public string Button = "Fire1";

#if !ENABLE_LEGACY_INPUT_MANAGER
void Update()
{
if (Input.GetButtonDown(Button))

Callable.Call(OnButtonUp, gameObject);
}
#endif
}
}

8
Runtime/LevelScripting/Events/OnKeyDownEvent.cs


namespace GameplayIngredients.Events
{
[AddComponentMenu(ComponentMenu.eventsPath + "On Key Down Event")]
#if !ENABLE_LEGACY_INPUT_MANAGER
[WarnDisabledModule("Legacy Input Manager","Player Settings")]
#endif
[AddComponentMenu(ComponentMenu.eventsPath + "On Key Down Event (Legacy Input)")]
public class OnKeyDownEvent : EventBase
{
public KeyCode Key = KeyCode.F5;

#if ENABLE_LEGACY_INPUT_MANAGER
if (Input.GetKeyDown(Key))
Callable.Call(OnKeyDown, gameObject);

#endif
}
}

17
Runtime/Managers/Implementations/ScreenshotManager.cs


using GameplayIngredients.Managers;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace GameplayIngredients
{
#if !MODULE_SCREENCAPTURE

public class ScreenshotManager : Manager
{
[Header("Capture")]
#if ENABLE_LEGACY_INPUT_MANAGER
#endif
#if ENABLE_INPUT_SYSTEM
public Key ScreenshotKey = Key.F11;
#endif
[Range(1, 5)]
public int SuperSize = 1;

public void Update()
{
#if ENABLE_LEGACY_INPUT_MANAGER
#elif ENABLE_INPUT_SYSTEM
if (InputSystemUtility.GetButton(ScreenshotKey).wasPressedThisFrame)
#else
if(false)
#endif
{
#if MODULE_SCREENCAPTURE
var now = System.DateTime.Now;

55
Runtime/Managers/Implementations/UIEventManager.cs


using NaughtyAttributes;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.UI;
#endif
using UnityEngine.UI;
#if ENABLE_LEGACY_INPUT_MANAGER
#endif
#if ENABLE_INPUT_SYSTEM
[RequireComponent(typeof(InputSystemUIInputModule))]
#endif
public EventSystem eventSystem { get { return m_EventSystem; } }
[SerializeField]
private EventSystem m_EventSystem;

if (TryGetComponent(out StandaloneInputModule im))
#if !ENABLE_LEGACY_INPUT_MANAGER
im.enabled = false;
#else
im.enabled = true;
#endif
#if ENABLE_INPUT_SYSTEM
if (!TryGetComponent(out InputSystemUIInputModule ism))
Debug.LogWarning("You are using the new Input System but the UI Event Manager prefab is not configured to use input from this package. In order to fix the issue, please add and configure a InputSystemUIInputModule component to your Assets/Resources/UIEventManagerPrefab. If the prefab is not present, use the Gameplay Ingredients Wizard located at Window/Gameplay Ingredients/Setup Wizard");
#endif
}
}
public void FocusUI(Selectable selectable)
{
// Before selecting, we ensure that there's no selection in the EventSystem
m_EventSystem.SetSelectedGameObject(null);
if(selectable != null)
selectable.Select();
}
internal static GameObject CreateManagerObject()
{
var go = new GameObject("UIEventManager");
var es = go.AddComponent<EventSystem>();
var uiem = go.AddComponent<UIEventManager>();
uiem.m_EventSystem = es;
#if ENABLE_LEGACY_INPUT_MANAGER
if(!go.TryGetComponent(out StandaloneInputModule sm))
sm = go.AddComponent<StandaloneInputModule>();
#endif
#if ENABLE_INPUT_SYSTEM
if (!go.TryGetComponent(out InputSystemUIInputModule ism))
ism = go.AddComponent<InputSystemUIInputModule>();
#endif
return go;
}
}
}

19
Runtime/Managers/Manager.cs


foreach(var type in kAllManagerTypes)
{
if(exclusionList != null && exclusionList.ToList().Contains(type.Name))
// Check for any Do Not Create Attribute
var doNotCreateAttr = type.GetCustomAttribute<DoNotCreateManagerAttribute>();
if (doNotCreateAttr != null)
continue;
// Check for entries in exclusion List
if (exclusionList != null && exclusionList.ToList().Contains(type.Name))
var attrib = type.GetCustomAttribute<ManagerDefaultPrefabAttribute>();
var prefabAttr = type.GetCustomAttribute<ManagerDefaultPrefabAttribute>();
if(attrib != null)
if(prefabAttr != null)
var prefab = Resources.Load<GameObject>(attrib.prefab);
var prefab = Resources.Load<GameObject>(prefabAttr.prefab);
prefab = Resources.Load<GameObject>("Default_"+attrib.prefab);
prefab = Resources.Load<GameObject>("Default_"+prefabAttr.prefab);
}
if(prefab != null)

else
{
Debug.LogError($"Could not instantiate default prefab for {type.ToString()} : No prefab '{attrib.prefab}' found in resources folders. Ignoring...");
Debug.LogError($"Could not instantiate default prefab for {type.ToString()} : No prefab '{prefabAttr.prefab}' found in resources folders. Ignoring...");
continue;
}
}

54
Editor/CustomInspectors/UIEventManagerEditor.cs


using UnityEngine;
using UnityEditor;
namespace GameplayIngredients.Editor
{
[CustomEditor(typeof(UIEventManager), true)]
public class UIEventManagerEditor : ManagerEditor
{
public override void OnInspectorGUI_PingArea()
{
base.OnInspectorGUI_PingArea();
#if ENABLE_INPUT_SYSTEM
if(!(serializedObject.targetObject as UIEventManager).gameObject.TryGetComponent(out UnityEngine.InputSystem.UI.InputSystemUIInputModule issim))
{
using(new EditorGUI.IndentLevelScope(1))
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Bad Configuration : New Input System Standalone Input", EditorStyles.boldLabel);
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.HelpBox("You are using the new Input System, but the current game object is missing a InputSystemUIInputModule", MessageType.Warning);
if (GUILayout.Button("Fix", GUILayout.ExpandHeight(true), GUILayout.Width(80)))
{
(serializedObject.targetObject as UIEventManager).gameObject.AddComponent<UnityEngine.InputSystem.UI.InputSystemUIInputModule>();
}
}
}
}
#endif
#if !ENABLE_LEGACY_INPUT_MANAGER
if ((serializedObject.targetObject as UIEventManager).gameObject.TryGetComponent(out UnityEngine.EventSystems.StandaloneInputModule sim))
{
using (new EditorGUI.IndentLevelScope(1))
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Bad Configuration : Legacy Input System", EditorStyles.boldLabel);
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.HelpBox("You are not using the Legacy Input System, but the current game object is hosting a StandaloneInputModule", MessageType.Warning);
if (GUILayout.Button("Remove", GUILayout.ExpandHeight(true), GUILayout.Width(80)))
{
DestroyImmediate((serializedObject.targetObject as UIEventManager).gameObject.GetComponent<UnityEngine.EventSystems.StandaloneInputModule>());
}
}
}
}
#endif
}
static readonly Color color = new Color(.8f, .6f, .1f, 1f);
}
}

11
Editor/CustomInspectors/UIEventManagerEditor.cs.meta


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

76
Editor/PropertyDrawers/InputAssetActionPropertyDrawer.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(InputAssetAction))]
public class InputAssetActionPropertyDrawer: 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;
var paths = GetPaths(asset.objectReferenceValue as InputActionAsset);
int selected = paths.IndexOf(path.stringValue);
selected = EditorGUI.Popup(position, "Action", selected, paths);
if(GUI.changed)
{
if (selected >= 0)
path.stringValue = paths[selected];
else
path.stringValue = string.Empty;
}
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

11
Editor/PropertyDrawers/InputAssetActionPropertyDrawer.cs.meta


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

64
Editor/PropertyDrawers/InputPlayerActionPropertyDrawer.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(PlayerInputAction))]
public class InputPlayerActionPropertyDrawer: 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 playerInput = property.FindPropertyRelative("playerInput");
var path = property.FindPropertyRelative("path");
position.height = EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(position, playerInput, new GUIContent("Player Input"));
EditorGUI.indentLevel++;
position.y += EditorGUIUtility.singleLineHeight + 2;
var paths = GetPaths(playerInput.objectReferenceValue as PlayerInput);
int selected = paths.IndexOf(path.stringValue);
selected = EditorGUI.Popup(position, "Action", selected, paths);
if(GUI.changed)
{
if (selected >= 0)
path.stringValue = paths[selected];
else
path.stringValue = string.Empty;
}
EditorGUI.indentLevel--;
}
string[] GetPaths(PlayerInput playerInput)
{
if (playerInput == null || playerInput.actions == null)
return new string[0];
List<string> paths = new List<string>();
foreach(var map in playerInput.actions.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();
}
}
}
#endif

11
Editor/PropertyDrawers/InputPlayerActionPropertyDrawer.cs.meta


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

2
Runtime/AssemblyInfo.cs


using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("GameplayIngredients-Editor")]

11
Runtime/AssemblyInfo.cs.meta


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

8
Runtime/Input.meta


fileFormatVersion: 2
guid: 672bda0d6f34a7746be00d708786bbb2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

37
Runtime/LevelScripting/Events/OnInputActionEvent.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 Input Action Event (New Input System)")]
public class OnInputActionEvent : EventBase
{
#if ENABLE_INPUT_SYSTEM
[SerializeField]
InputAction inputAction;
public Callable[] onButtonDown;
private void OnEnable()
{
InputActionManager.Request(inputAction, InputAction_performed);
}
private void OnDisable()
{
InputActionManager.Release(inputAction, InputAction_performed);
}
private void InputAction_performed(InputAction.CallbackContext obj)
{
Callable.Call(onButtonDown, gameObject);
}
#endif
}
}

11
Runtime/LevelScripting/Events/OnInputActionEvent.cs.meta


fileFormatVersion: 2
guid: 97ebdd020f382b24d91e934683a756de
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 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
}
}

11
Runtime/LevelScripting/Events/OnInputAssetActionEvent.cs.meta


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

81
Runtime/LevelScripting/Events/OnInputDirectEvent.cs


using GameplayIngredients.Managers;
using NaughtyAttributes;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
#endif
namespace GameplayIngredients.Events
{
#if !ENABLE_INPUT_SYSTEM
[WarnDisabledModule("New Input System")]
#endif
[AddComponentMenu(ComponentMenu.eventsPath + "On Input Direct Event (New Input System)")]
public class OnInputDirectEvent : EventBase
{
#if ENABLE_INPUT_SYSTEM
[SerializeField]
Device device = Device.Keyboard;
[SerializeField, ShowIf("IsMouse")]
MouseButton mouseButton = MouseButton.Left;
[SerializeField, ShowIf("IsGamepad")]
GamepadButton gamepadButton = GamepadButton.A;
[SerializeField, ShowIf("IsKeyboard")]
Key keyboardKey = Key.Space;
bool IsMouse() => device == Device.Mouse;
bool IsGamepad() => device == Device.Gamepad;
bool IsKeyboard() => device == Device.Keyboard;
#endif
public Callable[] onPressed;
public Callable[] onReleased;
#if ENABLE_INPUT_SYSTEM
ButtonControl button;
private void OnEnable()
{
button = GetButton(device);
Manager.Get<SingleUpdateManager>().Register(SingleUpdate);
}
private void OnDisable()
{
Manager.Get<SingleUpdateManager>().Remove(SingleUpdate);
}
private void SingleUpdate()
{
if (button == null)
return;
if (button.wasPressedThisFrame)
Callable.Call(onPressed, null);
if (button.wasReleasedThisFrame)
Callable.Call(onReleased, null);
}
ButtonControl GetButton(Device d)
{
switch (d)
{
case Device.Gamepad:
return InputSystemUtility.GetButton(gamepadButton);
case Device.Keyboard:
return InputSystemUtility.GetButton(keyboardKey);
case Device.Mouse:
return InputSystemUtility.GetButton(mouseButton);
default:
throw new System.NotImplementedException();
}
}
#endif
}
}

11
Runtime/LevelScripting/Events/OnInputDirectEvent.cs.meta


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

91
Runtime/LevelScripting/Events/OnPlayerInputActionEvent.cs


using System;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace GameplayIngredients.Events
{
#if ENABLE_INPUT_SYSTEM
[Serializable]
public struct PlayerInputAction
{
public PlayerInput playerInput;
public string path;
public InputAction action
{
get
{
if (playerInput == 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}'", playerInput);
return null;
}
int mapIdx = playerInput.actions.actionMaps.IndexOf(o => o.name == split[0]);
if(mapIdx == -1) // not found
{
Debug.LogWarning($"Could not find action map '{split[0]}' in asset {playerInput.name}", playerInput);
return null;
}
var map = playerInput.actions.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 {playerInput.name}", playerInput);
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 Player Input Action Event (New Input System)")]
public class OnPlayerInputActionEvent : EventBase
{
#if ENABLE_INPUT_SYSTEM
[SerializeField]
PlayerInputAction 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
}
}

11
Runtime/LevelScripting/Events/OnPlayerInputActionEvent.cs.meta


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

37
Runtime/LevelScripting/Logic/InputSystemLogic.cs


using NaughtyAttributes;
using UnityEngine;
namespace GameplayIngredients.Logic
{
[AddComponentMenu(ComponentMenu.logicPath + "Input System Logic")]
[Callable("Application", "Logic/ic-generic-logic.png")]
public class InputSystemLogic : LogicBase
{
[ShowIf("checkForLegacyInput")]
public Callable[] OnLegacyInputPresent;
[ShowIf("checkForLegacyInput")]
public Callable[] OnLegacyInputNotPresent;
[ShowIf("checkForNewInput")]
public Callable[] OnNewInputPresent;
[ShowIf("checkForNewInput")]
public Callable[] OnNewInputNotPresent;
public override void Execute(GameObject instigator = null)
{
#if ENABLE_LEGACY_INPUT_MANAGER
Call(OnLegacyInputPresent, instigator);
#else
Call(OnLegacyInputNotPresent, instigator);
#endif
#if ENABLE_INPUT_SYSTEM
Call(OnNewInputPresent, instigator);
#else
Call(OnLegacyInputNotPresent, instigator);
#endif
}
}
}

11
Runtime/LevelScripting/Logic/InputSystemLogic.cs.meta


fileFormatVersion: 2
guid: a579c054a1017f84e9e093fad80ad6cb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 6d0a734cdedf48d478f3fcc7612af66f, type: 3}
userData:
assetBundleName:
assetBundleVariant:

7
Runtime/Managers/DoNotCreateManagerAttribute.cs


using System;
namespace GameplayIngredients
{
[AttributeUsage(AttributeTargets.Class)]
public class DoNotCreateManagerAttribute : Attribute { }
}

11
Runtime/Managers/DoNotCreateManagerAttribute.cs.meta


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

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:

198
Runtime/Input/InputSystemUtility.cs


using System;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
#endif
namespace GameplayIngredients
{
public static class InputSystemUtility
{
#if ENABLE_INPUT_SYSTEM
public static ButtonControl GetButton(MouseButton b)
{
Mouse m = Mouse.current;
switch (b)
{
case MouseButton.Left: return m.leftButton;
case MouseButton.Right: return m.rightButton;
case MouseButton.Middle: return m.middleButton;
case MouseButton.Back: return m.backButton;
case MouseButton.Forward: return m.forwardButton;
default:
throw new System.NotImplementedException();
}
}
public static ButtonControl GetButton(GamepadButton b)
{
Gamepad p = Gamepad.current;
switch (b)
{
case GamepadButton.A: return p.aButton;
case GamepadButton.B: return p.bButton;
case GamepadButton.X: return p.xButton;
case GamepadButton.Y: return p.yButton;
case GamepadButton.LeftShoulder: return p.leftShoulder;
case GamepadButton.LeftTrigger: return p.leftTrigger;
case GamepadButton.RightShoulder: return p.rightShoulder;
case GamepadButton.RightTrigger: return p.rightTrigger;
case GamepadButton.LeftThumbStick: return p.leftStickButton;
case GamepadButton.RightThumbStick: return p.rightStickButton;
case GamepadButton.Start: return p.startButton;
case GamepadButton.Select: return p.selectButton;
default:
throw new System.NotImplementedException();
}
}
public static ButtonControl GetButton(Key k)
{
Keyboard kb = Keyboard.current;
switch (k)
{
case Key.Space: return kb.spaceKey;
case Key.Enter: return kb.enterKey;
case Key.Tab: return kb.tabKey;
case Key.Backquote: return kb.backquoteKey;
case Key.Quote: return kb.quoteKey;
case Key.Semicolon: return kb.semicolonKey;
case Key.Comma: return kb.commaKey;
case Key.Period: return kb.periodKey;
case Key.Slash: return kb.slashKey;
case Key.Backslash: return kb.backslashKey;
case Key.LeftBracket: return kb.leftBracketKey;
case Key.RightBracket: return kb.rightBracketKey;
case Key.Minus: return kb.minusKey;
case Key.Equals: return kb.equalsKey;
case Key.A: return kb.aKey;
case Key.B: return kb.bKey;
case Key.C: return kb.cKey;
case Key.D: return kb.dKey;
case Key.E: return kb.eKey;
case Key.F: return kb.fKey;
case Key.G: return kb.gKey;
case Key.H: return kb.hKey;
case Key.I: return kb.iKey;
case Key.J: return kb.jKey;
case Key.K: return kb.kKey;
case Key.L: return kb.lKey;
case Key.M: return kb.mKey;
case Key.N: return kb.nKey;
case Key.O: return kb.oKey;
case Key.P: return kb.pKey;
case Key.Q: return kb.qKey;
case Key.R: return kb.rKey;
case Key.S: return kb.sKey;
case Key.T: return kb.tKey;
case Key.U: return kb.uKey;
case Key.V: return kb.vKey;
case Key.W: return kb.wKey;
case Key.X: return kb.xKey;
case Key.Y: return kb.yKey;
case Key.Z: return kb.zKey;
case Key.Digit1: return kb.digit1Key;
case Key.Digit2: return kb.digit2Key;
case Key.Digit3: return kb.digit3Key;
case Key.Digit4: return kb.digit4Key;
case Key.Digit5: return kb.digit5Key;
case Key.Digit6: return kb.digit6Key;
case Key.Digit7: return kb.digit7Key;
case Key.Digit8: return kb.digit8Key;
case Key.Digit9: return kb.digit9Key;
case Key.Digit0: return kb.digit0Key;
case Key.LeftShift: return kb.leftShiftKey;
case Key.RightShift: return kb.rightShiftKey;
case Key.LeftAlt: return kb.leftAltKey;
case Key.RightAlt: return kb.rightAltKey;
case Key.LeftCtrl: return kb.leftCtrlKey;
case Key.RightCtrl: return kb.rightCtrlKey;
case Key.LeftMeta: return kb.leftMetaKey;
case Key.RightMeta: return kb.rightMetaKey;
case Key.ContextMenu: return kb.contextMenuKey;
case Key.Escape: return kb.escapeKey;
case Key.LeftArrow: return kb.leftArrowKey;
case Key.RightArrow: return kb.rightArrowKey;
case Key.UpArrow: return kb.upArrowKey;
case Key.DownArrow: return kb.downArrowKey;
case Key.Backspace: return kb.backspaceKey;
case Key.PageDown: return kb.pageDownKey;
case Key.PageUp: return kb.pageUpKey;
case Key.Home: return kb.homeKey;
case Key.End: return kb.endKey;
case Key.Insert: return kb.insertKey;
case Key.Delete: return kb.deleteKey;
case Key.CapsLock: return kb.capsLockKey;
case Key.NumLock: return kb.numLockKey;
case Key.PrintScreen: return kb.printScreenKey;
case Key.ScrollLock: return kb.scrollLockKey;
case Key.Pause: return kb.pauseKey;
case Key.NumpadEnter: return kb.numpadEnterKey;
case Key.NumpadDivide: return kb.numpadDivideKey;
case Key.NumpadMultiply: return kb.numpadMultiplyKey;
case Key.NumpadPlus: return kb.numpadPlusKey;
case Key.NumpadMinus: return kb.numpadMinusKey;
case Key.NumpadPeriod: return kb.numpadPeriodKey;
case Key.NumpadEquals: return kb.equalsKey;
case Key.Numpad0: return kb.numpad0Key;
case Key.Numpad1: return kb.numpad1Key;
case Key.Numpad2: return kb.numpad2Key;
case Key.Numpad3: return kb.numpad3Key;
case Key.Numpad4: return kb.numpad4Key;
case Key.Numpad5: return kb.numpad5Key;
case Key.Numpad6: return kb.numpad6Key;
case Key.Numpad7: return kb.numpad7Key;
case Key.Numpad8: return kb.numpad8Key;
case Key.Numpad9: return kb.numpad9Key;
case Key.F1: return kb.f1Key;
case Key.F2: return kb.f2Key;
case Key.F3: return kb.f3Key;
case Key.F4: return kb.f4Key;
case Key.F5: return kb.f5Key;
case Key.F6: return kb.f6Key;