Skip to content

Commit 13d15c7

Browse files
committed
Further stability to edge voice
1 parent e86f465 commit 13d15c7

File tree

12 files changed

+130
-94
lines changed

12 files changed

+130
-94
lines changed

SpeechMod/Configuration/SettingEntries/PlaybackStop.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
using HarmonyLib;
22
using Kingmaker;
3+
using Kingmaker.Blueprints.Root;
34
using Kingmaker.Code.UI.MVVM.View.Common.PC;
45
using Kingmaker.Code.UI.MVVM.VM.WarningNotification;
56
using Kingmaker.Localization;
7+
using Kingmaker.UI.Pointer;
68
using SpeechMod.Configuration.Settings;
9+
#if DEBUG
710
using UnityEngine;
11+
#endif
812

913
namespace SpeechMod.Configuration.SettingEntries;
1014

SpeechMod/Info.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
"AssemblyName": "W40KRTSpeechMod.dll",
88
"EntryMethod": "SpeechMod.Main.Load",
99
"HomePage": "https://www.nexusmods.com/warhammer40kroguetrader/mods/75",
10-
"Version": "0.9.3"
10+
"Version": "0.9.4"
1111
}

SpeechMod/Main.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using HarmonyLib;
22
using SpeechMod.Configuration;
33
using SpeechMod.Configuration.Settings;
4-
using SpeechMod.Unity;
54
using SpeechMod.Unity.Extensions;
65
using SpeechMod.Voice;
76
using System;
@@ -14,6 +13,7 @@
1413
using UnityEngine;
1514
using UnityModManagerNet;
1615
using SpeechMod.Unity.GUIs;
16+
using SpeechMod.Unity.Voices;
1717

1818
namespace SpeechMod;
1919

