更新
This commit is contained in:
Binary file not shown.
@@ -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:
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<DialogViewType>(viewerTypeStr);
|
||||
DialogCanvasManager.Instance.SwitchDialogView(viewType);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -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控制
|
||||
|
||||
/// <summary>
|
||||
@@ -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
|
||||
|
||||
/// <summary>
|
||||
/// 跳到下一句
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -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<bool> isAvailable);
|
||||
|
||||
static ILineAdvanceHandler Create(bool autoMode)
|
||||
{
|
||||
if (!IsInputAvailable())
|
||||
return autoMode ? new AutoAdvanceHandler() : new DefaultAdvanceHandler();
|
||||
}
|
||||
}
|
||||
|
||||
public class DefaultAdvanceHandler : ILineAdvanceHandler
|
||||
{
|
||||
public void Handle(LineSyncToken token, Func<bool> 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<bool> 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<bool> 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
|
||||
}
|
||||
}
|
||||
@@ -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<DialogViewType, ILineView> _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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc70491af0c642d28147d3dbf6a70ca6
|
||||
timeCreated: 1761551427
|
||||
@@ -11,65 +11,65 @@ namespace AibisDream
|
||||
/// </summary>
|
||||
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<int> 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<int> onOptionSelected)
|
||||
// {
|
||||
// Debug.Log($"[选项显示] ===== 显示 {dialogueOptions.Length} 个选项 =====");
|
||||
// EnumEventSystem.Global.Send(DialogEventEnum.OptionShow);
|
||||
// var options = DialogOption.GeneOptions(dialogueOptions, onOptionSelected);
|
||||
// DialogCanvasManager.Instance.ShowOptions(options);
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -171,7 +171,6 @@ namespace AibisDream.FixSystem
|
||||
// 加载气泡
|
||||
var data = FixSystemCenter.SystemDic.Get<ScreenSystem>().BubbleSlotGroup.CollectData();
|
||||
BubbleGroup.Instance.LoadBubbles(data);
|
||||
DialogCanvasManager.Instance.SwitchDialogView(DialogViewType.StandardBubble);
|
||||
|
||||
// 开启交互
|
||||
bodyModuleSystem.EnableSystem();
|
||||
|
||||
@@ -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<ScreenSystem>();
|
||||
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<TypewriterByCharacter>();
|
||||
// 估算文本高度
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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<GameObject>(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<LocalizedText>();
|
||||
// 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<RectTransform>());
|
||||
// }
|
||||
|
||||
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<TMP_Text>();
|
||||
task.text = $"\u25cf {dialogLine}";
|
||||
|
||||
_taskDict[lineId] = taskItem;
|
||||
EnumEventSystem.Global.Send(DialogEventEnum.LineShown);
|
||||
nextStep.Invoke();
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(_taskListParent.GetComponent<RectTransform>());
|
||||
}
|
||||
|
||||
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<TMP_Text>();
|
||||
task.text = $"\u25cf {token.lineInfo.lineText}";
|
||||
|
||||
_taskDict[token.lineInfo.lineId] = taskItem;
|
||||
token.ForceAdvance();
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(_taskListParent.GetComponent<RectTransform>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<PlayToolPanel>().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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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,
|
||||
|
||||
@@ -13,7 +13,6 @@ namespace AibisDream
|
||||
public override void OnSingletonInit()
|
||||
{
|
||||
// 加载气泡
|
||||
DialogCanvasManager.Instance.SwitchDialogView(DialogViewType.StandardBubble);
|
||||
BubbleGroup.Instance.LoadBubbles(bubbleSlotGroup.CollectData());
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,11 @@ namespace AibisDream
|
||||
_stringEvent.SetEntry(getBool.Invoke() ? data.trueKey : data.falseKey);
|
||||
}
|
||||
}
|
||||
|
||||
public void FreshState()
|
||||
{
|
||||
AfterClick();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
||||
@@ -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<CursorManager>
|
||||
{
|
||||
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, DialogText>(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, DialogText>(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, IInteraction>(TriggerEnum.PointerEnter, OnPointerEnter));
|
||||
_unRegisters.Add(
|
||||
EnumEventSystem.Global.Register<TriggerEnum, IInteraction>(TriggerEnum.PointerExit, OnPointerExit));
|
||||
_unRegisters.Add(
|
||||
EnumEventSystem.Global.Register<TriggerEnum, IInteraction>(TriggerEnum.PointerDown, OnPointerDown));
|
||||
_unRegisters.Add(
|
||||
EnumEventSystem.Global.Register<TriggerEnum, IInteraction>(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 指针切换
|
||||
|
||||
/// <summary>
|
||||
/// 直接切指针
|
||||
/// </summary>
|
||||
/// <param name="sprite">指针图片</param>
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<BubbleGroup>, IDialogView
|
||||
public class BubbleGroup : Singleton<BubbleGroup>, IDialogView, ILineView
|
||||
{
|
||||
[SerializeField] private TMP_Text widthEstimation;
|
||||
[SerializeField] private CenterBubble centerBubble;
|
||||
|
||||
private Dictionary<ActorRole, Bubble[]> _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
|
||||
}
|
||||
|
||||
@@ -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<DialogCanvasManager>
|
||||
{
|
||||
#region 引用
|
||||
|
||||
private readonly Dictionary<DialogViewType, IDialogView> _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<IUnRegister> _rmvList = new();
|
||||
|
||||
public override void OnSingletonInit()
|
||||
{
|
||||
InitEvent();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// 默认对话框直接加载
|
||||
var centerText = transform.Find("Center Text").GetComponent<IDialogView>();
|
||||
RegisterDialogView(DialogViewType.CenterText, centerText);
|
||||
var centerOption = transform.Find("Center Option").GetComponent<IDialogView>();
|
||||
RegisterDialogView(DialogViewType.CenterOption, centerOption);
|
||||
var bubbleGroup = transform.Find("Bubble Group").GetComponent<IDialogView>();
|
||||
RegisterDialogView(DialogViewType.StandardBubble, bubbleGroup);
|
||||
|
||||
_defaultView = _dialogViewDict[DialogViewType.StandardBubble];
|
||||
}
|
||||
|
||||
private void InitEvent()
|
||||
{
|
||||
// 记录相关
|
||||
_rmvList.Add(
|
||||
EnumEventSystem.Global.Register<DialogEventEnum, DialogText>(DialogEventEnum.LineStart,
|
||||
AddDialogueLine));
|
||||
_rmvList.Add(
|
||||
EnumEventSystem.Global.Register<DialogEventEnum, DialogText>(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 对话框相关处理
|
||||
|
||||
/// <summary>
|
||||
/// 注册对话框
|
||||
/// </summary>
|
||||
/// <param name="viewType"></param>
|
||||
/// <param name="dialogView"></param>
|
||||
public void RegisterDialogView(DialogViewType viewType, IDialogView dialogView)
|
||||
{
|
||||
_dialogViewDict.Add(viewType, dialogView);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注销对话框
|
||||
/// </summary>
|
||||
/// <param name="viewType"></param>
|
||||
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<RecordPanel>();
|
||||
|
||||
/// <summary>
|
||||
/// 记录对话
|
||||
/// </summary>
|
||||
/// <param name="line">对话</param>
|
||||
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<DialogViewType, IDialogView> _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<IUnRegister> _rmvList = new();
|
||||
//
|
||||
// public override void OnSingletonInit()
|
||||
// {
|
||||
// InitEvent();
|
||||
// }
|
||||
//
|
||||
// private void Start()
|
||||
// {
|
||||
// // 默认对话框直接加载
|
||||
// var centerText = transform.Find("Center Text").GetComponent<IDialogView>();
|
||||
// RegisterDialogView(DialogViewType.CenterText, centerText);
|
||||
// var centerOption = transform.Find("Center Option").GetComponent<IDialogView>();
|
||||
// RegisterDialogView(DialogViewType.CenterOption, centerOption);
|
||||
// var bubbleGroup = transform.Find("Bubble Group").GetComponent<IDialogView>();
|
||||
// RegisterDialogView(DialogViewType.StandardBubble, bubbleGroup);
|
||||
//
|
||||
// _defaultView = _dialogViewDict[DialogViewType.StandardBubble];
|
||||
// }
|
||||
//
|
||||
// private void InitEvent()
|
||||
// {
|
||||
// // 记录相关
|
||||
// _rmvList.Add(
|
||||
// EnumEventSystem.Global.Register<DialogEventEnum, DialogText>(DialogEventEnum.LineStart,
|
||||
// AddDialogueLine));
|
||||
// _rmvList.Add(
|
||||
// EnumEventSystem.Global.Register<DialogEventEnum, DialogText>(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 对话框相关处理
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 注册对话框
|
||||
// /// </summary>
|
||||
// /// <param name="viewType"></param>
|
||||
// /// <param name="dialogView"></param>
|
||||
// public void RegisterDialogView(DialogViewType viewType, IDialogView dialogView)
|
||||
// {
|
||||
// _dialogViewDict.Add(viewType, dialogView);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 注销对话框
|
||||
// /// </summary>
|
||||
// /// <param name="viewType"></param>
|
||||
// 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<RecordPanel>();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 记录对话
|
||||
// /// </summary>
|
||||
// /// <param name="line">对话</param>
|
||||
// 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
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using AibisDream.Kit;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class DialogUIManager : Singleton<DialogUIManager>
|
||||
{
|
||||
private CanvasGroup _canvasGroup;
|
||||
|
||||
[SerializeField] private LineRunner lineView;
|
||||
[SerializeField] private OptionView optionView;
|
||||
|
||||
public override void OnSingletonInit()
|
||||
{
|
||||
_canvasGroup = GetComponent<CanvasGroup>();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a38dd6a979b842b280fb73c921999a69
|
||||
timeCreated: 1761295222
|
||||
@@ -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<Button>().onClick.AddListener(OpenRecordPanel);
|
||||
|
||||
// 自动跳过和快进包括状态变换
|
||||
var auto = topBar.Find("Auto Skip").GetComponent<BoolButton>();
|
||||
auto.OnClick.AddListener(AutoSkip);
|
||||
auto.getBool = () => DialogController.Instance.autoRunMode;
|
||||
|
||||
var ffwd = topBar.Find("Quick Forward").GetComponent<BoolButton>();
|
||||
ffwd.OnClick.AddListener(QuickForward);
|
||||
ffwd.getBool = () => DialogController.Instance.quickRunMode;
|
||||
_autoBtn = topBar.Find("Auto Skip").GetComponent<BoolButton>();
|
||||
_autoBtn.OnClick.AddListener(AutoSkip);
|
||||
_autoBtn.getBool = () => DialogController.Instance.advanceMode.CurrentMode == AdvanceModeEnum.Auto;
|
||||
|
||||
_ffwdBtn = topBar.Find("Quick Forward").GetComponent<BoolButton>();
|
||||
_ffwdBtn.OnClick.AddListener(QuickForward);
|
||||
_ffwdBtn.getBool = () => DialogController.Instance.advanceMode.CurrentMode == AdvanceModeEnum.Quick;
|
||||
}
|
||||
|
||||
private void AutoSkip()
|
||||
{
|
||||
DialogController.Instance.autoRunMode = !DialogController.Instance.autoRunMode;
|
||||
DialogController.Instance.SwitchAutoMode();
|
||||
_autoBtn.FreshState();
|
||||
_ffwdBtn.FreshState();
|
||||
}
|
||||
|
||||
private void QuickForward()
|
||||
{
|
||||
DialogController.Instance.quickRunMode = !DialogController.Instance.quickRunMode;
|
||||
|
||||
Time.timeScale = DialogController.Instance.quickRunMode ? 8f : 1f;
|
||||
DialogController.Instance.SwitchQuickMode();
|
||||
_ffwdBtn.FreshState();
|
||||
_autoBtn.FreshState();
|
||||
}
|
||||
|
||||
private void OpenSettingPanel()
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.VisualScripting;
|
||||
@@ -72,6 +71,21 @@ namespace AibisDream.Utility
|
||||
return target;
|
||||
}
|
||||
|
||||
public static int Limit(int target, int max, int min)
|
||||
{
|
||||
if (target <= min)
|
||||
{
|
||||
return min;
|
||||
}
|
||||
|
||||
if (target >= max)
|
||||
{
|
||||
return max;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 步进循环
|
||||
/// </summary>
|
||||
@@ -194,64 +208,6 @@ namespace AibisDream.Utility
|
||||
return textArr.Length > 1 ? textArr[1].Trim() : lineText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拆分字符串为若干行
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="maxCharsPerLine"></param>
|
||||
/// <returns></returns>
|
||||
public static string SplitString(string input, int maxCharsPerLine)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input) || maxCharsPerLine <= 0)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
var result = new StringBuilder();
|
||||
var lines = input.Replace("<br>", "\n").Split('\n');
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var currentIndex = 0;
|
||||
|
||||
while (currentIndex < line.Length)
|
||||
{
|
||||
var length = Math.Min(maxCharsPerLine, line.Length - currentIndex);
|
||||
var substring = line.Substring(currentIndex, length);
|
||||
|
||||
// 检查是否需要调整长度以避免在单词中间断开
|
||||
if (currentIndex + length < line.Length && !char.IsWhiteSpace(line[currentIndex + length]) &&
|
||||
!char.IsPunctuation(line[currentIndex + length]))
|
||||
{
|
||||
var lastSpace = substring.LastIndexOf(' ');
|
||||
if (lastSpace > 0)
|
||||
{
|
||||
length = lastSpace;
|
||||
substring = line.Substring(currentIndex, length);
|
||||
}
|
||||
}
|
||||
|
||||
result.Append(substring.TrimStart());
|
||||
currentIndex += length;
|
||||
|
||||
if (currentIndex < line.Length)
|
||||
{
|
||||
result.Append('\n');
|
||||
}
|
||||
}
|
||||
|
||||
result.Append('\n');
|
||||
}
|
||||
|
||||
// Remove the last '\n' if needed
|
||||
if (result.Length > 0)
|
||||
{
|
||||
result.Length--;
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public static Vector2 GetPivotByType(PivotType pivotType)
|
||||
{
|
||||
return pivotType switch
|
||||
|
||||
@@ -62,15 +62,21 @@ namespace AibisDream.Utility
|
||||
#endregion
|
||||
|
||||
#region 动画配置
|
||||
|
||||
public const float TweenEndY = -10;
|
||||
public const float FallSpeed = 10;
|
||||
|
||||
public const float TargetAspect = 16f / 9f;
|
||||
|
||||
public const float PanelDelayDuration = 0.4f;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 文字速度配置 (毫秒)
|
||||
|
||||
public const int CharacterDelayTime = 20;
|
||||
public const int LineMaxDelay = 1000;
|
||||
public const int LineMinDelay = 200;
|
||||
public const int AutoHideDelay = 300;
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user