添加了对话UI,基本完成对话系统设计

This commit is contained in:
SepComet
2026-02-09 12:56:28 +08:00
parent 197ce38315
commit 26b69bc870
46 changed files with 2598 additions and 11 deletions
@@ -0,0 +1,144 @@
using Definition.Enum;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
namespace UI
{
public class BottomDialogForm : DialogFormBase
{
public override DialogFormMode UIMode => DialogFormMode.BottomBox;
[SerializeField] private TMP_Text _speakerNameText;
[SerializeField] private TMP_Text _contentText;
[SerializeField] private Image _leftSprite;
[SerializeField] private Image _rightSprite;
[SerializeField] private int _leftSpritePosition = 450;
[SerializeField] private int _rightSpritePosition = -450;
private readonly int _singleSpeakerCenterPosition = Screen.width / 2;
private string _leftSpeakerToken = string.Empty;
private string _rightSpeakerToken = string.Empty;
public override void StartDialog(DialogFormContext context)
{
if (context == null)
{
Log.Warning("BottomDialogForm start failed. context is null.");
return;
}
_context = context;
string speakerName = NormalizeValue(context.SpeakerName);
if (string.IsNullOrEmpty(speakerName))
{
speakerName = NormalizeValue(context.SpeakerId);
}
if (_speakerNameText != null)
{
_speakerNameText.text = speakerName;
}
if (_contentText != null)
{
_contentText.text = NormalizeValue(context.Text);
}
if (string.IsNullOrEmpty(speakerName))
{
ClearSpeakerState();
ApplySpeakerLayout(false, false);
return;
}
bool isRightSpeaker = context.Direction > 0;
if (isRightSpeaker)
{
_rightSpeakerToken = speakerName;
}
else
{
_leftSpeakerToken = speakerName;
}
bool hasLeftSpeaker = !string.IsNullOrEmpty(_leftSpeakerToken);
bool hasRightSpeaker = !string.IsNullOrEmpty(_rightSpeakerToken);
ApplySpeakerLayout(hasLeftSpeaker, hasRightSpeaker);
}
protected override void OnClose(bool isShutdown, object userData)
{
ClearSpeakerState();
ApplySpeakerLayout(false, false);
base.OnClose(isShutdown, userData);
}
private void ClearSpeakerState()
{
_leftSpeakerToken = string.Empty;
_rightSpeakerToken = string.Empty;
}
private void ApplySpeakerLayout(bool hasLeftSpeaker, bool hasRightSpeaker)
{
if (hasLeftSpeaker && hasRightSpeaker)
{
SetSpriteVisible(_leftSprite, true);
SetSpriteVisible(_rightSprite, true);
SetSpritePosition(_leftSprite.rectTransform, _leftSpritePosition);
SetSpritePosition(_rightSprite.rectTransform, _rightSpritePosition);
return;
}
if (hasLeftSpeaker)
{
SetSpriteVisible(_leftSprite, true);
SetSpriteVisible(_rightSprite, false);
SetSpritePosition(_leftSprite.rectTransform, _singleSpeakerCenterPosition);
return;
}
if (hasRightSpeaker)
{
SetSpriteVisible(_leftSprite, false);
SetSpriteVisible(_rightSprite, true);
SetSpritePosition(_rightSprite.rectTransform, -_singleSpeakerCenterPosition);
return;
}
SetSpriteVisible(_leftSprite, false);
SetSpriteVisible(_rightSprite, false);
}
private static void SetSpriteVisible(Image spriteImage, bool visible)
{
if (spriteImage == null)
{
return;
}
spriteImage.gameObject.SetActive(visible);
}
private static void SetSpritePosition(RectTransform rectTransform, float xPosition)
{
if (rectTransform == null)
{
return;
}
Vector2 anchoredPosition = rectTransform.anchoredPosition;
anchoredPosition.x = xPosition;
rectTransform.anchoredPosition = anchoredPosition;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ea6f55294a4cd2946a83649e7be82314
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,71 @@
using Definition.Enum;
using Event;
using UnityEngine;
namespace UI
{
public abstract class DialogFormBase : UGuiForm
{
[SerializeField] protected float _playSpeed;
protected DialogFormContext _context;
public abstract DialogFormMode UIMode { get; }
public abstract void StartDialog(DialogFormContext context);
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
if (!(userData is DialogFormContext context))
{
return;
}
_context = context;
StartDialog(context);
}
protected override void OnClose(bool isShutdown, object userData)
{
_context = null;
base.OnClose(isShutdown, userData);
}
public void OnClickNextLine()
{
GameEntry.Event.Fire(this, DialogNextLineRequestEventArgs.Create());
}
public void OnClickSkipDialog()
{
GameEntry.Event.Fire(this, DialogSkipRequestEventArgs.Create());
}
public void OnClickStopDialog()
{
GameEntry.Event.Fire(this, DialogStopRequestEventArgs.Create());
}
protected static string NormalizeValue(string value)
{
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
if (string.Equals(value, "Null", System.StringComparison.OrdinalIgnoreCase))
{
return string.Empty;
}
if (string.Equals(value, "None", System.StringComparison.OrdinalIgnoreCase))
{
return string.Empty;
}
return value;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aafc42873758b514282b3a75e3ba4665
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,38 @@
using Definition.Enum;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
namespace UI
{
public class MaskDialogForm : DialogFormBase
{
public override DialogFormMode UIMode => DialogFormMode.Mask;
[SerializeField] private Image _maskImage;
[SerializeField] private TMP_Text _text;
public override void StartDialog(DialogFormContext context)
{
if (context == null)
{
Log.Warning("MaskDialogForm start failed. context is null.");
return;
}
_context = context;
if (_maskImage != null)
{
_maskImage.gameObject.SetActive(true);
}
if (_text != null)
{
_text.text = NormalizeValue(context.Text);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5a63462640e70af40972b9841beafe6c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: