Add subtitle UI for voice playback
This commit is contained in:
@@ -45,7 +45,8 @@ namespace BriarQueen.Framework.Managers.Audio
|
||||
private AudioSource _musicSourceB;
|
||||
private AudioSource _voiceSource;
|
||||
|
||||
private string _activeVoiceSubtitleId;
|
||||
private VoiceKey _activeVoiceKey = VoiceKey.None;
|
||||
private SubtitleKey _activeSubtitleKey = SubtitleKey.None;
|
||||
private AudioFileSo _currentMusicTrack;
|
||||
|
||||
private CancellationTokenSource _musicDuckCts;
|
||||
@@ -140,7 +141,8 @@ namespace BriarQueen.Framework.Managers.Audio
|
||||
_musicSourceB = null;
|
||||
_voiceSource = null;
|
||||
_currentMusicTrack = null;
|
||||
_activeVoiceSubtitleId = null;
|
||||
_activeVoiceKey = VoiceKey.None;
|
||||
_activeSubtitleKey = SubtitleKey.None;
|
||||
_voiceFinishedPublished = false;
|
||||
Initialized = false;
|
||||
}
|
||||
@@ -205,8 +207,7 @@ namespace BriarQueen.Framework.Managers.Audio
|
||||
if (_audioMixer == null || string.IsNullOrWhiteSpace(parameter))
|
||||
return;
|
||||
|
||||
if (!_baseDb.TryGetValue(parameter, out var baseDb))
|
||||
baseDb = 0f;
|
||||
var baseDb = _baseDb.GetValueOrDefault(parameter, 0f);
|
||||
|
||||
var effective = baseDb;
|
||||
|
||||
@@ -340,10 +341,14 @@ namespace BriarQueen.Framework.Managers.Audio
|
||||
_voiceCts = new CancellationTokenSource();
|
||||
var token = _voiceCts.Token;
|
||||
|
||||
_activeVoiceSubtitleId = SubtitleIdentifiers.Get(audioData.MatchingSubtitleID);
|
||||
_activeVoiceKey = audioData.VoiceKey;
|
||||
_activeSubtitleKey = audioData.MatchingSubtitleID;
|
||||
_voiceFinishedPublished = false;
|
||||
|
||||
_eventCoordinator.Publish(new VoiceLineStartedEvent(_activeVoiceSubtitleId));
|
||||
_eventCoordinator.Publish(new VoicePlaybackStartedEvent(
|
||||
_activeVoiceKey,
|
||||
_activeSubtitleKey,
|
||||
audioData.Clip.length));
|
||||
|
||||
_voiceSource.clip = audioData.Clip;
|
||||
_voiceSource.pitch = audioData.Pitch;
|
||||
@@ -369,11 +374,16 @@ namespace BriarQueen.Framework.Managers.Audio
|
||||
{
|
||||
if (_voiceFinishedPublished) return;
|
||||
|
||||
if (!string.IsNullOrEmpty(_activeVoiceSubtitleId))
|
||||
_eventCoordinator.Publish(new VoiceLineFinishedEvent(_activeVoiceSubtitleId));
|
||||
if (_activeVoiceKey != VoiceKey.None || _activeSubtitleKey != SubtitleKey.None)
|
||||
{
|
||||
_eventCoordinator.Publish(new VoicePlaybackFinishedEvent(
|
||||
_activeVoiceKey,
|
||||
_activeSubtitleKey));
|
||||
}
|
||||
|
||||
_voiceFinishedPublished = true;
|
||||
_activeVoiceSubtitleId = null;
|
||||
_activeVoiceKey = VoiceKey.None;
|
||||
_activeSubtitleKey = SubtitleKey.None;
|
||||
}
|
||||
|
||||
public void StopVoice()
|
||||
@@ -666,4 +676,4 @@ namespace BriarQueen.Framework.Managers.Audio
|
||||
public float StartedAtUnscaled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,13 +449,12 @@ namespace BriarQueen.Framework.Managers.Input
|
||||
private void OnPause(InputAction.CallbackContext ctx)
|
||||
{
|
||||
var isMainMenu = _gameService != null && _gameService.IsMainMenuSceneLoaded;
|
||||
if (isMainMenu || _isAnyUIOpen)
|
||||
if (isMainMenu)
|
||||
{
|
||||
_eventCoordinator?.PublishImmediate(new UIBackRequestedEvent());
|
||||
return;
|
||||
}
|
||||
|
||||
_isPaused = true;
|
||||
_eventCoordinator?.Publish(new PauseButtonClickedEvent());
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,22 @@ namespace BriarQueen.Framework.Managers.Interaction
|
||||
Debug.Log($"[InteractManager] SetExclusiveRaycaster set to {raycaster.gameObject.name}.");
|
||||
}
|
||||
|
||||
public void ReleaseExclusiveRaycaster(GraphicRaycaster raycaster)
|
||||
{
|
||||
if (raycaster == null)
|
||||
return;
|
||||
|
||||
if (_exclusiveRaycaster != raycaster)
|
||||
return;
|
||||
|
||||
_exclusiveRaycaster = null;
|
||||
|
||||
if (_currentHovered != null)
|
||||
ClearHover().Forget();
|
||||
|
||||
Debug.Log($"[InteractManager] Released exclusive raycaster {raycaster.gameObject.name}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear exclusive mode and return to using all registered raycasters.
|
||||
/// </summary>
|
||||
@@ -453,4 +469,4 @@ namespace BriarQueen.Framework.Managers.Interaction
|
||||
_selectedItem = evt.Item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,15 @@ namespace BriarQueen.Framework.Managers.Player.Data.Codex
|
||||
[Header("Codex")]
|
||||
[SerializeField]
|
||||
private CodexEntrySo _codexEntry;
|
||||
|
||||
[SerializeField]
|
||||
private bool _removeTrigger;
|
||||
|
||||
[Header("Events")]
|
||||
[SerializeField]
|
||||
private SFXKey _soundEffect;
|
||||
[SerializeField]
|
||||
private VoiceKey _voiceLine;
|
||||
|
||||
public override UICursorService.CursorStyle ApplicableCursorStyle => UICursorService.CursorStyle.Inspect;
|
||||
|
||||
public override string InteractableName =>
|
||||
@@ -40,12 +45,23 @@ namespace BriarQueen.Framework.Managers.Player.Data.Codex
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
PlayerManager.UnlockCodexEntry(_codexEntry);
|
||||
|
||||
if (_removeTrigger)
|
||||
{
|
||||
await Remove();
|
||||
}
|
||||
|
||||
if (_soundEffect != SFXKey.None)
|
||||
{
|
||||
AudioManager.Play(AudioNameIdentifiers.Get(_soundEffect));
|
||||
}
|
||||
|
||||
if (_voiceLine != VoiceKey.None)
|
||||
{
|
||||
AudioManager.Play(AudioNameIdentifiers.Get(_voiceLine));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateSaveGameOnRemoval()
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace BriarQueen.Framework.Managers.UI.Base
|
||||
{
|
||||
public interface IUIOverlayHost
|
||||
{
|
||||
bool CanSuspendFor(WindowType incomingWindowType);
|
||||
UniTask SuspendForOverlay();
|
||||
UniTask ResumeFromOverlay();
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using PrimeTween;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BriarQueen.Framework.Managers.UI.Base
|
||||
{
|
||||
public enum UIPauseBehavior
|
||||
{
|
||||
TreatAsBackRequest,
|
||||
OpenPauseOverlay
|
||||
}
|
||||
|
||||
public interface IUIWindow
|
||||
{
|
||||
UniTask Show();
|
||||
UniTask Hide();
|
||||
|
||||
WindowType WindowType { get; }
|
||||
|
||||
UIPauseBehavior PauseBehavior { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace BriarQueen.Framework.Managers.UI.Base
|
||||
{
|
||||
PauseMenuWindow,
|
||||
SettingsWindow,
|
||||
CodexWindow
|
||||
CodexWindow,
|
||||
AshwickGateKeypadWindow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,14 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
private sealed record OverlayResumeContext(WindowType OverlayWindowType, IUIOverlayHost Host);
|
||||
|
||||
private IHud _hudContainer;
|
||||
private IPopup _infoPopup;
|
||||
private IPopup _tutorialPopup;
|
||||
private IScreenFader _screenFader;
|
||||
private IUIOverlayHost _mainMenuOverlayHost;
|
||||
private IUIOverlayHost _activeSettingsOverlayHost;
|
||||
private readonly Stack<OverlayResumeContext> _overlayResumeStack = new();
|
||||
|
||||
[Inject]
|
||||
public UIManager(
|
||||
@@ -127,6 +129,18 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
window.Hide().Forget();
|
||||
}
|
||||
|
||||
public void UnregisterWindow(IUIWindow window)
|
||||
{
|
||||
if (window == null)
|
||||
return;
|
||||
|
||||
if (_windows.TryGetValue(window.WindowType, out var registered) && ReferenceEquals(registered, window))
|
||||
_windows.Remove(window.WindowType);
|
||||
|
||||
if (window is IUIOverlayHost overlayHost)
|
||||
RemoveOverlayResumeContextsForHost(overlayHost);
|
||||
}
|
||||
|
||||
public void RegisterHUD(IHud hudContainer)
|
||||
{
|
||||
_hudContainer = hudContainer;
|
||||
@@ -169,9 +183,7 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
if (!ReferenceEquals(_mainMenuOverlayHost, host))
|
||||
return;
|
||||
|
||||
if (ReferenceEquals(_activeSettingsOverlayHost, host))
|
||||
_activeSettingsOverlayHost = null;
|
||||
|
||||
RemoveOverlayResumeContextsForHost(host);
|
||||
_mainMenuOverlayHost = null;
|
||||
}
|
||||
|
||||
@@ -186,6 +198,51 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
return target != null && _windowStack.Contains(target);
|
||||
}
|
||||
|
||||
private void RemoveOverlayResumeContextsForHost(IUIOverlayHost host)
|
||||
{
|
||||
if (host == null || _overlayResumeStack.Count == 0)
|
||||
return;
|
||||
|
||||
var contextsToKeep = new List<OverlayResumeContext>();
|
||||
foreach (var context in _overlayResumeStack)
|
||||
{
|
||||
if (!ReferenceEquals(context.Host, host))
|
||||
contextsToKeep.Add(context);
|
||||
}
|
||||
|
||||
_overlayResumeStack.Clear();
|
||||
|
||||
for (var i = contextsToKeep.Count - 1; i >= 0; i--)
|
||||
_overlayResumeStack.Push(contextsToKeep[i]);
|
||||
}
|
||||
|
||||
private async UniTask<bool> TrySuspendActiveWindowFor(WindowType incomingWindowType)
|
||||
{
|
||||
if (ActiveWindow is IUIOverlayHost overlayHost &&
|
||||
overlayHost.CanSuspendFor(incomingWindowType))
|
||||
{
|
||||
await overlayHost.SuspendForOverlay();
|
||||
_overlayResumeStack.Push(new OverlayResumeContext(incomingWindowType, overlayHost));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async UniTask RestoreUnderlyingUi(WindowType closedWindowType)
|
||||
{
|
||||
if (_overlayResumeStack.Count > 0 &&
|
||||
_overlayResumeStack.Peek().OverlayWindowType == closedWindowType)
|
||||
{
|
||||
var resumeContext = _overlayResumeStack.Pop();
|
||||
await resumeContext.Host.ResumeFromOverlay();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ActiveWindow != null)
|
||||
await ActiveWindow.Show();
|
||||
}
|
||||
|
||||
private async UniTask ApplyHudVisibility(bool visible)
|
||||
{
|
||||
if (_disposed || _hudContainer == null)
|
||||
@@ -206,13 +263,25 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
|
||||
private void OnPauseClickReceived(PauseButtonClickedEvent _)
|
||||
{
|
||||
if (_windowStack.Count > 0)
|
||||
if (ActiveWindow == null)
|
||||
{
|
||||
OpenWindow(WindowType.PauseMenuWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ActiveWindow.WindowType == WindowType.PauseMenuWindow)
|
||||
{
|
||||
TryHandleBackRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
OpenWindow(WindowType.PauseMenuWindow);
|
||||
if (ActiveWindow.PauseBehavior == UIPauseBehavior.OpenPauseOverlay)
|
||||
{
|
||||
OpenWindow(WindowType.PauseMenuWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
TryHandleBackRequest();
|
||||
}
|
||||
|
||||
private void OnBackRequested(UIBackRequestedEvent _)
|
||||
@@ -350,28 +419,22 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
if (_windowStack.Contains(window))
|
||||
return;
|
||||
|
||||
_activeSettingsOverlayHost = null;
|
||||
var suspended = false;
|
||||
|
||||
var openingSettingsOverPause =
|
||||
source == SettingsOpenSource.PauseMenu &&
|
||||
ActiveWindow?.WindowType == WindowType.PauseMenuWindow &&
|
||||
ActiveWindow is IUIOverlayHost;
|
||||
|
||||
var openingSettingsOverMainMenu =
|
||||
source == SettingsOpenSource.MainMenu &&
|
||||
_mainMenuOverlayHost != null;
|
||||
|
||||
if (openingSettingsOverPause)
|
||||
if (source == SettingsOpenSource.MainMenu &&
|
||||
_mainMenuOverlayHost != null &&
|
||||
_mainMenuOverlayHost.CanSuspendFor(WindowType.SettingsWindow))
|
||||
{
|
||||
_activeSettingsOverlayHost = (IUIOverlayHost)ActiveWindow;
|
||||
await _activeSettingsOverlayHost.SuspendForOverlay();
|
||||
await _mainMenuOverlayHost.SuspendForOverlay();
|
||||
_overlayResumeStack.Push(new OverlayResumeContext(WindowType.SettingsWindow, _mainMenuOverlayHost));
|
||||
suspended = true;
|
||||
}
|
||||
else if (openingSettingsOverMainMenu)
|
||||
else
|
||||
{
|
||||
_activeSettingsOverlayHost = _mainMenuOverlayHost;
|
||||
await _activeSettingsOverlayHost.SuspendForOverlay();
|
||||
suspended = await TrySuspendActiveWindowFor(WindowType.SettingsWindow);
|
||||
}
|
||||
else if (ActiveWindow != null)
|
||||
|
||||
if (!suspended && ActiveWindow != null)
|
||||
{
|
||||
await ActiveWindow.Hide();
|
||||
}
|
||||
@@ -407,7 +470,9 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
if (_windowStack.Contains(window))
|
||||
return;
|
||||
|
||||
if (ActiveWindow != null)
|
||||
var suspended = await TrySuspendActiveWindowFor(windowType);
|
||||
|
||||
if (!suspended && ActiveWindow != null)
|
||||
await ActiveWindow.Hide();
|
||||
|
||||
_windowStack.Push(window);
|
||||
@@ -452,15 +517,7 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
break;
|
||||
}
|
||||
|
||||
if (target.WindowType == WindowType.SettingsWindow && _activeSettingsOverlayHost != null)
|
||||
{
|
||||
await _activeSettingsOverlayHost.ResumeFromOverlay();
|
||||
_activeSettingsOverlayHost = null;
|
||||
}
|
||||
else if (ActiveWindow != null)
|
||||
{
|
||||
await ActiveWindow.Show();
|
||||
}
|
||||
await RestoreUnderlyingUi(target.WindowType);
|
||||
|
||||
NotifyUIStackChanged();
|
||||
}
|
||||
@@ -506,17 +563,8 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
NotifyWindowStateChanged(top.WindowType, false);
|
||||
}
|
||||
|
||||
if (top != null &&
|
||||
top.WindowType == WindowType.SettingsWindow &&
|
||||
_activeSettingsOverlayHost != null)
|
||||
{
|
||||
await _activeSettingsOverlayHost.ResumeFromOverlay();
|
||||
_activeSettingsOverlayHost = null;
|
||||
}
|
||||
else if (ActiveWindow != null)
|
||||
{
|
||||
await ActiveWindow.Show();
|
||||
}
|
||||
if (top != null)
|
||||
await RestoreUnderlyingUi(top.WindowType);
|
||||
|
||||
NotifyUIStackChanged();
|
||||
}
|
||||
@@ -536,17 +584,12 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
await _windowTransitionGate.WaitAsync();
|
||||
try
|
||||
{
|
||||
var shouldResumeSettingsHost = false;
|
||||
|
||||
while (_windowStack.Count > 0)
|
||||
{
|
||||
var window = _windowStack.Pop();
|
||||
if (window == null)
|
||||
continue;
|
||||
|
||||
if (window.WindowType == WindowType.SettingsWindow && _activeSettingsOverlayHost != null)
|
||||
shouldResumeSettingsHost = true;
|
||||
|
||||
try
|
||||
{
|
||||
await window.Hide();
|
||||
@@ -557,18 +600,7 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldResumeSettingsHost)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _activeSettingsOverlayHost.ResumeFromOverlay();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
_activeSettingsOverlayHost = null;
|
||||
_overlayResumeStack.Clear();
|
||||
|
||||
if (_tutorialPopup != null)
|
||||
{
|
||||
@@ -621,7 +653,7 @@ namespace BriarQueen.Framework.Managers.UI
|
||||
faderComponent.gameObject.SetActive(false);
|
||||
|
||||
_windowStack.Clear();
|
||||
_activeSettingsOverlayHost = null;
|
||||
_overlayResumeStack.Clear();
|
||||
_mainMenuOverlayHost = null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user