using System; using UnityEngine; using UnityEngine.InputSystem; namespace KitsuneCafe.SOAP { public class ReactiveInputAction : ScriptableObject where T : struct { [SerializeField] private ReactiveEvent started; [SerializeField] private ReactiveEvent performed; [SerializeField] private ReactiveEvent canceled; [SerializeField] private ReactiveEvent waiting; [SerializeField] private ReactiveEvent disabled; [SerializeField] private ReactiveValue reactiveValue; [SerializeField] private ReactiveValue valueAsButton; public virtual void Handle(InputAction.CallbackContext context) { T value = context.ReadValue(); Raise(context.phase, value); UpdateValue(reactiveValue, value); UpdateValue(valueAsButton, context); } protected void UpdateValue(ReactiveValue property, T value) { if (property != null) { property.Value = value; } } protected void UpdateValue(ReactiveValue property, InputAction.CallbackContext context) { if (property != null) { property.Value = context.ReadValue(); } } protected void UpdateValue(ReactiveValue property, InputAction.CallbackContext context) { if (property != null) { property.Value = context.ReadValueAsButton(); } } public virtual void UpdateValue(InputAction.CallbackContext context) { UpdateValue(reactiveValue, context.ReadValue()); UpdateValue(valueAsButton, context); } protected virtual void Raise(InputActionPhase phase, T value) { switch (phase) { case InputActionPhase.Started: TryRaise(started, value); break; case InputActionPhase.Performed: TryRaise(performed, value); break; case InputActionPhase.Canceled: TryRaise(canceled, value); break; case InputActionPhase.Waiting: TryRaise(waiting, value); break; case InputActionPhase.Disabled: TryRaise(disabled, value); break; default: throw new ArgumentException($"{phase} is not a valid InputActionPhase"); } } public virtual void Raise(InputAction.CallbackContext context) { Raise(context.phase, context.ReadValue()); } private void TryRaise(ReactiveEvent evt, T value) { if (evt != null) { evt.Raise(value); } } } }