SpeechMod/Patches/SurfaceStaticPartPCView_Patch.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ namespace SpeechMod.Patches;
1111
[HarmonyPatch]
1212
public static class SurfaceStaticPartPCView_Patch
1313
{
14+
private const string SPEECHMOD_DIALOGBUTTON_NAME = "SpeechMod_DialogButton";
1415
private const string SURFACE_SCROLL_VIEW_PATH = "/SurfacePCView(Clone)/SurfaceStaticPartPCView/StaticCanvas/SurfaceDialogPCView/LeftSide/CueAndHistoryPlace/ScrollView";
1516
private const string SPACE_SCROLL_VIEW_PATH = "/SpacePCView(Clone)/SpaceStaticPartPCView/StaticCanvas/SurfaceDialogPCView/LeftSide/CueAndHistoryPlace/ScrollView";
1617

17-
[HarmonyPatch(typeof(SurfaceStaticPartPCView), "Initialize")]
18+
[HarmonyPatch(typeof(SurfaceStaticPartPCView), nameof(SurfaceStaticPartPCView.BindViewImplementation))]
1819
[HarmonyPostfix]
1920
public static void AddSurfaceDialogButton()
2021
{
@@ -23,13 +24,13 @@ public static void AddSurfaceDialogButton()
2324

2425
#if DEBUG
2526
var sceneName = Game.Instance!.CurrentlyLoadedArea!.ActiveUIScene!.SceneName;
26-
Debug.Log($"{nameof(SurfaceStaticPartPCView)}_Initialize_Postfix @ {sceneName}");
27+
Debug.Log($"{nameof(SurfaceStaticPartPCView)}_BindViewImplementation_Postfix @ {sceneName}");
2728
#endif
2829

2930
AddDialogSpeechButton(SURFACE_SCROLL_VIEW_PATH);
3031
}
3132

32-
[HarmonyPatch(typeof(SpaceStaticPartPCView), "Initialize")]
33+
[HarmonyPatch(typeof(SpaceStaticPartPCView), nameof(SpaceStaticPartPCView.BindViewImplementation))]
3334
[HarmonyPostfix]
3435
public static void AddSpaceDialogButton()
3536
{
@@ -38,7 +39,7 @@ public static void AddSpaceDialogButton()
3839

3940
#if DEBUG
4041
var sceneName = Game.Instance!.CurrentlyLoadedArea!.ActiveUIScene!.SceneName;
41-
Debug.Log($"{nameof(SpaceStaticPartPCView)}_Initialize_Postfix @ {sceneName}");
42+
Debug.Log($"{nameof(SpaceStaticPartPCView)}_BindViewImplementation_Postfix @ {sceneName}");
4243
#endif
4344

4445
AddDialogSpeechButton(SPACE_SCROLL_VIEW_PATH);
@@ -59,17 +60,24 @@ private static void AddDialogSpeechButton(string path)
5960
return;
6061
}
6162

63+
64+
if (parent.TryFind(SPEECHMOD_DIALOGBUTTON_NAME) != null)
65+
{
66+
Debug.LogWarning("Button already exists!");
67+
return;
68+
}
69+
6270
var buttonGameObject = ButtonFactory.TryCreatePlayButton(parent, () =>
6371
{
64-
Main.Speech.SpeakDialog(Game.Instance?.DialogController?.CurrentCue?.DisplayText);
72+
Main.Speech?.SpeakDialog(Game.Instance?.DialogController?.CurrentCue?.DisplayText);
6573
});
6674

6775
if (buttonGameObject == null)
6876
{
6977
return;
7078
}
7179

72-
buttonGameObject.name = "SpeechMod_DialogButton";
80+
buttonGameObject.name = SPEECHMOD_DIALOGBUTTON_NAME;
7381
buttonGameObject.RectAlignTopLeft(new Vector2(40, 10));
7482
buttonGameObject.transform.localRotation = Quaternion.Euler(0, 0, 270);
7583

SpeechMod/Unity/AppleVoiceUnity.cs renamed to SpeechMod/Unity/Voices/AppleVoiceUnity.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using SpeechMod.Unity.Extensions;
77
using UnityEngine;
88

9-
namespace SpeechMod.Unity;
9+
namespace SpeechMod.Unity.Voices;
1010

1111
public class AppleVoiceUnity : MonoBehaviour
1212
{

SpeechMod/Unity/EdgeVoiceUnity.cs renamed to SpeechMod/Unity/Voices/EdgeVoiceUnity.cs

Lines changed: 61 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
using System.Threading.Tasks;
1010
using UnityEngine;
1111

12-
namespace SpeechMod.Unity;
12+
namespace SpeechMod.Unity.Voices;
1313

1414
public class EdgeVoiceUnity : MonoBehaviour
1515
{
1616
private const string TOKEN = "6A5AA1D4EAFF4E9FB37E23D68491D6F4";
17-
private int _playIndex;
18-
private List<Task<EdgeVoiceClient>> _voiceTasks = new();
1917
private static EdgeVoiceUnity s_Instance;
18+
public int PlayIndex;
19+
public List<Task<EdgeVoiceClient>> VoiceTasks = new();
20+
public CancellationToken CancellationToken;
2021

2122
private EdgeVoiceUnity()
2223
{
@@ -41,57 +42,56 @@ public static string[] SetAvailableVoices()
4142

4243
public static bool IsSpeaking()
4344
{
44-
if (s_Instance?._voiceTasks == null || s_Instance._voiceTasks.Count == 0)
45+
if (s_Instance?.VoiceTasks == null || s_Instance.VoiceTasks.Count == 0)
4546
return false;
4647

47-
if (s_Instance._playIndex < 0 || s_Instance._playIndex >= s_Instance._voiceTasks.Count)
48+
if (s_Instance.PlayIndex < 0 || s_Instance.PlayIndex >= s_Instance.VoiceTasks.Count)
4849
return false;
4950

50-
if (s_Instance._playIndex + 1 < s_Instance._voiceTasks.Count)
51+
if (s_Instance.PlayIndex + 1 < s_Instance.VoiceTasks.Count)
5152
return true;
5253

53-
var edgeVoiceClient = s_Instance._voiceTasks[s_Instance._playIndex]?.Result;
54+
var edgeVoiceClient = s_Instance.VoiceTasks[s_Instance.PlayIndex]?.Result;
5455
return edgeVoiceClient is { IsSpeaking: true };
5556
}
5657

5758
public static string GetStatusMessage()
5859
{
59-
if (s_Instance?._voiceTasks == null)
60-
return "Idle";
60+
if (s_Instance?.VoiceTasks == null)
61+
return EdgeVoiceClient.EdgeVoiceClientState.Ready.ToString();
6162

62-
if (s_Instance._playIndex < 0 || s_Instance._playIndex >= s_Instance._voiceTasks.Count)
63-
{
64-
s_Instance._playIndex = 0;
65-
return "Idle";
66-
}
63+
if (s_Instance.PlayIndex < 0 || s_Instance.PlayIndex >= s_Instance.VoiceTasks.Count)
64+
return EdgeVoiceClient.EdgeVoiceClientState.Ready.ToString();
6765

68-
var edgeVoiceClient = s_Instance._voiceTasks[s_Instance._playIndex]?.Result;
66+
var edgeVoiceClient = s_Instance.VoiceTasks[s_Instance.PlayIndex]?.Result;
6967
if (edgeVoiceClient != null)
7068
return edgeVoiceClient.CurrentState.ToString();
7169

72-
return "Error";
70+
return EdgeVoiceClient.EdgeVoiceClientState.Error.ToString();
7371
}
7472

7573
public static void Speak(EdgeVoiceDto edgeVoiceDTO)
7674
{
77-
var cancellationToken = new CancellationToken();
78-
SpeakInternal(edgeVoiceDTO, cancellationToken);
75+
s_Instance.CancellationToken = new CancellationToken();
76+
SpeakInternal(edgeVoiceDTO);
7977
}
8078

8179
public static void SpeakMulti(EdgeVoiceDto[] edgeVoiceDTOs)
8280
{
83-
var cancellationToken = new CancellationToken();
84-
SpeakMultiInternal(edgeVoiceDTOs, cancellationToken);
81+
s_Instance.CancellationToken = new CancellationToken();
82+
SpeakMultiInternal(edgeVoiceDTOs);
8583
}
8684

8785
public static void Stop()
8886
{
8987
if (!IsSpeaking())
9088
return;
9189

92-
var edgeVoiceClient = s_Instance?._voiceTasks?[s_Instance._playIndex]?.Result;
90+
s_Instance?.StopCoroutine(PlayMultipleCoroutine());
91+
92+
var edgeVoiceClient = s_Instance?.VoiceTasks?[s_Instance.PlayIndex]?.Result;
9393
edgeVoiceClient?.Stop();
94-
s_Instance._playIndex = 0;
94+
s_Instance.PlayIndex = 0;
9595
}
9696

9797
void OnDestroy()
@@ -124,39 +124,40 @@ private static async Task<string[]> SetAvailableVoicesInternal()
124124
return Main.EdgeAvailableVoices?.Select(x => x.ShortName).ToArray();
125125
}
126126

127-
private static async Task SpeakInternal(EdgeVoiceDto edgeVoiceDTO, CancellationToken cancellationToken)
127+
private static async Task SpeakInternal(EdgeVoiceDto edgeVoiceDTO)
128128
{
129-
Debug.Log($"SpeakInternal: '{edgeVoiceDTO.Voice}' - R: {edgeVoiceDTO.Rate}, P: {edgeVoiceDTO.Pitch}, V: {edgeVoiceDTO.Volume} ");
129+
#if DEBUG
130+
Debug.Log($"SpeakInternal: {edgeVoiceDTO.Text}");
131+
#endif
130132

131133
Stop();
132134
Reset();
133135

134-
s_Instance._voiceTasks.Add(new Task<EdgeVoiceClient>(() =>
136+
s_Instance.VoiceTasks.Add(new Task<EdgeVoiceClient>(() =>
135137
{
136138
var edgeVoice = new EdgeVoiceClient();
137139
edgeVoice.Load(edgeVoiceDTO, TOKEN);
138140
return edgeVoice;
139141
}));
140142

141-
var single = s_Instance._voiceTasks.First();
143+
var single = s_Instance.VoiceTasks.First();
144+
145+
//s_Instance.StartCoroutine(SpeakingCoroutine());
142146

143147
single.Start();
144148
await single;
145149

146-
if (cancellationToken.IsCancellationRequested)
150+
if (s_Instance.CancellationToken.IsCancellationRequested)
147151
return;
148152

149-
Debug.Log("Play");
150153
single.Result?.Play();
151154
}
152155

153-
private static async Task SpeakMultiInternal(EdgeVoiceDto[] edgeVoiceDTOs, CancellationToken cancellationToken)
156+
private static async Task SpeakMultiInternal(EdgeVoiceDto[] edgeVoiceDTOs)
154157
{
155-
foreach (var edgeVoiceDto in edgeVoiceDTOs)
156-
{
157-
Debug.Log($"Speak: '{edgeVoiceDto.Text}' '{edgeVoiceDto.Voice}'");
158-
}
159-
158+
#if DEBUG
159+
Debug.Log($"SpeakMultiInternal: {edgeVoiceDTOs.Length}");
160+
#endif
160161
Stop();
161162
Reset();
162163

@@ -165,60 +166,67 @@ private static async Task SpeakMultiInternal(EdgeVoiceDto[] edgeVoiceDTOs, Cance
165166
if (string.IsNullOrWhiteSpace(edgeVoiceDTO.Text))
166167
continue;
167168

168-
s_Instance._voiceTasks?.Add(new Task<EdgeVoiceClient>(() =>
169+
s_Instance.VoiceTasks?.Add(new Task<EdgeVoiceClient>(() =>
169170
{
170171
var edgeVoice = new EdgeVoiceClient();
171172
edgeVoice.Load(edgeVoiceDTO, TOKEN);
172173
return edgeVoice;
173174
}));
174175
}
175176

176-
foreach (var task in s_Instance._voiceTasks)
177+
//s_Instance.StartCoroutine(SpeakingCoroutine());
178+
179+
foreach (var task in s_Instance.VoiceTasks)
177180
{
178181
task.Start();
179182
}
180183

181-
await s_Instance._voiceTasks.First();
184+
await s_Instance.VoiceTasks.First();
182185

183-
if (cancellationToken.IsCancellationRequested)
186+
if (s_Instance.CancellationToken.IsCancellationRequested)
184187
return;
185188

186-
var voiceClient = s_Instance._voiceTasks[s_Instance._playIndex]?.Result;
189+
var voiceClient = s_Instance.VoiceTasks[s_Instance.PlayIndex]?.Result;
187190
if (voiceClient != null)
188191
{
189-
Debug.Log("Play first");
190192
voiceClient.Play();
191193

192-
Debug.Log("Starting Coroutine");
193-
s_Instance.StartCoroutine(PlayMultipleCoroutine(cancellationToken));
194+
s_Instance.StartCoroutine(PlayMultipleCoroutine());
194195
}
195196
}
196197

197-
private static IEnumerator PlayMultipleCoroutine(CancellationToken cancellationToken)
198+
private static IEnumerator PlayMultipleCoroutine()
198199
{
199-
Debug.Log("Play Multiple Coroutine");
200-
while (s_Instance._playIndex < s_Instance._voiceTasks.Count)
200+
while (s_Instance.PlayIndex < s_Instance.VoiceTasks.Count)
201201
{
202-
if (cancellationToken.IsCancellationRequested)
202+
if (s_Instance.CancellationToken.IsCancellationRequested)
203203
break;
204204

205-
var edgeVoiceClient = s_Instance._voiceTasks[s_Instance._playIndex].Result;
205+
var edgeVoiceClient = s_Instance.VoiceTasks[s_Instance.PlayIndex].Result;
206206
if (edgeVoiceClient is { IsSpeaking: true })
207207
yield return new WaitForSeconds(0.1f);
208208
else
209209
{
210-
if (++s_Instance._playIndex >= s_Instance._voiceTasks.Count)
210+
if (++s_Instance.PlayIndex >= s_Instance.VoiceTasks.Count)
211211
break;
212-
Debug.Log("Play next");
213-
s_Instance._voiceTasks[s_Instance._playIndex]?.Result?.Play();
212+
213+
s_Instance.VoiceTasks[s_Instance.PlayIndex]?.Result?.Play();
214214
}
215215
}
216216
}
217217

218+
private static IEnumerator SpeakingCoroutine()
219+
{
220+
while (IsSpeaking())
221+
{
222+
yield return new WaitForEndOfFrame();
223+
}
224+
}
225+
218226
private static void Reset()
219227
{
220-
s_Instance?.StopAllCoroutines();
221-
s_Instance._playIndex = 0;
222-
s_Instance._voiceTasks = new List<Task<EdgeVoiceClient>>();
228+
s_Instance?.StopCoroutine(PlayMultipleCoroutine());
229+
s_Instance.PlayIndex = 0;
230+
s_Instance.VoiceTasks = new List<Task<EdgeVoiceClient>>();
223231
}
224232
}

SpeechMod/Unity/WindowsVoiceUnity.cs renamed to SpeechMod/Unity/Voices/WindowsVoiceUnity.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using SpeechMod.Unity.Extensions;
55
using UnityEngine;
66

7-
namespace SpeechMod.Unity;
7+
namespace SpeechMod.Unity.Voices;
88

99
public class WindowsVoiceUnity : MonoBehaviour
1010
{
@@ -104,7 +104,7 @@ public static string GetStatusMessage()
104104

105105
public static float GetNormalizedProgress()
106106
{
107-
return 1-(float)(m_CurrentWordCount - getWordPosition()) / m_CurrentWordCount;
107+
return 1 - (float)(m_CurrentWordCount - getWordPosition()) / m_CurrentWordCount;
108108
}
109109

110110
public static void Stop()

SpeechMod/Voice/AppleSpeech.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using SpeechMod.Unity;
1+
using SpeechMod.Unity.Voices;
22
using System;
33
using System.Diagnostics;
44
using System.Text.RegularExpressions;

SpeechMod/Voice/Edge/EdgeSpeech.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using System.Text.RegularExpressions;
55
using Kingmaker.Blueprints.Base;
66
using UnityEngine;
7-
using SpeechMod.Unity;
7+
using SpeechMod.Unity.Voices;
88

99
namespace SpeechMod.Voice.Edge;
1010

@@ -70,9 +70,12 @@ private static EdgeVoiceDto[] ExtractOrderedStrings(string text)
7070
if (string.IsNullOrWhiteSpace(text))
7171
return null;
7272

73-
if (Game.Instance.DialogController.CurrentSpeaker.Gender == Gender.Female)
74-
return new EdgeVoiceDto(text, Main.Settings.FemaleVoice, Main.Settings.FemalePitch, Main.Settings.FemaleRate, Main.Settings.FemaleVolume);
75-
return new EdgeVoiceDto(text, Main.Settings.MaleVoice, Main.Settings.MalePitch, Main.Settings.MaleRate, Main.Settings.MaleVolume);
73+
return Game.Instance?.DialogController?.CurrentSpeaker?.Gender switch
74+
{
75+
Gender.Female => new EdgeVoiceDto(text, Main.Settings.FemaleVoice, Main.Settings.FemalePitch, Main.Settings.FemaleRate, Main.Settings.FemaleVolume),
76+
Gender.Male => new EdgeVoiceDto(text, Main.Settings.MaleVoice, Main.Settings.MalePitch, Main.Settings.MaleRate, Main.Settings.MaleVolume),
77+
_ => new EdgeVoiceDto(text, Main.Settings.NarratorVoice, Main.Settings.NarratorPitch, Main.Settings.NarratorRate, Main.Settings.NarratorVolume)
78+
};
7679
}
7780

7881
public string GetStatusMessage()

0 commit comments

Comments
 (0)