using System; using System.Collections.Generic; using System.Reflection; using HG.Reflection; using Rewired; using UnityEngine; namespace RoR2.GamepadVibration; public abstract class GamepadVibrationController : IDisposable { private Joystick _joystick; private float[] motorValues = Array.Empty(); private static List<(Func predicate, Type vibrationControllerType)> vibrationControllerTypeResolver = new List<(Func, Type)>(); private static Type defaultVibrationControllerType = typeof(DefaultGamepadVibrationController); public Joystick joystick { get { return _joystick; } private set { if (_joystick != value) { _joystick = value; if (_joystick != null) { Array.Resize(ref motorValues, _joystick.vibrationMotorCount); OnJoystickAssigned(_joystick); } } } } protected virtual void OnJoystickAssigned(Joystick joystick) { } public void Dispose() { StopVibration(); DisposeInternal(); joystick = null; } protected virtual void DisposeInternal() { } public void ApplyVibration(in VibrationContext vibrationContext) { Array.Clear(motorValues, 0, motorValues.Length); try { CalculateMotorValues(in vibrationContext, motorValues); } catch (Exception message) { Debug.LogError(message); } float userVibrationScale = vibrationContext.userVibrationScale; for (int i = 0; i < motorValues.Length; i++) { joystick.SetVibration(i, motorValues[i] * userVibrationScale); } try { ApplyNonStandardVibration(in vibrationContext); } catch (Exception message2) { Debug.LogError(message2); } } protected virtual void CalculateMotorValues(in VibrationContext vibrationContext, float[] motorValues) { } protected virtual void ApplyNonStandardVibration(in VibrationContext vibrationContext) { } public void StopVibration() { try { StopNonStandardVibration(); } catch (Exception message) { Debug.LogError(message); } joystick.StopVibration(); } protected virtual void StopNonStandardVibration() { } public static GamepadVibrationController Create(Joystick joystick) { Type item = defaultVibrationControllerType; for (int i = 0; i < vibrationControllerTypeResolver.Count; i++) { try { (Func, Type) tuple = vibrationControllerTypeResolver[i]; if (tuple.Item1(joystick)) { item = tuple.Item2; break; } } catch (Exception message) { Debug.LogError(message); } } GamepadVibrationController obj = (GamepadVibrationController)Activator.CreateInstance(item); obj.joystick = joystick; return obj; } public static void RegisterResolver(Func predicate, Type vibrationControllerType) { predicate = predicate ?? throw new ArgumentNullException("predicate"); vibrationControllerType = vibrationControllerType ?? throw new ArgumentNullException("vibrationControllerType"); if (!vibrationControllerType.IsSubclassOf(typeof(GamepadVibrationController))) { throw new ArgumentException("vibrationControllerType must inherit from GamepadVibrationController"); } vibrationControllerTypeResolver.Add((predicate, vibrationControllerType)); } [SystemInitializer(new Type[] { })] private static void Init() { List list = new List(); HG.Reflection.SearchableAttribute.GetInstances(list); foreach (GamepadVibrationControllerResolverAttribute item in list) { try { MethodInfo methodInfo = (MethodInfo)item.target; if (!methodInfo.IsStatic) { throw new Exception("GamepadVibrationControllerResolverAttribute target must be a static method. target=" + methodInfo.DeclaringType.FullName + "." + methodInfo.Name); } RegisterResolver((Func)methodInfo.CreateDelegate(typeof(Func)), item.vibrationControllerType); } catch (Exception message) { Debug.LogError(message); } } } }