167 lines
4.2 KiB
C#
167 lines
4.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.UI;
|
|
|
|
public class DialogueUI : MonoBehaviour
|
|
{
|
|
[Header("Panel")]
|
|
[SerializeField] private GameObject dialoguePanel;
|
|
|
|
[Header("Speaker UI")]
|
|
[SerializeField] private Image portraitImage;
|
|
[SerializeField] private TMP_Text nameText;
|
|
|
|
[Header("Dialogue UI")]
|
|
[SerializeField] private TMP_Text dialogueText;
|
|
[SerializeField] private Button nextButton;
|
|
|
|
[Header("Choice UI")]
|
|
[SerializeField] private Transform choiceRoot;
|
|
[SerializeField] private Button choiceButtonPrefab;
|
|
|
|
[Header("Settings")]
|
|
[SerializeField] private bool hidePortraitWhenNoSpeaker = true;
|
|
|
|
private readonly List<Button> spawnedChoiceButtons = new List<Button>();
|
|
|
|
public GameObject DialoguePanel => dialoguePanel;
|
|
|
|
public bool IsVisible
|
|
{
|
|
get
|
|
{
|
|
return dialoguePanel != null && dialoguePanel.activeSelf;
|
|
}
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
SetVisible(false);
|
|
ClearChoices();
|
|
}
|
|
|
|
public void SetVisible(bool visible)
|
|
{
|
|
if (dialoguePanel != null)
|
|
dialoguePanel.SetActive(visible);
|
|
}
|
|
|
|
public void SetSpeaker(NPCProfile speaker)
|
|
{
|
|
if (speaker == null)
|
|
{
|
|
if (nameText != null)
|
|
nameText.text = string.Empty;
|
|
|
|
if (portraitImage != null)
|
|
{
|
|
portraitImage.sprite = null;
|
|
portraitImage.enabled = !hidePortraitWhenNoSpeaker;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (nameText != null)
|
|
nameText.text = speaker.displayName;
|
|
|
|
if (portraitImage != null)
|
|
{
|
|
portraitImage.sprite = speaker.portrait;
|
|
portraitImage.enabled = speaker.portrait != null || !hidePortraitWhenNoSpeaker;
|
|
}
|
|
}
|
|
|
|
public void SetDialogueText(string text)
|
|
{
|
|
if (dialogueText != null)
|
|
dialogueText.text = text;
|
|
}
|
|
|
|
public void SetupNextButton(UnityAction onClick)
|
|
{
|
|
if (nextButton == null)
|
|
return;
|
|
|
|
nextButton.onClick.RemoveAllListeners();
|
|
|
|
if (onClick != null)
|
|
nextButton.onClick.AddListener(onClick);
|
|
}
|
|
|
|
public void SetNextButtonVisible(bool visible)
|
|
{
|
|
if (nextButton != null)
|
|
nextButton.gameObject.SetActive(visible);
|
|
}
|
|
|
|
public void CreateChoices(ChoiceData[] choices, Action<int> onChoiceClicked)
|
|
{
|
|
ClearChoices();
|
|
|
|
if (choices == null || choices.Length == 0)
|
|
return;
|
|
|
|
if (choiceRoot == null)
|
|
{
|
|
Debug.LogWarning("[DialogueUI] choiceRoot가 연결되지 않았습니다.");
|
|
return;
|
|
}
|
|
|
|
if (choiceButtonPrefab == null)
|
|
{
|
|
Debug.LogWarning("[DialogueUI] choiceButtonPrefab이 연결되지 않았습니다.");
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < choices.Length; i++)
|
|
{
|
|
ChoiceData choice = choices[i];
|
|
|
|
if (choice == null)
|
|
continue;
|
|
|
|
Button button = Instantiate(choiceButtonPrefab, choiceRoot);
|
|
button.gameObject.SetActive(true);
|
|
|
|
TMP_Text label = button.GetComponentInChildren<TMP_Text>(true);
|
|
|
|
if (label != null)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(choice.choiceText))
|
|
label.text = "(빈 선택지)";
|
|
else
|
|
label.text = choice.choiceText;
|
|
}
|
|
|
|
int capturedIndex = i;
|
|
|
|
button.onClick.RemoveAllListeners();
|
|
button.onClick.AddListener(() =>
|
|
{
|
|
onChoiceClicked?.Invoke(capturedIndex);
|
|
});
|
|
|
|
spawnedChoiceButtons.Add(button);
|
|
}
|
|
}
|
|
|
|
public void ClearChoices()
|
|
{
|
|
for (int i = spawnedChoiceButtons.Count - 1; i >= 0; i--)
|
|
{
|
|
if (spawnedChoiceButtons[i] == null)
|
|
continue;
|
|
|
|
if (Application.isPlaying)
|
|
Destroy(spawnedChoiceButtons[i].gameObject);
|
|
else
|
|
DestroyImmediate(spawnedChoiceButtons[i].gameObject);
|
|
}
|
|
|
|
spawnedChoiceButtons.Clear();
|
|
}
|
|
} |