Files
aibis-dream/Assets/Scripts/UI/DialogUI/DialogBox.cs
T

219 lines
6.4 KiB
C#

using System;
using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.Utility;
using Febucci.UI;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace AibisDream
{
public class DialogBox : MonoBehaviour, IDialogView
{
#region box组件名称
private const string ActorName = "Actor Name";
private const string DialogText = "Dialog Text";
private const string NextArray = "Next Array";
private const string ChoiceBox = "Choice Box";
#endregion
#region box组件
private TypewriterByCharacter _dialogText;
private TextMeshProUGUI _actorName;
private GameObject _nextArray;
private GameObject _choiceBox;
#endregion
private TextParam _textParam;
private Action _nextStep;
[SerializeReference] private GameObject choiceButtonPrefab;
private void Awake()
{
InitComponents();
RegisterEvents();
}
#region 初始化
private void InitComponents()
{
_actorName = transform.Find(ActorName)?.gameObject.GetComponentInChildren<TextMeshProUGUI>();
_dialogText = transform.Find(DialogText)?.gameObject.GetComponent<TypewriterByCharacter>();
_nextArray = transform.Find(NextArray)?.gameObject;
_choiceBox = transform.Find(ChoiceBox)?.gameObject;
}
private void RegisterEvents()
{
_dialogText.onTextShowed.AddListener(OnTextShowed);
}
#endregion
/// <summary>
/// 隐藏对话盒
/// </summary>
public void HideDialog()
{
gameObject.SetActive(false);
}
/// <summary>
/// 显示对话
/// </summary>
/// <param name="dialogLine">对话内容</param>
/// <param name="character">角色内容</param>
/// <param name="nextStep">下一步</param>
/// <param name="lineId">行号</param>
/// <param name="isAutoSkip">是否自动跳过,默认为false</param>
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId,
bool isAutoSkip = false)
{
gameObject.SetActive(true);
// 把原有对话清掉
ClearBox();
_dialogText.gameObject.SetActive(true);
_choiceBox?.SetActive(false);
// 显示内容
ShowActorName(character);
_dialogText.ShowText(dialogLine);
_nextStep = nextStep;
}
private void OnTextShowed()
{
_nextArray.gameObject.SetActive(true);
EnumEventSystem.Global.Send(DialogEventEnum.LineShown);
}
public void NextStep()
{
if (_nextStep == null) return;
ClearBox();
EnumEventSystem.Global.Send(DialogEventEnum.LineEnd);
var next = _nextStep;
_nextStep = null;
next.Invoke();
}
/// <summary>
/// 检查当前是否有活动的选项显示
/// </summary>
/// <returns>是否有活动选项</returns>
public bool HasActiveOptions()
{
return _choiceBox != null && _choiceBox.activeSelf;
}
public void OnLocalizationChanged(string value)
{
_textParam = JsonUtil.ReadBeanByText<TextParam>(value);
var tmp = _dialogText.GetComponent<TMP_Text>();
// 修改对话文本
tmp.characterSpacing = _textParam.charSpace;
}
/// <summary>
/// 展示选项
/// </summary>
/// <param name="dialogueOptions">对话选项</param>
public void ShowOptions(DialogOption[] dialogueOptions)
{
gameObject.SetActive(true);
// 没有选择框直接不显示选项
if (!_choiceBox)
{
return;
}
// 把原有对话清掉
ClearBox();
_choiceBox.SetActive(true);
_dialogText.gameObject.SetActive(false);
HideActorName();
// 销毁原来的按钮
foreach (Transform child in _choiceBox.transform)
{
Destroy(child.gameObject);
}
// 生成新按钮
foreach (var option in dialogueOptions)
{
if (!option.IsAvailable) continue;
var choiceInstance = Instantiate(choiceButtonPrefab, _choiceBox.transform);
var optionText = choiceInstance.GetComponentInChildren<TextMeshProUGUI>();
optionText.text = option.Line;
optionText.characterSpacing = _textParam.charSpace;
choiceInstance.GetComponent<Button>().onClick.AddListener(() =>
{
HideDialog();
option.Select();
});
}
}
/// <summary>
/// 尝试跳过对话
/// true说明成功快进了对话显示
/// false说明对话已经显示完成了,可以跳过
/// </summary>
/// <returns></returns>
public bool TrySkipLine(bool isForceSkip)
{
if (_dialogText.isShowingText)
{
_dialogText.SkipTypewriter();
return true;
}
_nextArray.gameObject.SetActive(false);
return false;
}
private void ClearBox()
{
gameObject.SetActive(true);
_dialogText?.ShowText("");
_nextArray?.SetActive(false);
if (!_actorName) _actorName.text = "";
}
private void ShowActorName(CharacterVo character)
{
if (!_actorName) return;
if (string.IsNullOrWhiteSpace(character.key))
{
_actorName.transform.parent.gameObject.SetActive(false);
}
else
{
_actorName.transform.parent.localPosition =
character.key == "me" ? new Vector3(310, 95, 0) : new Vector3(-458, 95, 0);
_actorName.transform.parent.gameObject.SetActive(true);
_actorName.text = character.GetActorName();
}
}
private void HideActorName()
{
_actorName.transform.parent.gameObject.SetActive(false);
}
}
}