186 lines
5.6 KiB
C#
186 lines
5.6 KiB
C#
using UnityEngine;
|
|
using Vanguard.Battle;
|
|
|
|
namespace Vanguard.Board3D
|
|
{
|
|
/// <summary>
|
|
/// Стрелка атаки на столе: линия от атакующего к цели и наконечник.
|
|
/// Точки обновляются каждый кадр, поэтому стрелка едет за картами.
|
|
/// </summary>
|
|
public sealed class AttackArrowView
|
|
{
|
|
private const float ShaftWidth = 0.075f;
|
|
private const float HeadWidth = 0.17f;
|
|
private const float HeadLength = 0.38f;
|
|
|
|
private GameObject _root;
|
|
private LineRenderer _shaft;
|
|
private LineRenderer _head;
|
|
private Material _material;
|
|
private AnimationConfig _config;
|
|
private Vector3 _from;
|
|
private Vector3 _to;
|
|
private bool _visible;
|
|
private float _alpha;
|
|
private float _widthScale = 1f;
|
|
|
|
public bool IsVisible => _visible || _alpha > 0.001f;
|
|
|
|
public void Build(Transform parent, AnimationConfig config)
|
|
{
|
|
_config = config;
|
|
_root = new GameObject("Attack Arrow");
|
|
_root.transform.SetParent(parent, false);
|
|
|
|
var shader = Shader.Find("Sprites/Default");
|
|
if (shader == null)
|
|
shader = Shader.Find("Unlit/Color");
|
|
|
|
_material = shader != null ? new Material(shader) : null;
|
|
_shaft = CreateLine("Shaft", ShaftWidth);
|
|
_head = CreateLine("Head", ShaftWidth * 0.7f);
|
|
_head.positionCount = 3;
|
|
_root.SetActive(false);
|
|
}
|
|
|
|
public void SetConfig(AnimationConfig config)
|
|
{
|
|
_config = config;
|
|
}
|
|
|
|
public void Show(Vector3 from, Vector3 to)
|
|
{
|
|
SetPoints(from, to);
|
|
_visible = true;
|
|
|
|
if (_root != null)
|
|
_root.SetActive(true);
|
|
}
|
|
|
|
public void Hide()
|
|
{
|
|
_visible = false;
|
|
}
|
|
|
|
public void HideImmediate()
|
|
{
|
|
_visible = false;
|
|
_alpha = 0f;
|
|
if (_root != null)
|
|
_root.SetActive(false);
|
|
}
|
|
|
|
public void SetPoints(Vector3 from, Vector3 to)
|
|
{
|
|
_from = from;
|
|
_to = to;
|
|
UpdateGeometry();
|
|
}
|
|
|
|
public void Tick(float deltaTime)
|
|
{
|
|
if (_root == null)
|
|
return;
|
|
|
|
var target = _visible ? 1f : 0f;
|
|
var duration = _visible
|
|
? (_config != null ? _config.arrowShowDuration : 0.25f)
|
|
: (_config != null ? _config.arrowHideDuration : 0.2f);
|
|
_alpha = Mathf.MoveTowards(
|
|
_alpha,
|
|
target,
|
|
deltaTime / Mathf.Max(0.01f, duration));
|
|
|
|
if (!_visible && _alpha <= 0.001f)
|
|
{
|
|
_root.SetActive(false);
|
|
return;
|
|
}
|
|
|
|
_root.SetActive(true);
|
|
_widthScale = 0.55f + (_alpha * 0.45f);
|
|
UpdateGeometry();
|
|
ApplyColor();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_root != null)
|
|
{
|
|
if (Application.isPlaying)
|
|
Object.Destroy(_root);
|
|
else
|
|
Object.DestroyImmediate(_root);
|
|
_root = null;
|
|
}
|
|
|
|
if (_material != null)
|
|
{
|
|
if (Application.isPlaying)
|
|
Object.Destroy(_material);
|
|
else
|
|
Object.DestroyImmediate(_material);
|
|
_material = null;
|
|
}
|
|
}
|
|
|
|
private LineRenderer CreateLine(string name, float width)
|
|
{
|
|
var go = new GameObject(name);
|
|
go.transform.SetParent(_root.transform, false);
|
|
var line = go.AddComponent<LineRenderer>();
|
|
line.useWorldSpace = false;
|
|
line.positionCount = 2;
|
|
line.widthMultiplier = width;
|
|
line.numCapVertices = 4;
|
|
line.numCornerVertices = 4;
|
|
line.alignment = LineAlignment.View;
|
|
line.textureMode = LineTextureMode.Stretch;
|
|
line.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
|
line.receiveShadows = false;
|
|
if (_material != null)
|
|
line.material = _material;
|
|
return line;
|
|
}
|
|
|
|
private void UpdateGeometry()
|
|
{
|
|
if (_shaft == null || _head == null)
|
|
return;
|
|
|
|
var direction = _to - _from;
|
|
if (direction.sqrMagnitude < 0.0001f)
|
|
direction = Vector3.forward;
|
|
direction.Normalize();
|
|
|
|
_shaft.SetPosition(0, _from);
|
|
_shaft.SetPosition(1, _to);
|
|
_shaft.widthMultiplier = ShaftWidth * _widthScale;
|
|
|
|
var tip = _to;
|
|
var back = _to - (direction * HeadLength);
|
|
var side = Vector3.Cross(Vector3.up, direction).normalized;
|
|
if (side.sqrMagnitude < 0.0001f)
|
|
side = Vector3.right;
|
|
var half = side * (HeadWidth * _widthScale);
|
|
_head.SetPosition(0, back + half);
|
|
_head.SetPosition(1, tip);
|
|
_head.SetPosition(2, back - half);
|
|
_head.widthMultiplier = ShaftWidth * 0.7f * _widthScale;
|
|
}
|
|
|
|
private void ApplyColor()
|
|
{
|
|
var color = new Color(1f, 0.72f, 0.26f, _alpha * 0.92f);
|
|
foreach (var line in new[] { _shaft, _head })
|
|
{
|
|
if (line == null)
|
|
continue;
|
|
|
|
line.startColor = color;
|
|
line.endColor = color;
|
|
}
|
|
}
|
|
}
|
|
}
|