366 lines
11 KiB
C#
366 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;
|
|
|
|
// Only poll enabled actions with callbacks
|
|
if (actionInfo.Enabled &&
|
|
actionInfo.Reference != null &&
|
|
(actionInfo.CallbacksList.Count > 0 || actionInfo.CallbacksVector2List.Count > 0) &&
|
|
actionInfo.Reference.action.IsPressed())
|
|
{
|
|
// Call Action callbacks
|
|
foreach (var callback in actionInfo.CallbacksList.ToArray())
|
|
{
|
|
callback?.Invoke();
|
|
}
|
|
|
|
// Call Vector2 callbacks
|
|
foreach (var callback in actionInfo.CallbacksVector2List.ToArray())
|
|
{
|
|
Vector2 value = actionInfo.Reference.action.ReadValue<Vector2>();
|
|
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);
|
|
}
|
|
}
|
|
} |