Add subtitle UI for voice playback
This commit is contained in:
148
Assets/Scripts/Framework/Services/Subtitles/SubtitleService.cs
Normal file
148
Assets/Scripts/Framework/Services/Subtitles/SubtitleService.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using BriarQueen.Data.Identifiers;
|
||||
using BriarQueen.Framework.Coordinators.Events;
|
||||
using BriarQueen.Framework.Events.Audio;
|
||||
using BriarQueen.Framework.Events.UI;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using VContainer;
|
||||
|
||||
namespace BriarQueen.Framework.Services.Subtitles
|
||||
{
|
||||
public class SubtitleService : IDisposable
|
||||
{
|
||||
private readonly EventCoordinator _eventCoordinator;
|
||||
|
||||
private CancellationTokenSource _subtitleCts;
|
||||
private SubtitleKey _activeSubtitleKey = SubtitleKey.None;
|
||||
private string _currentText = string.Empty;
|
||||
|
||||
public bool IsVisible => _activeSubtitleKey != SubtitleKey.None && !string.IsNullOrWhiteSpace(_currentText);
|
||||
public string CurrentText => _currentText;
|
||||
|
||||
[Inject]
|
||||
public SubtitleService(EventCoordinator eventCoordinator)
|
||||
{
|
||||
_eventCoordinator = eventCoordinator;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_eventCoordinator.Subscribe<VoicePlaybackStartedEvent>(OnVoicePlaybackStarted);
|
||||
_eventCoordinator.Subscribe<VoicePlaybackFinishedEvent>(OnVoicePlaybackFinished);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_eventCoordinator.Unsubscribe<VoicePlaybackStartedEvent>(OnVoicePlaybackStarted);
|
||||
_eventCoordinator.Unsubscribe<VoicePlaybackFinishedEvent>(OnVoicePlaybackFinished);
|
||||
CancelCurrentSubtitle();
|
||||
ClearSubtitle();
|
||||
}
|
||||
|
||||
public void PlayScriptedSubtitle(SubtitleKey subtitleKey, float durationOverrideSeconds = 0f)
|
||||
{
|
||||
if (subtitleKey == SubtitleKey.None)
|
||||
{
|
||||
ClearScriptedSubtitle();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SubtitleIdentifiers.TryGet(subtitleKey, out var entry) || string.IsNullOrWhiteSpace(entry.Text))
|
||||
return;
|
||||
|
||||
var duration = durationOverrideSeconds > 0f
|
||||
? durationOverrideSeconds
|
||||
: entry.PreferredDurationSeconds;
|
||||
|
||||
ShowSubtitle(subtitleKey, entry.Text, duration).Forget();
|
||||
}
|
||||
|
||||
public void ClearScriptedSubtitle()
|
||||
{
|
||||
CancelCurrentSubtitle();
|
||||
ClearSubtitle();
|
||||
}
|
||||
|
||||
private void OnVoicePlaybackStarted(VoicePlaybackStartedEvent evt)
|
||||
{
|
||||
if (evt.SubtitleKey == SubtitleKey.None)
|
||||
return;
|
||||
|
||||
if (!SubtitleIdentifiers.TryGet(evt.SubtitleKey, out var entry) || string.IsNullOrWhiteSpace(entry.Text))
|
||||
return;
|
||||
|
||||
var duration = entry.PreferredDurationSeconds > 0f
|
||||
? entry.PreferredDurationSeconds
|
||||
: evt.ClipLengthSeconds;
|
||||
|
||||
ShowSubtitle(evt.SubtitleKey, entry.Text, duration).Forget();
|
||||
}
|
||||
|
||||
private void OnVoicePlaybackFinished(VoicePlaybackFinishedEvent evt)
|
||||
{
|
||||
if (evt.SubtitleKey == SubtitleKey.None)
|
||||
return;
|
||||
|
||||
if (_activeSubtitleKey != evt.SubtitleKey)
|
||||
return;
|
||||
|
||||
CancelCurrentSubtitle();
|
||||
ClearSubtitle();
|
||||
}
|
||||
|
||||
private async UniTaskVoid ShowSubtitle(SubtitleKey subtitleKey, string text, float durationSeconds)
|
||||
{
|
||||
CancelCurrentSubtitle();
|
||||
|
||||
_activeSubtitleKey = subtitleKey;
|
||||
_currentText = text;
|
||||
_subtitleCts = new CancellationTokenSource();
|
||||
|
||||
_eventCoordinator.PublishImmediate(new SubtitleDisplayChangedEvent(text, true));
|
||||
|
||||
var safeDuration = Math.Max(0f, durationSeconds);
|
||||
if (safeDuration <= 0f)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await UniTask.Delay(
|
||||
TimeSpan.FromSeconds(safeDuration),
|
||||
DelayType.UnscaledDeltaTime,
|
||||
cancellationToken: _subtitleCts.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_activeSubtitleKey == subtitleKey)
|
||||
ClearSubtitle();
|
||||
}
|
||||
|
||||
private void CancelCurrentSubtitle()
|
||||
{
|
||||
if (_subtitleCts == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
_subtitleCts.Cancel();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
_subtitleCts.Dispose();
|
||||
_subtitleCts = null;
|
||||
}
|
||||
|
||||
private void ClearSubtitle()
|
||||
{
|
||||
_activeSubtitleKey = SubtitleKey.None;
|
||||
_currentText = string.Empty;
|
||||
_eventCoordinator.PublishImmediate(new SubtitleDisplayChangedEvent(string.Empty, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61b6e034a002e4319a76ebe6bd90f50f
|
||||
Reference in New Issue
Block a user