298 lines
8.6 KiB
C#
298 lines
8.6 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using TMPro;
|
|
|
|
public class EnemyCardController : MonoBehaviour
|
|
{
|
|
[Header("UI Elements")]
|
|
public Image avatarImage;
|
|
public Animator avatarAnimator;
|
|
public TMP_Text nicknameText;
|
|
public TMP_Text dialogueText;
|
|
public RectTransform dialoguePanel;
|
|
|
|
[Header("Settings")]
|
|
public float typingSpeed = 0.05f;
|
|
public float panelExpandWidth = 300f;
|
|
public float panelExpandSpeed = 5f;
|
|
|
|
[Header("Animation names")]
|
|
public string idleAnimationName = "Idle_bot_1";
|
|
public string transitionIn = "forvard_bot";
|
|
public string transitionOut = "back_bot";
|
|
|
|
private Coroutine panelAnimCoroutine;
|
|
private Coroutine textTypingCoroutine;
|
|
private Vector2 dialogueOriginalPos;
|
|
private WaitForSeconds cachedTypingWait;
|
|
private System.Collections.Generic.HashSet<string> availableStates = new System.Collections.Generic.HashSet<string>();
|
|
|
|
private void Awake()
|
|
{
|
|
if (dialoguePanel != null)
|
|
dialogueOriginalPos = dialoguePanel.anchoredPosition;
|
|
|
|
cachedTypingWait = new WaitForSeconds(typingSpeed);
|
|
ValidateReferences();
|
|
}
|
|
|
|
private void OnValidate()
|
|
{
|
|
ValidateReferences();
|
|
}
|
|
|
|
private void ValidateReferences()
|
|
{
|
|
if (avatarImage == null) Debug.LogWarning($"[{name}] avatarImage íå íàçíà÷åí!", this);
|
|
if (nicknameText == null) Debug.LogWarning($"[{name}] nicknameText íå íàçíà÷åí!", this);
|
|
if (dialogueText == null) Debug.LogWarning($"[{name}] dialogueText íå íàçíà÷åí!", this);
|
|
if (dialoguePanel == null) Debug.LogWarning($"[{name}] dialoguePanel íå íàçíà÷åí!", this);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
StopAllAnimations();
|
|
ResetUIState();
|
|
}
|
|
|
|
public void SetEnemy(EnemyData enemy)
|
|
{
|
|
if (enemy == null)
|
|
{
|
|
Debug.LogWarning($"[{name}] SetEnemy: enemy is null!");
|
|
return;
|
|
}
|
|
|
|
if (nicknameText != null)
|
|
nicknameText.text = enemy.nickname;
|
|
|
|
SetupAnimatorOrSprite(enemy);
|
|
ResetUIState();
|
|
|
|
// Óñòàíàâëèâàåì ïîðÿäîê ïàíåëè (òîëüêî êîãäà îáúåêò àêòèâåí)
|
|
if (dialoguePanel != null && gameObject.activeInHierarchy)
|
|
dialoguePanel.SetSiblingIndex(0);
|
|
}
|
|
|
|
private void SetupAnimatorOrSprite(EnemyData enemy)
|
|
{
|
|
availableStates.Clear();
|
|
|
|
if (enemy.animatorOverride != null && avatarAnimator != null)
|
|
{
|
|
avatarAnimator.runtimeAnimatorController = enemy.animatorOverride;
|
|
avatarAnimator.enabled = true;
|
|
|
|
// Êýøèðóåì äîñòóïíûå êëèïû îäèí ðàç
|
|
var overrides = new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<AnimationClip, AnimationClip>>();
|
|
enemy.animatorOverride.GetOverrides(overrides);
|
|
|
|
foreach (var pair in overrides)
|
|
{
|
|
if (pair.Value != null) // Åñòü ïåðåîïðåäåë¸ííûé êëèï
|
|
availableStates.Add(pair.Key.name);
|
|
}
|
|
|
|
SetEmotion(idleAnimationName);
|
|
}
|
|
else
|
|
{
|
|
if (avatarAnimator != null)
|
|
avatarAnimator.enabled = false;
|
|
|
|
if (enemy.characterSprite != null && avatarImage != null)
|
|
avatarImage.sprite = enemy.characterSprite;
|
|
}
|
|
}
|
|
|
|
private void ResetUIState()
|
|
{
|
|
if (dialogueText != null)
|
|
dialogueText.text = "";
|
|
|
|
if (dialoguePanel != null)
|
|
{
|
|
dialoguePanel.anchoredPosition = dialogueOriginalPos;
|
|
}
|
|
}
|
|
|
|
private void StopAllAnimations()
|
|
{
|
|
if (panelAnimCoroutine != null)
|
|
{
|
|
StopCoroutine(panelAnimCoroutine);
|
|
panelAnimCoroutine = null;
|
|
}
|
|
|
|
if (textTypingCoroutine != null)
|
|
{
|
|
StopCoroutine(textTypingCoroutine);
|
|
textTypingCoroutine = null;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Îòêðûâàåò êàðòî÷êó ñ àíèìàöèåé, âûçûâàåò callback êîãäà îòêðûëàñü
|
|
/// </summary>
|
|
public void ShowCard(string emotionState, System.Action onShown = null)
|
|
{
|
|
if (panelAnimCoroutine != null)
|
|
StopCoroutine(panelAnimCoroutine);
|
|
|
|
panelAnimCoroutine = StartCoroutine(ShowCardCoroutine(emotionState, onShown));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Çàêðûâàåò êàðòî÷êó ñ àíèìàöèåé, âûçûâàåò callback êîãäà çàêðûëàñü
|
|
/// </summary>
|
|
public void HideCard(System.Action onHidden = null)
|
|
{
|
|
if (panelAnimCoroutine != null)
|
|
StopCoroutine(panelAnimCoroutine);
|
|
|
|
panelAnimCoroutine = StartCoroutine(HideCardCoroutine(onHidden));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ïå÷àòàåò òåêñò ïîñèìâîëüíî, âûçûâàåò callback ïî îêîí÷àíèè
|
|
/// </summary>
|
|
public void TypeText(string text, System.Action onComplete = null, bool skipSizePreparation = false)
|
|
{
|
|
if (textTypingCoroutine != null)
|
|
StopCoroutine(textTypingCoroutine);
|
|
|
|
textTypingCoroutine = StartCoroutine(TypeTextCoroutine(text, onComplete, skipSizePreparation));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ìãíîâåííî óñòàíàâëèâàåò òåêñò áåç àíèìàöèè ïå÷àòè
|
|
/// </summary>
|
|
public void SetTextImmediate(string text)
|
|
{
|
|
if (textTypingCoroutine != null)
|
|
{
|
|
StopCoroutine(textTypingCoroutine);
|
|
textTypingCoroutine = null;
|
|
}
|
|
|
|
if (dialogueText != null)
|
|
dialogueText.text = text;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ïîäãîòàâëèâàåò ðàçìåð òåêñòà çàðàíåå (÷òîáû èçáåæàòü "áëèêà" ïðè îòêðûòèè ïàíåëè)
|
|
/// </summary>
|
|
public IEnumerator PrepareTextSizeAsync(string text)
|
|
{
|
|
yield return PrepareTextSize(text);
|
|
}
|
|
|
|
private IEnumerator ShowCardCoroutine(string emotionState, System.Action onShown)
|
|
{
|
|
if (dialoguePanel == null) yield break;
|
|
|
|
SetEmotion(transitionIn);
|
|
|
|
Vector2 hiddenPos = dialogueOriginalPos;
|
|
Vector2 shownPos = hiddenPos + new Vector2(panelExpandWidth, 0);
|
|
|
|
float t = 0f;
|
|
while (t < 1f)
|
|
{
|
|
t += Time.deltaTime * panelExpandSpeed;
|
|
dialoguePanel.anchoredPosition = Vector2.Lerp(hiddenPos, shownPos, t);
|
|
yield return null;
|
|
}
|
|
|
|
dialoguePanel.anchoredPosition = shownPos;
|
|
SetEmotion(emotionState);
|
|
|
|
onShown?.Invoke();
|
|
}
|
|
|
|
private IEnumerator HideCardCoroutine(System.Action onHidden)
|
|
{
|
|
if (dialoguePanel == null) yield break;
|
|
|
|
SetEmotion(transitionOut);
|
|
|
|
if (dialogueText != null)
|
|
dialogueText.text = "";
|
|
|
|
Vector2 hiddenPos = dialogueOriginalPos;
|
|
Vector2 shownPos = hiddenPos + new Vector2(panelExpandWidth, 0);
|
|
|
|
float t = 0f;
|
|
while (t < 1f)
|
|
{
|
|
t += Time.deltaTime * panelExpandSpeed;
|
|
dialoguePanel.anchoredPosition = Vector2.Lerp(shownPos, hiddenPos, t);
|
|
yield return null;
|
|
}
|
|
|
|
dialoguePanel.anchoredPosition = hiddenPos;
|
|
SetEmotion(idleAnimationName);
|
|
|
|
onHidden?.Invoke();
|
|
}
|
|
|
|
private IEnumerator TypeTextCoroutine(string text, System.Action onComplete, bool skipSizePreparation)
|
|
{
|
|
if (dialogueText == null) yield break;
|
|
|
|
// Ïîäãîòîâêà ðàçìåðà øðèôòà (ïðîïóñêàåì åñëè óæå ñäåëàíî)
|
|
if (!skipSizePreparation)
|
|
{
|
|
yield return PrepareTextSize(text);
|
|
}
|
|
|
|
// Ïå÷àòü ïî ñèìâîëàì ÷åðåç maxVisibleCharacters (îïòèìèçàöèÿ)
|
|
dialogueText.text = text;
|
|
dialogueText.ForceMeshUpdate();
|
|
|
|
int totalChars = dialogueText.textInfo.characterCount;
|
|
dialogueText.maxVisibleCharacters = 0;
|
|
|
|
for (int i = 0; i <= totalChars; i++)
|
|
{
|
|
dialogueText.maxVisibleCharacters = i;
|
|
yield return cachedTypingWait;
|
|
}
|
|
|
|
onComplete?.Invoke();
|
|
}
|
|
|
|
private IEnumerator PrepareTextSize(string text)
|
|
{
|
|
if (dialogueText == null) yield break;
|
|
|
|
dialogueText.enableWordWrapping = true;
|
|
dialogueText.overflowMode = TextOverflowModes.Overflow;
|
|
dialogueText.text = text;
|
|
dialogueText.enableAutoSizing = true;
|
|
dialogueText.fontSizeMin = 5;
|
|
|
|
yield return null; // Æä¸ì êàäð äëÿ ðàñ÷¸òà
|
|
|
|
float finalFontSize = dialogueText.fontSize;
|
|
dialogueText.enableAutoSizing = false;
|
|
dialogueText.fontSize = finalFontSize;
|
|
dialogueText.text = "";
|
|
}
|
|
|
|
|
|
public void SetEmotion(string stateName)
|
|
{
|
|
if (avatarAnimator == null || !avatarAnimator.enabled || string.IsNullOrEmpty(stateName))
|
|
return;
|
|
|
|
if (availableStates.Contains(stateName))
|
|
avatarAnimator.Play(stateName);
|
|
}
|
|
}
|
|
|
|
|
|
|