diff --git a/UOP1_Project/Assets/Scripts/Input/InputReader.cs b/UOP1_Project/Assets/Scripts/Input/InputReader.cs index 6db2a718a..94fb09221 100644 --- a/UOP1_Project/Assets/Scripts/Input/InputReader.cs +++ b/UOP1_Project/Assets/Scripts/Input/InputReader.cs @@ -16,22 +16,21 @@ public class InputReader : ScriptableObject, GameInput.IGameplayActions public event UnityAction enableMouseControlCameraEvent; public event UnityAction disableMouseControlCameraEvent; - public GameInput gameInput; + public GameInput GameInput { get; private set; } private void OnEnable() { - if (gameInput == null) + if (GameInput == null) { - gameInput = new GameInput(); - gameInput.Gameplay.SetCallbacks(this); + GameInput = new GameInput(); + GameInput.Gameplay.SetCallbacks(this); } - - gameInput.Gameplay.Enable(); + GameInput.Gameplay.Enable(); } private void OnDisable() { - gameInput.Gameplay.Disable(); + GameInput.Gameplay.Disable(); } public void OnAttack(InputAction.CallbackContext context) diff --git a/UOP1_Project/Assets/Scripts/Input/UOP1.Input.asmdef b/UOP1_Project/Assets/Scripts/Input/UOP1.Input.asmdef new file mode 100644 index 000000000..74e2a247d --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Input/UOP1.Input.asmdef @@ -0,0 +1,15 @@ +{ + "name": "UOP1.Input", + "references": [ + "GUID:75469ad4d38634e559750d17036d5f7c" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/UOP1_Project/Assets/Scripts/Input/UOP1.Input.asmdef.meta b/UOP1_Project/Assets/Scripts/Input/UOP1.Input.asmdef.meta new file mode 100644 index 000000000..568e95d6c --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Input/UOP1.Input.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: dec4756ac1b53d846826001e80d59690 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UOP1_Project/Assets/Scripts/Input.meta b/UOP1_Project/Assets/Scripts/Tests/Edit Mode.meta similarity index 77% rename from UOP1_Project/Assets/Scripts/Input.meta rename to UOP1_Project/Assets/Scripts/Tests/Edit Mode.meta index 8187a83ce..21339da57 100644 --- a/UOP1_Project/Assets/Scripts/Input.meta +++ b/UOP1_Project/Assets/Scripts/Tests/Edit Mode.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: de6f11827cc26d14790ec6cff08214fe +guid: 18f0272a0b3d9634199ae372ff97cf5c folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Edit Mode.asmdef b/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Edit Mode.asmdef new file mode 100644 index 000000000..cb26a14d8 --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Edit Mode.asmdef @@ -0,0 +1,22 @@ +{ + "name": "EditMode", + "references": [ + "UnityEngine.TestRunner", + "UnityEditor.TestRunner" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll" + ], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Edit Mode.asmdef.meta b/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Edit Mode.asmdef.meta new file mode 100644 index 000000000..36ed8debf --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Edit Mode.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 870e8bb3953f36848888e1e21f218890 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Example.meta b/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Example.meta new file mode 100644 index 000000000..3336b75e5 --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Example.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f65ee48fdcda4a9ea21b4e801ebc2315 +timeCreated: 1604443100 \ No newline at end of file diff --git a/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Example/ExampleTest.cs b/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Example/ExampleTest.cs new file mode 100644 index 000000000..f0ceaffc9 --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Example/ExampleTest.cs @@ -0,0 +1,13 @@ +using NUnit.Framework; + +namespace Tests.Edit_Mode.Example +{ + public class ExampleTest + { + [Test] + public void ExampleTestSimplePasses() + { + Assert.Pass(); + } + } +} diff --git a/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Example/ExampleTest.cs.meta b/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Example/ExampleTest.cs.meta new file mode 100644 index 000000000..a137b4c2b --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Edit Mode/Example/ExampleTest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4673233c211a4cca909f5726d6621cd0 +timeCreated: 1604443066 \ No newline at end of file diff --git a/UOP1_Project/Assets/Scripts/Tests/Play Mode.meta b/UOP1_Project/Assets/Scripts/Tests/Play Mode.meta new file mode 100644 index 000000000..b9a9c8c70 --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Play Mode.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da4e5da470f321b49b52c773c1ef9831 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader.meta b/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader.meta new file mode 100644 index 000000000..03dbfe124 --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ebe9c10d5eef4ef18d06820b4c12afec +timeCreated: 1604441258 \ No newline at end of file diff --git a/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/InputReaderTests.cs b/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/InputReaderTests.cs new file mode 100644 index 000000000..313d345c4 --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/InputReaderTests.cs @@ -0,0 +1,178 @@ +using System.Collections; +using System.Linq; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.InputSystem; +using UnityEngine.InputSystem.Utilities; +using UnityEngine.TestTools; + +namespace Tests.Play_Mode.InputReader +{ + public class InputReaderTests + { + class InputReaderTestFixture : InputTestFixture + { + // Input Boilerplate + private Keyboard Keyboard { get; set; } + private Mouse Mouse { get; set; } + private Gamepad Gamepad { get; set; } + // Systems being tested + private GameInput GameInput { get; set; } + private global::InputReader InputReader { get; set; } + + // counters for input event calls + private int MoveEvents { get; set; } + private int AttackEvents { get; set; } + private int JumpEvents { get; set; } + private int JumpCanceledEvents { get; set; } + + // callback targets for input event calls + public void OnMove(Vector2 v2) => MoveEvents++; + public void OnAttack() => AttackEvents++; + public void OnJump() => JumpEvents++; + public void OnJumpCanceled() => JumpCanceledEvents++; + + + [SetUp] // if asynchronous code is necessary use [UnitySetUp] + public void SetupInput() + { + // must AddDevice to get input in a test environment from those mappings + Keyboard = InputSystem.AddDevice(); + Mouse = InputSystem.AddDevice(); + Gamepad = InputSystem.AddDevice(); + + // instantiate a SO to act as the event Observer + InputReader = ScriptableObject.CreateInstance(); + GameInput = InputReader.GameInput; + + ResetCounters(); + + // add cb's + InputReader.moveEvent += OnMove; + InputReader.attackEvent += OnAttack; + InputReader.jumpEvent += OnJump; + InputReader.jumpCanceledEvent += OnJumpCanceled; + } + + /// + /// Removes subscriptions from input reader + /// + [TearDown] + public void Cleanup() + { + // remove cb's + InputReader.moveEvent -= OnMove; + InputReader.attackEvent -= OnAttack; + InputReader.jumpEvent -= OnJump; + InputReader.jumpCanceledEvent -= OnJumpCanceled; + + ResetCounters(); + } + + /// + /// Reset counters used to keep track of events being fired off by inputreader. + /// should be replaced by a spy or mock when we have access to some library that provides the functionality. + /// + private void ResetCounters() + { + MoveEvents = 0; + AttackEvents = 0; + JumpEvents = 0; + JumpCanceledEvents = 0; + } + + public static string[] InputMappings = + { + nameof(GamepadMappings), + nameof(KeyboardMappings), + }; + + [UnityTest] + public IEnumerator InputReaderHandlesAttackInput([ValueSource(nameof(InputMappings))] string mappingType) + { + var mapping = MappingProviderFactory.Create(mappingType); + + Press(mapping.Attack); + yield return new WaitForEndOfFrame(); + Release(mapping.Attack); + yield return new WaitForEndOfFrame(); + + Assert.That(AttackEvents, Is.EqualTo(1)); + } + + + [UnityTest] + public IEnumerator InputReaderHandlesMoveInput([ValueSource(nameof(InputMappings))] string mappingType) + { + var mapping = MappingProviderFactory.Create(mappingType); + + Press(mapping.MoveLeft); + yield return new WaitForEndOfFrame(); + Release(mapping.MoveLeft); + yield return new WaitForEndOfFrame(); + + Assert.That(MoveEvents, Is.EqualTo(3)); + } + + + /// + /// Example case for debugging input and a form of documentation. + /// + /// nameof(some input provider) + /// null + [UnityTest] + public IEnumerator InputReaderReceivesInput([ValueSource(nameof(InputMappings))] string mappingType) + { + var mapping = MappingProviderFactory.Create(mappingType); + + var attackAction = GameInput.Gameplay.Attack; + var moveAction = GameInput.Gameplay.Move; + + using (var trace = new InputActionTrace()) + { + // subscribe to relevant actions so we can track their activity + trace.SubscribeTo(attackAction); + trace.SubscribeTo(moveAction); + + yield return new WaitForEndOfFrame(); + Press(mapping.Attack); + yield return new WaitForEndOfFrame(); + Press(mapping.MoveLeft); + yield return new WaitForEndOfFrame(); + Release(mapping.Attack); + yield return new WaitForEndOfFrame(); + Release(mapping.MoveLeft); + yield return new WaitForEndOfFrame(); + + // grab the events from the trace + var actions = trace.ToArray(); + // LogActionsPerformed(actions); + + Assert.That(actions.Length, Is.EqualTo(6)); + } + } + + /// + /// Debugging tool to see which actions have been fired off. requires the usage of an InputTrace. + /// + /// + private static void LogActionsPerformed(InputActionTrace.ActionEventPtr[] actions) + { + foreach (var a in actions) + { + Debug.Log(a); + } + } + + /// + /// Set "time" of input fixutre. tracked in the event itself. + /// + /// new syste time + private void SetInputSystemTime(float t) + { + var time = t; + currentTime = time; + } + } + } +} diff --git a/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/InputReaderTests.cs.meta b/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/InputReaderTests.cs.meta new file mode 100644 index 000000000..e97bf659e --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/InputReaderTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d7e59d8c49aa0e94aa5b0b8a3ad2289c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/KeyMappings.cs b/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/KeyMappings.cs new file mode 100644 index 000000000..b3ecdf92a --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/KeyMappings.cs @@ -0,0 +1,67 @@ +using System; +using UnityEngine.InputSystem; +using UnityEngine.InputSystem.Controls; + +namespace Tests.Play_Mode.InputReader +{ + public interface IMappingProvider + { + ButtonControl MoveLeft { get; } + ButtonControl MoveRight { get; } + ButtonControl MoveUp { get; } + ButtonControl MoveDown { get; } + + ButtonControl Jump { get; } + ButtonControl Interact { get; } + ButtonControl Attack { get; } + ButtonControl Extra { get; } + + ButtonControl Pause { get; } + } + + public static class MappingProviderFactory + { + public static IMappingProvider Create(string type) + { + switch (type) + { + case nameof(KeyboardMappings): + return new KeyboardMappings(); + case nameof(GamepadMappings): + return new GamepadMappings(); + default: + throw new ArgumentException("string provided must be the nameof() some IMappingProvider. e.g. KeyboardMappings or GamepadMappings"); + } + } + } + + public class KeyboardMappings : IMappingProvider + { + public ButtonControl MoveLeft { get; private set; } = Keyboard.current.aKey; + public ButtonControl MoveRight { get; private set; } = Keyboard.current.aKey; + public ButtonControl MoveUp { get; private set; } = Keyboard.current.sKey; + public ButtonControl MoveDown { get; private set; } = Keyboard.current.wKey; + + public ButtonControl Interact { get; private set; } = Keyboard.current.kKey; + public ButtonControl Jump { get; private set; } = Keyboard.current.spaceKey; + public ButtonControl Attack { get; private set; } = Keyboard.current.jKey; + public ButtonControl Extra { get; private set; } = Keyboard.current.lKey; + + public ButtonControl Pause { get; private set; } = Keyboard.current.escapeKey; + } + + public class GamepadMappings : IMappingProvider + { + public ButtonControl MoveLeft { get; private set; } = Gamepad.current.leftStick.left; + public ButtonControl MoveRight { get; private set; } = Gamepad.current.leftStick.right; + public ButtonControl MoveUp { get; private set; } = Gamepad.current.leftStick.up; + public ButtonControl MoveDown { get; private set; } = Gamepad.current.leftStick.down; + + public ButtonControl Interact { get; private set; } = Gamepad.current.buttonEast; + public ButtonControl Jump { get; private set; } = Gamepad.current.buttonSouth; + public ButtonControl Attack { get; private set; } = Gamepad.current.buttonWest; + public ButtonControl Extra { get; private set; } = Gamepad.current.buttonNorth; + + public ButtonControl Pause { get; private set; } = Gamepad.current.startButton; + } +} diff --git a/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/KeyMappings.cs.meta b/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/KeyMappings.cs.meta new file mode 100644 index 000000000..b5d16a68b --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Play Mode/InputReader/KeyMappings.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3b6f2b7a187540939864a11804729bdf +timeCreated: 1604433683 \ No newline at end of file diff --git a/UOP1_Project/Assets/Scripts/Tests/Play Mode/Play Mode.asmdef b/UOP1_Project/Assets/Scripts/Tests/Play Mode/Play Mode.asmdef new file mode 100644 index 000000000..6720a14c8 --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Play Mode/Play Mode.asmdef @@ -0,0 +1,23 @@ +{ + "name": "PlayMode", + "references": [ + "UnityEngine.TestRunner", + "UnityEditor.TestRunner", + "Unity.InputSystem", + "Unity.InputSystem.TestFramework", + "UOP1.Input" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll" + ], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/UOP1_Project/Assets/Scripts/Tests/Play Mode/Play Mode.asmdef.meta b/UOP1_Project/Assets/Scripts/Tests/Play Mode/Play Mode.asmdef.meta new file mode 100644 index 000000000..bdf240804 --- /dev/null +++ b/UOP1_Project/Assets/Scripts/Tests/Play Mode/Play Mode.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3d379be36666a5640ade02274d231ace +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UOP1_Project/Packages/manifest.json b/UOP1_Project/Packages/manifest.json index d836b30e7..10279d741 100644 --- a/UOP1_Project/Packages/manifest.json +++ b/UOP1_Project/Packages/manifest.json @@ -44,5 +44,5 @@ "com.unity.modules.vr": "1.0.0", "com.unity.modules.wind": "1.0.0", "com.unity.modules.xr": "1.0.0" - } + }, "testables" : [ "com.unity.inputsystem" ] }