Danro/Assets/Scripts/Controls/ComInputToInputSystemAdapter.cs
Danil Iarosh 98d5285b46 feat(logging): add advanced logging example with file output
- Created AdvancedLoggingExample class demonstrating composite and file loggers
- Implemented multi-file logging setup with separate error and full logs
- Added game event and performance logging methods
- Included key input handling for log operations (flush, clear)
- Setup proper resource disposal on application quit
2025-11-07 14:12:50 +03:00

171 lines
6.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.LowLevel;
/// <summary>
/// Мост из твоего фасада In (COM/клава и т.д.) в новый Input System.
/// Создаёт виртуальный Gamepad и обновляет его состояние на основе:
/// - действий игроков (PlayerAction), или
/// - физических пинов (int / ButtonPinMapping)
/// Выбирай способ через списки маппинга в инспекторе.
/// </summary>
[DefaultExecutionOrder(-100)] // пораньше, чтобы UI увидел ввод
public class ComInputToInputSystemAdapter : MonoBehaviour
{
[Header("Источник состояния")]
[Tooltip("Если true — брать состояние из In.GetButton* AnyPlayer; если false — из CurrentPlayer.")]
public bool useAnyPlayer = true;
[Header("Маппинг по действиям (PlayerAction -> Gamepad)")]
public List<ActionBinding> actionBindings = new();
[Header("Маппинг по пинам (индекс пина -> Gamepad)")]
public List<PinBinding> pinBindings = new();
[Header("Отладка")]
public bool logCreateDevice = true;
private static Gamepad _virtualPad;
private GamepadState _state;
// Защита от дублей при отключённом Domain Reload
private static bool _deviceCreated;
[Serializable]
public struct ActionBinding
{
public PlayerAction action; // твой enum
public TargetTarget target;
public GamepadButton button; // если target == Button
public DpadDir dpadDirection; // если target == Dpad
}
[Serializable]
public struct PinBinding
{
public int pinIndex; // твой физический индекс пина
public TargetTarget target;
public GamepadButton button; // если target == Button
public DpadDir dpadDirection; // если target == Dpad
}
public enum TargetTarget { Button, Dpad }
public enum DpadDir { Up, Down, Left, Right }
private void Awake()
{
Initialize();
}
private void OnEnable() => Initialize();
private void Update()
{
if (_virtualPad == null) return;
_state = default;
// 1) По действиям
foreach (ActionBinding b in actionBindings)
{
bool pressed = useAnyPlayer
? In.GetButtonAnyPlayer(b.action)
: In.GetButtonCurrentPlayer(b.action);
ApplyBinding(ref _state, b.target, b.button, b.dpadDirection, pressed);
}
// 2) По пинам
foreach (PinBinding b in pinBindings)
{
bool pressed = In.GetButton(b.pinIndex);
ApplyBinding(ref _state, b.target, b.button, b.dpadDirection, pressed);
}
InputSystem.QueueStateEvent(_virtualPad, _state);
// Обновлять InputSystem вручную не нужно (обновится в цикле Unity)
}
public void Initialize()
{
EnsureVirtualGamepad();
TryAddDefaultBindingsIfEmpty();
}
private static void ApplyBinding(ref GamepadState st, TargetTarget target, GamepadButton btn, DpadDir dir, bool pressed)
{
if (!pressed) return;
if (target == TargetTarget.Button)
{
st = st.WithButton(btn);
}
else
{
st = dir switch
{
DpadDir.Up => st.WithButton(GamepadButton.DpadUp),
DpadDir.Down => st.WithButton(GamepadButton.DpadDown),
DpadDir.Left => st.WithButton(GamepadButton.DpadLeft),
DpadDir.Right => st.WithButton(GamepadButton.DpadRight),
_ => st
};
}
}
private void EnsureVirtualGamepad()
{
if (_deviceCreated && _virtualPad != null) return;
// ищем уже созданный «COM Bridge», чтобы не дублировать
foreach (InputDevice dev in InputSystem.devices)
{
if (dev is not Gamepad { description: { product: "COM Bridge Gamepad" } } gp) continue;
_virtualPad = gp;
_deviceCreated = true;
return;
}
InputDeviceDescription desc = new()
{
interfaceName = "Virtual",
deviceClass = "Gamepad",
product = "COM Bridge Gamepad",
manufacturer = "Robotic Retailers"
};
_virtualPad = (Gamepad)InputSystem.AddDevice(desc);
_deviceCreated = true;
if (logCreateDevice) Debug.Log("[InputBridge] Виртуальный Gamepad создан: " + _virtualPad);
}
private void TryAddDefaultBindingsIfEmpty()
{
// Если пусто — добавим базовый маппинг стрелок на D-Pad.
if (actionBindings.Count != 0) return;
TryAddActionBinding(PlayerAction.up, TargetTarget.Dpad, GamepadButton.North, DpadDir.Up);
TryAddActionBinding(PlayerAction.down, TargetTarget.Dpad, GamepadButton.South, DpadDir.Down);
TryAddActionBinding(PlayerAction.left, TargetTarget.Dpad, GamepadButton.West, DpadDir.Left);
TryAddActionBinding(PlayerAction.right, TargetTarget.Dpad, GamepadButton.East, DpadDir.Right);
TryAddActionBinding(PlayerAction.action, TargetTarget.Button, GamepadButton.South, DpadDir.Up);
TryAddActionBinding(PlayerAction.action, TargetTarget.Button, GamepadButton.East, DpadDir.Up);
// SafeTry(() => actionBindings.Add(new ActionBinding { action = PlayerAction.action, target = TargetTarget.Button, button = GamepadButton.South, dpadDirection = DpadDir.Up }));
// SafeTry(() => actionBindings.Add(new ActionBinding { action = PlayerAction.extra, target = TargetTarget.Button, button = GamepadButton.East, dpadDirection = DpadDir.Up }));
}
private void TryAddActionBinding(PlayerAction action, TargetTarget target, GamepadButton btn, DpadDir dir)
{
SafeTry(() => actionBindings.Add(new ActionBinding { action = action, target = target, button = btn, dpadDirection = dir }));
}
private static void SafeTry(Action a)
{
try { a(); } catch { /* если в твоём enum нет таких значений — просто пропустим */ }
}
}