Merge branch 'feature/录制模式相关改动' into 'develop'

fix(dialog): 修复点击 UI 时对话被误推进

See merge request aibis-dream/aibis-dream!738
This commit is contained in:
2026-07-15 08:53:25 +00:00
11 changed files with 1778 additions and 154 deletions
File diff suppressed because it is too large Load Diff
@@ -49,7 +49,7 @@ namespace AibisDream
private void LateUpdate()
{
_handler.Handle(_curSyncToken, IsInputAvailable);
_handler.Handle(_curSyncToken, IsInputAvailable, IsPointerOverUI);
}
public void SwitchAdvanceHandler(AdvanceModeEnum advanceMode)
@@ -77,12 +77,18 @@ namespace AibisDream
&& _curSyncToken.state != LineSyncState.Advanced;
}
private bool IsPointerOverUI()
{
return UIManager.Instance != null
&& UIManager.Instance.IsPointerOverUI(Input.mousePosition);
}
#endregion
}
public interface ILineAdvanceHandler
{
void Handle(LineSyncToken token, Func<bool> isAvailable);
void Handle(LineSyncToken token, Func<bool> isAvailable, Func<bool> isPointerOverUI);
static ILineAdvanceHandler Create(bool autoMode)
{
@@ -92,9 +98,12 @@ namespace AibisDream
public class DefaultAdvanceHandler : ILineAdvanceHandler
{
public void Handle(LineSyncToken token, Func<bool> isAvailable)
public void Handle(LineSyncToken token, Func<bool> isAvailable, Func<bool> isPointerOverUI)
{
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
var pointerAdvance = Input.GetMouseButtonDown(0) && !isPointerOverUI();
var keyboardAdvance = Input.GetKeyDown(KeyCode.Space);
if (pointerAdvance || keyboardAdvance)
{
if (isAvailable())
{
@@ -122,7 +131,7 @@ namespace AibisDream
public class AutoAdvanceHandler : ILineAdvanceHandler
{
public void Handle(LineSyncToken token, Func<bool> isAvailable)
public void Handle(LineSyncToken token, Func<bool> isAvailable, Func<bool> isPointerOverUI)
{
if (!isAvailable())
{
@@ -136,7 +145,10 @@ namespace AibisDream
return;
}
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
var pointerAdvance = Input.GetMouseButtonDown(0) && !isPointerOverUI();
var keyboardAdvance = Input.GetKeyDown(KeyCode.Space);
if (pointerAdvance || keyboardAdvance)
{
HandleInput(token);
}
@@ -161,7 +173,7 @@ namespace AibisDream
public class QuickAdvanceHandler : ILineAdvanceHandler
{
public void Handle(LineSyncToken token, Func<bool> isAvailable)
public void Handle(LineSyncToken token, Func<bool> isAvailable, Func<bool> isPointerOverUI)
{
if (!isAvailable())
{
@@ -180,4 +192,4 @@ namespace AibisDream
}
}
}
}
}
+2 -9
View File
@@ -1,4 +1,3 @@
using AibisDream.Framework;
using TMPro;
using UnityEngine;
@@ -9,17 +8,11 @@ namespace AibisDream.Kit
private void Start()
{
GetComponent<TMP_Text>().text = $"Ver.{Application.version}";
EnumEventSystem.Global.Register<UIEventEnum, bool>(UIEventEnum.RecordingModeChanged, OnRecordingModeChanged);
}
private void OnDestroy()
public void SetVisible(bool visible)
{
EnumEventSystem.Global.UnRegister<UIEventEnum, bool>(UIEventEnum.RecordingModeChanged, OnRecordingModeChanged);
}
private void OnRecordingModeChanged(bool isRecording)
{
gameObject.SetActive(!isRecording);
gameObject.SetActive(visible);
}
}
}
-5
View File
@@ -98,9 +98,4 @@ namespace AibisDream
PauseMenuAmbEnter,
PauseMenuAmbExit,
}
public enum UIEventEnum
{
RecordingModeChanged
}
}
+10 -12
View File
@@ -13,6 +13,7 @@ namespace AibisDream
public Sprite nextTalk, talking, option, interactive, holding, disable;
private Image _cursor;
private bool _cursorVisible = true;
private void Start()
{
@@ -23,29 +24,26 @@ namespace AibisDream
#else
InitCursor();
#endif
EnumEventSystem.Global.Register<UIEventEnum, bool>(UIEventEnum.RecordingModeChanged, OnRecordingModeChanged);
}
private void OnDestroy()
{
EnumEventSystem.Global.UnRegister<UIEventEnum, bool>(UIEventEnum.RecordingModeChanged, OnRecordingModeChanged);
}
private void OnRecordingModeChanged(bool isRecording)
public void SetCursorVisible(bool visible)
{
#if UNITY_ANDROID || UNITY_IOS
return;
#endif
_cursorVisible = visible;
ApplyCursorVisibility();
}
private void ApplyCursorVisibility()
{
if (_cursor != null)
{
_cursor.gameObject.SetActive(!isRecording);
_cursor.gameObject.SetActive(_cursorVisible);
}
if (isRecording)
{
Cursor.visible = false;
}
Cursor.visible = false;
}
private void InitCursor()
@@ -12,8 +12,16 @@ namespace AibisDream
[SerializeField] private OptionView optionView;
[SerializeField] private TMP_Text widthEstimation;
private CanvasGroup _canvasGroup;
public override void OnSingletonInit()
{
_canvasGroup = GetComponent<CanvasGroup>();
if (_canvasGroup == null)
{
_canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
EnumEventSystem.Global.Register<DialogEventEnum, LineInfo>(DialogEventEnum.LineStart, AddDialogueLine);
EnumEventSystem.Global.Register<DialogEventEnum, LineInfo>(DialogEventEnum.OptionSelected, AddDialogueLine);
EnumEventSystem.Global.Register(EventEnum.NextYarn, CleanDialogHistory);
@@ -55,6 +63,19 @@ namespace AibisDream
gameObject.SetActive(true);
}
/// <summary>
/// 仅隐藏对话视觉,不影响打字机、推进与选项交互。
/// </summary>
public void SetDialogVisualVisible(bool visible)
{
if (_canvasGroup == null)
{
_canvasGroup = GetComponent<CanvasGroup>();
}
_canvasGroup.alpha = visible ? 1f : 0f;
}
public void HideDialog()
{
lineView.HideDialog();
-8
View File
@@ -19,14 +19,6 @@ namespace AibisDream.UI
demoTimer.totalTimeInSeconds = time;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.I))
{
variableBar.gameObject.SetActive(!variableBar.gameObject.activeSelf);
}
}
public void Show()
{
gameObject.SetActive(true);
+18
View File
@@ -10,12 +10,15 @@ namespace AibisDream.UI
private BoolButton _autoBtn;
private BoolButton _ffwdBtn;
private Transform _topBar;
private bool _topBarVisible = true;
#region
public void Show()
{
gameObject.SetActive(true);
ApplyTopBarVisibility();
}
public void Hide()
@@ -23,10 +26,25 @@ namespace AibisDream.UI
gameObject.SetActive(false);
}
public void SetTopBarVisible(bool visible)
{
_topBarVisible = visible;
ApplyTopBarVisibility();
}
private void ApplyTopBarVisibility()
{
if (_topBar != null)
{
_topBar.gameObject.SetActive(_topBarVisible);
}
}
#endregion
private void Awake()
{
_topBar = transform.Find("Top Bar");
RegisterButton();
}
@@ -0,0 +1,85 @@
using AibisDream.Kit;
using UnityEngine;
using UnityEngine.UI;
namespace AibisDream.UI
{
/// <summary>
/// 录制 HUD 侧边栏:Ctrl+R 唤出,四个开关独立控制光标、版本号、Top Bar、对话视觉。
/// 挂在 Info Panel 下,与 VariableBar 同类调试 UI,不使用独立 Canvas。
/// UI 层级在 Persistence 场景中配置,不在运行时生成。
/// </summary>
public class RecordingToolPanel : MonoBehaviour
{
[SerializeField] private Toggle showCursorToggle;
[SerializeField] private Toggle showVersionToggle;
[SerializeField] private Toggle showTopBarToggle;
[SerializeField] private Toggle showDialogToggle;
private bool _showCursor = true;
private bool _showVersion = true;
private bool _showTopBar = true;
private bool _showDialog = true;
private VerText _verText;
private void Awake()
{
_verText = FindObjectOfType<VerText>(true);
gameObject.SetActive(false);
BindToggles();
ApplyAll();
}
public void TogglePanel()
{
gameObject.SetActive(!gameObject.activeSelf);
}
private void BindToggles()
{
showCursorToggle.isOn = _showCursor;
showVersionToggle.isOn = _showVersion;
showTopBarToggle.isOn = _showTopBar;
showDialogToggle.isOn = _showDialog;
showCursorToggle.onValueChanged.AddListener(OnShowCursorChanged);
showVersionToggle.onValueChanged.AddListener(OnShowVersionChanged);
showTopBarToggle.onValueChanged.AddListener(OnShowTopBarChanged);
showDialogToggle.onValueChanged.AddListener(OnShowDialogChanged);
}
private void OnShowCursorChanged(bool visible)
{
_showCursor = visible;
CursorManager.Instance?.SetCursorVisible(visible);
}
private void OnShowVersionChanged(bool visible)
{
_showVersion = visible;
_verText?.SetVisible(visible);
}
private void OnShowTopBarChanged(bool visible)
{
_showTopBar = visible;
UIManager.Instance?.GetPanel<MainPanel>()?.SetTopBarVisible(visible);
}
private void OnShowDialogChanged(bool visible)
{
_showDialog = visible;
DialogUIManager.Instance?.SetDialogVisualVisible(visible);
}
private void ApplyAll()
{
OnShowCursorChanged(_showCursor);
OnShowVersionChanged(_showVersion);
OnShowTopBarChanged(_showTopBar);
OnShowDialogChanged(_showDialog);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f3e2a1b9c4d5e6f8a0b1c2d3e4f5a6b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+32 -16
View File
@@ -23,7 +23,7 @@ namespace AibisDream
public RectTransform DialogCanvas { get; private set; }
private GraphicRaycaster _raycaster;
private bool _isRecordingMode;
private RecordingToolPanel _recordingToolPanel;
#endregion
@@ -52,24 +52,10 @@ namespace AibisDream
}
}
// 不明白为什么要用这个,不过留着也好
if (Input.GetKeyDown(KeyCode.C))
{
if (GetPanel<MainPanel>().IsOpen)
{
HidePanel<MainPanel>();
}
else
{
ShowPanel<MainPanel>();
}
}
if ((Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
&& Input.GetKeyDown(KeyCode.R))
{
_isRecordingMode = !_isRecordingMode;
EnumEventSystem.Global.Send(UIEventEnum.RecordingModeChanged, _isRecordingMode);
_recordingToolPanel?.TogglePanel();
}
}
@@ -81,6 +67,15 @@ namespace AibisDream
DialogCanvas = transform.Find("Dialog Canvas").GetComponent<RectTransform>();
// 获取 GraphicRaycaster
_raycaster = Canvas.GetComponent<GraphicRaycaster>();
_recordingToolPanel = GetComponentInChildren<RecordingToolPanel>(true);
if (_recordingToolPanel == null)
{
var infoPanel = transform.Find("UI Canvas/Info Panel");
if (infoPanel != null)
{
_recordingToolPanel = infoPanel.GetComponentInChildren<RecordingToolPanel>(true);
}
}
// 获取Panel
var panels = Canvas.GetComponentsInChildren<IUIPanel>(true);
_panelPool = new Dictionary<Type, IUIPanel>();
@@ -242,6 +237,27 @@ namespace AibisDream
return RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPos, UICamera, out localPoint);
}
/// <summary>
/// 检查屏幕坐标是否命中主 UI Canvas 上会接收射线的元素。
/// 对话 Canvas 不在此范围内,因此点击对话画面本身仍可正常推进。
/// </summary>
public bool IsPointerOverUI(Vector2 screenPosition)
{
if (EventSystem.current == null || _raycaster == null)
{
return false;
}
var eventData = new PointerEventData(EventSystem.current)
{
position = screenPosition
};
var results = new List<RaycastResult>();
_raycaster.Raycast(eventData, results);
return results.Count > 0;
}
/// <summary>
/// 检查鼠标是否在指定标记的 UI 区域上
/// </summary>