diff --git a/Assets/RawResources/Icon/Peipeiicon.png b/Assets/RawResources/Icon/Peipeiicon.png deleted file mode 100644 index e21291a24..000000000 --- a/Assets/RawResources/Icon/Peipeiicon.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e8f8de00d0bf16276ed9d5523767bc761d5a0f2eba47091a8fb2cc8c4da52dad -size 1173632 diff --git a/Assets/RawResources/Icon/Peipeiicon.png.meta b/Assets/RawResources/Icon/Peipeiicon.png.meta deleted file mode 100644 index 8a4e24d0e..000000000 --- a/Assets/RawResources/Icon/Peipeiicon.png.meta +++ /dev/null @@ -1,153 +0,0 @@ -fileFormatVersion: 2 -guid: b939a31a2f1b6524982f857bf92bf218 -TextureImporter: - internalIDToNameTable: [] - externalObjects: {} - serializedVersion: 12 - mipmaps: - mipMapMode: 0 - enableMipMap: 0 - sRGBTexture: 1 - linearTexture: 0 - fadeOut: 0 - borderMipMap: 0 - mipMapsPreserveCoverage: 0 - alphaTestReferenceValue: 0.5 - mipMapFadeDistanceStart: 1 - mipMapFadeDistanceEnd: 3 - bumpmap: - convertToNormalMap: 0 - externalNormalMap: 0 - heightScale: 0.25 - normalMapFilter: 0 - flipGreenChannel: 0 - isReadable: 0 - streamingMipmaps: 0 - streamingMipmapsPriority: 0 - vTOnly: 0 - ignoreMipmapLimit: 0 - grayScaleToAlpha: 0 - generateCubemap: 6 - cubemapConvolution: 0 - seamlessCubemap: 0 - textureFormat: 1 - maxTextureSize: 2048 - textureSettings: - serializedVersion: 2 - filterMode: 0 - aniso: 1 - mipBias: 0 - wrapU: 1 - wrapV: 1 - wrapW: 1 - nPOTScale: 0 - lightmap: 0 - compressionQuality: 50 - spriteMode: 1 - spriteExtrude: 1 - spriteMeshType: 1 - alignment: 0 - spritePivot: {x: 0.5, y: 0.5} - spritePixelsToUnits: 100 - spriteBorder: {x: 0, y: 0, z: 0, w: 0} - spriteGenerateFallbackPhysicsShape: 1 - alphaUsage: 1 - alphaIsTransparency: 1 - spriteTessellationDetail: -1 - textureType: 8 - textureShape: 1 - singleChannelComponent: 0 - flipbookRows: 1 - flipbookColumns: 1 - maxTextureSizeSet: 0 - compressionQualitySet: 0 - textureFormatSet: 0 - ignorePngGamma: 0 - applyGammaDecoding: 0 - swizzle: 50462976 - cookieLightType: 0 - platformSettings: - - serializedVersion: 3 - buildTarget: DefaultTexturePlatform - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 0 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: WebGL - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Standalone - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Android - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - - serializedVersion: 3 - buildTarget: Server - maxTextureSize: 2048 - resizeAlgorithm: 0 - textureFormat: -1 - textureCompression: 1 - compressionQuality: 50 - crunchedCompression: 0 - allowsAlphaSplitting: 0 - overridden: 0 - ignorePlatformSupport: 0 - androidETC2FallbackOverride: 0 - forceMaximumCompressionQuality_BC6H_BC7: 0 - spriteSheet: - serializedVersion: 2 - sprites: [] - outline: [] - physicsShape: [] - bones: [] - spriteID: 5e97eb03825dee720800000000000000 - internalID: 0 - vertices: [] - indices: - edges: [] - weights: [] - secondaryTextures: [] - nameFileIdTable: {} - mipmapLimitGroupName: - pSDRemoveMatte: 0 - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Render/Renderer2Dtest.asset b/Assets/Render/Renderer2Dtest.asset index fdae0d5da..197d64d62 100644 --- a/Assets/Render/Renderer2Dtest.asset +++ b/Assets/Render/Renderer2Dtest.asset @@ -463,15 +463,19 @@ MonoBehaviour: m_PostInfinity: 2 m_RotationOrder: 4 _filter: - - 0.007228916 - - 0.043749984 - - 0.12409639 - - 0.20444278 - - 0.24096388 - - 0.20444278 - - 0.12409639 - - 0.043749984 - - 0.007228916 + - 0.0048309183 + - 0.016401261 + - 0.04532712 + - 0.08293076 + - 0.12053438 + - 0.14946026 + - 0.1610306 + - 0.14946026 + - 0.12053438 + - 0.08293076 + - 0.04532712 + - 0.016401261 + - 0.0048309183 --- !u!114 &-6086986437317696584 MonoBehaviour: m_ObjectHideFlags: 3 diff --git a/Assets/Scenes/Persistence.unity b/Assets/Scenes/Persistence.unity index 75447296f..ef6671532 100644 --- a/Assets/Scenes/Persistence.unity +++ b/Assets/Scenes/Persistence.unity @@ -1589,7 +1589,6 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - - {fileID: 1584263514} - {fileID: 1936621685} m_Father: {fileID: 1009826577} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -1605,8 +1604,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 8912c53f0d9943940a6bb7e59888ada8, type: 3} m_Name: m_EditorClassIdentifier: - quickRunMode: 0 - autoRunMode: 0 + lineAdvanceInput: {fileID: 1977401368} --- !u!1 &77816930 GameObject: m_ObjectHideFlags: 0 @@ -4707,7 +4705,7 @@ RectTransform: m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 1820.0001, y: 980.2295} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &238296904 MonoBehaviour: @@ -4721,6 +4719,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a76234ef7ee34400b306a4823081ba62, type: 3} m_Name: m_EditorClassIdentifier: + widthEstimation: {fileID: 1318260399} centerBubble: {fileID: 1403558896} --- !u!1 &246580517 GameObject: @@ -6283,7 +6282,7 @@ RectTransform: m_AnchorMin: {x: 1, y: 0.5} m_AnchorMax: {x: 1, y: 0.5} m_AnchoredPosition: {x: 0, y: 540} - m_SizeDelta: {x: 312, y: 150} + m_SizeDelta: {x: 0, y: 150} m_Pivot: {x: 1, y: 1} --- !u!114 &367483173 MonoBehaviour: @@ -10430,9 +10429,9 @@ RectTransform: - {fileID: 576009914} m_Father: {fileID: 367483172} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 188, y: -25} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 64, y: 100} m_Pivot: {x: 1, y: 1} --- !u!222 &640896811 @@ -16373,9 +16372,9 @@ RectTransform: - {fileID: 527148464} m_Father: {fileID: 367483172} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 94, y: -25} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 64, y: 100} m_Pivot: {x: 1, y: 1} --- !u!222 &1164645868 @@ -21688,50 +21687,6 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1563634750} m_CullTransparentMesh: 1 ---- !u!1 &1584263513 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1584263514} - - component: {fileID: 1584263515} - m_Layer: 0 - m_Name: Line View - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1584263514 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1584263513} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 72512886} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1584263515 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1584263513} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 465bacc132ec6ce4e85f8e68354f60ad, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!1 &1586904152 GameObject: m_ObjectHideFlags: 0 @@ -22215,7 +22170,8 @@ GameObject: - component: {fileID: 1604842428} - component: {fileID: 1604842427} - component: {fileID: 1604842426} - - component: {fileID: 1604842430} + - component: {fileID: 1604842431} + - component: {fileID: 1604842432} m_Layer: 5 m_Name: Dialog Canvas m_TagString: Untagged @@ -22308,7 +22264,7 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0, y: 0} ---- !u!114 &1604842430 +--- !u!114 &1604842431 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -22317,13 +22273,23 @@ MonoBehaviour: m_GameObject: {fileID: 1604842425} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c14c52217dac70244b02fe48d9462bae, type: 3} + m_Script: {fileID: 11500000, guid: a38dd6a979b842b280fb73c921999a69, type: 3} m_Name: m_EditorClassIdentifier: - widthEstimation: {fileID: 1318260399} - blockDuration: 0.5 - autoSkipDelay: 1 - autoHideDuration: 0.2 + lineView: {fileID: 1829169897} + optionView: {fileID: 381795663} +--- !u!225 &1604842432 +CanvasGroup: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1604842425} + m_Enabled: 1 + m_Alpha: 1 + m_Interactable: 1 + m_BlocksRaycasts: 1 + m_IgnoreParentGroups: 0 --- !u!1 &1605070473 GameObject: m_ObjectHideFlags: 0 @@ -22441,7 +22407,7 @@ RectTransform: m_AnchorMin: {x: 1, y: 0.5} m_AnchorMax: {x: 1, y: 0.5} m_AnchoredPosition: {x: -20, y: -530} - m_SizeDelta: {x: 101.9, y: 25} + m_SizeDelta: {x: 0, y: 25} m_Pivot: {x: 1, y: 0} --- !u!114 &1609388205 MonoBehaviour: @@ -24679,10 +24645,10 @@ RectTransform: - {fileID: 238296903} m_Father: {fileID: 1604842429} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 100, y: 100} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1829169897 MonoBehaviour: @@ -24696,7 +24662,9 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: f0d1630fcebe4fb38afd0a2bc7b3112b, type: 3} m_Name: m_EditorClassIdentifier: + lineViewTypes: 000000000500000002000000 advanceInput: {fileID: 1977401368} + bubbleGroup: {fileID: 238296904} --- !u!1 &1846916304 GameObject: m_ObjectHideFlags: 0 @@ -25220,9 +25188,9 @@ RectTransform: - {fileID: 1970860741} m_Father: {fileID: 367483172} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 282, y: -25} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 64, y: 100} m_Pivot: {x: 1, y: 1} --- !u!222 &1928871882 @@ -25348,6 +25316,7 @@ MonoBehaviour: dialogueViews: - {fileID: 381795663} - {fileID: 1829169897} + - {fileID: 0} startNode: Start startAutomatically: 0 runSelectedOptionAsLine: 0 @@ -26117,7 +26086,6 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 4269da1f8c364e319da84b5fee61bafe, type: 3} m_Name: m_EditorClassIdentifier: - advanceKey: 8 --- !u!1 &1982630668 GameObject: m_ObjectHideFlags: 0 @@ -28761,7 +28729,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!224 &2135943277 RectTransform: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Dialog System/BaseYarnCommand.cs b/Assets/Scripts/Dialog System/BaseYarnCommand.cs index ed86a73dd..1bf5e48b2 100644 --- a/Assets/Scripts/Dialog System/BaseYarnCommand.cs +++ b/Assets/Scripts/Dialog System/BaseYarnCommand.cs @@ -55,7 +55,7 @@ namespace AibisDream [YarnCommand("hide_dialog")] public static void HideDialog() { - DialogCanvasManager.Instance.HideDialog(); + BubbleGroup.Instance.HideDialog(); } [YarnCommand("fade_in")] @@ -135,13 +135,6 @@ namespace AibisDream return panel.FlashRed(duration); } - [YarnCommand("switch_dialog_viewer")] - public static void SwitchDialogViewer(string viewerTypeStr) - { - var viewType = Enum.Parse(viewerTypeStr); - DialogCanvasManager.Instance.SwitchDialogView(viewType); - } - #endregion } } \ No newline at end of file diff --git a/Assets/Scripts/Dialog System/DialogController.cs b/Assets/Scripts/Dialog System/DialogController.cs index df1d43c72..7453a23a0 100644 --- a/Assets/Scripts/Dialog System/DialogController.cs +++ b/Assets/Scripts/Dialog System/DialogController.cs @@ -2,7 +2,6 @@ using System; using AibisDream.Framework; using AibisDream.Kit; using UnityEngine; -using UnityEngine.Events; using Yarn.Unity; namespace AibisDream @@ -12,12 +11,9 @@ namespace AibisDream private DialogueRunner _dialogueRunner; private LocalisedLineProvider _lineProvider; - # region controller状态标识 + [SerializeField] private LineAdvanceInput lineAdvanceInput; - public bool quickRunMode; - public bool autoRunMode; - - # endregion + public AdvanceMode advanceMode; private void Start() { @@ -34,6 +30,28 @@ namespace AibisDream }); } + private void OnEnable() + { + EnumEventSystem.Global.Register(GameLoopEnum.GameStart, ResetAdvanceMode); + } + + private void OnDisable() + { + EnumEventSystem.Global.UnRegister(GameLoopEnum.GameStart, ResetAdvanceMode); + } + + private void ResetAdvanceMode() + { + advanceMode = new AdvanceMode + { + isAuto = false, + isQuick = false + }; + + Time.timeScale = 1f; + lineAdvanceInput.ResetAdvanceMode(); + } + #region Yarn控制 /// @@ -46,13 +64,12 @@ namespace AibisDream _lineProvider.InitStringTable(yarnProject.name); _dialogueRunner.StartDialogue("Start"); } - + public void StopDialog() { _dialogueRunner.Stop(); StorageSystem.Instance.Clear(); - DialogCanvasManager.Instance.HideDialog(); - DialogCanvasManager.Instance.SwitchDialogView(DialogViewType.StandardBubble); + DialogUIManager.Instance.HideDialog(); } public void LoadDialog(YarnProject yarnProject) @@ -70,13 +87,13 @@ namespace AibisDream Debug.LogWarning($"对话正在运行中,无法启动新节点: {nodeName}"); return; } - + if (CheckIfNodeExistInCurrentYarnProject(nodeName)) { _dialogueRunner.StartDialogue(nodeName); } } - + private bool CheckIfNodeExistInCurrentYarnProject(string nodeName) { YarnProject currentProject = _dialogueRunner.yarnProject; @@ -93,16 +110,56 @@ namespace AibisDream } #endregion - - /// - /// 跳到下一句 - /// - public void JumpLine() + + #region 推进方式修改 + + public void SwitchAutoMode() { - if (!DialogCanvasManager.Instance.TrySkipLine()) + advanceMode.isAuto = !advanceMode.isAuto; + lineAdvanceInput.SwitchAdvanceHandler(advanceMode.CurrentMode); + } + + public void SwitchQuickMode() + { + advanceMode.isQuick = !advanceMode.isQuick; + + lineAdvanceInput.SwitchAdvanceHandler(advanceMode.CurrentMode); + Time.timeScale = advanceMode.CurrentMode == AdvanceModeEnum.Quick ? 8f : 1f; + } + + #endregion + } + + + public struct AdvanceMode + { + public bool isAuto; + public bool isQuick; + + public AdvanceModeEnum CurrentMode + { + get { - DialogCanvasManager.Instance.NextStep(); + if (isAuto) + { + return AdvanceModeEnum.Auto; + } + else if (isQuick) + { + return AdvanceModeEnum.Quick; + } + else + { + return AdvanceModeEnum.Default; + } } } } + + public enum AdvanceModeEnum + { + Default, + Auto, + Quick + } } \ No newline at end of file diff --git a/Assets/Scripts/Dialog System/LineAdvanceInput.cs b/Assets/Scripts/Dialog System/LineAdvanceInput.cs index bfaf6ab49..9c7ff99b9 100644 --- a/Assets/Scripts/Dialog System/LineAdvanceInput.cs +++ b/Assets/Scripts/Dialog System/LineAdvanceInput.cs @@ -1,4 +1,5 @@ -using AibisDream.Framework; +using System; +using AibisDream.Framework; using UnityEngine; namespace AibisDream @@ -11,82 +12,123 @@ namespace AibisDream private bool _isDialog; private LineSyncToken _curSyncToken; + private ILineAdvanceHandler _handler; + #endregion - - [SerializeField] private KeyCode advanceKey; - private void OnEnable() - { - RegisterEvents(); - } - - private void OnDisable() - { - UnRegisterEvents(); - } + private ILineAdvanceHandler _defaultHandler = new DefaultAdvanceHandler(); + private ILineAdvanceHandler _quickHandler; + private ILineAdvanceHandler _autoHandler = new AutoAdvanceHandler(); public void RunLine(LineSyncToken lineSyncEvent) { _curSyncToken = lineSyncEvent; } + + private void Update() + { + _handler.Handle(_curSyncToken, IsInputAvailable); + } + + public void SwitchAdvanceHandler(AdvanceModeEnum advanceMode) + { + _handler = advanceMode switch + { + AdvanceModeEnum.Auto => _autoHandler, + AdvanceModeEnum.Quick => _quickHandler, + AdvanceModeEnum.Default => _defaultHandler, + _ => _defaultHandler, + }; + } + + public void ResetAdvanceMode() + { + _handler = _defaultHandler; + } + + #region 输入事件处理 private bool IsInputAvailable() { return _inGame && _isDialog && _curSyncToken != null && _curSyncToken.state != LineSyncState.Advanced; } - private void OnAdvanceInput() + #endregion + } + + public interface ILineAdvanceHandler + { + void Handle(LineSyncToken token, Func isAvailable); + + static ILineAdvanceHandler Create(bool autoMode) { - if (!IsInputAvailable()) + return autoMode ? new AutoAdvanceHandler() : new DefaultAdvanceHandler(); + } + } + + public class DefaultAdvanceHandler : ILineAdvanceHandler + { + public void Handle(LineSyncToken token, Func isAvailable) + { + if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)) + { + if (isAvailable()) + { + HandleInput(token); + } + } + } + + private void HandleInput(LineSyncToken token) + { + switch (token.state) + { + case LineSyncState.PlayText: + token.TrySkip(); + break; + case LineSyncState.WaitForAdvance: + token.TryAdvance(); + break; + } + } + } + + public class AutoAdvanceHandler : ILineAdvanceHandler + { + public void Handle(LineSyncToken token, Func isAvailable) + { + if (!isAvailable()) { return; } - switch (_curSyncToken.state) + // 如果已经可以继续了,就直接往下 + if (token.state == LineSyncState.WaitForAdvance) { - case LineSyncState.PlayText: - _curSyncToken.TrySkip(); - break; - case LineSyncState.WaitForAdvance: - _curSyncToken.TryAdvance(); - break; + token.TryAdvance(); } } - - private void Update() + } + + public class QuickAdvanceHandler : ILineAdvanceHandler + { + public void Handle(LineSyncToken token, Func isAvailable) { - if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)) + if (!isAvailable()) { - OnAdvanceInput(); + return; + } + + // 加速模式强制快进 + if (token.state == LineSyncState.PlayText) + { + token.TrySkip(); + } + // 如果已经可以继续了,就直接往下 + if (token.state is LineSyncState.AdvanceDelay or LineSyncState.WaitForAdvance) + { + token.ForceAdvance(); } } - - #region 事件处理 - - private IUnRegister[] _unRegisters; - - private void RegisterEvents() - { - _unRegisters = new IUnRegister[6]; - - _unRegisters[0] = EnumEventSystem.Global.Register(GameLoopEnum.GameStart, () => _inGame = true); - _unRegisters[1] = EnumEventSystem.Global.Register(GameLoopEnum.UnPauseGame, () => _inGame = true); - - _unRegisters[2] = EnumEventSystem.Global.Register(GameLoopEnum.GameQuit, () => _inGame = false); - _unRegisters[3] = EnumEventSystem.Global.Register(GameLoopEnum.PauseGame, () => _inGame = false); - - _unRegisters[4] = EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, () => _isDialog = true); - _unRegisters[5] = EnumEventSystem.Global.Register(InteractionEventEnum.DialogEnd, () => _isDialog = true); - } - - private void UnRegisterEvents() - { - foreach (var unRegister in _unRegisters) - { - unRegister.UnRegister(); - } - } - - #endregion } } \ No newline at end of file diff --git a/Assets/Scripts/Dialog System/LineRunner.cs b/Assets/Scripts/Dialog System/LineRunner.cs new file mode 100644 index 000000000..9429bd1cc --- /dev/null +++ b/Assets/Scripts/Dialog System/LineRunner.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using AibisDream.Utility; +using UnityEngine; +using Yarn.Unity; + +namespace AibisDream +{ + public class LineRunner : DialogueViewBase + { + [SerializeField] private DialogViewType[] lineViewTypes; + [SerializeField] private LineAdvanceInput advanceInput; + [SerializeField] private BubbleGroup bubbleGroup; + + private readonly Dictionary _screenViewDict = new(); + + public override void RunLine(LocalizedLine dialogueLine, Action onDialogueLineFinished) + { + LineSyncToken lineSyncEvent; + if (!lineViewTypes.Contains(dialogueLine.GetCharacterVo().dialogViewType)) + { + // 手动推进视图 + lineSyncEvent = new LineSyncToken(dialogueLine, onDialogueLineFinished); + bubbleGroup.RunLine(lineSyncEvent); + } + else + { + // 自动推进视图 + lineSyncEvent = new LineSyncToken(dialogueLine, onDialogueLineFinished, true); + if (_screenViewDict.TryGetValue(dialogueLine.GetCharacterVo().dialogViewType, out var view)) + { + view.RunLine(lineSyncEvent); + } + else + { + Debug.LogWarning($"未注册的视图类型: {dialogueLine.GetCharacterVo().dialogViewType}"); + } + } + + // 最后交给推进处理 + advanceInput.RunLine(lineSyncEvent); + } + + public void RegisterView(DialogViewType dialogViewType, ILineView view) + { + _screenViewDict.Add(dialogViewType, view); + } + + public void UnRegisterView(DialogViewType dialogViewType) + { + _screenViewDict.Remove(dialogViewType); + } + } + + public interface ILineView + { + void RunLine(LineSyncToken token); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Dialog System/LineViewNew.cs.meta b/Assets/Scripts/Dialog System/LineRunner.cs.meta similarity index 100% rename from Assets/Scripts/Dialog System/LineViewNew.cs.meta rename to Assets/Scripts/Dialog System/LineRunner.cs.meta diff --git a/Assets/Scripts/Dialog System/LineSyncToken.cs b/Assets/Scripts/Dialog System/LineSyncToken.cs new file mode 100644 index 000000000..99a538ef4 --- /dev/null +++ b/Assets/Scripts/Dialog System/LineSyncToken.cs @@ -0,0 +1,153 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using AibisDream.Kit; +using AibisDream.Utility; +using UnityEngine; +using Yarn.Unity; + +namespace AibisDream +{ + public class LineSyncToken + { + private Action _nextStep; + private readonly ITextShown _textShown; + + public LineInfo lineInfo; + public LineSyncState state; + public CancellationTokenSource AdvanceDelayToken { get; private set; } + + public event Action SkipTextAnima; + public event Action OnAdvance; + + public LineSyncToken(LocalizedLine lineInfo, Action nextStep, bool isAutoSkip = false) + { + this.lineInfo = LineInfo.Generate(lineInfo); + _nextStep = nextStep; + state = LineSyncState.PlayText; + if (this.lineInfo.isAutoSkip && isAutoSkip) + { + _textShown = new AutoNextTextShown(); + } + else + { + _textShown = new DefaultTextShown(); + } + } + + public void TrySkip() + { + if (state == LineSyncState.PlayText) + { + SkipTextAnima?.Invoke(); + SkipTextAnima = null; + } + else + { + Debug.Log($"line{lineInfo.lineId} 状态为{state.ToString()}, 不能跳过文本"); + } + } + + public void TryAdvance() + { + if (state == LineSyncState.WaitForAdvance) + { + Advance(); + Dispose(); + } + else + { + Debug.Log($"line{lineInfo.lineId} 状态为{state.ToString()}, 不能向前推进"); + } + } + + public void ForceAdvance() + { + // 先中断延时 + AdvanceDelayToken?.Cancel(); + // 推进 + Advance(); + Dispose(); + } + + private void Advance() + { + OnAdvance?.Invoke(); + OnAdvance = null; + _nextStep?.Invoke(); + state = LineSyncState.Advanced; + } + + private void Dispose() + { + _nextStep = null; + SkipTextAnima = null; + } + + public async void TextShown() + { + AdvanceDelayToken = new CancellationTokenSource(); + await _textShown.OnTextShown(this); + } + } + + public struct LineInfo + { + public string lineId; + public string lineText; + public CharacterVo character; + public bool isAutoSkip; + + public static LineInfo Generate(LocalizedLine dialogueLine) + { + return new LineInfo + { + lineId = dialogueLine.TextID, + lineText = dialogueLine.TextWithoutCharacterName.Text, + character = dialogueLine.GetCharacterVo(), + isAutoSkip = dialogueLine.IsAutoSkipLine() + }; + } + + public int CalcDelayTime() + { + var delayTime = lineText.RemoveRichTextTags().Length * ConstRef.CharacterDelayTime; + return CommonUtil.Limit(delayTime, ConstRef.LineMaxDelay, ConstRef.LineMinDelay); + } + } + + public interface ITextShown + { + Task OnTextShown(LineSyncToken token); + } + + public class DefaultTextShown : ITextShown + { + public async Task OnTextShown(LineSyncToken token) + { + token.state = LineSyncState.AdvanceDelay; + await Task.Delay(token.lineInfo.CalcDelayTime(), token.AdvanceDelayToken.Token); + token.state = LineSyncState.WaitForAdvance; + } + } + + public class AutoNextTextShown : ITextShown + { + public async Task OnTextShown(LineSyncToken token) + { + token.state = LineSyncState.AdvanceDelay; + await Task.Delay(token.lineInfo.CalcDelayTime(), token.AdvanceDelayToken.Token); + token.state = LineSyncState.WaitForAdvance; + token.TryAdvance(); + } + } + + public enum LineSyncState + { + Default, + PlayText, + AdvanceDelay, + WaitForAdvance, + Advanced + } +} \ No newline at end of file diff --git a/Assets/Scripts/Dialog System/LineSyncToken.cs.meta b/Assets/Scripts/Dialog System/LineSyncToken.cs.meta new file mode 100644 index 000000000..36059b909 --- /dev/null +++ b/Assets/Scripts/Dialog System/LineSyncToken.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fc70491af0c642d28147d3dbf6a70ca6 +timeCreated: 1761551427 \ No newline at end of file diff --git a/Assets/Scripts/Dialog System/LineView.cs b/Assets/Scripts/Dialog System/LineView.cs index a54033a50..a4696f57c 100644 --- a/Assets/Scripts/Dialog System/LineView.cs +++ b/Assets/Scripts/Dialog System/LineView.cs @@ -11,65 +11,65 @@ namespace AibisDream /// public class LineView : DialogueViewBase { - public override void RunLine(LocalizedLine dialogueLine, Action onDialogueLineFinished) - { - string lineId = dialogueLine.TextID; - string shortText = dialogueLine.TextWithoutCharacterName.Text.Length > 30 - ? dialogueLine.TextWithoutCharacterName.Text.Substring(0, 30) + "..." - : dialogueLine.TextWithoutCharacterName.Text; - - Debug.Log($"[对话流程] [{lineId}] ===== 开始处理 ====="); - Debug.Log($"[对话流程] [{lineId}] 文本内容: {shortText}"); - - EnumEventSystem.Global.Send(DialogEventEnum.LineStart, DialogText.GetLine(dialogueLine)); - - HandleLineOutput(dialogueLine, NextStep); - - if (DialogController.Instance.quickRunMode) - { - Debug.Log($"[快速模式] [{lineId}] ===== 快速处理开始 ====="); - - // 快速模式:直接跳过文本显示并继续 - bool skipResult = DialogCanvasManager.Instance.TrySkipLine(true); - Debug.Log($"[快速模式] [{lineId}] TrySkipLine结果: {skipResult}"); - - EnumEventSystem.Global.Send(DialogEventEnum.LineShown); - Debug.Log($"[快速模式] [{lineId}] LineShown事件已发送"); - - DialogCanvasManager.Instance.NextStep(); - Debug.Log($"[快速模式] [{lineId}] NextStep已调用"); - Debug.Log($"[快速模式] [{lineId}] ===== 快速处理完成 ====="); - } - else - { - Debug.Log($"[正常模式] [{lineId}] 等待用户交互"); - } - - Debug.Log($"[对话流程] [{lineId}] ===== 处理完成 ====="); - return; - - void NextStep() - { - EnumEventSystem.Global.Send(DialogEventEnum.LineEnd); - onDialogueLineFinished(); - } - } - - private void HandleLineOutput(LocalizedLine dialogueLine, Action onDialogueLineFinished) - { - string lineId = dialogueLine.TextID; - Debug.Log($"[文本显示] [{lineId}] 开始显示文本"); - DialogCanvasManager.Instance.ShowLine(dialogueLine.TextWithoutCharacterName.Text, - dialogueLine.GetCharacterVo(), onDialogueLineFinished, dialogueLine.TextID, - dialogueLine.IsAutoSkipLine()); - } - - public override void RunOptions(DialogueOption[] dialogueOptions, Action onOptionSelected) - { - Debug.Log($"[选项显示] ===== 显示 {dialogueOptions.Length} 个选项 ====="); - EnumEventSystem.Global.Send(DialogEventEnum.OptionShow); - var options = DialogOption.GeneOptions(dialogueOptions, onOptionSelected); - DialogCanvasManager.Instance.ShowOptions(options); - } + // public override void RunLine(LocalizedLine dialogueLine, Action onDialogueLineFinished) + // { + // string lineId = dialogueLine.TextID; + // string shortText = dialogueLine.TextWithoutCharacterName.Text.Length > 30 + // ? dialogueLine.TextWithoutCharacterName.Text.Substring(0, 30) + "..." + // : dialogueLine.TextWithoutCharacterName.Text; + // + // Debug.Log($"[对话流程] [{lineId}] ===== 开始处理 ====="); + // Debug.Log($"[对话流程] [{lineId}] 文本内容: {shortText}"); + // + // EnumEventSystem.Global.Send(DialogEventEnum.LineStart, DialogText.GetLine(dialogueLine)); + // + // HandleLineOutput(dialogueLine, NextStep); + // + // if (DialogController.Instance.quickRunMode) + // { + // Debug.Log($"[快速模式] [{lineId}] ===== 快速处理开始 ====="); + // + // // 快速模式:直接跳过文本显示并继续 + // bool skipResult = DialogCanvasManager.Instance.TrySkipLine(true); + // Debug.Log($"[快速模式] [{lineId}] TrySkipLine结果: {skipResult}"); + // + // EnumEventSystem.Global.Send(DialogEventEnum.LineShown); + // Debug.Log($"[快速模式] [{lineId}] LineShown事件已发送"); + // + // DialogCanvasManager.Instance.NextStep(); + // Debug.Log($"[快速模式] [{lineId}] NextStep已调用"); + // Debug.Log($"[快速模式] [{lineId}] ===== 快速处理完成 ====="); + // } + // else + // { + // Debug.Log($"[正常模式] [{lineId}] 等待用户交互"); + // } + // + // Debug.Log($"[对话流程] [{lineId}] ===== 处理完成 ====="); + // return; + // + // void NextStep() + // { + // EnumEventSystem.Global.Send(DialogEventEnum.LineEnd); + // onDialogueLineFinished(); + // } + // } + // + // private void HandleLineOutput(LocalizedLine dialogueLine, Action onDialogueLineFinished) + // { + // string lineId = dialogueLine.TextID; + // Debug.Log($"[文本显示] [{lineId}] 开始显示文本"); + // DialogCanvasManager.Instance.ShowLine(dialogueLine.TextWithoutCharacterName.Text, + // dialogueLine.GetCharacterVo(), onDialogueLineFinished, dialogueLine.TextID, + // dialogueLine.IsAutoSkipLine()); + // } + // + // public override void RunOptions(DialogueOption[] dialogueOptions, Action onOptionSelected) + // { + // Debug.Log($"[选项显示] ===== 显示 {dialogueOptions.Length} 个选项 ====="); + // EnumEventSystem.Global.Send(DialogEventEnum.OptionShow); + // var options = DialogOption.GeneOptions(dialogueOptions, onOptionSelected); + // DialogCanvasManager.Instance.ShowOptions(options); + // } } } \ No newline at end of file diff --git a/Assets/Scripts/Dialog System/LineViewNew.cs b/Assets/Scripts/Dialog System/LineViewNew.cs deleted file mode 100644 index 1a5eed595..000000000 --- a/Assets/Scripts/Dialog System/LineViewNew.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Threading.Tasks; -using AibisDream.Kit; -using AibisDream.Utility; -using UnityEngine; -using Yarn.Unity; - -namespace AibisDream -{ - public class LineViewNew : DialogueViewBase - { - [SerializeField] private LineAdvanceInput advanceInput; - // [SerializeField] private BubbleCenter bubbleCenter; - - public override void RunLine(LocalizedLine dialogueLine, Action onDialogueLineFinished) - { - // 预处理Line和Event - var lineSyncEvent = new LineSyncToken(dialogueLine, onDialogueLineFinished); - // bubbleCenter.RunLine(lineSyncEvent); - advanceInput.RunLine(lineSyncEvent); - } - } - - public class LineSyncToken - { - public LineInfo lineInfo; - public LineSyncState state; - - public Action nextStep; - public event Action SkipTextAnima; - - public LineSyncToken(LocalizedLine lineInfo, Action nextStep) - { - this.lineInfo = LineInfo.Generate(lineInfo); - this.nextStep = nextStep; - state = LineSyncState.PlayText; - } - - public bool TrySkip() - { - if (state == LineSyncState.PlayText) - { - SkipTextAnima?.Invoke(); - SkipTextAnima = null; - return true; - } - else - { - Debug.Log($"line{lineInfo.lineId} 状态为{state.ToString()}, 不能跳过文本"); - return false; - } - } - - public bool TryAdvance() - { - if (state == LineSyncState.WaitForAdvance) - { - nextStep?.Invoke(); - state = LineSyncState.Advanced; - Dispose(); - return true; - } - else - { - Debug.Log($"line{lineInfo.lineId} 状态为{state.ToString()}, 不能向前推进"); - return false; - } - } - - private void Dispose() - { - nextStep = null; - SkipTextAnima = null; - } - - public void TextStart() - { - state = LineSyncState.PlayText; - } - - public void TextShown() - { - state = LineSyncState.AdvanceDelay; - // 延时 - - state = LineSyncState.WaitForAdvance; - } - } - - public struct LineInfo - { - public string lineId; - public string lineText; - public CharacterVo character; - public bool isAutoSkip; - - public static LineInfo Generate(LocalizedLine dialogueLine) - { - return new LineInfo - { - lineId = dialogueLine.TextID, - lineText = dialogueLine.TextWithoutCharacterName.Text, - character = dialogueLine.GetCharacterVo(), - isAutoSkip = dialogueLine.IsAutoSkipLine() - }; - } - } - - public enum LineSyncState - { - PlayText, - AdvanceDelay, - WaitForAdvance, - Advanced - } -} \ No newline at end of file diff --git a/Assets/Scripts/FixSystemNew/FixStateMachine.cs b/Assets/Scripts/FixSystemNew/FixStateMachine.cs index de34f7015..4fe5e72b5 100644 --- a/Assets/Scripts/FixSystemNew/FixStateMachine.cs +++ b/Assets/Scripts/FixSystemNew/FixStateMachine.cs @@ -171,7 +171,6 @@ namespace AibisDream.FixSystem // 加载气泡 var data = FixSystemCenter.SystemDic.Get().BubbleSlotGroup.CollectData(); BubbleGroup.Instance.LoadBubbles(data); - DialogCanvasManager.Instance.SwitchDialogView(DialogViewType.StandardBubble); // 开启交互 bodyModuleSystem.EnableSystem(); diff --git a/Assets/Scripts/FixSystemNew/Screen System/ScreenSystem.cs b/Assets/Scripts/FixSystemNew/Screen System/ScreenSystem.cs index 08f73700b..642a0f139 100644 --- a/Assets/Scripts/FixSystemNew/Screen System/ScreenSystem.cs +++ b/Assets/Scripts/FixSystemNew/Screen System/ScreenSystem.cs @@ -1,18 +1,17 @@ -using System; using System.Collections.Generic; using System.Linq; using AibisDream.Framework; -using AibisDream.Kit; using AibisDream.Utility; using DG.Tweening; using Febucci.UI; +using Febucci.UI.Core; using TMPro; using UnityEngine; using UnityEngine.UI; namespace AibisDream.FixSystem { - public class ScreenSystem : MonoBehaviour, IDialogView + public class ScreenSystem : MonoBehaviour, ILineView { #region 索引 @@ -47,15 +46,15 @@ namespace AibisDream.FixSystem private void Register() { FixSystemCenter.SystemDic.Register(this); - DialogCanvasManager.Instance.RegisterDialogView(DialogViewType.Screen, this); - DialogCanvasManager.Instance.RegisterDialogView(DialogViewType.Task, TaskScreen); + DialogUIManager.Instance.RegisterScreenView(DialogViewType.Screen, this); + DialogUIManager.Instance.RegisterScreenView(DialogViewType.Task, TaskScreen); } private void OnDestroy() { FixSystemCenter.SystemDic.Unregister(); - DialogCanvasManager.Instance.UnregisterDialogView(DialogViewType.Screen); - DialogCanvasManager.Instance.UnregisterDialogView(DialogViewType.Task); + DialogUIManager.Instance.UnRegisterScreenView(DialogViewType.Screen); + DialogUIManager.Instance.UnRegisterScreenView(DialogViewType.Task); } #region 基础功能 @@ -82,25 +81,38 @@ namespace AibisDream.FixSystem } #endregion - - #region 对话框功能实现 - - public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false) + + public void RunLine(LineSyncToken token) { - Debug.Log($"[ScreenSystem] ShowLine - 原始文本: '{dialogLine}'"); - - if (string.IsNullOrWhiteSpace(dialogLine)) + // 空格延长一点避免报错 + if (string.IsNullOrWhiteSpace(token.lineInfo.lineText)) { - dialogLine = " "; - // Debug.Log("[ScreenSystem] ShowLine - 空文本被替换为空格"); + token.lineInfo.lineText = " "; } - ShowTitle(character.GetActorName()); + // 显示标题 + ShowTitle(token.lineInfo.character.GetActorName()); + // 显示文本 + TypewriterCore textItemTypewriter = AddText(token.lineInfo.lineText); + textItemTypewriter.onTextShowed.AddListener(() => OnTextShown(token, textItemTypewriter)); + token.state = LineSyncState.PlayText; + // 强制更新布局 + LayoutRebuilder.ForceRebuildLayoutImmediate(textRoot); + } + + private void OnTextShown(LineSyncToken syncToken, TypewriterCore typewriter) + { + typewriter.onTextShowed.RemoveAllListeners(); + syncToken.TextShown(); + } + + private TypewriterByCharacter AddText(string newLine) + { // 生成新文本组件 var textItem = Instantiate(_textItemPrefab, textRoot); var textItemTypewriter = textItem.GetComponent(); // 估算文本高度 - var newLineNum = EstimateLineNum(dialogLine); + var newLineNum = EstimateLineNum(newLine); var oldLineNum = CalcTotalLineNum(); if (newLineNum + oldLineNum > maxLineNum) { @@ -109,57 +121,10 @@ namespace AibisDream.FixSystem _lineQueue.Enqueue(textItemTypewriter); // 播放文本 - textItemTypewriter.ShowText(dialogLine); - textItemTypewriter.onTextShowed.AddListener(() => AfterLineShown(textItemTypewriter, nextStep)); - - // 强制更新布局 - LayoutRebuilder.ForceRebuildLayoutImmediate(textRoot); - - Debug.Log($"[ScreenSystem] ShowLine - 文本播放开始,nextStep是否为null: {nextStep == null}"); - } + textItemTypewriter.ShowText(newLine); - private void AfterLineShown(TypewriterByCharacter typewriter, Action nextStop) - { - Debug.Log("[ScreenSystem] AfterLineShown - 文本显示完成"); - Debug.Log($"[ScreenSystem] AfterLineShown - nextStop是否为null: {nextStop == null}"); - - EnumEventSystem.Global.Send(DialogEventEnum.LineShown); - ActionKit.Delay(0.1f, () => - { - Debug.Log("[ScreenSystem] AfterLineShown - 延迟结束,调用回调"); - nextStop?.Invoke(); - Debug.Log("[ScreenSystem] AfterLineShown - 回调调用完成"); - }).StartGlobal(); - typewriter.onTextShowed.RemoveAllListeners(); + return textItemTypewriter; } - - public void ShowOptions(DialogOption[] dialogueOptions) - { - Debug.Log("不能在显示屏显示对话"); - } - - public void HideDialog() - { - // HideDialog应该由其他函数控制 - } - - public bool TrySkipLine(bool isAutoSkip) - { - // 这里不能跳过对话 - return true; - } - - public void NextStep() - { - // 这里不能手动跳到下一行 - } - - public void OnLocalizationChanged(string value) - { - // 屏幕不需要本地化 - } - - #endregion private int EstimateLineNum(string text) { diff --git a/Assets/Scripts/FixSystemNew/Screen System/TaskScreen.cs b/Assets/Scripts/FixSystemNew/Screen System/TaskScreen.cs index 7213e77e8..375847214 100644 --- a/Assets/Scripts/FixSystemNew/Screen System/TaskScreen.cs +++ b/Assets/Scripts/FixSystemNew/Screen System/TaskScreen.cs @@ -1,7 +1,5 @@ -using System; using System.Collections.Generic; using AibisDream.Framework; -using AibisDream.Kit; using AibisDream.Utility; using TMPro; using UnityEngine; @@ -9,7 +7,7 @@ using UnityEngine.UI; namespace AibisDream { - public class TaskScreen : MonoBehaviour, IDialogView + public class TaskScreen : MonoBehaviour, ILineView { #region 索引 @@ -24,72 +22,6 @@ namespace AibisDream _taskListParent = transform.Find("Record"); _taskItemPrefab = ResourceKit.LoadAssetSync(ConstRef.TaskItemName); } - - #region 对话框功能实现 - - // TODO 随时切换回头再加,先直接赋值 - // public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false) - // { - // var taskItem = Instantiate(_taskItemPrefab, _taskListParent); - // // 设置本地化数据 - // - // var localize = taskItem.GetComponent(); - // localize.SetLocalizedText(DialogController.Instance.GetCurLocalizedTableName(), lineId); - // _taskDict[lineId] = localize; - // - // EnumEventSystem.Global.Send(DialogEventEnum.LineShown); - // EnumEventSystem.Global.Send(DialogEventEnum.LineEnd); - // nextStep.Invoke(); - // LayoutRebuilder.ForceRebuildLayoutImmediate(_taskListParent.GetComponent()); - // } - - public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, - bool isAutoSkip = false) - { - if (_taskDict.ContainsKey(lineId)) - { - EnumEventSystem.Global.Send(DialogEventEnum.LineShown); - nextStep.Invoke(); - return; - } - - var taskItem = Instantiate(_taskItemPrefab, _taskListParent); - var task = taskItem.GetComponent(); - task.text = $"\u25cf {dialogLine}"; - - _taskDict[lineId] = taskItem; - EnumEventSystem.Global.Send(DialogEventEnum.LineShown); - nextStep.Invoke(); - LayoutRebuilder.ForceRebuildLayoutImmediate(_taskListParent.GetComponent()); - } - - public void ShowOptions(DialogOption[] dialogueOptions) - { - Debug.Log("Task 面板不能显示选项"); - } - - public void HideDialog() - { - // 无法隐藏 - } - - public bool TrySkipLine(bool isForceSkip = false) - { - // 直接继续不跳过 - return true; - } - - public void NextStep() - { - // 这里不能手动跳到下一行 - } - - public void OnLocalizationChanged(string value) - { - // TODO 有需要可以调整文本 - } - - #endregion public void CompleteTask(string lineId) { @@ -107,5 +39,23 @@ namespace AibisDream } _taskDict.Clear(); } + + public void RunLine(LineSyncToken token) + { + if (_taskDict.ContainsKey(token.lineInfo.lineId)) + { + EnumEventSystem.Global.Send(DialogEventEnum.LineShown); + token.ForceAdvance(); + return; + } + + var taskItem = Instantiate(_taskItemPrefab, _taskListParent); + var task = taskItem.GetComponent(); + task.text = $"\u25cf {token.lineInfo.lineText}"; + + _taskDict[token.lineInfo.lineId] = taskItem; + token.ForceAdvance(); + LayoutRebuilder.ForceRebuildLayoutImmediate(_taskListParent.GetComponent()); + } } } diff --git a/Assets/Scripts/Game Loop/GameManager.cs b/Assets/Scripts/Game Loop/GameManager.cs index 5a33a094e..ebbefc377 100644 --- a/Assets/Scripts/Game Loop/GameManager.cs +++ b/Assets/Scripts/Game Loop/GameManager.cs @@ -18,6 +18,8 @@ namespace AibisDream { #region 运行模式相关 + public GameLoopState state; + private TalkSceneSO[] _totalSceneSos; public RunMode runMode; @@ -129,7 +131,7 @@ namespace AibisDream // 音频全部暂停 AudioManager.Instance.PauseAll(); // 关闭Dialog - DialogCanvasManager.Instance.CloseCanvas(); + DialogUIManager.Instance.CloseCanvas(); } public void ContinueGame() @@ -141,7 +143,7 @@ namespace AibisDream // 音频继续 AudioManager.Instance.UnPauseAll(); // 打开Dialog - DialogCanvasManager.Instance.OpenCanvas(); + DialogUIManager.Instance.OpenCanvas(); } public void QuitGame() @@ -177,7 +179,7 @@ namespace AibisDream // 音频继续 AudioManager.Instance.UnPauseAll(); // 打开Dialog - DialogCanvasManager.Instance.OpenCanvas(); + DialogUIManager.Instance.OpenCanvas(); yield return UIManager.Instance.GetPanel().FadeOutAsync(); } @@ -240,6 +242,44 @@ namespace AibisDream { return _currentTalkSceneSo.Value.name; } + + #region 事件处理 + + private IUnRegister[] _unRegisters; + + private void OnEnable() + { + RegisterEvents(); + } + + private void OnDisable() + { + UnRegisterEvents(); + } + + private void RegisterEvents() + { + _unRegisters = new IUnRegister[6]; + + _unRegisters[0] = EnumEventSystem.Global.Register(GameLoopEnum.GameStart, () => state.OnGame(true)); + _unRegisters[1] = EnumEventSystem.Global.Register(GameLoopEnum.PauseGame, () => state.OnPause(true)); + + _unRegisters[2] = EnumEventSystem.Global.Register(GameLoopEnum.GameQuit, () => state.OnGame(false)); + _unRegisters[3] = EnumEventSystem.Global.Register(GameLoopEnum.UnPauseGame, () => state.OnPause(false)); + + _unRegisters[4] = EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, () => state.OnDialog(true)); + _unRegisters[5] = EnumEventSystem.Global.Register(InteractionEventEnum.DialogEnd, () => state.OnDialog(true)); + } + + private void UnRegisterEvents() + { + foreach (var unRegister in _unRegisters) + { + unRegister.UnRegister(); + } + } + + #endregion } /// @@ -287,6 +327,28 @@ namespace AibisDream } } + public struct GameLoopState + { + public bool isInGame; + public bool isInDialog; + public bool isInPause; + + public void OnGame(bool isInGame) + { + this.isInGame = isInGame; + } + + public void OnPause(bool isInPause) + { + this.isInPause = isInPause; + } + + public void OnDialog(bool isInDialog) + { + this.isInDialog = isInDialog; + } + } + public enum RunMode { Product, diff --git a/Assets/Scripts/SubWay/OutsideCenter.cs b/Assets/Scripts/SubWay/OutsideCenter.cs index babcbe6db..afec095e5 100644 --- a/Assets/Scripts/SubWay/OutsideCenter.cs +++ b/Assets/Scripts/SubWay/OutsideCenter.cs @@ -13,7 +13,6 @@ namespace AibisDream public override void OnSingletonInit() { // 加载气泡 - DialogCanvasManager.Instance.SwitchDialogView(DialogViewType.StandardBubble); BubbleGroup.Instance.LoadBubbles(bubbleSlotGroup.CollectData()); } diff --git a/Assets/Scripts/UI/Components/BoolButton.cs b/Assets/Scripts/UI/Components/BoolButton.cs index 6bba7947d..4f49e921a 100644 --- a/Assets/Scripts/UI/Components/BoolButton.cs +++ b/Assets/Scripts/UI/Components/BoolButton.cs @@ -46,6 +46,11 @@ namespace AibisDream _stringEvent.SetEntry(getBool.Invoke() ? data.trueKey : data.falseKey); } } + + public void FreshState() + { + AfterClick(); + } } [Serializable] diff --git a/Assets/Scripts/UI/Cursor/CursorManager.cs b/Assets/Scripts/UI/Cursor/CursorManager.cs index 3cde09319..615fd4e58 100644 --- a/Assets/Scripts/UI/Cursor/CursorManager.cs +++ b/Assets/Scripts/UI/Cursor/CursorManager.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using AibisDream.Framework; using AibisDream.Kit; @@ -12,8 +10,6 @@ namespace AibisDream { public class CursorManager : Singleton { - private const float DelayTime = 0.1f; - [SerializeField] private GameObject border; [Header("指针图片")] public Sprite defaultCursor; @@ -22,7 +18,6 @@ namespace AibisDream private Image _cursor; private GraphicRaycaster _raycaster; - private Sprite _curCursor; private CursorState _stateCache; #region 状态相关 @@ -47,7 +42,7 @@ namespace AibisDream private void InitCursor() { Cursor.visible = false; - SwitchCursor(defaultCursor); + _cursor.sprite = defaultCursor; } private void OnEnable() @@ -76,8 +71,6 @@ namespace AibisDream { // 此处监听所有可能对鼠标状态产生影响的事件 RegisterGameEvent(); - RegisterDialogEvent(); - RegisterTriggerEvent(); } private void RegisterGameEvent() @@ -111,67 +104,12 @@ namespace AibisDream private void OnGameQuit() { - _curCursor = defaultCursor; - _curState = CursorState.Default; _stateCache = CursorState.Default; _isInGame = false; } - private void RegisterDialogEvent() - { - // 对话相关 - _unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineStart, - OnLineStart)); - _unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineShown, () => SwitchCursor(nextTalk))); - _unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineEnd, OnLineEnd)); - _unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.OptionShow, OnOptionShow)); - _unRegisters.Add( - EnumEventSystem.Global.Register(DialogEventEnum.OptionSelected, - OnOptionSelect)); - } - - private void RegisterTriggerEvent() - { - // 交互相关 - _unRegisters.Add(EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, OnInteractiveStart)); - _unRegisters.Add(EnumEventSystem.Global.Register(InteractionEventEnum.DialogEnd, OnInteractiveEnd)); - - _unRegisters.Add( - EnumEventSystem.Global.Register(TriggerEnum.PointerEnter, OnPointerEnter)); - _unRegisters.Add( - EnumEventSystem.Global.Register(TriggerEnum.PointerExit, OnPointerExit)); - _unRegisters.Add( - EnumEventSystem.Global.Register(TriggerEnum.PointerDown, OnPointerDown)); - _unRegisters.Add( - EnumEventSystem.Global.Register(TriggerEnum.PointerUp, OnPointerUp)); - } - - private void Update() - { - UpdateCursor(); - HandleDialog(); - } - - private void UpdateCursor() - { - // 再判断是不是浮在可交互物上 - _cursor.sprite = !_isInGame || IsOverSelected() ? defaultCursor : _curCursor; - } - - private void HandleDialog() - { - if (!_isInGame) return; - if (!Input.GetMouseButtonDown(0) && !Input.GetKeyDown(KeyCode.Space)) return; - - // 控制对话 - if (_isTalking) - { - DialogController.Instance.JumpLine(); - } - } - private bool IsOverSelected() { if (!EventSystem.current.IsPointerOverGameObject()) @@ -200,129 +138,6 @@ namespace AibisDream // 在输入状态,要单独处理 } - - #region 对话相关 - - private void OnLineStart(DialogText line) - { - _isTalking = true; - SwitchCursor(talking); - } - - private void OnLineEnd() - { - StopDelayCursor(); - _switchCoroutine = StartCoroutine(DelayAction(() => - { - _isTalking = false; - _curCursor = defaultCursor; - })); - } - - private void OnOptionShow() - { - _isTalking = true; - SwitchCursor(option); - } - - private void OnOptionSelect(DialogText line) - { - StopDelayCursor(); - _switchCoroutine = StartCoroutine(DelayAction(() => - { - _isTalking = false; - _curCursor = defaultCursor; - })); - } - - #endregion - - #region 交互相关 - - private void OnInteractiveStart() - { - _curState = CursorState.Interactive; - if (EventSystemEx.Instance.pointerOverObj) - { - SwitchCursor(interactive); - } - else - { - SwitchCursor(defaultCursor); - } - } - - private void OnInteractiveEnd() - { - _curState = CursorState.Default; - // 退出时把Cursor置为Default - SwitchCursor(defaultCursor); - } - - private void OnPointerEnter(IInteraction target) - { - if (_curState == CursorState.Interactive && !_isTalking) - { - // 如果不可交互,就显示不可交互的指针 - SwitchCursor(target.IsActive ? interactive : disable); - } - } - - private void OnPointerExit(IInteraction target) - { - if (_curState == CursorState.Interactive && !_isTalking) - { - SwitchCursor(defaultCursor); - } - } - - private void OnPointerDown(IInteraction target) - { - if (_curState == CursorState.Interactive && !_isTalking) - { - SwitchCursor(target.IsActive ? holding : defaultCursor); - } - } - - private void OnPointerUp(IInteraction target) - { - if (_curState == CursorState.Interactive && !_isTalking) - { - // 如果松手时还在物体之上 - SwitchCursor(EventSystemEx.Instance.holdingObj == target.GetGameObject() ? interactive : defaultCursor); - } - } - - #endregion - - #region 指针切换 - - /// - /// 直接切指针 - /// - /// 指针图片 - private void SwitchCursor(Sprite sprite) - { - StopDelayCursor(); - _curCursor = sprite; - } - - private void StopDelayCursor() - { - if (_switchCoroutine != null) - { - StopCoroutine(_switchCoroutine); - _switchCoroutine = null; - } - } - - #endregion - - private static IEnumerator DelayAction(Action action) - { - yield return new WaitForSeconds(DelayTime); - action.Invoke(); - } } public enum CursorState diff --git a/Assets/Scripts/UI/DialogUI/Bubbles/Bubble.cs b/Assets/Scripts/UI/DialogUI/Bubbles/Bubble.cs index b4985cfcf..0b1805c95 100644 --- a/Assets/Scripts/UI/DialogUI/Bubbles/Bubble.cs +++ b/Assets/Scripts/UI/DialogUI/Bubbles/Bubble.cs @@ -140,7 +140,7 @@ namespace AibisDream private void HandleLayout(string line) { // 先去除富文本标签 - var width = DialogCanvasManager.Instance.EstimateTextWidth(line.RemoveRichTextTags(), _lineText.fontSize); + var width = BubbleGroup.Instance.EstimateTextWidth(line.RemoveRichTextTags(), _lineText.fontSize); if (width > maxWidth) { _layoutElement.preferredWidth = maxWidth; diff --git a/Assets/Scripts/UI/DialogUI/Bubbles/BubbleGroup.cs b/Assets/Scripts/UI/DialogUI/Bubbles/BubbleGroup.cs index e729476f2..89984325b 100644 --- a/Assets/Scripts/UI/DialogUI/Bubbles/BubbleGroup.cs +++ b/Assets/Scripts/UI/DialogUI/Bubbles/BubbleGroup.cs @@ -1,18 +1,24 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using AibisDream.Framework; using AibisDream.Kit; +using AibisDream.Utility; +using TMPro; using UnityEngine; namespace AibisDream { - public class BubbleGroup : Singleton, IDialogView + public class BubbleGroup : Singleton, IDialogView, ILineView { + [SerializeField] private TMP_Text widthEstimation; [SerializeField] private CenterBubble centerBubble; private Dictionary _bubbleDict; private BubbleFactory _bubbleFactory; + private CancellationTokenSource _autoHideToken; #region 一些索引 @@ -178,6 +184,10 @@ namespace AibisDream public void RunLine(LineSyncToken syncToken) { + // 先中断原来的事件 + _autoHideToken?.Cancel(); + _autoHideToken = null; + var character = syncToken.lineInfo.character; if (TryGetBubble(character.role, character.bubbleIdx, out var bubble)) @@ -185,9 +195,11 @@ namespace AibisDream // 注册事件 bubble.OnLineShown += syncToken.TextShown; syncToken.SkipTextAnima += () => bubble.SkipLine(); + syncToken.OnAdvance += AfterAdvance; // 播放文字 bubble.ShowActorName(character); bubble.ShowLine(syncToken.lineInfo.lineText); + syncToken.state = LineSyncState.PlayText; // 将非选定的Bubble隐藏 HideDialog(bubble); } @@ -197,6 +209,28 @@ namespace AibisDream HideDialog(); } } + + public float EstimateTextWidth(string text, float fontSize) + { + widthEstimation.fontSize = fontSize; + widthEstimation.text = text; + widthEstimation.ForceMeshUpdate(); + return widthEstimation.preferredWidth; + } + + private async void AfterAdvance() + { + _autoHideToken = new CancellationTokenSource(); + try + { + await Task.Delay(ConstRef.AutoHideDelay, _autoHideToken.Token); + HideDialog(); + } + catch (TaskCanceledException) + { + // 忽略取消 + } + } #endregion } diff --git a/Assets/Scripts/UI/DialogUI/DialogCanvasManager.cs b/Assets/Scripts/UI/DialogUI/DialogCanvasManager.cs index e0741b258..108c85f74 100644 --- a/Assets/Scripts/UI/DialogUI/DialogCanvasManager.cs +++ b/Assets/Scripts/UI/DialogUI/DialogCanvasManager.cs @@ -3,380 +3,355 @@ using System.Collections.Generic; using AibisDream.Framework; using AibisDream.Kit; using AibisDream.UI; -using TMPro; using UnityEngine; namespace AibisDream { public class DialogCanvasManager : Singleton { - #region 引用 - - private readonly Dictionary _dialogViewDict = new(); - private IDialogView _defaultView; - private IDialogView _showingView; - - private IActionController _autoNext; - private IActionController _block; - private IActionController _hideDialog; - - public TMP_Text widthEstimation; - - #endregion - - #region 参数 - - [SerializeField] private float blockDuration; - [SerializeField] private float autoSkipDelay; - [SerializeField] private float autoHideDuration; - - private bool _isNextAutoSkip; - private bool _isNextBlocked; - - #endregion - - private readonly List _rmvList = new(); - - public override void OnSingletonInit() - { - InitEvent(); - } - - private void Start() - { - // 默认对话框直接加载 - var centerText = transform.Find("Center Text").GetComponent(); - RegisterDialogView(DialogViewType.CenterText, centerText); - var centerOption = transform.Find("Center Option").GetComponent(); - RegisterDialogView(DialogViewType.CenterOption, centerOption); - var bubbleGroup = transform.Find("Bubble Group").GetComponent(); - RegisterDialogView(DialogViewType.StandardBubble, bubbleGroup); - - _defaultView = _dialogViewDict[DialogViewType.StandardBubble]; - } - - private void InitEvent() - { - // 记录相关 - _rmvList.Add( - EnumEventSystem.Global.Register(DialogEventEnum.LineStart, - AddDialogueLine)); - _rmvList.Add( - EnumEventSystem.Global.Register(DialogEventEnum.OptionSelected, - AddDialogueLine)); - _rmvList.Add(EnumEventSystem.Global.Register(EventEnum.NextYarn, CleanDialogHistory)); - - // 文本显示事件 - _rmvList.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineShown, OnTextShown)); - _rmvList.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineEnd, OnTextEnd)); - } - - private void OnTextShown() - { - Debug.Log("[事件处理] OnTextShown - 文本显示完成事件"); - - // 在快速模式下,不设置阻塞,因为快速模式会立即处理 - if (DialogController.Instance.quickRunMode) - { - Debug.Log("[事件处理] OnTextShown - 快速模式,跳过阻塞设置"); - return; - } - - // 阻塞部分 - 只在非快速模式下阻塞,确保文本能够显示 - _isNextBlocked = true; - _block = ActionKit.Delay(blockDuration, () => - { - Debug.Log("[事件处理] OnTextShown - 阻塞时间结束"); - _isNextBlocked = false; - _block = null; - } - ).Start(this); - - // 自动跳过部分 - 只在非快速模式下执行 - if (DialogController.Instance.autoRunMode || _isNextAutoSkip) - { - Debug.Log("[事件处理] OnTextShown - 设置自动跳过定时器"); - _autoNext = ActionKit.Delay(autoSkipDelay, () => - { - Debug.Log("[事件处理] OnTextShown - 自动跳过定时器触发"); - _autoNext = null; - NextStep(); - }).Start(this); - _isNextAutoSkip = false; - } - } - - private void OnTextEnd() - { - Debug.Log("[事件处理] OnTextEnd - 文本结束事件"); - - // 清理阻塞定时器 - if (_block != null) - { - Debug.Log("[事件处理] OnTextEnd - 清理阻塞定时器"); - _block.Deinit(); - _block = null; - } - _isNextBlocked = false; - - // 清理自动跳过定时器 - if (_autoNext != null) - { - Debug.Log("[事件处理] OnTextEnd - 清理自动跳过定时器"); - _autoNext.Deinit(); - _autoNext = null; - } - - Debug.Log("[事件处理] OnTextEnd - 清理完成"); - } - - public override void OnSingletonDestroy() - { - // 销毁前处理事件 - _rmvList.ForEach(item => item.UnRegister()); - } - - #region 对话结束后隐藏 - - private void OnEnable() - { - EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, HideDialog); - } - - private void OnDisable() - { - EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, HideDialog); - } - - #endregion - - #region 对话框相关处理 - - /// - /// 注册对话框 - /// - /// - /// - public void RegisterDialogView(DialogViewType viewType, IDialogView dialogView) - { - _dialogViewDict.Add(viewType, dialogView); - } - - /// - /// 注销对话框 - /// - /// - public void UnregisterDialogView(DialogViewType viewType) - { - _dialogViewDict.Remove(viewType); - } - - #endregion - - #region 对话框接口 - - public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, - bool isAutoSkip = false) - { - Debug.Log($"[DialogCanvasManager] ShowLine - 角色对话框类型: {character.dialogViewType}"); - Debug.Log($"[DialogCanvasManager] ShowLine - nextStep是否为null: {nextStep == null}"); - - _isNextAutoSkip = isAutoSkip; - // 根据DialogViewType确定在哪个对话框显示 - if (character.dialogViewType == DialogViewType.Default) - { - Debug.Log("[DialogCanvasManager] ShowLine - 使用默认对话框"); - if (_showingView != _defaultView) - { - _showingView?.HideDialog(); - } - else - { - _hideDialog?.Deinit(); - _hideDialog = null; - } - - _showingView = _defaultView; - - _showingView.ShowLine(dialogLine, character, nextStep, lineId, isAutoSkip); - } - else if (_dialogViewDict.TryGetValue(character.dialogViewType, out var view)) - { - Debug.Log($"[DialogCanvasManager] ShowLine - 使用指定对话框: {view.GetType().Name}"); - if (_showingView != view) - { - _showingView?.HideDialog(); - } - else - { - _hideDialog?.Deinit(); - _hideDialog = null; - } - - _showingView = view; - - // 对于指定了对话框的,就在指定对话框显示 - view.ShowLine(dialogLine, character, nextStep, lineId, isAutoSkip); - } - else - { - Debug.Log($"{character.dialogViewType.ToString()}类型对话框不存在"); - } - - Debug.Log($"[DialogCanvasManager] ShowLine - 当前_showingView类型: {_showingView?.GetType().Name}"); - } - - public void ShowOptions(DialogOption[] dialogueOptions) - { - var viewType = dialogueOptions[0].Character.dialogViewType; - // 根据状况选择不同的选择框 - if (viewType == DialogViewType.Default) - { - if (_showingView != _defaultView) - { - _showingView?.HideDialog(); - } - else - { - _hideDialog?.Deinit(); - _hideDialog = null; - } - _showingView = _defaultView; - - _showingView.ShowOptions(dialogueOptions); - } - else if(_dialogViewDict.TryGetValue(viewType, out var view)) - { - if (_showingView != view) - { - _showingView?.HideDialog(); - } - else - { - _hideDialog?.Deinit(); - _hideDialog = null; - } - _showingView = view; - _showingView.ShowOptions(dialogueOptions); - } - } - - public void HideDialog() - { - _showingView?.HideDialog(); - } - - public bool TrySkipLine(bool isForceSkip = false) - { - string skipType = isForceSkip ? "强制跳过" : "用户跳过"; - Debug.Log($"[跳过操作] {skipType} - 阻塞状态: {_isNextBlocked}"); - - if (_isNextBlocked) - { - Debug.Log("[跳过操作] ❌ 被阻塞,返回true"); - return true; - } - - bool result = _showingView != null && _showingView.TrySkipLine(isForceSkip); - Debug.Log($"[跳过操作] {skipType} - 结果: {(result ? "✅ 成功" : "❌ 失败")}"); - return result; - } - - public void NextStep() - { - Debug.Log("[对话继续] ===== NextStep开始 ====="); - Debug.Log($"[对话继续] 当前显示的对话框类型: {_showingView?.GetType().Name}"); - - // 在快速模式下,不设置延迟隐藏,避免定时器冲突 - if (!DialogController.Instance.quickRunMode) - { - var view = _showingView; - _hideDialog = ActionKit.Delay(autoHideDuration, () => - { - Debug.Log("[对话继续] 延迟隐藏对话框"); - _hideDialog = null; - view?.HideDialog(); - }).Start(this); - } - else - { - Debug.Log("[对话继续] 快速模式,跳过延迟隐藏设置"); - // 清理可能存在的延迟隐藏定时器 - if (_hideDialog != null) - { - _hideDialog.Deinit(); - _hideDialog = null; - } - } - - Debug.Log("[对话继续] 调用对话框NextStep"); - _showingView?.NextStep(); - - Debug.Log("[对话继续] ===== NextStep完成 ====="); - } - - public void OnLocalizationChanged(string value) - { - } - - public void SwitchDialogView(DialogViewType dialogViewType) - { - if (_dialogViewDict.TryGetValue(dialogViewType, out var view)) - { - _defaultView?.HideDialog(); - _showingView?.HideDialog(); - _defaultView = view; - } - else - { - Debug.Log($"{dialogViewType.ToString()}类型对话框不存在"); - } - } - - #endregion - - #region 对话回顾 - - private RecordPanel RecordPanel => UIManager.Instance.GetPanel(); - - /// - /// 记录对话 - /// - /// 对话 - private void AddDialogueLine(DialogText line) - { - if (line.actor.dialogViewType == DialogViewType.Task) - { - return; - } - - RecordPanel.AppendDialogLine(line); - } - - private void CleanDialogHistory() - { - RecordPanel.ClearDialog(); - } - - public void CloseCanvas() - { - gameObject.SetActive(false); - } - - public void OpenCanvas() - { - gameObject.SetActive(true); - } - - #endregion - - public float EstimateTextWidth(string text, float fontSize) - { - widthEstimation.fontSize = fontSize; - widthEstimation.text = text; - widthEstimation.ForceMeshUpdate(); - return widthEstimation.preferredWidth; - } + // #region 引用 + // + // private readonly Dictionary _dialogViewDict = new(); + // private IDialogView _defaultView; + // private IDialogView _showingView; + // + // private IActionController _autoNext; + // private IActionController _block; + // private IActionController _hideDialog; + // + // #endregion + // + // #region 参数 + // + // [SerializeField] private float blockDuration; + // [SerializeField] private float autoSkipDelay; + // [SerializeField] private float autoHideDuration; + // + // private bool _isNextAutoSkip; + // private bool _isNextBlocked; + // + // #endregion + // + // private readonly List _rmvList = new(); + // + // public override void OnSingletonInit() + // { + // InitEvent(); + // } + // + // private void Start() + // { + // // 默认对话框直接加载 + // var centerText = transform.Find("Center Text").GetComponent(); + // RegisterDialogView(DialogViewType.CenterText, centerText); + // var centerOption = transform.Find("Center Option").GetComponent(); + // RegisterDialogView(DialogViewType.CenterOption, centerOption); + // var bubbleGroup = transform.Find("Bubble Group").GetComponent(); + // RegisterDialogView(DialogViewType.StandardBubble, bubbleGroup); + // + // _defaultView = _dialogViewDict[DialogViewType.StandardBubble]; + // } + // + // private void InitEvent() + // { + // // 记录相关 + // _rmvList.Add( + // EnumEventSystem.Global.Register(DialogEventEnum.LineStart, + // AddDialogueLine)); + // _rmvList.Add( + // EnumEventSystem.Global.Register(DialogEventEnum.OptionSelected, + // AddDialogueLine)); + // _rmvList.Add(EnumEventSystem.Global.Register(EventEnum.NextYarn, CleanDialogHistory)); + // + // // 文本显示事件 + // _rmvList.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineShown, OnTextShown)); + // _rmvList.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineEnd, OnTextEnd)); + // } + // + // private void OnTextShown() + // { + // Debug.Log("[事件处理] OnTextShown - 文本显示完成事件"); + // + // // 在快速模式下,不设置阻塞,因为快速模式会立即处理 + // if (DialogController.Instance.quickRunMode) + // { + // Debug.Log("[事件处理] OnTextShown - 快速模式,跳过阻塞设置"); + // return; + // } + // + // // 阻塞部分 - 只在非快速模式下阻塞,确保文本能够显示 + // _isNextBlocked = true; + // _block = ActionKit.Delay(blockDuration, () => + // { + // Debug.Log("[事件处理] OnTextShown - 阻塞时间结束"); + // _isNextBlocked = false; + // _block = null; + // } + // ).Start(this); + // + // // 自动跳过部分 - 只在非快速模式下执行 + // if (DialogController.Instance.autoRunMode || _isNextAutoSkip) + // { + // Debug.Log("[事件处理] OnTextShown - 设置自动跳过定时器"); + // _autoNext = ActionKit.Delay(autoSkipDelay, () => + // { + // Debug.Log("[事件处理] OnTextShown - 自动跳过定时器触发"); + // _autoNext = null; + // NextStep(); + // }).Start(this); + // _isNextAutoSkip = false; + // } + // } + // + // private void OnTextEnd() + // { + // Debug.Log("[事件处理] OnTextEnd - 文本结束事件"); + // + // // 清理阻塞定时器 + // if (_block != null) + // { + // Debug.Log("[事件处理] OnTextEnd - 清理阻塞定时器"); + // _block.Deinit(); + // _block = null; + // } + // _isNextBlocked = false; + // + // // 清理自动跳过定时器 + // if (_autoNext != null) + // { + // Debug.Log("[事件处理] OnTextEnd - 清理自动跳过定时器"); + // _autoNext.Deinit(); + // _autoNext = null; + // } + // + // Debug.Log("[事件处理] OnTextEnd - 清理完成"); + // } + // + // public override void OnSingletonDestroy() + // { + // // 销毁前处理事件 + // _rmvList.ForEach(item => item.UnRegister()); + // } + // + // #region 对话结束后隐藏 + // + // private void OnEnable() + // { + // EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, HideDialog); + // } + // + // private void OnDisable() + // { + // EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, HideDialog); + // } + // + // #endregion + // + // #region 对话框相关处理 + // + // /// + // /// 注册对话框 + // /// + // /// + // /// + // public void RegisterDialogView(DialogViewType viewType, IDialogView dialogView) + // { + // _dialogViewDict.Add(viewType, dialogView); + // } + // + // /// + // /// 注销对话框 + // /// + // /// + // public void UnregisterDialogView(DialogViewType viewType) + // { + // _dialogViewDict.Remove(viewType); + // } + // + // #endregion + // + // #region 对话框接口 + // + // public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, + // bool isAutoSkip = false) + // { + // Debug.Log($"[DialogCanvasManager] ShowLine - 角色对话框类型: {character.dialogViewType}"); + // Debug.Log($"[DialogCanvasManager] ShowLine - nextStep是否为null: {nextStep == null}"); + // + // _isNextAutoSkip = isAutoSkip; + // // 根据DialogViewType确定在哪个对话框显示 + // if (character.dialogViewType == DialogViewType.Default) + // { + // Debug.Log("[DialogCanvasManager] ShowLine - 使用默认对话框"); + // if (_showingView != _defaultView) + // { + // _showingView?.HideDialog(); + // } + // else + // { + // _hideDialog?.Deinit(); + // _hideDialog = null; + // } + // + // _showingView = _defaultView; + // + // _showingView.ShowLine(dialogLine, character, nextStep, lineId, isAutoSkip); + // } + // else if (_dialogViewDict.TryGetValue(character.dialogViewType, out var view)) + // { + // Debug.Log($"[DialogCanvasManager] ShowLine - 使用指定对话框: {view.GetType().Name}"); + // if (_showingView != view) + // { + // _showingView?.HideDialog(); + // } + // else + // { + // _hideDialog?.Deinit(); + // _hideDialog = null; + // } + // + // _showingView = view; + // + // // 对于指定了对话框的,就在指定对话框显示 + // view.ShowLine(dialogLine, character, nextStep, lineId, isAutoSkip); + // } + // else + // { + // Debug.Log($"{character.dialogViewType.ToString()}类型对话框不存在"); + // } + // + // Debug.Log($"[DialogCanvasManager] ShowLine - 当前_showingView类型: {_showingView?.GetType().Name}"); + // } + // + // public void ShowOptions(DialogOption[] dialogueOptions) + // { + // var viewType = dialogueOptions[0].Character.dialogViewType; + // // 根据状况选择不同的选择框 + // if (viewType == DialogViewType.Default) + // { + // if (_showingView != _defaultView) + // { + // _showingView?.HideDialog(); + // } + // else + // { + // _hideDialog?.Deinit(); + // _hideDialog = null; + // } + // _showingView = _defaultView; + // + // _showingView.ShowOptions(dialogueOptions); + // } + // else if(_dialogViewDict.TryGetValue(viewType, out var view)) + // { + // if (_showingView != view) + // { + // _showingView?.HideDialog(); + // } + // else + // { + // _hideDialog?.Deinit(); + // _hideDialog = null; + // } + // _showingView = view; + // _showingView.ShowOptions(dialogueOptions); + // } + // } + // + // public void HideDialog() + // { + // _showingView?.HideDialog(); + // } + // + // public bool TrySkipLine(bool isForceSkip = false) + // { + // string skipType = isForceSkip ? "强制跳过" : "用户跳过"; + // Debug.Log($"[跳过操作] {skipType} - 阻塞状态: {_isNextBlocked}"); + // + // if (_isNextBlocked) + // { + // Debug.Log("[跳过操作] ❌ 被阻塞,返回true"); + // return true; + // } + // + // bool result = _showingView != null && _showingView.TrySkipLine(isForceSkip); + // Debug.Log($"[跳过操作] {skipType} - 结果: {(result ? "✅ 成功" : "❌ 失败")}"); + // return result; + // } + // + // public void NextStep() + // { + // Debug.Log("[对话继续] ===== NextStep开始 ====="); + // Debug.Log($"[对话继续] 当前显示的对话框类型: {_showingView?.GetType().Name}"); + // + // // 在快速模式下,不设置延迟隐藏,避免定时器冲突 + // if (!DialogController.Instance.quickRunMode) + // { + // var view = _showingView; + // _hideDialog = ActionKit.Delay(autoHideDuration, () => + // { + // Debug.Log("[对话继续] 延迟隐藏对话框"); + // _hideDialog = null; + // view?.HideDialog(); + // }).Start(this); + // } + // else + // { + // Debug.Log("[对话继续] 快速模式,跳过延迟隐藏设置"); + // // 清理可能存在的延迟隐藏定时器 + // if (_hideDialog != null) + // { + // _hideDialog.Deinit(); + // _hideDialog = null; + // } + // } + // + // Debug.Log("[对话继续] 调用对话框NextStep"); + // _showingView?.NextStep(); + // + // Debug.Log("[对话继续] ===== NextStep完成 ====="); + // } + // + // public void OnLocalizationChanged(string value) + // { + // } + // + // #endregion + // + // #region 对话回顾 + // + // private RecordPanel RecordPanel => UIManager.Instance.GetPanel(); + // + // /// + // /// 记录对话 + // /// + // /// 对话 + // private void AddDialogueLine(DialogText line) + // { + // if (line.actor.dialogViewType == DialogViewType.Task) + // { + // return; + // } + // + // RecordPanel.AppendDialogLine(line); + // } + // + // private void CleanDialogHistory() + // { + // RecordPanel.ClearDialog(); + // } + // + // public void CloseCanvas() + // { + // gameObject.SetActive(false); + // } + // + // public void OpenCanvas() + // { + // gameObject.SetActive(true); + // } + // + // #endregion } public enum DialogViewType diff --git a/Assets/Scripts/UI/DialogUI/DialogUIManager.cs b/Assets/Scripts/UI/DialogUI/DialogUIManager.cs new file mode 100644 index 000000000..3161a612b --- /dev/null +++ b/Assets/Scripts/UI/DialogUI/DialogUIManager.cs @@ -0,0 +1,44 @@ +using AibisDream.Kit; +using UnityEngine; + +namespace AibisDream +{ + public class DialogUIManager : Singleton + { + private CanvasGroup _canvasGroup; + + [SerializeField] private LineRunner lineView; + [SerializeField] private OptionView optionView; + + public override void OnSingletonInit() + { + _canvasGroup = GetComponent(); + } + + public void CloseCanvas() + { + gameObject.SetActive(false); + } + + public void OpenCanvas() + { + gameObject.SetActive(true); + } + + public void HideDialog() + { + // 关闭所有对话框 + BubbleGroup.Instance.HideDialog(); + } + + public void RegisterScreenView(DialogViewType dialogViewType, ILineView screenView) + { + lineView.RegisterView(dialogViewType, screenView); + } + + public void UnRegisterScreenView(DialogViewType dialogViewType) + { + lineView.UnRegisterView(dialogViewType); + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/UI/DialogUI/DialogUIManager.cs.meta b/Assets/Scripts/UI/DialogUI/DialogUIManager.cs.meta new file mode 100644 index 000000000..c0bdddd3e --- /dev/null +++ b/Assets/Scripts/UI/DialogUI/DialogUIManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a38dd6a979b842b280fb73c921999a69 +timeCreated: 1761295222 \ No newline at end of file diff --git a/Assets/Scripts/UI/Panel/MainPanel.cs b/Assets/Scripts/UI/Panel/MainPanel.cs index 9588c8e82..a3282fae7 100644 --- a/Assets/Scripts/UI/Panel/MainPanel.cs +++ b/Assets/Scripts/UI/Panel/MainPanel.cs @@ -8,6 +8,9 @@ namespace AibisDream.UI public bool IsOpen => gameObject.activeSelf; public bool IsCloseable => false; + private BoolButton _autoBtn; + private BoolButton _ffwdBtn; + #region 面板控制 public void Show() @@ -45,25 +48,27 @@ namespace AibisDream.UI topBar.Find("Record").GetComponent