From 6736a02e33c8ad0e086e16604aa122e64b17fcbd Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Thu, 1 Feb 2024 10:57:26 +1100 Subject: [PATCH] AudioLineProvider now correctly changes text locale at runtime --- CHANGELOG.md | 1 + Runtime/LineProviders/AudioLineProvider.cs | 92 ++++++++++++++-------- 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bd4b6e2..037f62bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - defaults to on release. - Actions Registration now dumps generated code into the same temporary folder the logs live in - `ActionsGenerator` will now generate C# warnings for incorrectly named methods that are attributed as `YarnFunction` or `YarnCommand`. +- Fixed a bug where `AudioLineProvider` didn't allow runtime changing of the text locale. ### Removed diff --git a/Runtime/LineProviders/AudioLineProvider.cs b/Runtime/LineProviders/AudioLineProvider.cs index 738903ea..10f2ca29 100644 --- a/Runtime/LineProviders/AudioLineProvider.cs +++ b/Runtime/LineProviders/AudioLineProvider.cs @@ -13,38 +13,44 @@ namespace Yarn.Unity public class AudioLineProvider : LineProviderBehaviour { #region AudioLineProviderInternalObjects - private interface IAudioLineProvider + private interface IAssetLineProvider { LocalizedLine GetLocalizedLine(Yarn.Line line); void PrepareForLines(IEnumerable lineIDs); bool LinesAvailable { get; } - YarnProject YarnProject { set; } - string textLanguageCode { set; get; } - string audioLanguage { set; get; } + AudioLineProvider audioLineProvider { get; set; } } - private class DirectReferenceAudioLineProvider: IAudioLineProvider + private class NullProvider: IAssetLineProvider { - public string textLanguageCode { get; set; } - - public string audioLanguage { set; get; } + public LocalizedLine GetLocalizedLine(Yarn.Line line) + { + Debug.LogWarning($"asked for line {line.ID} but this provider has no project."); + return null; + } + public void PrepareForLines(IEnumerable lineIDs) { } + public bool LinesAvailable { get { return false; } } + public AudioLineProvider audioLineProvider { get; set; } + } - public YarnProject YarnProject { get; set; } + private class DirectReferenceAudioLineProvider: IAssetLineProvider + { + public AudioLineProvider audioLineProvider { get; set; } // Lines are always available because they loaded with the scene public bool LinesAvailable => true; public LocalizedLine GetLocalizedLine(Line line) { - Localization audioLocalization = YarnProject.GetLocalization(audioLanguage); + Localization audioLocalization = audioLineProvider.YarnProject.GetLocalization(audioLineProvider.audioLanguageCode); Localization textLocalization; // If the audio language is different to the text language, // pull the text data from a different localization - if (audioLanguage != textLanguageCode) + if (audioLineProvider.audioLanguageCode != audioLineProvider.textLanguageCode) { - textLocalization = YarnProject.GetLocalization(textLanguageCode); + textLocalization = audioLineProvider.YarnProject.GetLocalization(audioLineProvider.textLanguageCode); } else { @@ -65,7 +71,7 @@ public LocalizedLine GetLocalizedLine(Line line) TextID = line.ID, RawText = text, Substitutions = line.Substitutions, - Metadata = YarnProject.lineMetadata.GetMetadata(line.ID), + Metadata = audioLineProvider.YarnProject.lineMetadata.GetMetadata(line.ID), Asset = audioClip, }; } @@ -79,11 +85,7 @@ public void PrepareForLines(IEnumerable lineIDs) #if USE_ADDRESSABLES private class AddressablesAudioLineProvider: IAudioLineProvider { - public string textLanguageCode { get; set; } - - public string audioLanguage { set; get; } - - public YarnProject YarnProject { get; set; } + AudioLineProvider audioLineProvider { get; set; } // Lines are available if there are no outstanding load operations public bool LinesAvailable => pendingLoadOperations.Count == 0; @@ -96,7 +98,7 @@ private class AddressablesAudioLineProvider: IAudioLineProvider public LocalizedLine GetLocalizedLine(Line line) { - Localization audioLocalization = YarnProject.GetLocalization(audioLanguage); + Localization audioLocalization = audioLineProvider.YarnProject.GetLocalization(audioLineProvider.audioLanguageCode); Localization textLocalization; @@ -104,7 +106,7 @@ public LocalizedLine GetLocalizedLine(Line line) // pull the text data from a different localization if (audioLanguage != textLanguageCode) { - textLocalization = YarnProject.GetLocalization(textLanguageCode); + textLocalization = audioLineProvider.YarnProject.GetLocalization(audioLineProvider.textLanguageCode); } else { @@ -151,11 +153,11 @@ public LocalizedLine GetLocalizedLine(Line line) public void PrepareForLines(IEnumerable lineIDs) { - var audioAddressableLocalization = YarnProject.GetLocalization(audioLanguage); + var audioAddressableLocalization = audioLineProvider.YarnProject.GetLocalization(audioLineProvider.audioLanguageCode); if (audioAddressableLocalization.UsesAddressableAssets == false) { - Debug.LogError($"The Yarn project {YarnProject.name} isn't using addressable assets, but the {nameof(AudioLineProvider)} is attempting to do so. Double check your project settings."); + Debug.LogError($"The Yarn project {audioLineProvider.YarnProject.name} isn't using addressable assets, but the {nameof(AudioLineProvider)} is attempting to do so. Double check your project settings."); return; } @@ -246,42 +248,62 @@ private void AssetLoadComplete(AsyncOperationHandle operation) /// Specifies the language code to use for audio content /// for this . [Language] - public string audioLanguage = System.Globalization.CultureInfo.CurrentCulture.Name; + public string audioLanguageCode = System.Globalization.CultureInfo.CurrentCulture.Name; public override string LocaleCode => textLanguageCode; - private IAudioLineProvider _provider; - private IAudioLineProvider provider + private IAssetLineProvider _provider; + private IAssetLineProvider provider { get { - if (_provider == null) + IAssetLineProvider configureProvider() { + IAssetLineProvider p; if (this.YarnProject != null) { - if (YarnProject.GetLocalization(audioLanguage).UsesAddressableAssets) + if (YarnProject.GetLocalization(audioLanguageCode).UsesAddressableAssets) { #if USE_ADDRESSABLES - _provider = new AddressablesAudioLineProvider(); + p = new AddressablesAudioLineProvider(); #else Debug.LogError($"The Yarn project {YarnProject.name} is configured to use Addressable assets, but the package is not installed. Double check your package settings. Falling back to providing non-Addressable audio loading"); - _provider = new DirectReferenceAudioLineProvider(); + p = new DirectReferenceAudioLineProvider(); #endif } else { - _provider = new DirectReferenceAudioLineProvider(); + p = new DirectReferenceAudioLineProvider(); } } else { - Debug.LogError($"The {nameof(AudioLineProvider)} is attempting to configure itself but the project isn't defined. Falling back to providing non-Addressable audio loading"); - _provider = new DirectReferenceAudioLineProvider(); + Debug.LogError($"The {nameof(AudioLineProvider)} is attempting to configure itself but the project isn't defined."); + p = new NullProvider(); } - _provider.YarnProject = this.YarnProject; - _provider.textLanguageCode = this.textLanguageCode; - _provider.audioLanguage = this.audioLanguage; + p.audioLineProvider = this; + return p; } + + // do we have an already set up provider? + // first time this runs it will always be null so we need to set one up + if (_provider == null) + { + _provider = configureProvider(); + } + // we have been configured but it is the null one + // this only happens when a yarn project hasn't been provided so there isn't really any solution + // except to try to configure it again and hope + else if (_provider is NullProvider) + { + // do we have a project yet? + // if so we reconfigure and try again + if (this.YarnProject != null) + { + _provider = configureProvider(); + } + } + return _provider; } }