init
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using VOID.Generic.Dict;
|
||||
using VOID.Generic.Objects.Abstract.Events;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
using VOID.Generic.Objects.Unit.Events;
|
||||
using VOID.Generic.Player.Input;
|
||||
using VOID.Generic.Player.Util;
|
||||
using VOID.UserInterface;
|
||||
using VOID.Generic.Util;
|
||||
|
||||
namespace VOID.Generic.Player
|
||||
{
|
||||
[DefaultExecutionOrder(-1)]
|
||||
public class PathVisualizer : MonoBehaviour
|
||||
{
|
||||
public static PathVisualizer current { get; private set; }
|
||||
|
||||
// Configuration
|
||||
[SerializeField] private float redrawTimer = 0.1f;
|
||||
[SerializeField] private float lineSize = 0.05f;
|
||||
[SerializeField] private float verticalOffset = 0.1f;
|
||||
[SerializeField, Required] private Material reachableMaterial;
|
||||
[SerializeField, Required] private Material unreachableMaterial;
|
||||
[SerializeField, Required] private Material dangerousMaterial;
|
||||
[SerializeField, Required] private Material neutralMaterial;
|
||||
|
||||
// References
|
||||
private UnitObject _activeUnit;
|
||||
private readonly List<LineRenderer> _pathLineRenderers = new();
|
||||
|
||||
private bool _autoRedraw;
|
||||
private float _lastRedrawTimer;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
current = this;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
PlayerController.current.OnActiveUnitChange += OnActiveUnitChange;
|
||||
PlayerInputManager.current.OnForceMoveStart += ShouldAutoRedraw;
|
||||
PlayerInputManager.current.OnForceMoveEnd += ShouldAutoRedraw;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (_autoRedraw == false) return;
|
||||
if (GameUI.current.isCursorOverUI)
|
||||
{
|
||||
HidePath();
|
||||
return;
|
||||
}
|
||||
|
||||
_lastRedrawTimer += Time.fixedDeltaTime;
|
||||
if (_lastRedrawTimer < redrawTimer) return;
|
||||
_lastRedrawTimer = 0f;
|
||||
|
||||
_activeUnit.unitNavAgent.CalculatePathTo(SelectUtil.SelectPosition());
|
||||
UpdatePath(_activeUnit.unitNavAgent.GetCorrectedPath().ToArray());
|
||||
}
|
||||
|
||||
private void ShouldAutoRedraw()
|
||||
{
|
||||
// No player's active unit!
|
||||
if (!_activeUnit)
|
||||
{
|
||||
_autoRedraw = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Unit is moving on drawn path - don't draw another one
|
||||
if (_activeUnit.unitState.isMoving)
|
||||
{
|
||||
_autoRedraw = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Is something forcing path drawing?
|
||||
var isForcedMove = PlayerInputManager.current.isForceMove;
|
||||
var isActiveUnitTurn = _activeUnit.basicState.turnManager && _activeUnit.basicState.turnManager.currentUnitTurn == _activeUnit;
|
||||
if (!isForcedMove && !isActiveUnitTurn)
|
||||
{
|
||||
_autoRedraw = false;
|
||||
HidePath();
|
||||
return;
|
||||
}
|
||||
|
||||
// Is unit casting ability?
|
||||
if (_activeUnit.unitState.isCasting) {
|
||||
_autoRedraw = false;
|
||||
HidePath();
|
||||
return;
|
||||
}
|
||||
|
||||
_autoRedraw = true;
|
||||
}
|
||||
|
||||
private void AddLineRenderers(int needed)
|
||||
{
|
||||
// Add missing LineRenderers to current poll
|
||||
for (var i = 0; i < needed - _pathLineRenderers.Count; i++)
|
||||
{
|
||||
var lineRendererGameObject = new GameObject($"Path Renderer - part {_pathLineRenderers.Count+1}");
|
||||
lineRendererGameObject.transform.parent = gameObject.transform;
|
||||
var lineRenderer = lineRendererGameObject.AddComponent<LineRenderer>();
|
||||
lineRenderer.enabled = false;
|
||||
lineRenderer.startWidth = lineSize;
|
||||
lineRenderer.endWidth = lineSize;
|
||||
lineRenderer.shadowCastingMode = ShadowCastingMode.Off;
|
||||
lineRenderer.numCapVertices = 3;
|
||||
lineRenderer.numCornerVertices = 3;
|
||||
|
||||
_pathLineRenderers.Add(lineRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLineRenderers(List<PathType> pathTypes, List<Vector3[]> paths)
|
||||
{
|
||||
AddLineRenderers(paths.Count);
|
||||
|
||||
for (var i = 0; i < paths.Count; i++)
|
||||
{
|
||||
var lineRenderer = _pathLineRenderers[i];
|
||||
var pathType = pathTypes[i];
|
||||
var path = paths[i];
|
||||
var material = pathType switch
|
||||
{
|
||||
PathType.Reachable => reachableMaterial,
|
||||
PathType.UnReachable => unreachableMaterial,
|
||||
PathType.Dangerous => dangerousMaterial,
|
||||
PathType.Neutral => neutralMaterial,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(pathType), pathType, null)
|
||||
};
|
||||
|
||||
var offsetPath = path.Select(point => point + new Vector3(0, verticalOffset, 0)).ToArray();
|
||||
lineRenderer.positionCount = path.Length;
|
||||
lineRenderer.SetPositions(offsetPath);
|
||||
lineRenderer.sharedMaterial = material;
|
||||
lineRenderer.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnActiveUnitChange(UnitObject unitObject)
|
||||
{
|
||||
if (_activeUnit)
|
||||
{
|
||||
_activeUnit.unitEvents.onMoveStart.RemoveListener(OnUnitMoveStart);
|
||||
_activeUnit.unitEvents.onMoveEnd.RemoveListener(OnUnitMoveEnd);
|
||||
_activeUnit.basicEvents.onTurnSelfStart.RemoveListener(OnTurnSelfStart);
|
||||
_activeUnit.basicEvents.onTurnSelfEnd.RemoveListener(OnTurnSelfEnd);
|
||||
_activeUnit.basicEvents.onTurnQueueEnter.RemoveListener(OnTurnQueueEnter);
|
||||
_activeUnit.basicEvents.onTurnQueueLeave.RemoveListener(OnTurnQueueLeave);
|
||||
_activeUnit.unitEvents.onStartCasting.RemoveListener(OnStartCasting);
|
||||
_activeUnit.unitEvents.onEndCasting.RemoveListener(OnEndCasting);
|
||||
}
|
||||
HidePath();
|
||||
ShouldAutoRedraw();
|
||||
_activeUnit = unitObject;
|
||||
_activeUnit.unitEvents.onMoveStart.AddListener(OnUnitMoveStart);
|
||||
_activeUnit.unitEvents.onMoveEnd.AddListener(OnUnitMoveEnd);
|
||||
_activeUnit.basicEvents.onTurnSelfStart.AddListener(OnTurnSelfStart);
|
||||
_activeUnit.basicEvents.onTurnSelfEnd.AddListener(OnTurnSelfEnd);
|
||||
_activeUnit.basicEvents.onTurnQueueEnter.AddListener(OnTurnQueueEnter);
|
||||
_activeUnit.basicEvents.onTurnQueueLeave.AddListener(OnTurnQueueLeave);
|
||||
_activeUnit.unitEvents.onStartCasting.AddListener(OnStartCasting);
|
||||
_activeUnit.unitEvents.onEndCasting.AddListener(OnEndCasting);
|
||||
}
|
||||
|
||||
private void OnUnitMoveStart(MoveEvent moveEvent)
|
||||
{
|
||||
_autoRedraw = false;
|
||||
UpdatePath(moveEvent.pathCorrected.path.ToArray());
|
||||
}
|
||||
|
||||
private void OnUnitMoveEnd(MoveEvent moveEvent)
|
||||
{
|
||||
HidePath();
|
||||
ShouldAutoRedraw();
|
||||
}
|
||||
|
||||
private void OnTurnSelfStart(TurnEvent turnEvent)
|
||||
{
|
||||
ShouldAutoRedraw();
|
||||
}
|
||||
|
||||
private void OnTurnSelfEnd(TurnEvent turnEvent)
|
||||
{
|
||||
ShouldAutoRedraw();
|
||||
}
|
||||
|
||||
private void OnTurnQueueEnter(TurnEvent turnEvent)
|
||||
{
|
||||
ShouldAutoRedraw();
|
||||
}
|
||||
|
||||
private void OnTurnQueueLeave(TurnEvent turnEvent)
|
||||
{
|
||||
ShouldAutoRedraw();
|
||||
}
|
||||
|
||||
private void OnStartCasting(CastingEvent castingEvent) {
|
||||
ShouldAutoRedraw();
|
||||
}
|
||||
|
||||
private void OnEndCasting(CastingEvent castingEvent) {
|
||||
ShouldAutoRedraw();
|
||||
}
|
||||
|
||||
private void UpdatePath(Vector3[] path)
|
||||
{
|
||||
HidePath();
|
||||
|
||||
Vector3[] reachablePath;
|
||||
Vector3[] unreachablePath;
|
||||
|
||||
if (_activeUnit.basicState.turnManager)
|
||||
{
|
||||
// Inside combat - some part of path can be unreachable (not enough move points)
|
||||
var movePoints = _activeUnit.unitData.currentResources.movePoints;
|
||||
NavMeshPathUtil.SplitPath(path, movePoints, out reachablePath, out unreachablePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outside combat - whole path is reachable
|
||||
reachablePath = path;
|
||||
unreachablePath = null;
|
||||
}
|
||||
|
||||
NavMeshPathUtil.SplitReachablePath(reachablePath, out var pathTypes, out var paths);
|
||||
|
||||
if (unreachablePath is not null)
|
||||
{
|
||||
pathTypes.Add(PathType.UnReachable);
|
||||
paths.Add(unreachablePath);
|
||||
}
|
||||
|
||||
UpdateLineRenderers(pathTypes, paths);
|
||||
}
|
||||
|
||||
private void HidePath()
|
||||
{
|
||||
_pathLineRenderers.ForEach(lineRenderer => lineRenderer.enabled = false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user