sea-battle/Assets/Scripts/PlayerCursorUI.cs
2026-05-15 13:02:11 +03:00

388 lines
13 KiB
C#
Raw Permalink 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 UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class PlayerCursorUI : MonoBehaviour
{
public GameManager gameManager;
public Canvas parentCanvas; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public int playerId = 1; // 1 <20><><EFBFBD> 2 (<28><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
private List<Button> buttons = new List<Button>();
private int currentIndex = 0;
private ButtonPinMapping upKey;
private ButtonPinMapping downKey;
private ButtonPinMapping leftKey;
private ButtonPinMapping rightKey;
private ButtonPinMapping selectKey;
// дублирующие кнопки для перключения влево вправо по UI
private ButtonPinMapping leftKey2;
private ButtonPinMapping rightKey2;
private bool useJoystick = false;
// Cache UIManager for active panel tracking
private UIManager uiManager;
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
private bool panelChanged = false;
// 2D grid navigation state (используется когда активный экран имеет ButtonGridLayout)
private int gridRow = 0;
private int gridCol = 0;
void Start()
{
var player = GetComponentInParent<Player>();
if (player != null)
playerId = player.PlayerId;
EnsureUIManager();
DetectInputDevice();
BindControls();
RefreshButtons();
}
void Awake()
{
EnsureUIManager();
}
void DetectInputDevice()
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
var joysticks = Input.GetJoystickNames();
if (joysticks.Length > 0 && !string.IsNullOrEmpty(joysticks[0]))
useJoystick = true;
else
useJoystick = false;
}
void BindControls()
{
if (!useJoystick) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
if (playerId == 1)
{
upKey = ButtonPinMapping.up1 ;
downKey = ButtonPinMapping.down1;
leftKey = ButtonPinMapping.left1;
rightKey = ButtonPinMapping.right1;
leftKey2 = ButtonPinMapping.turnLeft1;
rightKey2 = ButtonPinMapping.turnRight1;
selectKey = ButtonPinMapping.action1;
}
else
{
upKey = ButtonPinMapping.up2;
downKey = ButtonPinMapping.down2;
leftKey = ButtonPinMapping.left2;
rightKey = ButtonPinMapping.right2;
leftKey2 = ButtonPinMapping.turnLeft2;
rightKey2 = ButtonPinMapping.turnRight2;
selectKey = ButtonPinMapping.action2;
}
}
}
void OnEnable()
{
if (gameManager != null)
gameManager.OnInputModeChanged += HandleInputModeChanged;
EnsureUIManager();
if (uiManager != null)
uiManager.OnPanelChanged += HandlePanelChanged;
}
void OnDisable()
{
if (gameManager != null)
gameManager.OnInputModeChanged -= HandleInputModeChanged;
if (uiManager != null)
uiManager.OnPanelChanged -= HandlePanelChanged;
}
void EnsureUIManager()
{
// Prefer UIManager from the associated GameManager
var candidate = gameManager != null ? gameManager.uiManager : null;
if (candidate == null)
candidate = FindObjectOfType<UIManager>();
if (candidate == uiManager)
return;
// Rewire event subscription if UIManager instance changed
if (uiManager != null)
uiManager.OnPanelChanged -= HandlePanelChanged;
uiManager = candidate;
if (uiManager != null && isActiveAndEnabled)
uiManager.OnPanelChanged += HandlePanelChanged;
}
void HandlePanelChanged()
{
panelChanged = true;
}
void HandleInputModeChanged(GameManager.InputMode mode)
{
if (mode == GameManager.InputMode.UI)
{
RefreshButtons();
}
else
{
ClearHighlight();
}
}
void Update()
{
if (gameManager == null || gameManager.currentInputMode != GameManager.InputMode.UI)
return;
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (panelChanged)
{
RefreshButtons();
panelChanged = false;
return; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (buttons.Count == 0 || !buttons[currentIndex].gameObject.activeInHierarchy)
{
RefreshButtons();
}
if (buttons.Count == 0) return;
bool moved = false;
// Проверяем есть ли ButtonGridLayout на активном экране.
// Если активен оверлей — grid не используем: его кнопки не входят в сетку экрана.
ButtonGridLayout grid = null;
if (uiManager != null && uiManager.GetActiveOverlay() == null)
{
var activeScreen = uiManager.GetActiveScreen();
if (activeScreen != null)
grid = activeScreen.GetComponent<ButtonGridLayout>();
}
if (grid != null && grid.RowCount > 0)
{
// --- 2D навигация: Up/Down — ряды, Left/Right — столбцы ---
// Синхронизируем gridRow/gridCol с текущей кнопкой
if (grid.TryFindButton(buttons[currentIndex], out int fr, out int fc))
{ gridRow = fr; gridCol = fc; }
if (In.GetButtonDown(upKey))
{
gridRow = (gridRow - 1 + grid.RowCount) % grid.RowCount;
moved = true;
}
if (In.GetButtonDown(downKey))
{
gridRow = (gridRow + 1) % grid.RowCount;
moved = true;
}
if (In.GetButtonDown(leftKey) || In.GetButtonDown(leftKey2))
{
bool overlayActive = uiManager != null && uiManager.GetActiveOverlay() != null;
if (gameManager.currentState == GameState.ShipPlacement && !overlayActive)
{
ClearHighlight();
gameManager.SetInputMode(GameManager.InputMode.ShipPlacement);
return;
}
int cols = grid.ColCount(gridRow);
if (cols > 0) { gridCol = (gridCol - 1 + cols) % cols; moved = true; }
}
if (In.GetButtonDown(rightKey) || In.GetButtonDown(rightKey2))
{
int cols = grid.ColCount(gridRow);
if (cols > 0) { gridCol = (gridCol + 1) % cols; moved = true; }
}
if (moved)
{
Button target = grid.GetButton(gridRow, gridCol);
if (target != null)
{
int idx = buttons.IndexOf(target);
if (idx >= 0) currentIndex = idx;
}
UpdateCursorHighlight();
}
}
else
{
if (gameManager.currentState != GameState.ShipPlacement)
{
if(In.GetButtonDown(leftKey2)){MoveNext(-1);moved = true;}
if(In.GetButtonDown(rightKey2)){MoveNext(1);moved = true;}
}
// --- Старая линейная навигация (все экраны без ButtonGridLayout) ---
if (In.GetButtonDown(upKey)) { MoveNext(-1); moved = true; }
if (In.GetButtonDown(downKey)) { MoveNext(1); moved = true; }
if (In.GetButtonDown(leftKey))
{
bool overlayActive = uiManager != null && uiManager.GetActiveOverlay() != null;
if (gameManager.currentState == GameState.ShipPlacement && !overlayActive)
{
ClearHighlight();
gameManager.SetInputMode(GameManager.InputMode.ShipPlacement);
return;
}
else { MoveNext(-1); moved = true; }
}
if (In.GetButtonDown(rightKey)) { MoveNext(1); moved = true; }
if (moved) UpdateCursorHighlight();
}
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (In.GetButtonDown(selectKey))
{
if (buttons[currentIndex].interactable)
buttons[currentIndex].onClick.Invoke();
}
}
void MoveNext(int direction)
{
int startIndex = currentIndex;
do
{
currentIndex = (currentIndex + direction + buttons.Count) % buttons.Count;
}
while (!buttons[currentIndex].interactable && currentIndex != startIndex);
UpdateCursorHighlight();
}
void RefreshButtons()
{
buttons.Clear();
Button[] foundButtons = GetButtonsFromTopPanel();
foreach (Button btn in foundButtons)
{
if (btn.gameObject.activeInHierarchy)
buttons.Add(btn);
}
if (buttons.Count == 0)
{
currentIndex = 0;
ClearHighlight();
return;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> interactable <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
currentIndex = 0;
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!buttons[currentIndex].interactable)
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> interactable <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (int i = 0; i < buttons.Count; i++)
{
if (buttons[i].interactable)
{
currentIndex = i;
break;
}
}
}
UpdateCursorHighlight();
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
/// </summary>
private Button[] GetButtonsFromTopPanel()
{
if (parentCanvas == null)
return new Button[0];
if (uiManager == null)
return parentCanvas.GetComponentsInChildren<Button>(false);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> overlay <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> UIManager
GameObject activeOverlay = uiManager.GetActiveOverlay();
if (activeOverlay != null)
return activeOverlay.GetComponentsInChildren<Button>(false);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD> overlay - <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> screen
GameObject activeScreen = uiManager.GetActiveScreen();
if (activeScreen != null)
return activeScreen.GetComponentsInChildren<Button>(false);
// Fallback <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> Canvas
return parentCanvas.GetComponentsInChildren<Button>(false);
}
void UpdateCursorHighlight()
{
for (int i = 0; i < buttons.Count; i++)
{
var btn = buttons[i];
bool isCurrent = (i == currentIndex);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1: <20><><EFBFBD><EFBFBD><EFBFBD> UIButtonHighlight (<28><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
var highlight = btn.GetComponent<UIButtonHighlight>();
if (highlight)
{
highlight.SetHighlighted(isCurrent);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 2: <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Sprite Swap - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SelectableState
else if (btn.transition == Selectable.Transition.SpriteSwap)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (isCurrent)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Highlighted <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
btn.OnPointerEnter(null);
}
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Normal <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
btn.OnPointerExit(null);
}
}
}
}
void ClearHighlight()
{
foreach (var btn in buttons)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1: <20><><EFBFBD><EFBFBD><EFBFBD> UIButtonHighlight
var highlight = btn.GetComponent<UIButtonHighlight>();
if (highlight)
{
highlight.SetHighlighted(false);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 2: <20><><EFBFBD> Sprite Swap <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
else if (btn.transition == Selectable.Transition.SpriteSwap)
{
btn.OnPointerExit(null);
}
}
}
}