From 046f262b11464775ef3613a6bc5a629177a3ceae Mon Sep 17 00:00:00 2001 From: bottlefish <781230111@qq.com> Date: Sun, 26 Jul 2026 23:43:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(dialog):=20=E6=94=AF=E6=8C=81=E5=8F=99?= =?UTF-8?q?=E4=BA=8B=E6=96=87=E6=9C=AC=E8=AF=AD=E4=B9=89=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E5=B1=95=E5=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- .../Common/NarrativeTextStyleConfig.asset | 21 +++++ .../NarrativeTextStyleConfig.asset.meta | 8 ++ .../AibisDream.Menus/AibisAssetMenus.cs | 1 + .../Dialog System/AibisLineProvider.cs | 7 +- .../Dialog System/NarrativeTextStyleConfig.cs | 78 +++++++++++++++++++ .../NarrativeTextStyleConfig.cs.meta | 11 +++ 6 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 Assets/GameContent/Common/NarrativeTextStyleConfig.asset create mode 100644 Assets/GameContent/Common/NarrativeTextStyleConfig.asset.meta create mode 100644 Assets/Scripts/Dialog System/NarrativeTextStyleConfig.cs create mode 100644 Assets/Scripts/Dialog System/NarrativeTextStyleConfig.cs.meta diff --git a/Assets/GameContent/Common/NarrativeTextStyleConfig.asset b/Assets/GameContent/Common/NarrativeTextStyleConfig.asset new file mode 100644 index 000000000..cab9519cb --- /dev/null +++ b/Assets/GameContent/Common/NarrativeTextStyleConfig.asset @@ -0,0 +1,21 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0df9c4430661480e9c647ea7e22a92b6, type: 3} + m_Name: NarrativeTextStyleConfig + m_EditorClassIdentifier: + _asideColor: {r: 0.37254903, g: 0.37254903, b: 0.37254903, a: 1} + _termColor: {r: 0.32156864, g: 0.7137255, b: 1, a: 1} + _keyColor: {r: 1, g: 0.69803923, b: 0, a: 1} + _commaPauseSeconds: 0.2 + _ulmEffectPrefix: '[[vertexp d=0.05 bot]]' + _jokeOpenTag: + _jokeCloseTag: diff --git a/Assets/GameContent/Common/NarrativeTextStyleConfig.asset.meta b/Assets/GameContent/Common/NarrativeTextStyleConfig.asset.meta new file mode 100644 index 000000000..c886ed5c2 --- /dev/null +++ b/Assets/GameContent/Common/NarrativeTextStyleConfig.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b14d9162528749f68d1229a5de940dab +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/AibisDream.Menus/AibisAssetMenus.cs b/Assets/Scripts/AibisDream.Menus/AibisAssetMenus.cs index 8e291fec3..044cf2672 100644 --- a/Assets/Scripts/AibisDream.Menus/AibisAssetMenus.cs +++ b/Assets/Scripts/AibisDream.Menus/AibisAssetMenus.cs @@ -8,6 +8,7 @@ namespace AibisDream public const string Root = "AIBIS"; public const string NarrativeTalkScene = Root + "/叙事/对话场景"; + public const string NarrativeTextStyle = Root + "/叙事/文本样式"; public const string FrameAnimationGraph = Root + "/角色动画/帧动画 Graph"; public const string FrameClip = Root + "/角色动画/帧动画 Clip"; public const string BubbleStyle = Root + "/对话 UI/气泡样式"; diff --git a/Assets/Scripts/Dialog System/AibisLineProvider.cs b/Assets/Scripts/Dialog System/AibisLineProvider.cs index d6c648f66..825e9baef 100644 --- a/Assets/Scripts/Dialog System/AibisLineProvider.cs +++ b/Assets/Scripts/Dialog System/AibisLineProvider.cs @@ -29,6 +29,9 @@ namespace AibisDream [SerializeField, Language] private string _fallbackLocaleCode = System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName; + [SerializeField] + private NarrativeTextStyleConfig _narrativeTextStyle; + public string AssetLocaleCode { get => _assetLocaleCode; @@ -82,7 +85,9 @@ namespace AibisDream line.Substitutions[i] = LocalizationKit.LocalizeParam(line.Substitutions[i]); } - // 保留旧 LocalisedLineProvider 的文本转义处理 + // 先展开项目级语义标记,再保留旧 LocalisedLineProvider 的文本转义处理。 + // ULM 的 [[vertexp ...]] 会由 Escape 转成 Text Animator 使用的花括号标签。 + text = NarrativeTextStyleExpander.Expand(text, _narrativeTextStyle); text = CommonUtil.Escape(text); var parseResult = lineParser.ParseString(Yarn.Markup.LineParser.ExpandSubstitutions(text, line.Substitutions), LocaleCode); diff --git a/Assets/Scripts/Dialog System/NarrativeTextStyleConfig.cs b/Assets/Scripts/Dialog System/NarrativeTextStyleConfig.cs new file mode 100644 index 000000000..6de5f1b78 --- /dev/null +++ b/Assets/Scripts/Dialog System/NarrativeTextStyleConfig.cs @@ -0,0 +1,78 @@ +using System.Globalization; +using UnityEngine; + +namespace AibisDream +{ + [CreateAssetMenu( + fileName = "NarrativeTextStyleConfig", + menuName = AibisAssetMenus.NarrativeTextStyle)] + public sealed class NarrativeTextStyleConfig : ScriptableObject + { + [Header("语义颜色")] + [SerializeField] private Color _asideColor = new Color32(0x5F, 0x5F, 0x5F, 0xFF); + [SerializeField] private Color _termColor = new Color32(0x52, 0xB6, 0xFF, 0xFF); + [SerializeField] private Color _keyColor = new Color32(0xFF, 0xB2, 0x00, 0xFF); + + [Header("节奏与效果")] + [SerializeField, Min(0f)] private float _commaPauseSeconds = 0.2f; + [SerializeField] private string _ulmEffectPrefix = "[[vertexp d=0.05 bot]]"; + [SerializeField] private string _jokeOpenTag = ""; + [SerializeField] private string _jokeCloseTag = ""; + + public Color AsideColor => _asideColor; + public Color TermColor => _termColor; + public Color KeyColor => _keyColor; + public float CommaPauseSeconds => _commaPauseSeconds; + public string UlmEffectPrefix => _ulmEffectPrefix; + public string JokeOpenTag => _jokeOpenTag; + public string JokeCloseTag => _jokeCloseTag; + } + + public static class NarrativeTextStyleExpander + { + private static readonly Color DefaultAsideColor = new Color32(0x5F, 0x5F, 0x5F, 0xFF); + private static readonly Color DefaultTermColor = new Color32(0x52, 0xB6, 0xFF, 0xFF); + private static readonly Color DefaultKeyColor = new Color32(0xFF, 0xB2, 0x00, 0xFF); + + public static string Expand(string text, NarrativeTextStyleConfig config) + { + if (string.IsNullOrEmpty(text)) + { + return text; + } + + Color asideColor = config != null ? config.AsideColor : DefaultAsideColor; + Color termColor = config != null ? config.TermColor : DefaultTermColor; + Color keyColor = config != null ? config.KeyColor : DefaultKeyColor; + float commaPause = config != null ? config.CommaPauseSeconds : 0.2f; + string ulmPrefix = config != null + ? config.UlmEffectPrefix + : "[[vertexp d=0.05 bot]]"; + string jokeOpen = config != null + ? config.JokeOpenTag + : ""; + string jokeClose = config != null ? config.JokeCloseTag : ""; + + return text + .Replace("[[aside]]", ColorOpen(asideColor)) + .Replace("[[/aside]]", "") + .Replace("[[term]]", ColorOpen(termColor)) + .Replace("[[/term]]", "") + .Replace("[[key]]", ColorOpen(keyColor)) + .Replace("[[/key]]", "") + .Replace( + "[[comma-pause]]", + $"") + .Replace("[[ulm]]", ulmPrefix) + .Replace("[[joke]]", jokeOpen) + .Replace("[[/joke]]", jokeClose); + } + + private static string ColorOpen(Color color) + { + // This runs after Yarn has parsed the source, so the hash must not + // carry Yarn's source-level escape into TextMesh Pro. + return $""; + } + } +} diff --git a/Assets/Scripts/Dialog System/NarrativeTextStyleConfig.cs.meta b/Assets/Scripts/Dialog System/NarrativeTextStyleConfig.cs.meta new file mode 100644 index 000000000..427912324 --- /dev/null +++ b/Assets/Scripts/Dialog System/NarrativeTextStyleConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0df9c4430661480e9c647ea7e22a92b6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: