Files
WhaleAdventure_VR/Assets/My project/Dialogue Scripts/UI/DialogueUI.cs
skrwns304@gmail.com b1e85a5b89 2026-06-19 UI, UI로직
2026-06-19 14:27:40 +09:00

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();
}
}