Files
Ipseity-Demo/Packages/OctoCore/Runtime/Scripts/Inputs/OctoInputs.cs
T

367 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using static OctoCore.OctoSettings;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
namespace OctoCore.Inputs
{
/// <summary>
/// Input management module that wraps Unity's Input System.
/// Provides enum-based API with automatic enable/disable based on subscriptions.
/// </summary>
[System.Serializable]
public class OctoInputs : IOctoModule
{
[System.Serializable]
public class ActionInfo
{
[HideInInspector]
public string Name;
[HideInInspector]
public string MapName;
public bool Enabled;
[Tooltip("List of registered callbacks")]
public string[] Callbacks;
#if ENABLE_INPUT_SYSTEM
[System.NonSerialized]
public InputActionReference Reference;
[System.NonSerialized]
public List<Action> CallbacksList = new List<Action>();
[System.NonSerialized]
public List<Action<Vector2>> CallbacksVector2List = new List<Action<Vector2>>();
[System.NonSerialized]
public Vector2 LastValue = Vector2.zero;
#endif
public ActionInfo(string name, string mapName)
{
Name = name;
MapName = mapName;
Enabled = false;
Callbacks = new string[0];
}
}
[Header("Actions")]
public List<ActionInfo> Actions = new List<ActionInfo>();
#if ENABLE_INPUT_SYSTEM
private MappingSettings _mappingData;
private Dictionary<OctoActions, ActionInfo> _actionsDict = new Dictionary<OctoActions, ActionInfo>();
private Dictionary<string, InputActionMap> _actionMaps = new Dictionary<string, InputActionMap>();
private bool _initialized;
#endif
public void Init(OctoSettings settings)
{
#if ENABLE_INPUT_SYSTEM
_mappingData = settings.Mapping;
if (_mappingData == null)
{
Debug.LogError("[OctoInputs] No mapping settings found in OctoSettings.");
return;
}
if (_mappingData.InputActionAsset == null)
{
Debug.LogError("[OctoInputs] No InputActionAsset assigned in OctoSettings.");
return;
}
BuildActions();
_initialized = true;
if (OctoCore.Instance.Development.Log)
Debug.Log($"[OctoInputs] Initialized with {_actionsDict.Count} actions.");
#else
Debug.LogWarning("[OctoInputs] Input System Package is not enabled.");
#endif
// Callback OctoEvents
if (OctoEvents.Instance)
OctoEvents.Instance.SetInputsInitialized();
}
#if ENABLE_INPUT_SYSTEM
private void BuildActions()
{
Actions.Clear();
_actionsDict.Clear();
_actionMaps.Clear();
// Cache all action maps
foreach (var map in _mappingData.InputActionAsset.actionMaps)
{
_actionMaps[map.name] = map;
}
// Build actions list
foreach (var actionData in _mappingData.Actions)
{
var actionInfo = new ActionInfo(actionData.Name, actionData.MapName);
actionInfo.Reference = actionData.Reference;
Actions.Add(actionInfo);
_actionsDict[actionData.Action] = actionInfo;
}
}
private void EnableAction(OctoActions action)
{
if (!_actionsDict.TryGetValue(action, out var actionInfo))
return;
if (actionInfo.Enabled || actionInfo.Reference == null)
return;
actionInfo.Reference.action.Enable();
actionInfo.Enabled = true;
// Enable parent action map if needed
if (_actionMaps.TryGetValue(actionInfo.MapName, out var actionMap))
{
if (!actionMap.enabled)
{
actionMap.Enable();
if (OctoCore.Instance.Development.Log)
Debug.Log($"[OctoInputs] Enabled action map: {actionInfo.MapName}");
}
}
if (OctoCore.Instance.Development.Log)
Debug.Log($"[OctoInputs] Enabled action: {action}");
}
private void DisableAction(OctoActions action)
{
if (!_actionsDict.TryGetValue(action, out var actionInfo))
return;
if (!actionInfo.Enabled || actionInfo.Reference == null)
return;
// Check if there are still callbacks
int totalCallbacks = actionInfo.CallbacksList.Count + actionInfo.CallbacksVector2List.Count;
if (totalCallbacks > 0)
return;
actionInfo.Reference.action.Disable();
actionInfo.Enabled = false;
// Check if we should disable the action map
CheckActionMapState(actionInfo.MapName);
if (OctoCore.Instance.Development.Log)
Debug.Log($"[OctoInputs] Disabled action: {action}");
}
private void CheckActionMapState(string mapName)
{
if (!_actionMaps.TryGetValue(mapName, out var actionMap))
return;
// Check if any actions in this map are still enabled
bool hasActiveActions = false;
foreach (var actionInfo in Actions)
{
if (actionInfo.MapName == mapName && actionInfo.Enabled)
{
hasActiveActions = true;
break;
}
}
// Disable map if no active actions
if (!hasActiveActions && actionMap.enabled)
{
actionMap.Disable();
if (OctoCore.Instance.Development.Log)
Debug.Log($"[OctoInputs] Disabled action map: {mapName}");
}
}
private void UpdateCallbacksList(OctoActions action)
{
if (!_actionsDict.TryGetValue(action, out var actionInfo))
return;
var callbackNames = new List<string>();
foreach (var callback in actionInfo.CallbacksList)
{
if (callback != null)
callbackNames.Add($"{callback.Method.DeclaringType?.Name}.{callback.Method.Name}");
}
foreach (var callback in actionInfo.CallbacksVector2List)
{
if (callback != null)
callbackNames.Add($"{callback.Method.DeclaringType?.Name}.{callback.Method.Name} (Vector2)");
}
actionInfo.Callbacks = callbackNames.ToArray();
}
#endif
public void Tick()
{
#if ENABLE_INPUT_SYSTEM
if (!_initialized)
return;
// Poll continuous actions (Vector2 callbacks)
foreach (var kvp in _actionsDict)
{
var actionInfo = kvp.Value;
Vector2 value = actionInfo.Reference.action.ReadValue<Vector2>();
// Only poll enabled actions with callbacks
if (actionInfo.Enabled &&
actionInfo.Reference != null &&
(actionInfo.CallbacksList.Count > 0 || actionInfo.CallbacksVector2List.Count > 0) &&
value.sqrMagnitude > .0001f)
{
// Call Action callbacks
foreach (var callback in actionInfo.CallbacksList.ToArray())
{
callback?.Invoke();
}
// Call Vector2 callbacks
foreach (var callback in actionInfo.CallbacksVector2List.ToArray())
{
callback?.Invoke(value);
}
}
}
#endif
}
public void OnSceneChanged(Scene current, Scene next)
{
}
public void OnQuit()
{
#if ENABLE_INPUT_SYSTEM
if (_mappingData != null && _mappingData.InputActionAsset != null)
{
_mappingData.InputActionAsset.Disable();
}
#endif
}
/// <summary>
/// Subscribe to an action with no parameters (button press).
/// </summary>
public void SubscribeAction(OctoActions action, Action callback, bool subscribe = true)
{
#if ENABLE_INPUT_SYSTEM
if (!_initialized || callback == null)
return;
if (!_actionsDict.TryGetValue(action, out var actionInfo))
{
Debug.LogWarning($"[OctoInputs] Action {action} not found.");
return;
}
if (actionInfo.Reference == null)
{
Debug.LogWarning($"[OctoInputs] InputActionReference is null for {action}.");
return;
}
if (subscribe)
{
if (!actionInfo.CallbacksList.Contains(callback))
{
actionInfo.CallbacksList.Add(callback);
EnableAction(action);
UpdateCallbacksList(action);
}
}
else
{
actionInfo.CallbacksList.Remove(callback);
DisableAction(action);
UpdateCallbacksList(action);
}
#endif
}
/// <summary>
/// Subscribe to an action with Vector2 parameter (movement, look).
/// Uses continuous polling in Tick() to call the callback while pressed.
/// </summary>
public void SubscribeAction(OctoActions action, Action<Vector2> callback, bool subscribe = true)
{
#if ENABLE_INPUT_SYSTEM
if (!_initialized || callback == null)
return;
if (!_actionsDict.TryGetValue(action, out var actionInfo))
{
Debug.LogWarning($"[OctoInputs] Action {action} not found.");
return;
}
if (actionInfo.Reference == null)
{
Debug.LogWarning($"[OctoInputs] InputActionReference is null for {action}.");
return;
}
if (subscribe)
{
if (!actionInfo.CallbacksVector2List.Contains(callback))
{
actionInfo.CallbacksVector2List.Add(callback);
EnableAction(action);
UpdateCallbacksList(action);
}
}
else
{
actionInfo.CallbacksVector2List.Remove(callback);
DisableAction(action);
UpdateCallbacksList(action);
}
#endif
}
/// <summary>
/// Unsubscribe from an action.
/// </summary>
public void UnsubscribeAction(OctoActions action, Action callback)
{
SubscribeAction(action, callback, false);
}
/// <summary>
/// Unsubscribe from an action with Vector2.
/// </summary>
public void UnsubscribeAction(OctoActions action, Action<Vector2> callback)
{
SubscribeAction(action, callback, false);
}
}
}