Package input arcade
This commit is contained in:
commit
510a2961f6
24
CHANGELOG.MD
Normal file
24
CHANGELOG.MD
Normal file
@ -0,0 +1,24 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in the notion.
|
||||
|
||||
## [1.0.0] - 2025-09-20
|
||||
|
||||
### Added
|
||||
- Initial release of Conjure Arcade Controller package
|
||||
- Custom Input Device implementation for Conjure Arcade Controllers
|
||||
- Support for arcade joystick with directional buttons
|
||||
- Support for 8 buttons (Home, Start, 1-3, A-C)
|
||||
- Multi-controller support with controller indexing
|
||||
- Input Action Asset extension methods for easy controller assignment
|
||||
- Custom input processors for stick normalization
|
||||
- Comprehensive documentation and examples
|
||||
|
||||
### Features
|
||||
- `ConjureArcadeController` - Main controller device class
|
||||
- `ConjureArcadeStickControl` - Custom stick control with directional buttons
|
||||
- `ConjureArcadeControllerState` - HID input state definition
|
||||
- `ConjureInputSystem` - Automatic registration and initialization
|
||||
- `InputActionAssetExtension` - Helper methods for controller assignment
|
||||
- Controller detection and management system
|
||||
- Event system for controller connect/disconnect
|
||||
7
CHANGELOG.MD.meta
Normal file
7
CHANGELOG.MD.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53be246cbe313b7478b9302289a1e5ea
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Documentation.meta
Normal file
8
Documentation.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5727b7fcbb3ce444ca212cbaf2c56dd3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
174
README.md
Normal file
174
README.md
Normal file
@ -0,0 +1,174 @@
|
||||
# Conjure Arcade Controller Package
|
||||
|
||||
Unity Input System support for Conjure Arcade Controllers.
|
||||
|
||||
## Features
|
||||
|
||||
- Custom Input Device implementation for Conjure Arcade Controllers
|
||||
- Arcade stick support with directional buttons (up, down, left, right)
|
||||
- 8 button support (Home, Start, 1-3, A-C)
|
||||
- Multi-controller support with controller indexing
|
||||
- Integration with Unity's Input System
|
||||
- Input Action Asset extensions for easy controller assignment
|
||||
|
||||
## Requirements
|
||||
|
||||
- Unity 2021.3 or later
|
||||
- Unity Input System package (1.4.4 or later)
|
||||
|
||||
## Installation
|
||||
|
||||
### Via Package Manager (Git URL)
|
||||
1. Open the Package Manager in Unity
|
||||
2. Click the "+" button and select "Add package from git URL"
|
||||
3. Enter the repository URL
|
||||
|
||||
### Via Package Manager (Local)
|
||||
1. Download or clone this repository
|
||||
2. Open the Package Manager in Unity
|
||||
3. Click the "+" button and select "Add package from disk"
|
||||
4. Select the `package.json` file from the downloaded folder
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```csharp
|
||||
using ConjureOS.Input;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerController : MonoBehaviour
|
||||
{
|
||||
void Update()
|
||||
{
|
||||
var controller = ConjureArcadeController.current;
|
||||
if (controller == null) return;
|
||||
|
||||
// Read stick input
|
||||
Vector2 stickInput = controller.stick.ReadValue();
|
||||
|
||||
// Check button presses
|
||||
if (controller.buttonA.wasPressedThisFrame)
|
||||
{
|
||||
// Handle A button press
|
||||
}
|
||||
|
||||
if (controller.start.wasPressedThisFrame)
|
||||
{
|
||||
// Handle start button press
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Using Input Actions
|
||||
|
||||
1. Create an Input Action Asset in your project
|
||||
2. Add actions and bind them to Conjure controller inputs:
|
||||
- Stick: `<ConjureArcadeController>/stick`
|
||||
- Buttons: `<ConjureArcadeController>/buttonA`, `<ConjureArcadeController>/start`, etc.
|
||||
|
||||
```csharp
|
||||
using ConjureOS.Input;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
public class InputActionExample : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private InputActionAsset inputActions;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Assign controller 0 to this input action asset
|
||||
inputActions.AssignConjureController(0);
|
||||
inputActions.Enable();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-Controller Support
|
||||
|
||||
```csharp
|
||||
// Check how many controllers are connected
|
||||
int controllerCount = ConjureArcadeController.ControllerCount;
|
||||
|
||||
// Get specific controller by index
|
||||
ConjureArcadeController player1 = ConjureArcadeController.GetForIndex(0);
|
||||
ConjureArcadeController player2 = ConjureArcadeController.GetForIndex(1);
|
||||
|
||||
// Check if controller exists for index
|
||||
if (ConjureArcadeController.ExistForIndex(0))
|
||||
{
|
||||
// Controller 0 is available
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### ConjureArcadeController
|
||||
|
||||
Main controller class that provides access to all inputs.
|
||||
|
||||
**Properties:**
|
||||
- `stick` - ConjureArcadeStickControl for joystick input
|
||||
- `home`, `start` - ButtonControl for system buttons
|
||||
- `button1`, `button2`, `button3` - ButtonControl for numbered buttons
|
||||
- `buttonA`, `buttonB`, `buttonC` - ButtonControl for lettered buttons
|
||||
- `ControllerIndex` - The index of this controller instance
|
||||
|
||||
**Static Properties:**
|
||||
- `current` - Currently active controller
|
||||
- `allControllers` - Array of all connected controllers
|
||||
- `ControllerCount` - Number of connected controllers
|
||||
|
||||
**Static Methods:**
|
||||
- `ExistForIndex(int)` - Check if controller exists for index
|
||||
- `GetForIndex(int)` - Get controller by index
|
||||
|
||||
**Events:**
|
||||
- `OnControllerAdded` - Fired when a controller is connected
|
||||
- `OnControllerRemoved` - Fired when a controller is disconnected
|
||||
|
||||
### ConjureArcadeStickControl
|
||||
|
||||
Custom stick control that provides both Vector2 input and directional buttons.
|
||||
|
||||
**Properties:**
|
||||
- `up`, `down`, `left`, `right` - ButtonControl for directional input
|
||||
- Standard Vector2Control properties for analog input
|
||||
|
||||
### InputActionAssetExtension
|
||||
|
||||
Extension methods for InputActionAsset to simplify controller assignment.
|
||||
|
||||
**Methods:**
|
||||
- `AssignConjureController(int, bool)` - Assign specific controller to asset
|
||||
- `CanAssignConjureController(int)` - Check if controller can be assigned
|
||||
- `GetConjureControllerIndex()` - Get assigned controller index
|
||||
- `GetConjureControllerIndexes()` - Get all assigned controller indexes
|
||||
|
||||
## Input Bindings
|
||||
|
||||
When setting up Input Actions, use these binding paths:
|
||||
|
||||
- **Stick (Vector2)**: `<ConjureArcadeController>/stick`
|
||||
- **Stick Directions**:
|
||||
- `<ConjureArcadeController>/stick/up`
|
||||
- `<ConjureArcadeController>/stick/down`
|
||||
- `<ConjureArcadeController>/stick/left`
|
||||
- `<ConjureArcadeController>/stick/right`
|
||||
- **Buttons**:
|
||||
- `<ConjureArcadeController>/home`
|
||||
- `<ConjureArcadeController>/start`
|
||||
- `<ConjureArcadeController>/button1`
|
||||
- `<ConjureArcadeController>/button2`
|
||||
- `<ConjureArcadeController>/button3`
|
||||
- `<ConjureArcadeController>/buttonA`
|
||||
- `<ConjureArcadeController>/buttonB`
|
||||
- `<ConjureArcadeController>/buttonC`
|
||||
|
||||
## Hardware Information
|
||||
|
||||
The controller is detected as:
|
||||
- **Interface**: HID
|
||||
- **Product**: "Generic USB Joystick " (note the extra spaces)
|
||||
7
README.md.meta
Normal file
7
README.md.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f42a6a74cfb6af41bc1b91caf3bfc1b
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Runtime.meta
Normal file
8
Runtime.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d47fc24aa1724934197bbef7ba60988e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
135
Runtime/ConjureArcadeController.cs
Normal file
135
Runtime/ConjureArcadeController.cs
Normal file
@ -0,0 +1,135 @@
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
// Reason: It's normal that some stuff is not used here because this is meant to be used as a library.
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
// Reason: According to our code guidelines, property should be UpperCamelCase.
|
||||
// However, to be consistent with other input devices in Unity (e.g. Joystick, Gamepad) we will use lowerCamelCase here.
|
||||
|
||||
namespace ConjureOS.Input
|
||||
{
|
||||
[InputControlLayout(stateType = typeof(ConjureArcadeControllerState), displayName = "Conjure Arcade Controller")]
|
||||
public class ConjureArcadeController : InputDevice
|
||||
{
|
||||
public static event Action<ConjureArcadeController> OnControllerAdded;
|
||||
public static event Action<ConjureArcadeController> OnControllerRemoved;
|
||||
|
||||
public ConjureArcadeStickControl stick { get; protected set; }
|
||||
|
||||
public ButtonControl home { get; protected set; }
|
||||
public ButtonControl start { get; protected set; }
|
||||
|
||||
public ButtonControl button1 { get; protected set; }
|
||||
public ButtonControl button2 { get; protected set; }
|
||||
public ButtonControl button3 { get; protected set; }
|
||||
|
||||
public ButtonControl buttonA { get; protected set; }
|
||||
public ButtonControl buttonB { get; protected set; }
|
||||
public ButtonControl buttonC { get; protected set; }
|
||||
|
||||
public static ConjureArcadeController current { get; private set; }
|
||||
public static ConjureArcadeController[] allControllers => allInstances.ToArray();
|
||||
public static int ControllerCount => count;
|
||||
|
||||
/// <summary>
|
||||
/// The controller index of this specific Conjure Arcade Controller.
|
||||
/// The value will be between 0 and <see cref="ControllerCount"/> - 1.
|
||||
/// If the value is -1, it means this controller was not initialized correctly and is not valid.
|
||||
/// </summary>
|
||||
public int ControllerIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return allInstances.IndexOf(this);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not a Conjure Arcade Controller exist for the following index.
|
||||
/// </summary>
|
||||
public static bool ExistForIndex(int controllerIndex)
|
||||
{
|
||||
return allInstances.Exists(instance => instance.ControllerIndex == controllerIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the Conjure Arcade Controller associated with the specific controller index.
|
||||
/// </summary>
|
||||
/// <returns>The controller if it exist for the specific index or null if it does not exist.</returns>
|
||||
public static ConjureArcadeController GetForIndex(int controllerIndex)
|
||||
{
|
||||
return allInstances.Find(instance => instance.ControllerIndex == controllerIndex);
|
||||
}
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
stick = GetChildControl<ConjureArcadeStickControl>("stick");
|
||||
|
||||
home = GetChildControl<ButtonControl>("home");
|
||||
start = GetChildControl<ButtonControl>("start");
|
||||
|
||||
button1 = GetChildControl<ButtonControl>("button1");
|
||||
button2 = GetChildControl<ButtonControl>("button2");
|
||||
button3 = GetChildControl<ButtonControl>("button3");
|
||||
|
||||
buttonA = GetChildControl<ButtonControl>("buttonA");
|
||||
buttonB = GetChildControl<ButtonControl>("buttonB");
|
||||
buttonC = GetChildControl<ButtonControl>("buttonC");
|
||||
|
||||
base.FinishSetup();
|
||||
}
|
||||
|
||||
public override void MakeCurrent()
|
||||
{
|
||||
base.MakeCurrent();
|
||||
current = this;
|
||||
}
|
||||
|
||||
protected override void OnAdded()
|
||||
{
|
||||
base.OnAdded();
|
||||
|
||||
if (!allInstances.Contains(this))
|
||||
{
|
||||
allInstances.Add(this);
|
||||
++count;
|
||||
OnControllerAdded?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRemoved()
|
||||
{
|
||||
if (current == this)
|
||||
{
|
||||
current = null;
|
||||
}
|
||||
|
||||
if (allInstances.Remove(this))
|
||||
{
|
||||
--count;
|
||||
OnControllerRemoved?.Invoke(this);
|
||||
}
|
||||
|
||||
base.OnRemoved();
|
||||
}
|
||||
|
||||
private static int count;
|
||||
private static readonly List<ConjureArcadeController> allInstances = new();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
2
Runtime/ConjureArcadeController.cs.meta
Normal file
2
Runtime/ConjureArcadeController.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 036811b2c9f17694498f695d3074d167
|
||||
31
Runtime/ConjureArcadeControllerInfo.cs
Normal file
31
Runtime/ConjureArcadeControllerInfo.cs
Normal file
@ -0,0 +1,31 @@
|
||||
namespace ConjureOS.Input
|
||||
{
|
||||
public static class ConjureArcadeControllerInfo
|
||||
{
|
||||
// The information in this class will need to change if we change the way the controller is made.
|
||||
// Everything in this class needs to be static since it is used at compile time to setup the Conjure Arcade Controller state description.
|
||||
|
||||
public const string Interface = "HID";
|
||||
public const string Product = "Generic USB Joystick "; // The extra spaces are normal as they are part of the product name created by the board's vendor
|
||||
|
||||
public const int StateSizeInBytes = 8;
|
||||
public const int ReportIdByte = 0;
|
||||
public const int StickXByte = 1;
|
||||
public const int StickYByte = 1;
|
||||
public const int ButtonByte = 7;
|
||||
|
||||
public enum ButtonBit : uint
|
||||
{
|
||||
Home = 0,
|
||||
Start = 1,
|
||||
|
||||
One = 2,
|
||||
Two = 3,
|
||||
Three = 4,
|
||||
|
||||
A = 5,
|
||||
B = 6,
|
||||
C = 7,
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Runtime/ConjureArcadeControllerInfo.cs.meta
Normal file
2
Runtime/ConjureArcadeControllerInfo.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8c08e87547cb3a4a8471054f99c9442
|
||||
53
Runtime/ConjureArcadeControllerState.cs
Normal file
53
Runtime/ConjureArcadeControllerState.cs
Normal file
@ -0,0 +1,53 @@
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||||
// Reason: This is a configuration class with specific requirements for its interface.
|
||||
|
||||
// ReSharper disable StringLiteralTypo
|
||||
// ReSharper disable CommentTypo
|
||||
// Reason: SHRT is not a typo in this case.
|
||||
|
||||
// Inspired by: https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/HID.html
|
||||
// This class describes the data received by the controller in a way that can be read by the new input system.
|
||||
// If the physical controller ever changes, this class will need to be reworked.
|
||||
|
||||
namespace ConjureOS.Input
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Size = ConjureArcadeControllerInfo.StateSizeInBytes)]
|
||||
public struct ConjureArcadeControllerState : IInputStateTypeInfo
|
||||
{
|
||||
public FourCC format => new FourCC('H', 'I', 'D');
|
||||
|
||||
[FieldOffset(ConjureArcadeControllerInfo.ReportIdByte)]
|
||||
public byte reportId;
|
||||
|
||||
[InputControl(name = "stick", layout = "ConjureArcadeStick", format = "VC2B", displayName = "Stick", processors = "ConjureArcadeVector2(minX=0.0, maxX=1.0, minY=0.0, maxY=1.0, invertY)")]
|
||||
[InputControl(name = "stick/x", offset = 0, format = "BYTE", parameters = "clamp=false, invert=false, normalize=false")]
|
||||
[InputControl(name = "stick/left", offset = 0, format = "BYTE")]
|
||||
[InputControl(name = "stick/right", offset = 0, format = "BYTE")]
|
||||
[InputControl(name = "stick/y", offset = 1, format = "BYTE", parameters = "clamp=false, invert=false, normalize=false")]
|
||||
[InputControl(name = "stick/up", offset = 1, format = "BYTE")]
|
||||
[InputControl(name = "stick/down", offset = 1, format = "BYTE")]
|
||||
[FieldOffset(ConjureArcadeControllerInfo.StickXByte)]
|
||||
public byte stickX;
|
||||
[FieldOffset(ConjureArcadeControllerInfo.StickYByte)]
|
||||
public byte stickY;
|
||||
|
||||
[InputControl(name = "home", layout = "Button", bit = (uint) ConjureArcadeControllerInfo.ButtonBit.Home, displayName = "Home")]
|
||||
[InputControl(name = "start", layout = "Button", bit = (uint) ConjureArcadeControllerInfo.ButtonBit.Start, displayName = "Start")]
|
||||
[InputControl(name = "button1", layout = "Button", bit = (uint) ConjureArcadeControllerInfo.ButtonBit.One, displayName = "Button 1", shortDisplayName = "1")]
|
||||
[InputControl(name = "button2", layout = "Button", bit = (uint) ConjureArcadeControllerInfo.ButtonBit.Two, displayName = "Button 2", shortDisplayName = "2")]
|
||||
[InputControl(name = "button3", layout = "Button", bit = (uint) ConjureArcadeControllerInfo.ButtonBit.Three, displayName = "Button 3", shortDisplayName = "3")]
|
||||
[InputControl(name = "buttonA", layout = "Button", bit = (uint) ConjureArcadeControllerInfo.ButtonBit.A, displayName = "Button A", shortDisplayName = "A")]
|
||||
[InputControl(name = "buttonB", layout = "Button", bit = (uint) ConjureArcadeControllerInfo.ButtonBit.B, displayName = "Button B", shortDisplayName = "B")]
|
||||
[InputControl(name = "buttonC", layout = "Button", bit = (uint) ConjureArcadeControllerInfo.ButtonBit.C, displayName = "Button C", shortDisplayName = "C")]
|
||||
[FieldOffset(ConjureArcadeControllerInfo.ButtonByte)]
|
||||
public byte buttons;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
2
Runtime/ConjureArcadeControllerState.cs.meta
Normal file
2
Runtime/ConjureArcadeControllerState.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afefdccae19d04943bdf5bb615f7325e
|
||||
46
Runtime/ConjureArcadeStickControl.cs
Normal file
46
Runtime/ConjureArcadeStickControl.cs
Normal file
@ -0,0 +1,46 @@
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// Reason: It's normal that some stuff is not used here because this is meant to be used as a library.
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
// Reason: According to our code guidelines, property should be UpperCamelCase.
|
||||
// However, to be consistent with other input controls in Unity (e.g. StickControl) we will use lowerCamelCase here.
|
||||
|
||||
// This class exists to allow the Conjure arcade stick input to work with the input system.
|
||||
// It uses the ConjureArcadeValue processor in order to define the down/left/right/up buttons.
|
||||
// It is registered in when ConjureInputSystem is initialized and is used for the stick input in the controller state.
|
||||
|
||||
namespace ConjureOS.Input
|
||||
{
|
||||
public class ConjureArcadeStickControl : Vector2Control
|
||||
{
|
||||
[InputControl(useStateFrom = "y", processors = "ConjureArcadeValue(min=0.0, max=1.0, invert)", synthetic = true, displayName = "Up")]
|
||||
[InputControl(name = "x", minValue = -1f, maxValue = 1f, layout = "Axis", processors = "ConjureArcadeValue(min=0.0, max=1.0)", format = "BYTE", sizeInBits = 8)]
|
||||
[InputControl(name = "y", minValue = -1f, maxValue = 1f, layout = "Axis", processors = "ConjureArcadeValue(min=0.0, max=1.0, invert)", format ="BYTE", sizeInBits = 8, offset = 1)]
|
||||
public ButtonControl up { get; set; }
|
||||
|
||||
[InputControl(useStateFrom = "y" , processors = "ConjureArcadeValue(min=0.0, max=1.0)", synthetic = true, displayName = "Down")]
|
||||
public ButtonControl down { get; set; }
|
||||
|
||||
[InputControl(useStateFrom = "x", processors = "ConjureArcadeValue(min=0.0, max=1.0, invert)", synthetic = true, displayName = "Left")]
|
||||
public ButtonControl left { get; set; }
|
||||
|
||||
[InputControl(useStateFrom = "x", processors = "ConjureArcadeValue(min=0.0, max=1.0)", synthetic = true, displayName = "Right")]
|
||||
public ButtonControl right { get; set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
up = GetChildControl<ButtonControl>("up");
|
||||
down = GetChildControl<ButtonControl>("down");
|
||||
left = GetChildControl<ButtonControl>("left");
|
||||
right = GetChildControl<ButtonControl>("right");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
2
Runtime/ConjureArcadeStickControl.cs.meta
Normal file
2
Runtime/ConjureArcadeStickControl.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab2d6e2ab1431cf4faf722a4c7b0e16d
|
||||
79
Runtime/ConjureArcadeStickProcessor.cs
Normal file
79
Runtime/ConjureArcadeStickProcessor.cs
Normal file
@ -0,0 +1,79 @@
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using JetBrains.Annotations;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
// ReSharper disable ConvertToConstant.Local
|
||||
// Reason: Attributes cannot be made into constants here since they are changed by Unity's internal input system.
|
||||
|
||||
// Those classes exist to allow the conversion of the stick input into a normalized (-1.0, 1.0) range.
|
||||
// They are registered when ConjureInputSystem is initialized and are used for stick inputs in the controller state and the stick control.
|
||||
|
||||
namespace ConjureOS.Input
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public class ConjureArcadeVector2Processor : InputProcessor<Vector2>
|
||||
{
|
||||
private readonly float minX = -1.0f;
|
||||
private readonly float maxX = 1.0f;
|
||||
private readonly bool invertX = false;
|
||||
|
||||
private readonly float minY = -1.0f;
|
||||
private readonly float maxY = 1.0f;
|
||||
private readonly bool invertY = false;
|
||||
|
||||
private readonly float deadZone = 0.1f;
|
||||
|
||||
public override Vector2 Process(Vector2 value, InputControl control)
|
||||
{
|
||||
return new Vector2(
|
||||
ConjureArcadeStickProcessorHelper.ProcessValue(value.x, minX, maxX, deadZone, invertX),
|
||||
ConjureArcadeStickProcessorHelper.ProcessValue(value.y, minY, maxY, deadZone, invertY));
|
||||
}
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public class ConjureArcadeValueProcessor : InputProcessor<float>
|
||||
{
|
||||
private readonly float min = -1.0f;
|
||||
private readonly float max = 1.0f;
|
||||
private readonly bool invert = false;
|
||||
|
||||
private readonly float deadZone = 0.1f;
|
||||
|
||||
public override float Process(float value, InputControl control)
|
||||
{
|
||||
return ConjureArcadeStickProcessorHelper.ProcessValue(value, min, max, deadZone, invert);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ConjureArcadeStickProcessorHelper
|
||||
{
|
||||
private const float MinStickValue = -1.0f;
|
||||
private const float MaxStickValue = 1.0f;
|
||||
private const float StickRange = MaxStickValue - MinStickValue;
|
||||
|
||||
internal static float ProcessValue(float originalValue, float min, float max, float deadZone, bool invert)
|
||||
{
|
||||
float zero = (min + max) / 2;
|
||||
if (Mathf.Approximately(originalValue, zero))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float originalRange = max - min;
|
||||
if (Mathf.Approximately(originalRange, 0.0f))
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float processedValue = (((originalValue - min) * StickRange) / originalRange) + MinStickValue;
|
||||
processedValue = Mathf.Clamp(processedValue, MinStickValue, MaxStickValue);
|
||||
processedValue = invert ? -processedValue : processedValue;
|
||||
processedValue = processedValue > -deadZone && processedValue < deadZone ? 0.0f : processedValue;
|
||||
|
||||
return processedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
2
Runtime/ConjureArcadeStickProcessor.cs.meta
Normal file
2
Runtime/ConjureArcadeStickProcessor.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb4dcc44d20ac444ea46786d048561a3
|
||||
38
Runtime/ConjureInputSystem.cs
Normal file
38
Runtime/ConjureInputSystem.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace ConjureOS.Input
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoad]
|
||||
#endif
|
||||
public static class ConjureInputSystem
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
static ConjureInputSystem()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
#endif
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
|
||||
private static void Initialize()
|
||||
{
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
InputSystem.RegisterProcessor(typeof(ConjureArcadeVector2Processor), "ConjureArcadeVector2");
|
||||
InputSystem.RegisterProcessor(typeof(ConjureArcadeValueProcessor), "ConjureArcadeValue");
|
||||
|
||||
InputSystem.RegisterLayout<ConjureArcadeStickControl>("ConjureArcadeStick");
|
||||
|
||||
InputSystem.RegisterLayout<ConjureArcadeController>(
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface(ConjureArcadeControllerInfo.Interface)
|
||||
.WithProduct(ConjureArcadeControllerInfo.Product));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Runtime/ConjureInputSystem.cs.meta
Normal file
2
Runtime/ConjureInputSystem.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb240260947f798488f8c7566ac4c85e
|
||||
24
Runtime/ConjureOS.Input.asmdef
Normal file
24
Runtime/ConjureOS.Input.asmdef
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "ConjureOS.Input",
|
||||
"rootNamespace": "ConjureOS.Input",
|
||||
"references": [
|
||||
"Unity.InputSystem"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"ENABLE_INPUT_SYSTEM"
|
||||
],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.inputsystem",
|
||||
"expression": "1.0.0",
|
||||
"define": "ENABLE_INPUT_SYSTEM"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Runtime/ConjureOS.Input.asmdef.meta
Normal file
7
Runtime/ConjureOS.Input.asmdef.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92470253e98b5064e9b025cb4b38e9c9
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
109
Runtime/InputActionAssetExtension.cs
Normal file
109
Runtime/InputActionAssetExtension.cs
Normal file
@ -0,0 +1,109 @@
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
// ReSharper disable InvalidXmlDocComment
|
||||
// Reason: We don't want to comment the "this" parameter in the extension functions.
|
||||
|
||||
namespace ConjureOS.Input
|
||||
{
|
||||
public static class InputActionAssetExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Assign a specific Conjure Arcade Controller to this Input Action Asset.
|
||||
/// All other Conjure Arcade Controllers will be disabled for this asset.
|
||||
/// If the controller cannot be found for the controller index, there will be no assigned Conjure Arcade Controller.
|
||||
/// </summary>
|
||||
/// <param name="keepOtherDevices">
|
||||
/// If this is false, all devices will be disabled for this Input Action Asset except for the Conjure Arcade Controller associated to the given controller index.
|
||||
/// If this is true, the devices that are not Conjure Arcade Controller (e.g. mouse/keyboard) will not be disabled.
|
||||
/// </param>
|
||||
public static void AssignConjureController(this InputActionAsset inputActionAsset, int controllerIndex, bool keepOtherDevices = true)
|
||||
{
|
||||
List<InputDevice> inputDevices = new List<InputDevice>();
|
||||
if (keepOtherDevices)
|
||||
{
|
||||
if (inputActionAsset.devices == null)
|
||||
{
|
||||
inputDevices.AddRange(InputSystem.devices);
|
||||
}
|
||||
else
|
||||
{
|
||||
inputDevices = new List<InputDevice>(inputActionAsset.devices);
|
||||
}
|
||||
|
||||
inputDevices.RemoveAll(inputDevice => inputDevice is ConjureArcadeController);
|
||||
}
|
||||
|
||||
ConjureArcadeController controller = ConjureArcadeController.GetForIndex(controllerIndex);
|
||||
if (controller != null)
|
||||
{
|
||||
inputDevices.Add(controller);
|
||||
}
|
||||
|
||||
inputActionAsset.devices = inputDevices.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not it is possible to assign a specific controller index to this Input Action Asset.
|
||||
/// </summary>
|
||||
public static bool CanAssignConjureController(this InputActionAsset inputActionAsset, int controllerIndex)
|
||||
{
|
||||
return ConjureArcadeController.ExistForIndex(controllerIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the controller index of the Conjure Arcade Controller associated with this Input Action Asset.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The controller index found.
|
||||
/// If there was no Conjure Arcade Controller associated with this Input Action Asset, return false.
|
||||
/// If there was multiple Conjure Arcade Controllers associated with this Input Action Asset, return the index of the first controller found.
|
||||
/// </returns>
|
||||
public static int GetConjureControllerIndex(this InputActionAsset inputActionAsset)
|
||||
{
|
||||
ConjureArcadeController[] controllers = GetConjureArcadeControllersFromDevices(inputActionAsset.devices);
|
||||
if (controllers.Length == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return controllers[0].ControllerIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the controller index of all the Conjure Arcade Controllers associated with this Input Action Asset.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The controller indexes found.
|
||||
/// If there was no Conjure Arcade Controller associated with this Input Action Asset, return an empty array.
|
||||
/// </returns>
|
||||
public static int[] GetConjureControllerIndexes(this InputActionAsset inputActionAsset)
|
||||
{
|
||||
ConjureArcadeController[] controllers = GetConjureArcadeControllersFromDevices(inputActionAsset.devices);
|
||||
return controllers.Select(controller => controller.ControllerIndex).ToArray();
|
||||
}
|
||||
|
||||
private static ConjureArcadeController[] GetConjureArcadeControllersFromDevices(ReadOnlyArray<InputDevice>? devices)
|
||||
{
|
||||
if (devices == null)
|
||||
{
|
||||
return ConjureArcadeController.allControllers;
|
||||
}
|
||||
|
||||
List<ConjureArcadeController> controllers = new List<ConjureArcadeController>();
|
||||
foreach (InputDevice inputDevice in devices)
|
||||
{
|
||||
if (inputDevice is ConjureArcadeController device)
|
||||
{
|
||||
controllers.Add(device);
|
||||
}
|
||||
}
|
||||
|
||||
return controllers.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
2
Runtime/InputActionAssetExtension.cs.meta
Normal file
2
Runtime/InputActionAssetExtension.cs.meta
Normal file
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc3a0f8cabb44494e8be1efd5c3a73bf
|
||||
23
package.json
Normal file
23
package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "com.conjureos.input",
|
||||
"version": "1.0.0",
|
||||
"displayName": "Conjure Arcade Controller",
|
||||
"description": "Unity Input System support for Conjure Arcade Controllers. Provides custom input device implementation for arcade-style controllers with joystick and button controls.",
|
||||
"unity": "2021.3",
|
||||
"unityRelease": "0f1",
|
||||
"dependencies": {
|
||||
"com.unity.inputsystem": "1.4.4"
|
||||
},
|
||||
"keywords": [
|
||||
"input",
|
||||
"controller",
|
||||
"arcade",
|
||||
"joystick",
|
||||
"hid"
|
||||
],
|
||||
"author": {
|
||||
"name": "ConjureOS"
|
||||
},
|
||||
"type": "library",
|
||||
"hideInEditor": false
|
||||
}
|
||||
7
package.json.meta
Normal file
7
package.json.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30590bcda1dcd6342a558e59162358b8
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Loading…
x
Reference in New Issue
Block a user