init
This commit is contained in:
@@ -0,0 +1,259 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Sirenix.Utilities;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using VOID.Generic.Objects.Abstract;
|
||||
using VOID.Generic.Objects.Abstract.Events;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
using VOID.Generic.Player;
|
||||
using VOID.Generic.Turn;
|
||||
using VOID.UserInterface.Game.Party;
|
||||
|
||||
namespace VOID.UserInterface.Game
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages TurnQueue elements for current player only:<br/>
|
||||
/// - Displays all participating <see cref="UnitObject"/> by their turn order with <see cref="UnitPortraitUI"/><br/>
|
||||
/// - Additional info when currently active unit is waiting for its turn<br/>
|
||||
/// </summary>
|
||||
public class TurnQueueUI : MonoBehaviour
|
||||
{
|
||||
public static TurnQueueUI current { get; private set; }
|
||||
|
||||
// Visual Elements
|
||||
private VisualElement _rootElement;
|
||||
private VisualElement _currentQueueElement;
|
||||
private VisualElement _nextQueueElement;
|
||||
private VisualElement _waitingElement;
|
||||
|
||||
// Portraits for units in current and next queue
|
||||
private readonly Dictionary<UnitObject, UnitPortraitUI> _currentQueuePortraits = new();
|
||||
private readonly Dictionary<UnitObject, UnitPortraitUI> _nextQueuePortraits = new();
|
||||
|
||||
// References
|
||||
private UnitObject _activeUnit;
|
||||
private UnitObject _currentUnitTurn;
|
||||
private TurnManager _turnManager;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
current = this;
|
||||
|
||||
var uiDocument = gameObject.GetComponent<UIDocument>();
|
||||
var templateElement = uiDocument.rootVisualElement;
|
||||
|
||||
_rootElement = templateElement.Q("root-turn-queue");
|
||||
_currentQueueElement = _rootElement.Q("current-queue");
|
||||
_nextQueueElement = _rootElement.Q("next-queue");
|
||||
_waitingElement = _rootElement.Q("waiting");
|
||||
|
||||
HideTurnQueue();
|
||||
|
||||
_rootElement.dataSource = this;
|
||||
_rootElement.pickingMode = PickingMode.Position;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
PlayerController.current.OnActiveUnitChange += OnActiveUnitChange;
|
||||
}
|
||||
|
||||
private void OnActiveUnitChange(UnitObject nextUnit)
|
||||
{
|
||||
var sameQueue = false;
|
||||
if (_activeUnit)
|
||||
{
|
||||
sameQueue = _activeUnit.basicState.turnManager == nextUnit.basicState.turnManager;
|
||||
_activeUnit.basicEvents.onTurnQueueEnter.RemoveListener(OnActiveUnitTurnQueueEnter);
|
||||
_activeUnit.basicEvents.onTurnQueueLeave.RemoveListener(OnActiveUnitTurnQueueLeave);
|
||||
_activeUnit.basicEvents.onTurnSelfStart.RemoveListener(OnActiveUnitTurnSelfStart);
|
||||
_activeUnit.basicEvents.onTurnSelfEnd.RemoveListener(OnActiveUnitTurnSelfEnd);
|
||||
_activeUnit.basicEvents.onTurnQueueSwap.RemoveListener(OnActiveUnitTurnQueueSwap);
|
||||
}
|
||||
nextUnit.basicEvents.onTurnQueueEnter.AddListener(OnActiveUnitTurnQueueEnter);
|
||||
nextUnit.basicEvents.onTurnQueueLeave.AddListener(OnActiveUnitTurnQueueLeave);
|
||||
nextUnit.basicEvents.onTurnSelfStart.AddListener(OnActiveUnitTurnSelfStart);
|
||||
nextUnit.basicEvents.onTurnSelfEnd.AddListener(OnActiveUnitTurnSelfEnd);
|
||||
nextUnit.basicEvents.onTurnQueueSwap.AddListener(OnActiveUnitTurnQueueSwap);
|
||||
|
||||
if (!sameQueue)
|
||||
{
|
||||
HideTurnQueue();
|
||||
if (nextUnit.basicState.turnManager) ShowTurnQueue(nextUnit.basicState.turnManager);
|
||||
}
|
||||
_activeUnit = nextUnit;
|
||||
|
||||
UpdateWaitingForTurn();
|
||||
}
|
||||
|
||||
private void OnActiveUnitTurnQueueSwap(TurnEvent turnEvent)
|
||||
{
|
||||
_turnManager = turnEvent.turnManager;
|
||||
_turnManager.allUnitsInQueue.ForEach((unit, index) =>
|
||||
{
|
||||
if (_nextQueuePortraits.Keys.Contains(unit)) return;
|
||||
var nextUnit = _turnManager.allUnitsInQueue.ElementAtOrDefault(index + 1);
|
||||
AddPortrait(unit, false, nextUnit);
|
||||
});
|
||||
_turnManager.unitsInCurrentQueue.ForEach((unit, index) =>
|
||||
{
|
||||
if (_currentQueuePortraits.Keys.Contains(unit)) return;
|
||||
var nextUnit = _turnManager.unitsInCurrentQueue.ElementAtOrDefault(index + 1);
|
||||
AddPortrait(unit, true, nextUnit);
|
||||
});
|
||||
|
||||
SetActiveTurn(_turnManager.unitsInCurrentQueue.First());
|
||||
}
|
||||
|
||||
private void OnActiveUnitTurnQueueEnter(TurnEvent turnEvent)
|
||||
{
|
||||
ShowTurnQueue(turnEvent.turnManager);
|
||||
UpdateWaitingForTurn();
|
||||
}
|
||||
|
||||
private void OnActiveUnitTurnQueueLeave(TurnEvent turnEvent)
|
||||
{
|
||||
HideTurnQueue();
|
||||
UpdateWaitingForTurn();
|
||||
}
|
||||
|
||||
private void OnActiveUnitTurnSelfStart(TurnEvent turnEvent) => UpdateWaitingForTurn();
|
||||
|
||||
private void OnActiveUnitTurnSelfEnd(TurnEvent turnEvent) => UpdateWaitingForTurn();
|
||||
|
||||
private void OnUnitEnter(AbstractObject obj)
|
||||
{
|
||||
if (obj is not UnitObject unit) return;
|
||||
var beforeUnitInCurrent = _turnManager.unitsInCurrentQueue.ElementAtOrDefault(
|
||||
_turnManager.unitsInCurrentQueue.IndexOf(unit) + 1);
|
||||
var beforeUnitInNext = _turnManager.allUnitsInQueue.ElementAtOrDefault(
|
||||
_turnManager.allUnitsInQueue.IndexOf(unit) + 1);
|
||||
AddPortrait(unit, true, beforeUnitInCurrent);
|
||||
AddPortrait(unit, false, beforeUnitInNext);
|
||||
}
|
||||
|
||||
private void OnUnitLeave(AbstractObject obj)
|
||||
{
|
||||
if (obj is not UnitObject unit) return;
|
||||
RemovePortrait(unit);
|
||||
}
|
||||
|
||||
private void OnNextTurn()
|
||||
{
|
||||
if (_currentUnitTurn)
|
||||
{
|
||||
_currentQueuePortraits.GetValueOrDefault(_currentUnitTurn)?.Destroy();
|
||||
_currentQueuePortraits.Remove(_currentUnitTurn);
|
||||
}
|
||||
_currentUnitTurn = _turnManager.currentUnitTurn;
|
||||
SetActiveTurn(_currentUnitTurn);
|
||||
}
|
||||
|
||||
private void OnNextQueue()
|
||||
{
|
||||
_currentUnitTurn = null;
|
||||
_currentQueuePortraits.Values.ForEach(portrait => portrait.Destroy());
|
||||
_currentQueuePortraits.Clear();
|
||||
_turnManager.unitsInCurrentQueue.ForEach(unit => AddPortrait(unit));
|
||||
}
|
||||
|
||||
private void ShowTurnQueue(TurnManager turnManager)
|
||||
{
|
||||
HideTurnQueue();
|
||||
_turnManager = turnManager;
|
||||
_rootElement.style.display = DisplayStyle.Flex;
|
||||
_turnManager.unitsInCurrentQueue.ForEach(unit => AddPortrait(unit));
|
||||
_turnManager.allUnitsInQueue.ForEach(unit => AddPortrait(unit, false));
|
||||
if (_turnManager.currentUnitTurn) SetActiveTurn(_turnManager.currentUnitTurn);
|
||||
_turnManager.OnNextTurn += OnNextTurn;
|
||||
_turnManager.OnNextQueue += OnNextQueue;
|
||||
_turnManager.OnObjectEnter += OnUnitEnter;
|
||||
_turnManager.OnObjectLeave += OnUnitLeave;
|
||||
_turnManager.OnNextQueueOrderChange += OnNextQueueOrderChange;
|
||||
_turnManager.OnCurrentQueueOrderChange += OnCurrentQueueOrderChange;
|
||||
}
|
||||
|
||||
private void HideTurnQueue()
|
||||
{
|
||||
_rootElement.style.display = DisplayStyle.None;
|
||||
_currentQueuePortraits.Values.ForEach(unitPortrait => unitPortrait.Destroy());
|
||||
_currentQueuePortraits.Clear();
|
||||
_currentQueueElement.Clear();
|
||||
_nextQueuePortraits.Values.ForEach(unitPortrait => unitPortrait.Destroy());
|
||||
_nextQueuePortraits.Clear();
|
||||
_nextQueueElement.Clear();
|
||||
if (!_turnManager) return;
|
||||
_turnManager.OnNextTurn -= OnNextTurn;
|
||||
_turnManager.OnNextQueue -= OnNextQueue;
|
||||
_turnManager.OnObjectEnter -= OnUnitEnter;
|
||||
_turnManager.OnObjectLeave -= OnUnitLeave;
|
||||
_turnManager.OnNextQueueOrderChange -= OnNextQueueOrderChange;
|
||||
_turnManager.OnCurrentQueueOrderChange -= OnCurrentQueueOrderChange;
|
||||
_currentUnitTurn = null;
|
||||
_turnManager = null;
|
||||
}
|
||||
|
||||
private void AddPortrait(UnitObject unit, bool putIntoCurrent = true, UnitObject putBefore = null)
|
||||
{
|
||||
var element = putIntoCurrent ? _currentQueueElement : _nextQueueElement;
|
||||
var dict = putIntoCurrent ? _currentQueuePortraits : _nextQueuePortraits;
|
||||
var unitPortrait = new UnitPortraitUI();
|
||||
unitPortrait.InitNew(element);
|
||||
unitPortrait.SetUnit(unit);
|
||||
if (putBefore)
|
||||
{
|
||||
var behindElement = dict.GetValueOrDefault(putBefore).templateElement;
|
||||
unitPortrait.templateElement.PlaceBehind(behindElement);
|
||||
}
|
||||
dict.Add(unit, unitPortrait);
|
||||
}
|
||||
|
||||
private void RemovePortrait(UnitObject unit)
|
||||
{
|
||||
_currentQueuePortraits.GetValueOrDefault(unit)?.Destroy();
|
||||
_nextQueuePortraits.GetValueOrDefault(unit)?.Destroy();
|
||||
_currentQueuePortraits.Remove(unit);
|
||||
_nextQueuePortraits.Remove(unit);
|
||||
}
|
||||
|
||||
private void MovePortrait(UnitObject unit, bool putIntoCurrent = true, UnitObject putBefore = null)
|
||||
{
|
||||
var dict = putIntoCurrent ? _currentQueuePortraits : _nextQueuePortraits;
|
||||
if (putBefore)
|
||||
{
|
||||
var behindElement = dict.GetValueOrDefault(putBefore).templateElement;
|
||||
dict.GetValueOrDefault(unit).templateElement.PlaceBehind(behindElement);
|
||||
}
|
||||
else
|
||||
{
|
||||
dict.GetValueOrDefault(unit).templateElement.BringToFront();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnNextQueueOrderChange(UnitObject unit, int newIndex)
|
||||
{
|
||||
MovePortrait(unit, false, _turnManager.allUnitsInQueue.ElementAtOrDefault(newIndex + 1));
|
||||
}
|
||||
|
||||
private void OnCurrentQueueOrderChange(UnitObject unit, int newIndex)
|
||||
{
|
||||
MovePortrait(unit, true, _turnManager.unitsInCurrentQueue.ElementAtOrDefault(newIndex + 1));
|
||||
}
|
||||
|
||||
private void SetActiveTurn(UnitObject unit)
|
||||
{
|
||||
_currentQueueElement.Q(className: "active-turn")?.RemoveFromClassList("active-turn");
|
||||
_currentQueuePortraits.GetValueOrDefault(unit)?.templateElement.AddToClassList("active-turn");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes TurnQueue's waiting element visible if it is not active unit's turn.
|
||||
/// </summary>
|
||||
private void UpdateWaitingForTurn()
|
||||
{
|
||||
var isWaiting = _activeUnit.basicState.turnManager && _activeUnit.basicState.turnManager.currentUnitTurn != _activeUnit;
|
||||
_waitingElement.style.display = isWaiting ? DisplayStyle.Flex : DisplayStyle.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user