Add subtitle UI for voice playback

This commit is contained in:
2026-05-16 21:33:00 +01:00
parent 58050abded
commit 3174079e37
81 changed files with 8657 additions and 1231 deletions

View File

@@ -1,5 +1,6 @@
using BriarQueen.Framework.Managers.Levels.Data;
using BriarQueen.Framework.Managers.Player.Data;
using BriarQueen.Framework.Managers.UI;
using Cysharp.Threading.Tasks;
using UnityEngine;
@@ -7,10 +8,13 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
{
public class AshwickGate : BaseItem
{
[Header("Keypad")]
[SerializeField] private AshwickGateKeypadPuzzle _keypadPuzzle;
public override string InteractableName => "Iron Gate";
public override UICursorService.CursorStyle ApplicableCursorStyle => UICursorService.CursorStyle.Interact;
public override UniTask OnInteract(ItemDataSo item = null)
{
if (!CheckEmptyHands())

View File

@@ -5,7 +5,10 @@ using BriarQueen.Data.IO.Saves;
using BriarQueen.Framework.Effects;
using BriarQueen.Framework.Events.Save;
using BriarQueen.Framework.Managers.Interaction;
using BriarQueen.Framework.Managers.UI;
using BriarQueen.Framework.Managers.UI.Base;
using BriarQueen.Framework.Services.Puzzles.Base;
using BriarQueen.Framework.Services.Tutorials;
using BriarQueen.Game.Levels.ChapterOne.Ashwick;
using Cysharp.Threading.Tasks;
using MemoryPack;
@@ -24,7 +27,7 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
public string Digits;
}
public class AshwickGateKeypadPuzzle : BasePuzzle, IPuzzleStateful
public class AshwickGateKeypadPuzzle : BasePuzzle, IPuzzleStateful, IUIWindow, IUIBackHandler, IUIOverlayHost
{
private const string CorrectCode = "312";
private const int RequiredDigits = 3;
@@ -63,14 +66,25 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
private bool _isEvaluating;
private bool _isOpen;
private bool _raycasterRegistered;
private bool _skipSaveOnHide;
private TutorialService _tutorialService;
private UIManager _uiManager;
public override string PuzzleID => PuzzleIdentifiers.AllPuzzles[PuzzleKey.AshwickMarketGate];
public bool IsCompleted => _isCompleted || SaveManager.GetLevelFlag(LevelFlag.AshwickGateOpen);
public WindowType WindowType => WindowType.AshwickGateKeypadWindow;
public UIPauseBehavior PauseBehavior => UIPauseBehavior.OpenPauseOverlay;
[Inject]
public void ConstructKeypad(InteractManager interactManager)
public void ConstructKeypad(
InteractManager interactManager,
UIManager uiManager,
TutorialService tutorialService)
{
_interactManager = interactManager;
_uiManager = uiManager;
_tutorialService = tutorialService;
}
private void Awake()
@@ -86,8 +100,14 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
SyncDisplay();
}
private void Start()
{
_uiManager?.RegisterWindow(this);
}
private void OnDestroy()
{
_uiManager?.UnregisterWindow(this);
UnbindButtons();
TryUnregisterRaycaster();
CancelPanelTween();
@@ -98,10 +118,7 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
_isCompleted = SaveManager.GetLevelFlag(LevelFlag.AshwickGateOpen);
_isOpen = false;
_isEvaluating = false;
SetPanelState(0f, false, false);
SyncDisplay();
_statusGlow?.TurnOff().Forget();
_skipSaveOnHide = false;
return UniTask.CompletedTask;
}
@@ -113,12 +130,15 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
public void Open()
{
OpenInternal().Forget();
if (IsCompleted || _uiManager == null)
return;
_uiManager.OpenWindow(WindowType);
}
public void Close()
{
CloseInternal(requestSave: true).Forget();
_uiManager?.CloseWindow(WindowType);
}
public UniTask<byte[]> CaptureState()
@@ -159,12 +179,13 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
SyncDisplay();
SaveManager.SetPuzzleCompleted(PuzzleKey.AshwickMarketGate, true, requestSave: false);
await CloseInternal(requestSave: false);
_skipSaveOnHide = true;
_uiManager?.CloseWindow(WindowType);
AudioManager.Play(AudioNameIdentifiers.Get(SFXKey.AshwickGateOpening));
await _outskirts.OpenGate();
}
private async UniTaskVoid OpenInternal()
public async UniTask Show()
{
if (IsCompleted || _isEvaluating || _isOpen)
return;
@@ -174,8 +195,7 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
SetPanelState(0f, false, true);
SyncDisplay();
TryRegisterRaycaster();
_statusGlow?.TurnOff().Forget();
EnsureExclusiveRaycaster();
try
{
@@ -199,9 +219,10 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
}
SetPanelState(1f, true, true);
_tutorialService?.DisplayTutorial(TutorialPopupID.LeavingPuzzles);
}
private async UniTask CloseInternal(bool requestSave)
public async UniTask Hide()
{
if (!_isOpen)
return;
@@ -239,8 +260,91 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
SetPanelState(0f, false, false);
TryUnregisterRaycaster();
if (requestSave)
if (!_skipSaveOnHide && !_isCompleted)
EventCoordinator.PublishImmediate(new RequestGameSaveEvent());
_skipSaveOnHide = false;
}
public bool HandleBackRequest()
{
Close();
return true;
}
public bool CanSuspendFor(WindowType incomingWindowType)
{
return incomingWindowType == WindowType.PauseMenuWindow;
}
public async UniTask SuspendForOverlay()
{
if (!_isOpen)
return;
ResetPanelTween();
if (_panelGroup != null)
{
_panelGroup.interactable = false;
_panelGroup.blocksRaycasts = false;
}
try
{
_panelSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_panelGroup, new TweenSettings<float>
{
startValue = _panelGroup != null ? _panelGroup.alpha : 1f,
endValue = 0f,
settings = _panelFadeTweenSettings
}));
await _panelSequence.ToUniTask(cancellationToken: _panelCts.Token);
}
catch (OperationCanceledException)
{
return;
}
finally
{
_panelSequence = default;
}
SetPanelState(0f, false, false);
}
public async UniTask ResumeFromOverlay()
{
if (!_isOpen)
return;
ResetPanelTween();
EnsureExclusiveRaycaster();
SetPanelState(0f, false, true);
try
{
_panelSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_panelGroup, new TweenSettings<float>
{
startValue = 0f,
endValue = 1f,
settings = _panelFadeTweenSettings
}));
await _panelSequence.ToUniTask(cancellationToken: _panelCts.Token);
}
catch (OperationCanceledException)
{
return;
}
finally
{
_panelSequence = default;
}
SetPanelState(1f, !_isEvaluating, true);
}
private void OnDigitPressed(int digit)
@@ -370,14 +474,18 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
}
}
private void TryRegisterRaycaster()
private void EnsureExclusiveRaycaster()
{
if (_raycasterRegistered || _interactManager == null || _graphicRaycaster == null)
if (_interactManager == null || _graphicRaycaster == null)
return;
_interactManager.AddUIRaycaster(_graphicRaycaster);
if (!_raycasterRegistered)
{
_interactManager.AddUIRaycaster(_graphicRaycaster);
_raycasterRegistered = true;
}
_interactManager.SetExclusiveRaycaster(_graphicRaycaster);
_raycasterRegistered = true;
}
private void TryUnregisterRaycaster()
@@ -386,7 +494,7 @@ namespace BriarQueen.Game.Puzzles.ChapterOne.AshwickHallow
return;
_interactManager.RemoveUIRaycaster(_graphicRaycaster);
_interactManager.ClearExclusiveRaycaster();
_interactManager.ReleaseExclusiveRaycaster(_graphicRaycaster);
_raycasterRegistered = false;
}
}